Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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.
  • Loading branch information
code-asher committed Apr 5, 2023
commit be064e6822760fbfad51ccc7257c50149f2db13e
11 changes: 2 additions & 9 deletions src/main/kotlin/com/coder/gateway/sdk/CoderCLIManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class CoderCLIManager @JvmOverloads constructor(deployment: URL, destinationDir:
conn.connect()
logger.info("GET ${conn.responseCode} $remoteBinaryUrl")
when (conn.responseCode) {
200 -> {
HttpURLConnection.HTTP_OK -> {
logger.info("Downloading binary to ${localBinaryPath.toAbsolutePath()}")
Files.createDirectories(localBinaryPath.parent)
conn.inputStream.use {
Expand All @@ -103,7 +103,7 @@ class CoderCLIManager @JvmOverloads constructor(deployment: URL, destinationDir:
return true
}

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

/**
* Return the binary version.
*/
fun version(): String {
return exec("version")
}

/**
* Execute the binary with the provided arguments.
*
Expand Down
95 changes: 72 additions & 23 deletions src/test/groovy/CoderCLIManagerTest.groovy
Original file line number Diff line number Diff line change
@@ -1,32 +1,81 @@
package com.coder.gateway.sdk

import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpHandler
import com.sun.net.httpserver.HttpServer
import spock.lang.Requires
import spock.lang.Shared
import spock.lang.Unroll

import java.nio.file.Files
import java.nio.file.Path

@Unroll
class CoderCLIManagerTest extends spock.lang.Specification {
/**
* Create a CLI manager pointing to the URL in the environment or to the
default URLs.
*
* @TODO: Implement a mock.
*/
def createCLIManager(Boolean alternate = false) {
var url = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT")
if (url == null) {
url = "https://dev.coder.com"
}
if (alternate) {
url = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT_ALT")
if (url == null) {
url = "https://oss.demo.coder.com"
@Shared
private Path tmpdir = Path.of(System.getProperty("java.io.tmpdir")).resolve("coder-gateway-test")
@Shared
private String deploymentURL = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT")
@Shared
private String altDeploymentURL = System.getenv("CODER_GATEWAY_TEST_DEPLOYMENT_ALT")
@Shared
private def servers = []

String startMockServer() {
HttpServer srv = HttpServer.create(new InetSocketAddress(0), 0)
srv.createContext("/", new HttpHandler() {
void handle(HttpExchange exchange) {
int code = HttpURLConnection.HTTP_OK
String response = "not a real binary"

String[] etags = exchange.requestHeaders.get("If-None-Match")
if (etags != null && etags.contains("\"cb25cf6f41bb3127d7e05b0c3c6403be9ab052bc\"")) {
code = HttpURLConnection.HTTP_NOT_MODIFIED
response = "not modified"
}

if (!exchange.requestURI.path.startsWith("/bin/coder-")) {
code = HttpURLConnection.HTTP_NOT_FOUND
response = "not found"
}

byte[] body = response.getBytes()
exchange.sendResponseHeaders(code, code == HttpURLConnection.HTTP_OK ? body.length : -1)
exchange.responseBody.write(body)
exchange.close()
}
})
servers << srv
srv.start()
return "http://localhost:" + srv.address.port
}

void setupSpec() {
// Clean up from previous runs otherwise they get cluttered since the
// port is random.
tmpdir.toFile().deleteDir()

// Spin up mock server(s).
if (deploymentURL == null) {
deploymentURL = startMockServer()
}
if (altDeploymentURL == null) {
altDeploymentURL = startMockServer()
}
var tmpdir = Path.of(System.getProperty("java.io.tmpdir")).resolve("coder-gateway-test")
return new CoderCLIManager(new URL(url), tmpdir)
}

void cleanupSpec() {
servers.each {
it.stop(0)
}
}

/**
* Create a CLI manager pointing to the URLs in the environment or to mocked
* servers.
*/
CoderCLIManager createCLIManager(Boolean alternate = false) {
return new CoderCLIManager(new URL(alternate ? altDeploymentURL : deploymentURL), tmpdir)
}

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

then:
downloaded
ccm.version().contains("Coder")
ccm.localBinaryPath.toFile().canExecute()
}

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

then:
downloaded
ccm.version().contains("Coder")
ccm.localBinaryPath.toFile().canExecute()
}

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

then:
!downloaded
ccm.version().contains("Coder")
ccm.localBinaryPath.toFile().canExecute()
}

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

def testEnv = [
Map<String, String> testEnv = [
"APPDATA" : "/tmp/coder-gateway-test/appdata",
"LOCALAPPDATA" : "/tmp/coder-gateway-test/localappdata",
"HOME" : "/tmp/coder-gateway-test/home",
Expand All @@ -110,7 +159,7 @@ class CoderCLIManagerTest extends spock.lang.Specification {
/**
* Get a config dir using default environment variable values.
*/
def configDir(Map<String, String> env = [:]) {
Path configDir(Map<String, String> env = [:]) {
return CoderCLIManager.getConfigDir(new Environment(testEnv + env))
}

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