Skip to content

Commit 958f8da

Browse files
committed
Use real deployment for just one test
That is enough to prove the downloading works and the rest can just test their own extra assumptions on top of that.
1 parent 7f654e4 commit 958f8da

File tree

2 files changed

+75
-49
lines changed

2 files changed

+75
-49
lines changed

src/main/kotlin/com/coder/gateway/sdk/CoderCLIManager.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,12 @@ class CoderCLIManager @JvmOverloads constructor(deployment: URL, destinationDir:
160160
}
161161

162162
/**
163-
* Execute the binary with the provided arguments.
164-
*
165-
* @return The command's output.
163+
* Return the binary version.
166164
*/
165+
fun version(): String {
166+
return exec("version")
167+
}
168+
167169
private fun exec(vararg args: String): String {
168170
val stdout = ProcessExecutor()
169171
.command(localBinaryPath.toString(), *args)

src/test/groovy/CoderCLIManagerTest.groovy

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,23 @@ import java.nio.file.Path
1414
class CoderCLIManagerTest extends spock.lang.Specification {
1515
@Shared
1616
private Path tmpdir = Path.of(System.getProperty("java.io.tmpdir")).resolve("coder-gateway-test")
17-
@Shared
18-
private String deploymentURL = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT")
19-
@Shared
20-
private String altDeploymentURL = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT_ALT")
21-
@Shared
22-
private def servers = []
17+
private String mockBinaryContent = "#!/bin/sh\necho Coder"
2318

2419
/**
2520
* Create, start, and return a server that mocks Coder.
2621
*/
27-
HttpServer startMockServer(errorCode = 0) {
22+
def mockServer(errorCode = 0) {
2823
HttpServer srv = HttpServer.create(new InetSocketAddress(0), 0)
2924
srv.createContext("/", new HttpHandler() {
3025
void handle(HttpExchange exchange) {
3126
int code = HttpURLConnection.HTTP_OK
32-
String response = "not a real binary"
27+
// TODO: Is there some simple way to create an executable file
28+
// on Windows without having to execute something to generate
29+
// said executable or having to commit one to the repo?
30+
String response = mockBinaryContent
3331

3432
String[] etags = exchange.requestHeaders.get("If-None-Match")
35-
if (etags != null && etags.contains("\"cb25cf6f41bb3127d7e05b0c3c6403be9ab052bc\"")) {
33+
if (etags != null && etags.contains("\"2f1960264fc0f332a2a7fef2fe678f258dcdff9c\"")) {
3634
code = HttpURLConnection.HTTP_NOT_MODIFIED
3735
response = "not modified"
3836
}
@@ -53,37 +51,14 @@ class CoderCLIManagerTest extends spock.lang.Specification {
5351
exchange.close()
5452
}
5553
})
56-
servers << srv
5754
srv.start()
58-
return "http://localhost:" + srv.address.port
55+
return [srv, "http://localhost:" + srv.address.port]
5956
}
6057

6158
void setupSpec() {
6259
// Clean up from previous runs otherwise they get cluttered since the
63-
// port is random.
60+
// mock server port is random.
6461
tmpdir.toFile().deleteDir()
65-
66-
// Spin up mock server(s).
67-
if (deploymentURL == null) {
68-
deploymentURL = startMockServer()
69-
}
70-
if (altDeploymentURL == null) {
71-
altDeploymentURL = startMockServer()
72-
}
73-
}
74-
75-
void cleanupSpec() {
76-
servers.each {
77-
it.stop(0)
78-
}
79-
}
80-
81-
/**
82-
* Create a CLI manager pointing to the URLs in the environment or to mocked
83-
* servers.
84-
*/
85-
CoderCLIManager createCLIManager(Boolean alternate = false) {
86-
return new CoderCLIManager(new URL(alternate ? altDeploymentURL : deploymentURL), tmpdir)
8762
}
8863

8964
def "defaults to a sub-directory in the data directory"() {
@@ -112,8 +87,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
11287

11388
def "fails to download"() {
11489
given:
115-
HttpServer server = startMockServer(HttpURLConnection.HTTP_INTERNAL_ERROR)
116-
String url = "http://localhost:" + server.address.port
90+
def (srv, url) = mockServer(HttpURLConnection.HTTP_INTERNAL_ERROR)
11791
def ccm = new CoderCLIManager(new URL(url), tmpdir)
11892

11993
when:
@@ -122,59 +96,109 @@ class CoderCLIManagerTest extends spock.lang.Specification {
12296
then:
12397
def e = thrown(ResponseException)
12498
e.code == HttpURLConnection.HTTP_INTERNAL_ERROR
99+
100+
cleanup:
101+
srv.stop(0)
102+
}
103+
104+
// This test uses a real deployment if possible to make sure we really
105+
// download a working CLI and that it runs on each platform.
106+
@Requires({ env["CODER_GATEWAY_TEST_DEPLOYMENT"] != "mock" })
107+
def "downloads a real working cli"() {
108+
given:
109+
def url = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT")
110+
if (url == null) {
111+
url = "https://dev.coder.com"
112+
}
113+
def ccm = new CoderCLIManager(new URL(url), tmpdir)
114+
ccm.localBinaryPath.getParent().toFile().deleteDir()
115+
116+
when:
117+
def downloaded = ccm.downloadCLI()
118+
119+
then:
120+
downloaded
121+
ccm.version().contains("Coder")
125122
}
126123

127-
def "downloads a working cli"() {
124+
def "downloads a mocked cli"() {
128125
given:
129-
def ccm = createCLIManager()
126+
def (srv, url) = mockServer()
127+
def ccm = new CoderCLIManager(new URL(url), tmpdir)
130128
ccm.localBinaryPath.getParent().toFile().deleteDir()
131129

132130
when:
133131
def downloaded = ccm.downloadCLI()
134132

135133
then:
136134
downloaded
137-
ccm.localBinaryPath.toFile().canExecute()
135+
// The mock does not serve a binary that works on Windows so do not
136+
// actually execute. Checking the contents works just as well as proof
137+
// that the binary was correctly downloaded anyway.
138+
ccm.localBinaryPath.toFile().readBytes() == mockBinaryContent.getBytes()
139+
140+
cleanup:
141+
srv.stop(0)
138142
}
139143

140144
def "overwrites cli if incorrect version"() {
141145
given:
142-
def ccm = createCLIManager()
146+
def (srv, url) = mockServer()
147+
def ccm = new CoderCLIManager(new URL(url), tmpdir)
143148
Files.createDirectories(ccm.localBinaryPath.getParent())
144149
ccm.localBinaryPath.toFile().write("cli")
150+
ccm.localBinaryPath.toFile().setLastModified(0)
145151

146152
when:
147153
def downloaded = ccm.downloadCLI()
148154

149155
then:
150156
downloaded
151-
ccm.localBinaryPath.toFile().canExecute()
157+
ccm.localBinaryPath.toFile().readBytes() != "cli".getBytes()
158+
ccm.localBinaryPath.toFile().lastModified() > 0
159+
160+
cleanup:
161+
srv.stop(0)
152162
}
153163

154164
def "skips cli download if it already exists"() {
155165
given:
156-
def ccm = createCLIManager()
166+
def (srv, url) = mockServer()
167+
def ccm = new CoderCLIManager(new URL(url), tmpdir)
157168

158169
when:
159170
ccm.downloadCLI()
171+
ccm.localBinaryPath.toFile().setLastModified(0)
160172
def downloaded = ccm.downloadCLI()
161173

162174
then:
163175
!downloaded
164-
ccm.localBinaryPath.toFile().canExecute()
176+
ccm.localBinaryPath.toFile().lastModified() == 0
177+
ccm.version().contains("Coder")
178+
179+
cleanup:
180+
srv.stop(0)
165181
}
166182

167183
def "does not clobber other deployments"() {
168-
given:
169-
def ccm1 = createCLIManager(true)
170-
def ccm2 = createCLIManager()
184+
setup:
185+
def (srv1, url1) = mockServer()
186+
def (srv2, url2) = mockServer()
187+
def ccm1 = new CoderCLIManager(new URL(url1), tmpdir)
188+
def ccm2 = new CoderCLIManager(new URL(url2), tmpdir)
171189

172190
when:
173191
ccm1.downloadCLI()
174192
ccm2.downloadCLI()
175193

176194
then:
177195
ccm1.localBinaryPath != ccm2.localBinaryPath
196+
ccm1.localBinaryPath.toFile().exists()
197+
ccm2.localBinaryPath.toFile().exists()
198+
199+
cleanup:
200+
srv1.stop(0)
201+
srv2.stop(0)
178202
}
179203

180204
Map<String, String> testEnv = [

0 commit comments

Comments
 (0)