@@ -14,25 +14,23 @@ import java.nio.file.Path
14
14
class CoderCLIManagerTest extends spock.lang. Specification {
15
15
@Shared
16
16
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"
23
18
24
19
/**
25
20
* Create, start, and return a server that mocks Coder.
26
21
*/
27
- HttpServer startMockServer (errorCode = 0 ) {
22
+ def mockServer (errorCode = 0 ) {
28
23
HttpServer srv = HttpServer . create(new InetSocketAddress (0 ), 0 )
29
24
srv. createContext(" /" , new HttpHandler () {
30
25
void handle (HttpExchange exchange ) {
31
26
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
33
31
34
32
String [] etags = exchange. requestHeaders. get(" If-None-Match" )
35
- if (etags != null && etags. contains(" \" cb25cf6f41bb3127d7e05b0c3c6403be9ab052bc \" " )) {
33
+ if (etags != null && etags. contains(" \" 2f1960264fc0f332a2a7fef2fe678f258dcdff9c \" " )) {
36
34
code = HttpURLConnection . HTTP_NOT_MODIFIED
37
35
response = " not modified"
38
36
}
@@ -53,37 +51,14 @@ class CoderCLIManagerTest extends spock.lang.Specification {
53
51
exchange. close()
54
52
}
55
53
})
56
- servers << srv
57
54
srv. start()
58
- return " http://localhost:" + srv. address. port
55
+ return [srv, " http://localhost:" + srv. address. port]
59
56
}
60
57
61
58
void setupSpec () {
62
59
// Clean up from previous runs otherwise they get cluttered since the
63
- // port is random.
60
+ // mock server port is random.
64
61
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)
87
62
}
88
63
89
64
def " defaults to a sub-directory in the data directory" () {
@@ -112,8 +87,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
112
87
113
88
def " fails to download" () {
114
89
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 )
117
91
def ccm = new CoderCLIManager (new URL (url), tmpdir)
118
92
119
93
when :
@@ -122,59 +96,109 @@ class CoderCLIManagerTest extends spock.lang.Specification {
122
96
then :
123
97
def e = thrown(ResponseException )
124
98
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" )
125
122
}
126
123
127
- def " downloads a working cli" () {
124
+ def " downloads a mocked cli" () {
128
125
given :
129
- def ccm = createCLIManager()
126
+ def (srv, url) = mockServer()
127
+ def ccm = new CoderCLIManager (new URL (url), tmpdir)
130
128
ccm. localBinaryPath. getParent(). toFile(). deleteDir()
131
129
132
130
when :
133
131
def downloaded = ccm. downloadCLI()
134
132
135
133
then :
136
134
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 )
138
142
}
139
143
140
144
def " overwrites cli if incorrect version" () {
141
145
given :
142
- def ccm = createCLIManager()
146
+ def (srv, url) = mockServer()
147
+ def ccm = new CoderCLIManager (new URL (url), tmpdir)
143
148
Files . createDirectories(ccm. localBinaryPath. getParent())
144
149
ccm. localBinaryPath. toFile(). write(" cli" )
150
+ ccm. localBinaryPath. toFile(). setLastModified(0 )
145
151
146
152
when :
147
153
def downloaded = ccm. downloadCLI()
148
154
149
155
then :
150
156
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 )
152
162
}
153
163
154
164
def " skips cli download if it already exists" () {
155
165
given :
156
- def ccm = createCLIManager()
166
+ def (srv, url) = mockServer()
167
+ def ccm = new CoderCLIManager (new URL (url), tmpdir)
157
168
158
169
when :
159
170
ccm. downloadCLI()
171
+ ccm. localBinaryPath. toFile(). setLastModified(0 )
160
172
def downloaded = ccm. downloadCLI()
161
173
162
174
then :
163
175
! downloaded
164
- ccm. localBinaryPath. toFile(). canExecute()
176
+ ccm. localBinaryPath. toFile(). lastModified() == 0
177
+ ccm. version(). contains(" Coder" )
178
+
179
+ cleanup :
180
+ srv. stop(0 )
165
181
}
166
182
167
183
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)
171
189
172
190
when :
173
191
ccm1. downloadCLI()
174
192
ccm2. downloadCLI()
175
193
176
194
then :
177
195
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 )
178
202
}
179
203
180
204
Map<String , String > testEnv = [
0 commit comments