2020-09-17 12:07:43 +00:00
|
|
|
package server_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
2020-09-17 12:18:31 +00:00
|
|
|
"time"
|
2020-09-17 12:07:43 +00:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
|
|
|
"nano-run/server"
|
2020-09-28 13:46:37 +00:00
|
|
|
"nano-run/server/runner"
|
2020-09-17 12:07:43 +00:00
|
|
|
"nano-run/services/meta"
|
|
|
|
)
|
|
|
|
|
|
|
|
var tmpDir string
|
|
|
|
|
|
|
|
func TestMain(main *testing.M) {
|
|
|
|
var err error
|
|
|
|
tmpDir, err = ioutil.TempDir("", "")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
code := main.Run()
|
|
|
|
_ = os.RemoveAll(tmpDir)
|
|
|
|
os.Exit(code)
|
|
|
|
}
|
|
|
|
|
2020-09-28 13:46:37 +00:00
|
|
|
func testServer(t *testing.T, cfg runner.Config, units map[string]server.Unit) *runner.Server {
|
2020-09-17 12:07:43 +00:00
|
|
|
sub, err := ioutil.TempDir(tmpDir, "")
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.Fatal("failed to create temp dir", err)
|
|
|
|
}
|
|
|
|
cfg.ConfigDirectory = filepath.Join(sub, "config")
|
|
|
|
cfg.WorkingDirectory = filepath.Join(sub, "data")
|
|
|
|
err = cfg.CreateDirs()
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.Fatal("failed to create dirs", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, unit := range units {
|
|
|
|
err = unit.SaveFile(filepath.Join(cfg.ConfigDirectory, name+".yaml"))
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.Fatal("failed to create unit", name, ":", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
srv, err := cfg.Create(context.Background())
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
srv.Close()
|
|
|
|
t.Fatal("failed to create server")
|
|
|
|
}
|
|
|
|
return srv
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_create(t *testing.T) {
|
2020-09-28 13:46:37 +00:00
|
|
|
srv := testServer(t, runner.DefaultConfig(), map[string]server.Unit{
|
2020-09-17 12:07:43 +00:00
|
|
|
"hello": {
|
2020-09-19 12:32:42 +00:00
|
|
|
Command: "echo -n hello world",
|
2020-09-17 12:07:43 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
defer srv.Close()
|
|
|
|
|
2020-09-28 13:46:37 +00:00
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/hello/", bytes.NewBufferString("hello world"))
|
2020-09-17 12:07:43 +00:00
|
|
|
res := httptest.NewRecorder()
|
|
|
|
srv.ServeHTTP(res, req)
|
|
|
|
assert.Equal(t, http.StatusSeeOther, res.Code)
|
|
|
|
assert.NotEmpty(t, res.Header().Get("X-Correlation-Id"))
|
2020-09-28 13:46:37 +00:00
|
|
|
assert.Equal(t, "/api/hello/"+res.Header().Get("X-Correlation-Id"), res.Header().Get("Location"))
|
2020-09-17 12:07:43 +00:00
|
|
|
requestID := res.Header().Get("X-Correlation-Id")
|
|
|
|
|
|
|
|
infoURL := res.Header().Get("Location")
|
2020-09-28 13:46:37 +00:00
|
|
|
t.Log("Location:", infoURL)
|
2020-09-17 12:07:43 +00:00
|
|
|
req = httptest.NewRequest(http.MethodGet, infoURL, nil)
|
|
|
|
res = httptest.NewRecorder()
|
|
|
|
srv.ServeHTTP(res, req)
|
|
|
|
assert.Equal(t, http.StatusOK, res.Code)
|
|
|
|
assert.Equal(t, requestID, res.Header().Get("X-Correlation-Id"))
|
2020-09-28 13:46:37 +00:00
|
|
|
assert.Contains(t, res.Header().Get("Content-Type"), "application/json")
|
2020-09-17 12:07:43 +00:00
|
|
|
var info meta.Request
|
|
|
|
err := json.Unmarshal(res.Body.Bytes(), &info)
|
|
|
|
assert.NoError(t, err)
|
2020-09-17 12:18:31 +00:00
|
|
|
|
|
|
|
// wait for result
|
|
|
|
var resultLocation string
|
|
|
|
for {
|
|
|
|
req = httptest.NewRequest(http.MethodGet, infoURL+"/completed", nil)
|
|
|
|
res = httptest.NewRecorder()
|
|
|
|
srv.ServeHTTP(res, req)
|
|
|
|
if res.Code == http.StatusMovedPermanently {
|
|
|
|
resultLocation = res.Header().Get("Location")
|
|
|
|
break
|
|
|
|
}
|
2020-09-28 13:46:37 +00:00
|
|
|
if !assert.Equal(t, http.StatusTooEarly, res.Code) {
|
2020-09-17 12:18:31 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
}
|
|
|
|
|
|
|
|
req = httptest.NewRequest(http.MethodGet, resultLocation, nil)
|
|
|
|
res = httptest.NewRecorder()
|
|
|
|
srv.ServeHTTP(res, req)
|
|
|
|
assert.Equal(t, http.StatusOK, res.Code)
|
|
|
|
assert.Equal(t, "hello world", res.Body.String())
|
2020-09-17 12:07:43 +00:00
|
|
|
}
|
2020-09-19 12:32:42 +00:00
|
|
|
|
|
|
|
func Test_retryIfDataReturnedInBinMode(t *testing.T) {
|
2020-09-28 13:46:37 +00:00
|
|
|
srv := testServer(t, runner.DefaultConfig(), map[string]server.Unit{
|
2020-09-19 12:32:42 +00:00
|
|
|
"hello": {
|
|
|
|
Command: "echo hello world; exit 1",
|
|
|
|
},
|
|
|
|
})
|
|
|
|
defer srv.Close()
|
|
|
|
|
2020-09-28 13:46:37 +00:00
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/hello/", bytes.NewBufferString("hello world"))
|
2020-09-19 12:32:42 +00:00
|
|
|
res := httptest.NewRecorder()
|
|
|
|
srv.ServeHTTP(res, req)
|
|
|
|
assert.Equal(t, http.StatusSeeOther, res.Code)
|
|
|
|
assert.NotEmpty(t, res.Header().Get("X-Correlation-Id"))
|
2020-09-28 13:46:37 +00:00
|
|
|
assert.Equal(t, "/api/hello/"+res.Header().Get("X-Correlation-Id"), res.Header().Get("Location"))
|
2020-09-19 12:32:42 +00:00
|
|
|
location := res.Header().Get("Location")
|
|
|
|
|
|
|
|
// wait for first result
|
|
|
|
for {
|
|
|
|
req = httptest.NewRequest(http.MethodGet, location, nil)
|
|
|
|
res = httptest.NewRecorder()
|
|
|
|
srv.ServeHTTP(res, req)
|
|
|
|
if !assert.Equal(t, http.StatusOK, res.Code) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var info meta.Request
|
|
|
|
err := json.Unmarshal(res.Body.Bytes(), &info)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
if len(info.Attempts) == 0 {
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
atp := info.Attempts[0]
|
|
|
|
assert.Equal(t, http.StatusBadGateway, atp.Code)
|
|
|
|
assert.Equal(t, "1", atp.Headers.Get("X-Return-Code"))
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2020-11-07 13:38:13 +00:00
|
|
|
|
|
|
|
func TestCron(t *testing.T) {
|
|
|
|
srv := testServer(t, runner.DefaultConfig(), map[string]server.Unit{
|
|
|
|
"hello": {
|
|
|
|
Command: "echo hello world",
|
|
|
|
Cron: []server.CronSpec{
|
|
|
|
{Spec: "@every 1s"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
defer srv.Close()
|
|
|
|
time.Sleep(time.Second + 100*time.Millisecond)
|
|
|
|
|
|
|
|
var first *meta.Request
|
|
|
|
err := srv.Workers()[0].Meta().Iterate(func(id string, record meta.Request) error {
|
|
|
|
first = &record
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.True(t, first.Complete)
|
|
|
|
assert.Len(t, first.Attempts, 1)
|
|
|
|
}
|