mirror of
https://github.com/simon987/task_tracker.git
synced 2025-12-12 06:28:50 +00:00
Web dashboard, task release, logs api
This commit is contained in:
28
test/api_index_test.go
Normal file
28
test/api_index_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"src/task_tracker/api"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIndex(t *testing.T) {
|
||||
|
||||
r := Get("/")
|
||||
|
||||
body, _ := ioutil.ReadAll(r.Body)
|
||||
var info api.Info
|
||||
err := json.Unmarshal(body, &info)
|
||||
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
if len(info.Name) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
if len(info.Version) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,20 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"io/ioutil"
|
||||
"src/task_tracker/api"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
func TestTraceValid(t *testing.T) {
|
||||
|
||||
r := Post("/log/trace", api.LogEntry{
|
||||
Scope:"test",
|
||||
Message:"This is a test message",
|
||||
r := Post("/log/trace", api.LogRequest{
|
||||
Scope: "test",
|
||||
Message: "This is a test message",
|
||||
TimeStamp: time.Now().Unix(),
|
||||
})
|
||||
|
||||
@@ -21,8 +24,8 @@ func TestTraceValid(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTraceInvalidScope(t *testing.T) {
|
||||
r := Post("/log/trace", api.LogEntry{
|
||||
Message:"this is a test message",
|
||||
r := Post("/log/trace", api.LogRequest{
|
||||
Message: "this is a test message",
|
||||
TimeStamp: time.Now().Unix(),
|
||||
})
|
||||
|
||||
@@ -30,9 +33,9 @@ func TestTraceInvalidScope(t *testing.T) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
r = Post("/log/trace", api.LogEntry{
|
||||
Scope:"",
|
||||
Message:"this is a test message",
|
||||
r = Post("/log/trace", api.LogRequest{
|
||||
Scope: "",
|
||||
Message: "this is a test message",
|
||||
TimeStamp: time.Now().Unix(),
|
||||
})
|
||||
|
||||
@@ -45,9 +48,9 @@ func TestTraceInvalidScope(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTraceInvalidMessage(t *testing.T) {
|
||||
r := Post("/log/trace", api.LogEntry{
|
||||
Scope:"test",
|
||||
Message:"",
|
||||
r := Post("/log/trace", api.LogRequest{
|
||||
Scope: "test",
|
||||
Message: "",
|
||||
TimeStamp: time.Now().Unix(),
|
||||
})
|
||||
|
||||
@@ -60,10 +63,9 @@ func TestTraceInvalidMessage(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTraceInvalidTime(t *testing.T) {
|
||||
r := Post("/log/trace", api.LogEntry{
|
||||
Scope: "test",
|
||||
Message:"test",
|
||||
|
||||
r := Post("/log/trace", api.LogRequest{
|
||||
Scope: "test",
|
||||
Message: "test",
|
||||
})
|
||||
if r.StatusCode != 500 {
|
||||
t.Fail()
|
||||
@@ -75,10 +77,10 @@ func TestTraceInvalidTime(t *testing.T) {
|
||||
|
||||
func TestWarnValid(t *testing.T) {
|
||||
|
||||
r := Post("/log/warn", api.LogEntry{
|
||||
Scope: "test",
|
||||
Message:"test",
|
||||
TimeStamp:time.Now().Unix(),
|
||||
r := Post("/log/warn", api.LogRequest{
|
||||
Scope: "test",
|
||||
Message: "test",
|
||||
TimeStamp: time.Now().Unix(),
|
||||
})
|
||||
if r.StatusCode != 200 {
|
||||
t.Fail()
|
||||
@@ -87,10 +89,10 @@ func TestWarnValid(t *testing.T) {
|
||||
|
||||
func TestInfoValid(t *testing.T) {
|
||||
|
||||
r := Post("/log/info", api.LogEntry{
|
||||
Scope: "test",
|
||||
Message:"test",
|
||||
TimeStamp:time.Now().Unix(),
|
||||
r := Post("/log/info", api.LogRequest{
|
||||
Scope: "test",
|
||||
Message: "test",
|
||||
TimeStamp: time.Now().Unix(),
|
||||
})
|
||||
if r.StatusCode != 200 {
|
||||
t.Fail()
|
||||
@@ -99,12 +101,82 @@ func TestInfoValid(t *testing.T) {
|
||||
|
||||
func TestErrorValid(t *testing.T) {
|
||||
|
||||
r := Post("/log/error", api.LogEntry{
|
||||
Scope: "test",
|
||||
Message:"test",
|
||||
TimeStamp:time.Now().Unix(),
|
||||
r := Post("/log/error", api.LogRequest{
|
||||
Scope: "test",
|
||||
Message: "test",
|
||||
TimeStamp: time.Now().Unix(),
|
||||
})
|
||||
if r.StatusCode != 200 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLogs(t *testing.T) {
|
||||
|
||||
now := time.Now()
|
||||
|
||||
logrus.WithTime(now.Add(time.Second * -100)).WithFields(logrus.Fields{
|
||||
"test": "value",
|
||||
}).Debug("This is a test log")
|
||||
|
||||
logrus.WithTime(now.Add(time.Second * -200)).WithFields(logrus.Fields{
|
||||
"test": "value",
|
||||
}).Debug("This one shouldn't be returned")
|
||||
|
||||
logrus.WithTime(now.Add(time.Second * -100)).WithFields(logrus.Fields{
|
||||
"test": "value",
|
||||
}).Error("error")
|
||||
|
||||
r := getLogs(time.Now().Add(time.Second*-150).Unix(), logrus.DebugLevel)
|
||||
|
||||
if r.Ok != true {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(*r.Logs) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
debugFound := false
|
||||
for _, log := range *r.Logs {
|
||||
if log.Message == "This one shouldn't be returned" {
|
||||
t.Error()
|
||||
} else if log.Message == "error" {
|
||||
t.Error()
|
||||
} else if log.Message == "This is a test log" {
|
||||
debugFound = true
|
||||
}
|
||||
}
|
||||
|
||||
if !debugFound {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLogsInvalid(t *testing.T) {
|
||||
|
||||
r := getLogs(-1, logrus.ErrorLevel)
|
||||
|
||||
if r.Ok != false {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(r.Message) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func getLogs(since int64, level logrus.Level) *api.GetLogResponse {
|
||||
|
||||
r := Post(fmt.Sprintf("/logs"), api.GetLogRequest{
|
||||
Since: since,
|
||||
Level: level,
|
||||
})
|
||||
|
||||
resp := &api.GetLogResponse{}
|
||||
data, _ := ioutil.ReadAll(r.Body)
|
||||
err := json.Unmarshal(data, resp)
|
||||
handleErr(err)
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package test
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/google/uuid"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"src/task_tracker/api"
|
||||
@@ -17,6 +18,7 @@ func TestCreateGetProject(t *testing.T) {
|
||||
GitRepo: "drone/webhooktest",
|
||||
Version: "Test Version",
|
||||
Priority: 123,
|
||||
Motd: "motd",
|
||||
})
|
||||
|
||||
id := resp.Id
|
||||
@@ -51,6 +53,9 @@ func TestCreateGetProject(t *testing.T) {
|
||||
if getResp.Project.Priority != 123 {
|
||||
t.Error()
|
||||
}
|
||||
if getResp.Project.Motd != "motd" {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateProjectInvalid(t *testing.T) {
|
||||
@@ -114,6 +119,82 @@ func TestGetProjectNotFound(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetProjectStats(t *testing.T) {
|
||||
|
||||
r := createProject(api.CreateProjectRequest{
|
||||
Motd: "motd",
|
||||
Name: "Name",
|
||||
Version: "version",
|
||||
CloneUrl: "http://github.com/drone/test",
|
||||
GitRepo: "drone/test",
|
||||
Priority: 3,
|
||||
})
|
||||
|
||||
pid := r.Id
|
||||
|
||||
createTask(api.CreateTaskRequest{
|
||||
Priority: 1,
|
||||
Project: pid,
|
||||
MaxRetries: 0,
|
||||
Recipe: "{}",
|
||||
})
|
||||
createTask(api.CreateTaskRequest{
|
||||
Priority: 2,
|
||||
Project: pid,
|
||||
MaxRetries: 0,
|
||||
Recipe: "{}",
|
||||
})
|
||||
createTask(api.CreateTaskRequest{
|
||||
Priority: 3,
|
||||
Project: pid,
|
||||
MaxRetries: 0,
|
||||
Recipe: "{}",
|
||||
})
|
||||
|
||||
stats := getProjectStats(pid)
|
||||
|
||||
if stats.Ok != true {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if stats.Stats.Project.Id != pid {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if stats.Stats.NewTaskCount != 3 {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if stats.Stats.Assignees[0].Assignee != uuid.Nil {
|
||||
t.Error()
|
||||
}
|
||||
if stats.Stats.Assignees[0].TaskCount != 3 {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetProjectStatsNotFound(t *testing.T) {
|
||||
|
||||
r := createProject(api.CreateProjectRequest{
|
||||
Motd: "eeeeeeeeej",
|
||||
Name: "Namaaaaaaaaaaaa",
|
||||
Version: "versionsssssssss",
|
||||
CloneUrl: "http://github.com/drone/test1",
|
||||
GitRepo: "drone/test1",
|
||||
Priority: 1,
|
||||
})
|
||||
s := getProjectStats(r.Id)
|
||||
|
||||
if s.Ok != false {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(s.Message) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func createProject(req api.CreateProjectRequest) *api.CreateProjectResponse {
|
||||
|
||||
r := Post("/project/create", req)
|
||||
@@ -137,3 +218,15 @@ func getProject(id int64) (*api.GetProjectResponse, *http.Response) {
|
||||
|
||||
return &getResp, r
|
||||
}
|
||||
|
||||
func getProjectStats(id int64) *api.GetProjectStatsResponse {
|
||||
|
||||
r := Get(fmt.Sprintf("/project/stats/%d", id))
|
||||
|
||||
var getResp api.GetProjectStatsResponse
|
||||
data, _ := ioutil.ReadAll(r.Body)
|
||||
err := json.Unmarshal(data, &getResp)
|
||||
handleErr(err)
|
||||
|
||||
return &getResp
|
||||
}
|
||||
|
||||
28
test/api_task_bench_test.go
Normal file
28
test/api_task_bench_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"src/task_tracker/api"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkCreateTask(b *testing.B) {
|
||||
|
||||
resp := createProject(api.CreateProjectRequest{
|
||||
Name: "BenchmarkCreateTask" + strconv.Itoa(b.N),
|
||||
Priority: 1,
|
||||
GitRepo: "benchmark_test" + strconv.Itoa(b.N),
|
||||
Version: "f09e8c9r0w839x0c43",
|
||||
CloneUrl: "http://localhost",
|
||||
})
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
createTask(api.CreateTaskRequest{
|
||||
Project: resp.Id,
|
||||
Priority: 1,
|
||||
Recipe: "{}",
|
||||
MaxRetries: 1,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -38,11 +38,52 @@ func TestCreateTaskInvalidProject(t *testing.T) {
|
||||
})
|
||||
|
||||
if resp.Ok != false {
|
||||
t.Fail()
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(resp.Message) <= 0 {
|
||||
t.Fail()
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTaskInvalidWid(t *testing.T) {
|
||||
|
||||
resp := getTask(nil)
|
||||
|
||||
if resp.Ok != false {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(resp.Message) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTaskInvalidWorker(t *testing.T) {
|
||||
|
||||
id := uuid.New()
|
||||
resp := getTask(&id)
|
||||
|
||||
if resp.Ok != false {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(resp.Message) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTaskFromProjectInvalidWorker(t *testing.T) {
|
||||
|
||||
id := uuid.New()
|
||||
resp := getTaskFromProject(1, &id)
|
||||
|
||||
if resp.Ok != false {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(resp.Message) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,11 +95,28 @@ func TestCreateTaskInvalidRetries(t *testing.T) {
|
||||
})
|
||||
|
||||
if resp.Ok != false {
|
||||
t.Fail()
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(resp.Message) <= 0 {
|
||||
t.Fail()
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateTaskInvalidRecipe(t *testing.T) {
|
||||
|
||||
resp := createTask(api.CreateTaskRequest{
|
||||
Project: 1,
|
||||
Recipe: "",
|
||||
MaxRetries: 3,
|
||||
})
|
||||
|
||||
if resp.Ok != false {
|
||||
t.Error()
|
||||
}
|
||||
|
||||
if len(resp.Message) <= 0 {
|
||||
t.Error()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,11 +270,33 @@ func TestNoMoreTasks(t *testing.T) {
|
||||
|
||||
wid := genWid()
|
||||
|
||||
for i := 0; i < 30; i++ {
|
||||
for i := 0; i < 15; i++ {
|
||||
getTask(wid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseTaskSuccess(t *testing.T) {
|
||||
|
||||
//wid := genWid()
|
||||
|
||||
pid := createProject(api.CreateProjectRequest{
|
||||
Priority: 0,
|
||||
GitRepo: "testreleasetask",
|
||||
CloneUrl: "lllllllll",
|
||||
Version: "11111111111111111",
|
||||
Name: "testreleasetask",
|
||||
Motd: "",
|
||||
}).Id
|
||||
|
||||
createTask(api.CreateTaskRequest{
|
||||
Priority: 0,
|
||||
Project: pid,
|
||||
Recipe: "{}",
|
||||
MaxRetries: 3,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func createTask(request api.CreateTaskRequest) *api.CreateTaskResponse {
|
||||
|
||||
r := Post("/task/create", request)
|
||||
|
||||
@@ -3,6 +3,8 @@ server:
|
||||
|
||||
database:
|
||||
conn_str: "user=task_tracker dbname=task_tracker_test sslmode=disable"
|
||||
# log_levels: ["debug", "error"]
|
||||
log_levels: ["debug", "error", "trace", "info", "warning"]
|
||||
|
||||
git:
|
||||
webhook_secret: "very_secret_secret"
|
||||
|
||||
@@ -12,6 +12,7 @@ func TestMain(m *testing.M) {
|
||||
config.SetupConfig()
|
||||
|
||||
testApi := api.New()
|
||||
testApi.SetupLogger()
|
||||
testApi.Database.Reset()
|
||||
go testApi.Run()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
DROP TABLE IF EXISTS workerIdentity, Worker, Project, Task;
|
||||
DROP TYPE IF EXISTS Status;
|
||||
DROP TABLE IF EXISTS workeridentity, Worker, Project, Task, log_entry;
|
||||
DROP TYPE IF EXISTS status;
|
||||
DROP TYPE IF EXISTS loglevel;
|
||||
|
||||
CREATE TYPE status as ENUM (
|
||||
'new',
|
||||
@@ -7,6 +8,10 @@ CREATE TYPE status as ENUM (
|
||||
'closed'
|
||||
);
|
||||
|
||||
CREATE TYPE loglevel as ENUM (
|
||||
'fatal', 'panic', 'error', 'warning', 'info', 'debug', 'trace'
|
||||
);
|
||||
|
||||
CREATE TABLE workerIdentity
|
||||
(
|
||||
id SERIAL PRIMARY KEY,
|
||||
@@ -27,6 +32,7 @@ CREATE TABLE project
|
||||
(
|
||||
id SERIAL PRIMARY KEY,
|
||||
priority INTEGER DEFAULT 0,
|
||||
motd TEXT DEFAULT '',
|
||||
name TEXT UNIQUE,
|
||||
clone_url TEXT,
|
||||
git_repo TEXT UNIQUE,
|
||||
@@ -45,4 +51,12 @@ CREATE TABLE task
|
||||
recipe TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE log_entry
|
||||
(
|
||||
level loglevel,
|
||||
message TEXT,
|
||||
message_data TEXT,
|
||||
timestamp INT
|
||||
);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user