Skip to content

Commit 684c15f

Browse files
drganjooFahad Zubair
andauthored
Set MSRV in rust-toolchain.toml using the gradle.property (#3841)
The `rust-toolchain.toml` file for tests now uses the `rust.msrv` value from the `gradle.properties` file. This PR also fixes an issue where the `rust-toolchain.toml` file was not created in the overridden test directory when `overrideTestDir` was set. This caused the installed compiler version to be used, resulting in errors with the latest compiler and preventing the use of `overrideTestDir`. Closes: #2048 --------- Co-authored-by: Fahad Zubair <[email protected]>
1 parent abd28bc commit 684c15f

File tree

2 files changed

+131
-9
lines changed
  • codegen-core/src

2 files changed

+131
-9
lines changed

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ import software.amazon.smithy.rust.codegen.core.util.letIf
4040
import software.amazon.smithy.rust.codegen.core.util.orNullIfEmpty
4141
import software.amazon.smithy.rust.codegen.core.util.runCommand
4242
import java.io.File
43+
import java.io.FileInputStream
4344
import java.nio.file.Files
4445
import java.nio.file.Files.createTempDirectory
4546
import java.nio.file.Path
47+
import java.util.Properties
4648
import kotlin.io.path.absolutePathString
4749
import kotlin.io.path.writeText
4850

@@ -54,6 +56,8 @@ val TestModuleDocProvider =
5456
}
5557
}
5658

59+
val projectRootDir by lazy { File("git rev-parse --show-toplevel".runCommand().replace("\n", "")) }
60+
5761
/**
5862
* Waiting for Kotlin to stabilize their temp directory functionality
5963
*/
@@ -65,6 +69,38 @@ private fun tempDir(directory: File? = null): File {
6569
}
6670
}
6771

