139 lines
4.8 KiB
Nim
139 lines
4.8 KiB
Nim
import cliutils, httpclient, json, os, osproc, sequtils, strutils, tempfile,
|
|
times, unittest, untar
|
|
|
|
from langutils import sameContents
|
|
|
|
import ../testutil
|
|
import ../../../main/nim/strawbosspkg/configuration
|
|
|
|
let apiBase = "http://localhost:8180/api"
|
|
let cfgFilePath = "src/test/json/strawboss.config.json"
|
|
let cfg = loadStrawBossConfig(cfgFilePath)
|
|
let TIMEOUT = 2.minutes
|
|
|
|
# Util template intended for use to manually review test case.
|
|
# Inserting into a test case will prevent the test case from cleaning up it's
|
|
# working files and echo the command to start StrawBoss using that test's
|
|
# configuration and working files.
|
|
template keepEnv(): untyped =
|
|
preserveEnv = true
|
|
echo "artifacts dir: " & tempArtifactsDir
|
|
echo "strawboss serve -c " & tempCfgPath
|
|
|
|
suite "strawboss server":
|
|
|
|
# Suite setup: extract test project
|
|
let testProjTempDir = mkdtemp()
|
|
let testProjTarFile = newTarFile("src/test/test-project.tar.gz")
|
|
let testProjName = "test-project"
|
|
testProjTarFile.extract(testProjTempDir)
|
|
|
|
# per-test setup: spin up a fresh strawboss instance
|
|
setup:
|
|
let tempArtifactsDir = mkdtemp()
|
|
let (_, tempCfgPath) = mkstemp()
|
|
var preserveEnv = false
|
|
|
|
# copy our test config
|
|
var newCfg = cfg
|
|
newCfg.artifactsRepo = tempArtifactsDir
|
|
|
|
# update the repo string for the extracted test project
|
|
var testProjDef = newCfg.findProject(testProjName)
|
|
testProjDef.repo = testProjTempDir
|
|
newCfg.setProject(testProjName, testProjDef)
|
|
|
|
# save the updated config and start the strawboss instance using it
|
|
writeFile(tempCfgPath, $newCfg)
|
|
let serverProcess = startProcess("./strawboss", ".",
|
|
@["serve", "-c", tempCfgPath], loadEnv(), {poUsePath})
|
|
|
|
# give the server time to spin up
|
|
sleep(100)
|
|
|
|
teardown:
|
|
discard newAsyncHttpClient().post(apiBase & "/service/debug/stop")
|
|
|
|
if not preserveEnv:
|
|
removeDir(tempArtifactsDir)
|
|
removeFile(tempCfgPath)
|
|
|
|
# give the server time to spin down but kill it after that
|
|
sleep(100)
|
|
if serverProcess.running: kill(serverProcess)
|
|
|
|
test "handle missing project configuration":
|
|
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
|
let resp = http.get(apiBase & "/projects/" & cfg.projects[0].name)
|
|
check resp.status.startsWith("404")
|
|
|
|
test "gives 404 when no versions built":
|
|
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
|
let resp = http.get(apiBase & "/projects/" & testProjName & "/versions")
|
|
check resp.status.startsWith("404")
|
|
|
|
test "GET /api/project/@projectName/versions":
|
|
let projArtifactsDir = tempArtifactsDir & "/" & testProjName
|
|
let expectedVersions = @["alpha", "beta", "1.0.0", "1.0.1"]
|
|
|
|
# Touch configuration files
|
|
createDir(projArtifactsDir)
|
|
for v in expectedVersions:
|
|
var f: File
|
|
check open(f, projArtifactsDir & "/configuration." & v & ".json", fmWrite)
|
|
close(f)
|
|
|
|
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
|
let resp = http.get(apiBase & "/project/" & testProjName & "/versions")
|
|
let returnedVersions = parseJson(resp.body).getElems.mapIt(it.getStr)
|
|
check sameContents(expectedVersions, returnedVersions)
|
|
|
|
test "run a successful build with artifacts":
|
|
let http = newAuthenticatedHttpClient(apibase, "bob@builder.com", "password")
|
|
let resp = http.post(apiBase & "/project/" & testProjName & "/step/build/run/0.1.0")
|
|
check resp.status.startsWith("200")
|
|
|
|
# give the filesystem time to create stuff
|
|
sleep(100)
|
|
|
|
# check that the project directory has been created in the artifacts repo
|
|
let runArtifactsDir = tempArtifactsDir & "/" & testProjName & "/build/0.1.0"
|
|
check existsDir(runArtifactsDir)
|
|
|
|
# check that the run status file has been created in the artifacts repo
|
|
let statusFile = runArtifactsDir & "/status.json"
|
|
check fileExists(statusFile)
|
|
|
|
# check that the run status is not failed
|
|
var status = loadBuildStatus(statusFile)
|
|
check status.state != "failed"
|
|
|
|
# wait for the build to complete
|
|
let expTime = getTime() + TIMEOUT
|
|
while getTime() < expTime and not contains(["complete", "failed"], status.state):
|
|
sleep(1000)
|
|
status = loadBuildStatus(statusFile)
|
|
|
|
# check that the status is "complete"
|
|
check status.state == "complete"
|
|
|
|
# check that the artifacts we expect are present
|
|
let binFile = runArtifactsDir & "/test_project"
|
|
check existsFile(binFile)
|
|
|
|
# TODO
|
|
test "run a time-consuming build and check the status via the API":
|
|
check false
|
|
|
|
# TODO
|
|
#test "kick off multiple runs and check the list of active runs via the API":
|
|
# check false
|
|
|
|
# Last-chance catch to kill the server in case some test err'ed and didn't
|
|
# reach it's teardown handler
|
|
discard newAsyncHttpClient().post(apiBase & "/service/debug/stop")
|
|
|
|
# Also, delete the extracted test project "source" repo
|
|
removeDir(testProjTempDir)
|
|
|