gitdeploy/internal/api/api_test.go

140 lines
3.3 KiB
Go

package api
import (
"encoding/json"
"fmt"
"io/ioutil"
"math"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"time"
"git.rootprojects.org/root/gitdeploy/internal/jobs"
"git.rootprojects.org/root/gitdeploy/internal/options"
"git.rootprojects.org/root/gitdeploy/internal/webhooks"
"github.com/go-chi/chi"
)
var server *httptest.Server
var runOpts *options.ServerConfig
var debounceDelay time.Duration
var jobDelay time.Duration
var logDir string
func init() {
tmpDir, _ := ioutil.TempDir("", "gitdeploy-*")
runOpts = &options.ServerConfig{
//Addr: "localhost:4483",
ScriptsPath: "./testdata",
LogDir: "./test-logs/api",
TmpDir: tmpDir,
DebounceDelay: 25 * time.Millisecond,
DefaultMaxJobTime: 5 * time.Second, // very short
StaleJobAge: 5 * time.Minute,
StaleLogAge: 5 * time.Minute,
ExpiredLogAge: 10 * time.Minute,
}
logDir, _ = filepath.Abs(runOpts.LogDir)
r := chi.NewRouter()
server = httptest.NewServer(r)
runOpts.Addr = server.Listener.Addr().String()
RouteStopped(r, runOpts)
os.Setenv("GIT_DEPLOY_TEST_WAIT", "0.1")
debounceDelay = 50 * time.Millisecond
jobDelay = 250 * time.Millisecond
jobs.Start(runOpts)
//server.Close()
}
func ToUnixSeconds(t time.Time) float64 {
// 1614236182.651912345
secs := float64(t.Unix()) // 1614236182
nanos := float64(t.Nanosecond()) / 1_000_000_000.0 // 0.651912345
//nanos := (float64(t.UnixNano()) - secs) / 1_000_000_000.0 // 0.651912345
// in my case I want to truncate the precision to milliseconds
nanos = math.Round((10000 * nanos) / 10000) // 0.6519
s := secs + nanos // 1614236182.651912345
return s
}
func TestCallback(t *testing.T) {
// TODO use full API request with local webhook
t7 := time.Now().Add(-40 * time.Second)
r7 := "ef1234abcd"
// skip debounce
hook := webhooks.Ref{
Timestamp: t7,
RepoID: "git.example.com/owner/repo",
HTTPSURL: "https://git.example.com/owner/repo.git",
Rev: r7,
RefName: "master",
RefType: "branch",
Owner: "owner",
Repo: "repo",
}
// , _ := json.MarshallIndent(&hook , "", " ")
jobs.Debounce(hook)
/*
body := bytes.NewReader(hook)
r := httptest.NewRequest("POST", "/api/local/webhook", body)
*/
// TODO use callback or chan chan to avoid sleeps?
time.Sleep(debounceDelay)
t.Log("sleep so job can finish")
time.Sleep(jobDelay)
time.Sleep(jobDelay)
// TODO test that the API gives this back to us
urlRevID := hook.GetURLSafeRevID()
s := ToUnixSeconds(t7.Add(-1 * time.Second))
// TODO needs auth
reqURL := fmt.Sprintf(
"http://%s/api/admin/logs/%s?since=%f",
runOpts.Addr, string(urlRevID), s,
)
resp, err := http.Get(reqURL)
if nil != err {
t.Errorf("HTTP response error: %s\n%#v", reqURL, err)
return
}
job := &jobs.Job{}
b, _ := ioutil.ReadAll(resp.Body)
if err := json.Unmarshal(b, job); nil != err {
t.Errorf(
"response decode error: %d %s\n%#v\n%#v",
resp.StatusCode, reqURL, resp.Header, err,
)
return
}
if len(job.Logs) < 3 {
t.Errorf("too few logs: %s\n%s\n%#v", reqURL, string(b), job)
return
}
if nil == job.Report || len(job.Report.Results) < 1 {
t.Errorf("too few results: %s\n%#v", reqURL, job)
return
}
if nil == job.ExitCode || 0 != *job.ExitCode {
t.Errorf("non-zero exit code: %s\n%#v", reqURL, job)
return
}
}