72+
/**
73+
* This function returns the minimum supported Rust version, as specified in the `gradle.properties` file
74+
* located at the root of the project.
75+
*/
76+
fun msrv(): String {
77+
val properties = Properties()
78+
val propertiesFilePath = projectRootDir.resolve("gradle.properties")
79+
80+
FileInputStream(propertiesFilePath).use { inputStream ->
81+
properties.load(inputStream)
82+
}
83+
84+
return properties.getProperty("rust.msrv")
85+
}
86+
87+
/**
88+
* Generates the `rust-toolchain.toml` file in the specified directory.
89+
*
90+
* The compiler version is set in `gradle.properties` under the `rust.msrv` property.
91+
* The Gradle task `GenerateMsrvTask` generates the Kotlin class
92+
* `software.amazon.smithy.rust.codegen.core.Msrv` and writes the value of `rust.msrv` into it.
93+
*/
94+
private fun File.generateRustToolchainToml() {
95+
resolve("rust-toolchain.toml").writeText(
96+
// Help rust select the right version when we run cargo test.
97+
"""
98+
[toolchain]
99+
channel = "${msrv()}"
100+
""".trimIndent(),
101+
)
102+
}
103+
68104
/**
69105
* Creates a Cargo workspace shared among all tests
70106
*
@@ -87,8 +123,7 @@ object TestWorkspace {
87123
private val subprojects = mutableListOf<String>()
88124

89125
private val cargoLock: File by lazy {
90-
val projectDir = "git rev-parse --show-toplevel".runCommand().replace("\n", "")
91-
File(projectDir).resolve("aws/sdk/Cargo.lock")
126+
projectRootDir.resolve("aws/sdk/Cargo.lock")
92127
}
93128

94129
init {
@@ -121,12 +156,7 @@ object TestWorkspace {
121156
version = "0.0.1"
122157
""".trimIndent(),
123158
)
124-
newProject.resolve("rust-toolchain.toml").writeText(
125-
// help rust select the right version when we run cargo test
126-
// TODO(https://github.com/smithy-lang/smithy-rs/issues/2048): load this from the msrv property using a
127-
// method as we do for runtime crate versions
128-
"[toolchain]\nchannel = \"1.78.0\"\n",
129-
)
159+
newProject.generateRustToolchainToml()
130160
// ensure there at least an empty lib.rs file to avoid broken crates
131161
newProject.resolve("src").mkdirs()
132162
newProject.resolve("src/lib.rs").writeText("")
@@ -181,7 +211,11 @@ fun generatePluginContext(
181211
runtimeConfig: RuntimeConfig? = null,
182212
overrideTestDir: File? = null,
183213
): Pair<PluginContext, Path> {
184-
val testDir = overrideTestDir ?: TestWorkspace.subproject()
214+
val testDir =
215+
overrideTestDir?.apply {
216+
mkdirs()
217+
generateRustToolchainToml()
218+
} ?: TestWorkspace.subproject()
185219
val moduleName = "test_${testDir.nameWithoutExtension}"
186220
val testPath = testDir.toPath()
187221
val manifest = FileManifest.create(testPath)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.rust.codegen.core.util
7+
8+
import io.kotest.matchers.booleans.shouldBeTrue
9+
import io.kotest.matchers.paths.shouldExist
10+
import io.kotest.matchers.shouldNotBe
11+
import org.junit.jupiter.api.Test
12+
import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel
13+
import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext
14+
import software.amazon.smithy.rust.codegen.core.testutil.projectRootDir
15+
import java.nio.file.Files.createTempDirectory
16+
import java.util.regex.Pattern
17+
18+
internal class RustToolChainTomlTest {
19+
val model =
20+
"""
21+
namespace test
22+
23+
service TestService {
24+
version: "123",
25+
operations: [TestOperation]
26+
}
27+
28+
operation TestOperation {
29+
input:= {}
30+
output:= {}
31+
}
32+
""".asSmithyModel(smithyVersion = "2")
33+
34+
@Test
35+
fun `override test directory in integration test has a rust-toolchain toml file`() {
36+
val dir = createTempDirectory("smithy-test").toFile()
37+
val (_, path) = generatePluginContext(model, overrideTestDir = dir)
38+
path.shouldExist()
39+
val rustToolchainTomlPath = path.resolve("rust-toolchain.toml")
40+
rustToolchainTomlPath.shouldExist()
41+
}
42+
43+
@Test
44+
fun `rust-toolchain toml file has correct value from gradle properties for rust-msrv`() {
45+
val (_, path) = generatePluginContext(model)
46+
val rustToolchainTomlPath = path.resolve("rust-toolchain.toml")
47+
rustToolchainTomlPath.shouldExist()
48+
49+
// Read the MSRV written in `gradle.properties` file.
50+
val msrvPattern = Pattern.compile("rust\\.msrv=(.+)")
51+
val gradlePropertiesPath = projectRootDir.resolve("gradle.properties")
52+
val msrv =
53+
gradlePropertiesPath.useLines { lines ->
54+
lines.firstNotNullOfOrNull { line ->
55+
msrvPattern.matcher(line).let { matcher ->
56+
if (matcher.find()) matcher.group(1) else null
57+
}
58+
}
59+
}
60+
msrv shouldNotBe null
61+
62+
// Read `channel = (\d+)` from `rust-toolchain.toml` file, and
63+
// ensure it matches the one in `gradle.properties`.
64+
val toolchainPattern = Pattern.compile("\\[toolchain]")
65+
val channelPattern = Pattern.compile("channel\\s*=\\s*\"(.+)\"")
66+
67+
val channelMatches =
68+
rustToolchainTomlPath.toFile().useLines { lines ->
69+
// Skip lines until the [toolchain] table is found, then take all lines until the next table.
70+
val toolchainSection =
71+
lines
72+
.dropWhile { !toolchainPattern.matcher(it).find() }
73+
.drop(1)
74+
.takeWhile { !it.trim().startsWith("[") }
75+
76+
// There should be a [toolchain] table, and it must have a key called 'channel' whose value must
77+
// match the `rust.msrv` specified in gradle.properties.
78+
toolchainSection != null &&
79+
toolchainSection.any { line ->
80+
channelPattern.matcher(line).let { matcher ->
81+
matcher.find() && matcher.group(1) == msrv
82+
}
83+
}
84+
}
85+
86+
channelMatches.shouldBeTrue()
87+
}
88+
}

0 commit comments

Comments
 (0)