Example #1
0
func TestRegisterStoredCronJobsOnStart(t *testing.T) {
	// Create configuration, storage and test vars
	cfg := config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
	cfg.DontScheduleJobsStart = false

	stCli := storage.NewDummy()

	wantExitStatus := job.ResultOK
	wantOut := fmt.Sprintf("Result: %d", rand.Int())
	iterations := 3

	// Create jobs and set on dummy store
	u, _ := url.Parse("http://test.org/test")
	js := map[string]*job.Job{
		"job:1": &job.Job{ID: 1, URL: u, When: "@every 1s", Active: true},
		"job:2": &job.Job{ID: 2, URL: u, When: "@every 1s", Active: true},
	}
	stCli.Jobs = js
	stCli.JobCounter = len(js)

	// Create our cron engine and start
	dCron := NewDummyCron(cfg, stCli, wantExitStatus, wantOut)

	// start our cron (this will load the crons)
	dCron.Start(nil)

	// wait the number of iterations
	time.Sleep(time.Duration(iterations) * time.Second)

	// stop and check iterations where ok
	dCron.Stop()

	// Check the number of jobs registered
	if len(stCli.Results) != len(js) {
		t.Errorf("Wrong number of registered stored jobs; expected: %d; got: %d", len(js), len(stCli.Results))
	}

	// Check the number of jobs executed (checking result) for each stored job loaded on startup
	for k, v := range stCli.Results {
		if len(v) != iterations {
			t.Errorf("Wrong result list for %s job; expected: %d; got: %d", k, iterations, len(v))
		}
	}

	// Start check of register stored jobs only once per cron engine instance
	// Flush results
	stCli.Results = map[string]map[string]*job.Result{}
	stCli.ResultsCounter = map[string]int{}

	// Start again
	dCron.Start(nil)
	time.Sleep(time.Duration(iterations) * time.Second)
	dCron.Stop()

	// Check the number of jobs registered (should be the same as the first cron engien start)
	if len(stCli.Results) != len(js) {
		t.Errorf("Wrong number of registered stored jobs after starting the cron engine a second time; expected: %d; got: %d", len(js), len(stCli.Results))
	}
}
Example #2
0
func TestRegisterCronJobStoreResults(t *testing.T) {
	// Create configuration, storage and test vars
	cfg := config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
	stCli := storage.NewDummy()
	wantExitStatus := job.ResultOK
	wantOut := fmt.Sprintf("Result: %d", rand.Int())
	iterations := 3

	// Create a job & a result
	u, _ := url.Parse("http://test.org/test")
	j := &job.Job{
		ID:     1,
		URL:    u,
		When:   "@every 1s",
		Active: true,
	}

	// Create our cron engine and start
	dCron := NewDummyCron(cfg, stCli, wantExitStatus, wantOut)
	dCron.Start(nil)

	// Register the job
	dCron.RegisterCronJob(j)

	// wait the number of iterations
	time.Sleep(time.Duration(iterations) * time.Second)

	// stop and check iterations where ok
	dCron.Stop()

	// Check stored results
	results, err := stCli.GetResults(j, 0, 0)
	if err != nil {
		t.Errorf("Error retrieving stored results: %v", err)
	}

	if len(results) != iterations {
		t.Errorf("Wrong result list; expected: %d; got: %d", iterations, len(results))
	}

	for _, r := range results {
		if r.Job != j {
			t.Errorf("Wrong result Job; expected: %d; got: %d", j, r.Job)
		}
		if r.Status != wantExitStatus {
			t.Errorf("Wrong result status; expected: %d; got: %d", wantExitStatus, r.Status)
		}
		if r.Out != wantOut {
			t.Errorf("Wrong result out; expected: %s; got: %s", wantOut, r.Out)
		}
	}

}
Example #3
0
func TestAuthenticationMiddleware(t *testing.T) {

	// These are the valid tokens to make the requests
	validTokens := map[string]struct{}{
		"123456789": struct{}{},
	}

	tests := []struct {
		GivenAuthHeader string
		WantCode        int
		SecurityEnabled bool
	}{
		{GivenAuthHeader: "", WantCode: http.StatusForbidden, SecurityEnabled: true},
		{GivenAuthHeader: "", WantCode: http.StatusOK, SecurityEnabled: false},
		{GivenAuthHeader: "Bearer ", WantCode: http.StatusForbidden, SecurityEnabled: true},
		{GivenAuthHeader: "Bearer 987654321", WantCode: http.StatusForbidden, SecurityEnabled: true},
		{GivenAuthHeader: "Bearer 123456789", WantCode: http.StatusOK, SecurityEnabled: true},
		{GivenAuthHeader: "123456789", WantCode: http.StatusForbidden, SecurityEnabled: true},
		{GivenAuthHeader: "Bearer  123456789", WantCode: http.StatusForbidden, SecurityEnabled: true},
	}

	for _, test := range tests {
		testConfig := config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
		// Disable or enable security based on the test
		testConfig.APIDisableSecurity = !test.SecurityEnabled
		testStorageClient := storage.NewDummy()
		// mock custom auth tokens on database
		testStorageClient.Tokens = validTokens
		testSchedulerClient := schedule.NewDummyCron(testConfig, testStorageClient, 0, "OK")

		s := &KhronosService{
			Config:  testConfig,
			Storage: testStorageClient,
			Cron:    testSchedulerClient,
		}

		// Create a testing request
		r, _ := http.NewRequest("GET", "/", nil)
		r.Header.Add("Authorization", test.GivenAuthHeader)
		w := httptest.NewRecorder()

		// Apply middleware to test
		s.AuthenticationHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(http.StatusOK)
		})).ServeHTTP(w, r)

		// Check testing ok
		if w.Code != test.WantCode {
			t.Errorf("Authorization middleware error on response status code; expected %d, got %d instead", test.WantCode, w.Code)
		}
	}

}
Example #4
0
func TestRegisterCronJob(t *testing.T) {
	// Create configuration, storage and test vars
	cfg := config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
	stCli := storage.NewDummy()
	wantExitStatus := job.ResultOK
	wantOut := fmt.Sprintf("Result: %d", rand.Int())
	iterations := 3

	// Create a job & a result
	u, _ := url.Parse("http://test.org/test")
	j := &job.Job{
		ID:     1,
		URL:    u,
		When:   "@every 1s",
		Active: true,
	}

	// Create our cron engine and start
	dCron := NewDummyCron(cfg, stCli, wantExitStatus, wantOut)
	var results []*job.Result
	dCron.Start(func(r *job.Result) {
		results = append(results, r)
	})

	// Register the job
	dCron.RegisterCronJob(j)

	// wait the number of iterations
	time.Sleep(time.Duration(iterations) * time.Second)

	// stop and check iterations where ok
	dCron.Stop()

	// Check the number of jobs executed and completed is the expected
	if len(results) != iterations {
		t.Errorf("Wrong result list; expected: %d; got: %d", iterations, len(results))
	}

	// Check the the dummy schedule was executed ok by checking the expected results
	for _, r := range results {
		if r.Status != wantExitStatus {
			t.Errorf("Wrong result status; expected: %d; got: %d", wantExitStatus, r.Status)
		}
		if r.Out != wantOut {
			t.Errorf("Wrong result out; expected: %s; got: %s", wantOut, r.Out)
		}
	}
}
Example #5
0
File: main.go Project: slok/khronos
func main() {
	// Get config location file
	configFile := os.Getenv(config.KhronosConfigFileKey)

	// Load config
	cfg := config.NewAppConfig(configFile)
	server.Init("khronos", cfg.Server)

	var stCli storage.Client
	var err error

	// Create the storage client
	switch cfg.StorageEngine {
	case "dummy":
		stCli = storage.NewDummy()
	case "boltdb":
		to := time.Duration(cfg.BoltDBTimeoutSeconds)
		stCli, err = storage.NewBoltDB(cfg.BoltDBPath, to)
		if err != nil {
			logrus.Fatalf("Error opening boltdb database: %v", err)
		}
	default:
		logrus.Fatal("Wrong Storage engine")
	}

	// Create scheduler and start
	cr := schedule.NewDummyCron(cfg, stCli, 0, "OK")
	cr.Start(nil)
	defer cr.Stop()

	// Load service
	khronosService := service.NewKhronosService(cfg, stCli, cr)

	// Register the service on the server
	err = server.Register(khronosService)
	if err != nil {
		logrus.Fatalf("unable to register service: %v", err)
	}

	// Serve our service
	err = server.Run()
	if err != nil {
		logrus.Fatalf("server encountered a fatal error: %v", err)
	}
}
Example #6
0
func TestStarCronEngine(t *testing.T) {
	cfg := config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
	stCli := storage.NewDummy()
	dCron := NewDummyCron(cfg, stCli, 0, "")

	// First time should start ok
	if err := dCron.Start(nil); err != nil {
		t.Errorf("Starting the first time should not get an error: %v", err)
	}

	// Second time should fail
	if err := dCron.Start(nil); err == nil {
		t.Errorf("Starting the second time should get an error")
	}

	// Stop and start again perfectly
	dCron.Stop()
	if err := dCron.Start(nil); err != nil {
		t.Errorf("Starting after stopping should not get an error: %v", err)
	}

}
Example #7
0
func TestStopCronEngine(t *testing.T) {
	cfg := config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
	stCli := storage.NewDummy()
	dCron := NewDummyCron(cfg, stCli, 0, "")

	// Stopping without starting should fail
	if err := dCron.Stop(); err == nil {
		t.Errorf("Stopping without starting should get an error")
	}

	// Stopping after starting should go ok
	dCron.Start(nil)
	if err := dCron.Stop(); err != nil {
		t.Errorf("Stopping after starting should not get an error %v", err)
	}

	// Stopping after stopping should fail
	dCron.Stop()
	if err := dCron.Stop(); err == nil {
		t.Errorf("Stopping after stopping should get an error")
	}

}
Example #8
0
func TestGetResultsPaginated(t *testing.T) {
	results := map[string]map[string]*job.Result{
		"job:1:results": map[string]*job.Result{},
	}
	totalResults := 54
	pageSize := 7
	testStorageClient := storage.NewDummy()
	// Custom pagination
	paginationTestConfig := config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
	paginationTestConfig.APIResourcesPerPage = pageSize
	testCronEngine := schedule.NewDummyCron(paginationTestConfig, testStorageClient, 0, "OK")
	testCronEngine.Start(nil)

	// Create our custom dummy results database
	j := &job.Job{ID: 1, Name: "test1", When: "@daily", Active: true, URL: &url.URL{}}
	for i := 1; i <= totalResults; i++ {
		v := &job.Result{ID: i, Job: j, Out: fmt.Sprintf("test%d", i), Status: job.ResultInternalError, Start: time.Now().UTC(), Finish: time.Now().UTC()}
		k := fmt.Sprintf("result:%d", i)
		results["job:1:results"][k] = v
	}

	// Testing data
	tests := []struct {
		givenURI      string
		wantResultIDs []int
	}{
		{
			givenURI:      "/api/v1/jobs/1/results",
			wantResultIDs: []int{1, 2, 3, 4, 5, 6, 7},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=0",
			wantResultIDs: []int{1, 2, 3, 4, 5, 6, 7},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=1",
			wantResultIDs: []int{1, 2, 3, 4, 5, 6, 7},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=2",
			wantResultIDs: []int{8, 9, 10, 11, 12, 13, 14},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=3",
			wantResultIDs: []int{15, 16, 17, 18, 19, 20, 21},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=4",
			wantResultIDs: []int{22, 23, 24, 25, 26, 27, 28},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=5",
			wantResultIDs: []int{29, 30, 31, 32, 33, 34, 35},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=6",
			wantResultIDs: []int{36, 37, 38, 39, 40, 41, 42},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=7",
			wantResultIDs: []int{43, 44, 45, 46, 47, 48, 49},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=8",
			wantResultIDs: []int{50, 51, 52, 53, 54},
		},
		{
			givenURI:      "/api/v1/jobs/1/results?page=9",
			wantResultIDs: []int{},
		},
	}

	// Tests
	for _, test := range tests {
		// Set our dummy 'database' on the storage client
		testStorageClient.Results = results
		testStorageClient.Jobs = map[string]*job.Job{"job:1": j}

		// Create a testing server
		testServer := server.NewSimpleServer(nil)

		// Register our service on the server (we don't need configuration for this service)
		testServer.Register(&KhronosService{
			Config:  paginationTestConfig,
			Storage: testStorageClient,
			Cron:    testCronEngine,
		})

		// Create request and a test recorder
		r, _ := http.NewRequest("GET", test.givenURI, nil)
		w := httptest.NewRecorder()
		testServer.ServeHTTP(w, r)

		var got []*job.Result
		err := json.NewDecoder(w.Body).Decode(&got)
		if err != nil {
			t.Error(err)
		}

		// Check length
		if len(got) != len(test.wantResultIDs) {
			t.Errorf("Expected length '%d'. Got '%d' instead ", len(test.wantResultIDs), len(got))
		}

		// Check IDs ok (should be in order)
		for k, i := range test.wantResultIDs {
			if got[k].ID != i {
				t.Errorf("Expected result id '%d'. Got '%d' instead ", i, got[k].ID)
			}
		}
	}
}
Example #9
0
func TestGetJobsPaginated(t *testing.T) {
	jobs := make(map[string]*job.Job)
	totalJobs := 27
	pageSize := 5
	testStorageClient := storage.NewDummy()
	// Custom pagination
	paginationTestConfig := config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
	paginationTestConfig.APIResourcesPerPage = pageSize
	testCronEngine := schedule.NewDummyCron(paginationTestConfig, testStorageClient, 0, "OK")
	testCronEngine.Start(nil)

	// Create our custom dummy job database
	for i := 1; i <= totalJobs; i++ {
		k := fmt.Sprintf("job:%d", i)
		v := &job.Job{ID: i, Name: fmt.Sprintf("test%d", i), When: "@daily", URL: &url.URL{}}
		jobs[k] = v
	}

	// Testing data
	tests := []struct {
		givenURI   string
		wantJobIDs []int
	}{
		{
			givenURI:   "/api/v1/jobs",
			wantJobIDs: []int{1, 2, 3, 4, 5},
		},
		{
			givenURI:   "/api/v1/jobs?page=0",
			wantJobIDs: []int{1, 2, 3, 4, 5},
		},
		{
			givenURI:   "/api/v1/jobs?page=1",
			wantJobIDs: []int{1, 2, 3, 4, 5},
		},
		{
			givenURI:   "/api/v1/jobs?page=2",
			wantJobIDs: []int{6, 7, 8, 9, 10},
		},
		{
			givenURI:   "/api/v1/jobs?page=3",
			wantJobIDs: []int{11, 12, 13, 14, 15},
		},
		{
			givenURI:   "/api/v1/jobs?page=4",
			wantJobIDs: []int{16, 17, 18, 19, 20},
		},
		{
			givenURI:   "/api/v1/jobs?page=5",
			wantJobIDs: []int{21, 22, 23, 24, 25},
		},
		{
			givenURI:   "/api/v1/jobs?page=6",
			wantJobIDs: []int{26, 27},
		},
		{
			givenURI:   "/api/v1/jobs?page=7",
			wantJobIDs: []int{},
		},
	}

	// Tests
	for _, test := range tests {
		// Set our dummy 'database' on the storage client
		testStorageClient.Jobs = jobs
		testStorageClient.JobCounter = totalJobs

		// Create a testing server
		testServer := server.NewSimpleServer(nil)

		// Register our service on the server (we don't need configuration for this service)
		testServer.Register(&KhronosService{
			Config:  paginationTestConfig,
			Storage: testStorageClient,
			Cron:    testCronEngine,
		})

		// Create request and a test recorder
		r, _ := http.NewRequest("GET", test.givenURI, nil)
		w := httptest.NewRecorder()
		testServer.ServeHTTP(w, r)

		var got []*job.Job
		err := json.NewDecoder(w.Body).Decode(&got)
		if err != nil {
			t.Error(err)
		}

		// Check length
		if len(got) != len(test.wantJobIDs) {
			t.Errorf("Expected length '%d'. Got '%d' instead ", len(test.wantJobIDs), len(got))
		}

		// Check IDs ok (should be in order)
		for k, i := range test.wantJobIDs {
			if got[k].ID != i {
				t.Errorf("Expected job id '%d'. Got '%d' instead ", i, got[k].ID)
			}
		}
	}
}
Example #10
0
	"net/url"
	"os"
	"reflect"
	"testing"
	"time"

	"github.com/NYTimes/gizmo/server"

	"github.com/slok/khronos/config"
	"github.com/slok/khronos/job"
	"github.com/slok/khronos/schedule"
	"github.com/slok/khronos/storage"
)

var (
	testConfig = config.NewAppConfig(os.Getenv(config.KhronosConfigFileKey))
)

func TestPing(t *testing.T) {
	testStorageClient := storage.NewDummy()
	testCronEngine := schedule.NewDummyCron(testConfig, testStorageClient, 0, "OK")
	testCronEngine.Start(nil)

	// Testing data
	tests := []struct {
		givenURI string
		wantCode int
		wantBody interface{}
	}{
		{
			givenURI: "/api/v1/ping",