diff --git a/search/search_test.go b/search/search_test.go new file mode 100644 index 0000000000000000000000000000000000000000..333a254b6a8a5807db4e2e0670bab6ae39f7b9f3 --- /dev/null +++ b/search/search_test.go @@ -0,0 +1,121 @@ +package search_test + +import ( + "fmt" + "math/rand" + "sort" + "testing" + "time" + + "gitlab.com/uafrica/go-utils/logger" + "gitlab.com/uafrica/go-utils/search" +) + +func TestLocalWriter(t *testing.T) { + test(t, search.Config{ + Addresses: []string{"https://localhost:9200"}, + }) +} + +func TestDevWriter(t *testing.T) { + test(t, search.Config{ + Addresses: []string{"https://search-uafrica-v3-api-logs-fefgiypvmb3sg5wqohgsbqnzvq.af-south-1.es.amazonaws.com/"}, //from AWS Console OpenSearch Service > Domains > uafrica-v3-api-logs > General Information: Domain Endpoints + Username: "uafrica", + Password: "Aiz}a4ee", + }) +} + +func test(t *testing.T, c search.Config) { + logger.SetGlobalFormat(logger.NewConsole()) + logger.SetGlobalLevel(logger.LevelDebug) + a, err := search.New(c) + if err != nil { + t.Fatalf("failed to create writer: %+v", err) + } + + indexName := "go-utils-audit-test" + ts, err := a.TimeSeries(indexName, testStruct{}) + if err != nil { + t.Fatalf("failed to create time series: %+v", err) + } + + //write N records + methods := []string{"GET", "POST", "GET", "PATCH", "GET", "GET", "DELETE", "GET", "GET"} //more gets than others + paths := []string{"/users", "/orders", "/accounts", "/shipment", "/rates", "/accounts", "/shipment", "/rates", "/accounts", "/shipment", "/rates", "/accounts", "/shipment", "/rates"} + N := 100 + testTime := time.Now().Add(-time.Hour * time.Duration(N)) + for i := 0; i < N; i++ { + testTime = testTime.Add(time.Duration(float64(rand.Intn(100)) / 60.0 * float64(time.Hour))) + method := methods[i%len(methods)] + path := paths[i%len(paths)] + if err := ts.Write( + testTime, + testTime.Add(-time.Duration(float64(time.Second)*(float64(rand.Intn(100))/100.0+0.1))), + testStruct{ + TimeSeriesHeader: search.TimeSeriesHeader{}, + Test1: fmt.Sprintf("%d", i+1), //1,2,3,... + Test2: fmt.Sprintf("ACC_%05d", 93+i%7), //ACC_00093..ACC00100 + Test3: i%3 + 8, //8,9, or 10 + HTTP: httpData{ + Method: method, + Path: path, + }, + HTTPMethod: method, + HTTPPath: path, + }); err != nil { + t.Fatalf("failed to add doc: %+v", err) + } + } + + docs, totalCount, err := ts.Search(10) + if err != nil { + t.Errorf("failed to search: %+v", err) + } else { + t.Logf("search: %d: %+v", totalCount, docs) + } + + oldList, err := a.DelOldTimeSeries(indexName, 2) + if err != nil { + t.Fatalf("failed to del old: %+v", err) + } + sort.Slice(oldList, func(i, j int) bool { return oldList[i] < oldList[j] }) + + t.Logf("Deleted %d old series", len(oldList)) + //indexes deleted depends on current time, so not verifying + // if len(oldList) != 2 || oldList[0] != "go-utils-audit-test-20211029" || oldList[1] != "go-utils-audit-test-20211030" { + // t.Fatalf("Did not delete expected indices") + // } + t.Logf("Done") +} + +type testStruct struct { + search.TimeSeriesHeader + Test1 string `json:"test1"` + Test2 string `json:"test2"` + Test3 int `json:"test3"` + HTTP httpData `json:"http"` + HTTPMethod string `json:"http_method" search:"keyword"` + HTTPPath string `json:"http_path" search:"keyword"` +} + +type httpData struct { + Method string `json:"method" search:"keyword"` + Path string `json:"path" search:"keyword"` +} + +func TestOlderThan(t *testing.T) { + local := time.Now().Location() + + //time now for test (using a fixed value in SAST) + t0, _ := time.ParseInLocation("2006-01-02 15:04:05", "2021-10-20 14:15:16", local) + t.Logf("t0=%s", t0) + + //threshold is 2 days older, applying at midnight in location SAST + olderThanDays := 2 + t.Logf("n=%d", olderThanDays) + + t1 := time.Date(t0.Year(), t0.Month(), t0.Day(), 0, 0, 0, 0, local) + t.Logf("t1=%s", t1) + t1 = t1.Add(-time.Hour * 24 * time.Duration(olderThanDays)) + t.Logf("Threshold = %s", t1) +}