Skip to content

Commit edf950b

Browse files
committed
Test against a mocked server
Environment variables can be used to test against a real deployment. I now just check if the file is executable rather than trying to actually execute it since we would need to actually compile something that can run as a .exe on Windows.
1 parent 5bb8182 commit edf950b

File tree

2 files changed

+74
-32
lines changed

2 files changed

+74
-32
lines changed

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class CoderCLIManager @JvmOverloads constructor(deployment: URL, destinationDir:
8383
conn.connect()
8484
logger.info("GET ${conn.responseCode} $remoteBinaryUrl")
8585
when (conn.responseCode) {
86-
200 -> {
86+
HttpURLConnection.HTTP_OK -> {
8787
logger.info("Downloading binary to ${localBinaryPath.toAbsolutePath()}")
8888
Files.createDirectories(localBinaryPath.parent)
8989
conn.inputStream.use {
@@ -103,7 +103,7 @@ class CoderCLIManager @JvmOverloads constructor(deployment: URL, destinationDir:
103103
return true
104104
}
105105

106-
304 -> {
106+
HttpURLConnection.HTTP_NOT_MODIFIED -> {
107107
logger.info("Using cached binary at ${localBinaryPath.toAbsolutePath()}")
108108
conn.disconnect()
109109
return false
@@ -151,13 +151,6 @@ class CoderCLIManager @JvmOverloads constructor(deployment: URL, destinationDir:
151151
return exec("config-ssh", "--yes", "--use-previous-options")
152152
}
153153

154-
/**
155-
* Return the binary version.
156-
*/
157-
fun version(): String {
158-
return exec("version")
159-
}
160-
161154
/**
162155
* Execute the binary with the provided arguments.
163156
*

src/test/groovy/CoderCLIManagerTest.groovy

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,81 @@
11
package com.coder.gateway.sdk
22

3+
import com.sun.net.httpserver.HttpExchange
4+
import com.sun.net.httpserver.HttpHandler
5+
import com.sun.net.httpserver.HttpServer
36
import spock.lang.Requires
7+
import spock.lang.Shared
48
import spock.lang.Unroll
59

610
import java.nio.file.Files
711
import java.nio.file.Path
812

913
@Unroll
1014
class CoderCLIManagerTest extends spock.lang.Specification {
11-
/**
12-
* Create a CLI manager pointing to the URL in the environment or to the
13-
default URLs.
14-
*
15-
* @TODO: Implement a mock.
16-
*/
17-
def createCLIManager(Boolean alternate = false) {
18-
var url = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT")
19-
if (url == null) {
20-
url = "https://dev.coder.com"
21-
}
22-
if (alternate) {
23-
url = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT_ALT")
24-
if (url == null) {
25-
url = "https://oss.demo.coder.com"
15+
@Shared
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 = []
23+
24+
String startMockServer() {
25+
HttpServer srv = HttpServer.create(new InetSocketAddress(0), 0)
26+
srv.createContext("/", new HttpHandler() {
27+
void handle(HttpExchange exchange) {
28+
int code = HttpURLConnection.HTTP_OK
29+
byte[] response = "!#/bin/sh\r\necho Coder".getBytes()
30+
int length = response.length
31+
32+
String[] etags = exchange.requestHeaders.get("If-None-Match")
33+
if (etags != null) {
34+
etags.each {
35+
if (it == "\"cb49efaa845b9018e49bd3b16efbec29b4f27f58\"") {
36+
code = HttpURLConnection.HTTP_NOT_MODIFIED
37+
response = "not modified".getBytes()
38+
length = -1
39+
}
40+
}
41+
}
42+
43+
exchange.sendResponseHeaders(code, length)
44+
exchange.responseBody.write(response)
45+
exchange.close()
2646
}
47+
})
48+
servers << srv
49+
srv.start()
50+
return "http://localhost:" + srv.address.port
51+
}
52+
53+
void setupSpec() {
54+
// Clean up from previous runs otherwise they get cluttered since the
55+
// port is random.
56+
tmpdir.toFile().deleteDir()
57+
58+
// Spin up mock server(s).
59+
if (deploymentURL == null) {
60+
deploymentURL = startMockServer()
61+
}
62+
if (altDeploymentURL == null) {
63+
altDeploymentURL = startMockServer()
2764
}
28-
var tmpdir = Path.of(System.getProperty("java.io.tmpdir")).resolve("coder-gateway-test")
29-
return new CoderCLIManager(new URL(url), tmpdir)
65+
}
66+
67+
void cleanupSpec() {
68+
servers.each {
69+
it.stop(0)
70+
}
71+
}
72+
73+
/**
74+
* Create a CLI manager pointing to the URLs in the environment or to mocked
75+
* servers.
76+
*/
77+
CoderCLIManager createCLIManager(Boolean alternate = false) {
78+
return new CoderCLIManager(new URL(alternate ? altDeploymentURL : deploymentURL), tmpdir)
3079
}
3180

3281
def "defaults to a sub-directory in the data directory"() {
@@ -55,7 +104,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
55104

56105
then:
57106
downloaded
58-
ccm.version().contains("Coder")
107+
ccm.localBinaryPath.toFile().canExecute()
59108
}
60109

61110
def "overwrites cli if incorrect version"() {
@@ -69,7 +118,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
69118

70119
then:
71120
downloaded
72-
ccm.version().contains("Coder")
121+
ccm.localBinaryPath.toFile().canExecute()
73122
}
74123

75124
def "skips cli download if it already exists"() {
@@ -82,7 +131,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
82131

83132
then:
84133
!downloaded
85-
ccm.version().contains("Coder")
134+
ccm.localBinaryPath.toFile().canExecute()
86135
}
87136

88137
def "does not clobber other deployments"() {
@@ -98,7 +147,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
98147
ccm1.localBinaryPath != ccm2.localBinaryPath
99148
}
100149

101-
def testEnv = [
150+
Map<String, String> testEnv = [
102151
"APPDATA" : "/tmp/coder-gateway-test/appdata",
103152
"LOCALAPPDATA" : "/tmp/coder-gateway-test/localappdata",
104153
"HOME" : "/tmp/coder-gateway-test/home",
@@ -110,7 +159,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
110159
/**
111160
* Get a config dir using default environment variable values.
112161
*/
113-
def configDir(Map<String, String> env = [:]) {
162+
Path configDir(Map<String, String> env = [:]) {
114163
return CoderCLIManager.getConfigDir(new Environment(testEnv + env))
115164
}
116165

@@ -159,7 +208,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
159208
/**
160209
* Get a data dir using default environment variable values.
161210
*/
162-
def dataDir(Map<String, String> env = [:]) {
211+
Path dataDir(Map<String, String> env = [:]) {
163212
return CoderCLIManager.getDataDir(new Environment(testEnv + env))
164213
}
165214
// Mostly just a sanity check to make sure the default System.getenv runs

0 commit comments

Comments
 (0)