Jonathan Bernard e000b37c35 WIP Moving back towards using named runs.
* Rename artifactsRepo -> buildDataDir to be more explicit about the fact that
  it holds more than just the artifacts.
* Revert removal of run ids.
* Move Worker definition into core as part of making the core responsible for
  accepting run requests.
* Make the core module more responsible for internal details of data structure
  and storage. External callers should not need to construct paths to
  artifacts, versions, etc. but should be able to call method in the core
  module to do this work for them.
* The working directory no longer contains anything but the checked-out code.
  All StrawBoss-specific data is stored by StrawBoss elsewhere.
* Add a regular maintenance cycle to the server module.
2017-11-22 10:47:04 -06:00

140 lines
4.9 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: " & tempBuildDataDir
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 tempBuildDataDir = mkdtemp()
let (_, tempCfgPath) = mkstemp()
var preserveEnv = false
# copy our test config
var newCfg = cfg
newCfg.buildDataDir = tempBuildDataDir
# 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(tempBuildDataDir)
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 cachedConfsDir = tempBuildDataDir & "/" & testProjName & "/configurations"
let expectedVersions = @["alpha", "beta", "1.0.0", "1.0.1"]
# Touch configuration files
createDir(cachedConfsDir)
for v in expectedVersions:
var f: File
check open(f, cachedConfsDir & "/" & 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 run request has been
# check that the project directory has been created in the artifacts repo
let runArtifactsDir = tempBuildDataDir & "/" & testProjName & "/artifacts/build/0.1.0"
check existsDir(runArtifactsDir)
# check that the run status file has been created in the artifacts repo
let statusFile = tempBuildDataDir & "/" & testProjName & "/status/0.1.0.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)