@@ -14,25 +14,23 @@ import java.nio.file.Path
1414class 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\n echo 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,108 @@ 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+
178+ cleanup :
179+ srv. stop(0 )
165180 }
166181
167182 def " does not clobber other deployments" () {
168- given :
169- def ccm1 = createCLIManager(true )
170- def ccm2 = createCLIManager()
183+ setup :
184+ def (srv1, url1) = mockServer()
185+ def (srv2, url2) = mockServer()
186+ def ccm1 = new CoderCLIManager (new URL (url1), tmpdir)
187+ def ccm2 = new CoderCLIManager (new URL (url2), tmpdir)
171188
172189 when :
173190 ccm1. downloadCLI()
174191 ccm2. downloadCLI()
175192
176193 then :
177194 ccm1. localBinaryPath != ccm2. localBinaryPath
195+ ccm1. localBinaryPath. toFile(). exists()
196+ ccm2. localBinaryPath. toFile(). exists()
197+
198+ cleanup :
199+ srv1. stop(0 )
200+ srv2. stop(0 )
178201 }
179202
180203 Map<String , String > testEnv = [
0 commit comments