Added test coverage for helpers, api, listener, init and buffer manager
diff --git a/api_helper_test.go b/api_helper_test.go new file mode 100644 index 0000000..2ccc9f5 --- /dev/null +++ b/api_helper_test.go
@@ -0,0 +1,112 @@ +package apidAnalytics + +import ( + "bytes" + "encoding/json" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +// BeforeSuite setup and AfterSuite cleanup is in apidAnalytics_suite_test.go +var _ = Describe("test valid() directly", func() { + Context("invalid record", func() { + It("should return invalid record", func() { + By("payload with missing required keys") + + var record = []byte(`{ + "response_status_code": 200, + "client_id":"testapikey" + }`) + raw := getRaw(record) + valid, e := validate(raw) + + Expect(valid).To(Equal(false)) + Expect(e.ErrorCode).To(Equal("MISSING_FIELD")) + + By("payload with clst > clet") + record = []byte(`{ + "response_status_code": 200, + "client_id":"testapikey", + "client_received_start_timestamp": 1486406248277, + "client_received_end_timestamp": 1486406248260 + }`) + raw = getRaw(record) + valid, e = validate(raw) + + Expect(valid).To(Equal(false)) + Expect(e.ErrorCode).To(Equal("BAD_DATA")) + Expect(e.Reason).To(Equal("client_received_start_timestamp > client_received_end_timestamp")) + + }) + }) + Context("valid record", func() { + It("should return true", func() { + var record = []byte(`{ + "response_status_code": 200, + "client_id":"testapikey", + "client_received_start_timestamp": 1486406248277, + "client_received_end_timestamp": 1486406248290 + }`) + raw := getRaw(record) + valid, _ := validate(raw) + Expect(valid).To(Equal(true)) + }) + }) +}) + +var _ = Describe("test enrich() directly", func() { + Context("enrich record for existing apiKey", func() { + It("developer related fields should be added", func() { + var record = []byte(`{ + "response_status_code": 200, + "client_id":"testapikey", + "client_received_start_timestamp": 1486406248277, + "client_received_end_timestamp": 1486406248290 + }`) + + raw := getRaw(record) + tenant := tenant{Org: "testorg", Env: "testenv", TenantId: "tenantid"} + enrich(raw, "testid", tenant) + + Expect(raw["organization"]).To(Equal(tenant.Org)) + Expect(raw["environment"]).To(Equal(tenant.Env)) + Expect(raw["api_product"]).To(Equal("testproduct")) + Expect(raw["developer_app"]).To(Equal("testapp")) + Expect(raw["developer_email"]).To(Equal("testdeveloper@test.com")) + Expect(raw["developer"]).To(Equal("testdeveloper")) + }) + }) + + Context("enrich record where no apikey is set", func() { + It("developer related fields should not be added", func() { + var record = []byte(`{ + "response_status_code": 200, + "client_received_start_timestamp": 1486406248277, + "client_received_end_timestamp": 1486406248290 + }`) + + raw := getRaw(record) + tenant := tenant{Org: "testorg", Env: "testenv", TenantId: "tenantid"} + enrich(raw, "testid", tenant) + + Expect(raw["organization"]).To(Equal(tenant.Org)) + Expect(raw["environment"]).To(Equal(tenant.Env)) + Expect(raw["api_product"]).To(BeNil()) + Expect(raw["developer_app"]).To(BeNil()) + Expect(raw["developer_email"]).To(BeNil()) + Expect(raw["developer"]).To(BeNil()) + }) + }) +}) + +func getRaw(record []byte) map[string]interface{} { + var raw map[string]interface{} + + decoder := json.NewDecoder(bytes.NewReader(record)) // Decode payload to JSON data + decoder.UseNumber() + err := decoder.Decode(&raw) + + Expect(err).ShouldNot(HaveOccurred()) + return raw +}
diff --git a/api_test.go b/api_test.go index d172a29..83ce5a2 100644 --- a/api_test.go +++ b/api_test.go
@@ -1,49 +1,203 @@ package apidAnalytics import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" "net/http" "net/url" - "strings" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) // BeforeSuite setup and AfterSuite cleanup is in apidAnalytics_suite_test.go -var _ = Describe("testing saveAnalyticsRecord() directly", func() { - Context("valid scopeuuid", func() { - It("should successfully return", func() { +var _ = Describe("POST /analytics/{scopeuuid}", func() { + Context("invalid content type header", func() { + It("should return bad request", func() { uri, err := url.Parse(testServer.URL) - uri.Path = analyticsBasePath - - v := url.Values{} - v.Add("bundle_scope_uuid", "testid") - - client := &http.Client{} - req, err := http.NewRequest("POST", uri.String(), - strings.NewReader(v.Encode())) - res, err := client.Do(req) - defer res.Body.Close() + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "test") Expect(err).ShouldNot(HaveOccurred()) - Expect(res.StatusCode, http.StatusOK) + + req, _ := http.NewRequest("POST", uri.String(), nil) + req.Header.Set("Content-Type", "application/x-gzip") + + res, e := makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusBadRequest)) + Expect(e.ErrorCode).To(Equal("UNSUPPORTED_CONTENT_TYPE")) + }) + }) + + Context("invalid content encoding header", func() { + It("should return bad request", func() { + uri, err := url.Parse(testServer.URL) + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "testid") + Expect(err).ShouldNot(HaveOccurred()) + + req, _ := http.NewRequest("POST", uri.String(), nil) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Content-Encoding", "application/gzip") + + res, e := makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusBadRequest)) + Expect(e.ErrorCode).To(Equal("UNSUPPORTED_CONTENT_ENCODING")) }) }) Context("invalid scopeuuid", func() { It("should return bad request", func() { uri, err := url.Parse(testServer.URL) - uri.Path = analyticsBasePath - - v := url.Values{} - v.Add("bundle_scope_uuid", "wrongId") - - client := &http.Client{} - req, err := http.NewRequest("POST", uri.String(), - strings.NewReader(v.Encode())) - res, err := client.Do(req) - defer res.Body.Close() + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "wrongid") Expect(err).ShouldNot(HaveOccurred()) - Expect(res.StatusCode, http.StatusBadRequest) + + req, _ := http.NewRequest("POST", uri.String(), nil) + req.Header.Set("Content-Type", "application/json") + + res, e := makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusBadRequest)) + Expect(e.ErrorCode).To(Equal("UNKNOWN_SCOPE")) + }) + }) + + Context("Unitialized DB", func() { + It("should return internal server error", func() { + db := getDB() + setDB(nil) + + uri, err := url.Parse(testServer.URL) + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "testid") + Expect(err).ShouldNot(HaveOccurred()) + + req, _ := http.NewRequest("POST", uri.String(), nil) + req.Header.Set("Content-Type", "application/json") + + res, e := makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusInternalServerError)) + Expect(e.ErrorCode).To(Equal("INTERNAL_SERVER_ERROR")) + + setDB(db) + + }) + }) + + Context("bad payload", func() { + It("should return bad request", func() { + + By("no payload") + uri, err := url.Parse(testServer.URL) + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "testid") + Expect(err).ShouldNot(HaveOccurred()) + + req, _ := http.NewRequest("POST", uri.String(), nil) + req.Header.Set("Content-Type", "application/json") + + res, e := makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusBadRequest)) + Expect(e.ErrorCode).To(Equal("BAD_DATA")) + Expect(e.Reason).To(Equal("Not a valid JSON payload")) + + By("payload with 0 records") + uri, err = url.Parse(testServer.URL) + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "testid") + Expect(err).ShouldNot(HaveOccurred()) + + var payload = []byte(`{}`) + req, _ = http.NewRequest("POST", uri.String(), bytes.NewReader(payload)) + req.Header.Set("Content-Type", "application/json") + + res, e = makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusBadRequest)) + Expect(e.ErrorCode).To(Equal("NO_RECORDS")) + + By("set content encoding to gzip but send json data") + uri, err = url.Parse(testServer.URL) + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "testid") + Expect(err).ShouldNot(HaveOccurred()) + + payload = []byte(`{ + "records":[{ + "response_status_code": 200, + "client_id":"testapikey" + }] + }`) + + req, _ = http.NewRequest("POST", uri.String(), bytes.NewReader(payload)) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Content-Encoding", "gzip") + + res, e = makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusBadRequest)) + Expect(e.ErrorCode).To(Equal("BAD_DATA")) + Expect(e.Reason).To(Equal("Gzip Encoded data cannot be read")) + + By("1 bad record") + uri, err = url.Parse(testServer.URL) + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "testid") + Expect(err).ShouldNot(HaveOccurred()) + + payload = []byte(`{ + "records":[{ + "response_status_code": 200, + "client_id":"testapikey", + "client_received_start_timestamp": 1486406248277, + "client_received_end_timestamp": 1486406248290 + },{ + "response_status_code": 200, + "client_id":"testapikey" + }] + }`) + + req, _ = http.NewRequest("POST", uri.String(), bytes.NewReader(payload)) + req.Header.Set("Content-Type", "application/json") + + res, e = makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusBadRequest)) + Expect(e.ErrorCode).To(Equal("MISSING_FIELD")) + }) + }) + + Context("valid payload", func() { + It("should return successfully", func() { + uri, err := url.Parse(testServer.URL) + uri.Path = fmt.Sprintf(analyticsBasePath+"/%s", "testid") + Expect(err).ShouldNot(HaveOccurred()) + + var payload = []byte(`{ + "records":[{ + "response_status_code": 200, + "client_id":"testapikey", + "client_received_start_timestamp": 1486406248277, + "client_received_end_timestamp": 1486406248290 + }] + }`) + + req, _ := http.NewRequest("POST", uri.String(), bytes.NewReader(payload)) + req.Header.Set("Content-Type", "application/json") + + res, _ := makeRequest(req) + + Expect(res.StatusCode).To(Equal(http.StatusOK)) }) }) }) + +func makeRequest(req *http.Request) (*http.Response, errResponse) { + res, err := client.Do(req) + defer res.Body.Close() + Expect(err).ShouldNot(HaveOccurred()) + + var body errResponse + respBody, _ := ioutil.ReadAll(res.Body) + json.Unmarshal(respBody, &body) + + return res, body +}
diff --git a/apidAnalytics_suite_test.go b/apidAnalytics_suite_test.go index 1e5c128..345b4b8 100644 --- a/apidAnalytics_suite_test.go +++ b/apidAnalytics_suite_test.go
@@ -26,36 +26,42 @@ var _ = BeforeSuite(func() { apid.Initialize(factory.DefaultServicesFactory()) - config := apid.Config() + config = apid.Config() var err error testTempDir, err = ioutil.TempDir("", "api_test") Expect(err).NotTo(HaveOccurred()) + config.Set("local_storage_path", testTempDir) config.Set("data_path", testTempDir) - config.Set(uapServerBase, "http://localhost:9000") // dummy value - config.Set("apigeesync_apid_instance_id", - "abcdefgh-ijkl-mnop-qrst-uvwxyz123456") // dummy value - config.Set(useCaching, true) + config.Set("apigeesync_apid_instance_id", "abcdefgh-ijkl-mnop-qrst-uvwxyz123456") // dummy value db, err := apid.Data().DB() Expect(err).NotTo(HaveOccurred()) - setDB(db) + createApidClusterTables(db) createTables(db) insertTestData(db) - apid.InitializePlugins() + setDB(db) - // Create cache else its created in listener.go when a snapshot is received + // required config uapServerBase is not set, thus init should panic + Expect(apid.InitializePlugins).To(Panic()) + + config.Set(uapServerBase, "http://localhost:9000") // dummy value + Expect(apid.InitializePlugins).ToNot(Panic()) + + config.Set(useCaching, true) createTenantCache() - createDeveloperInfoCache() + Expect(len(tenantCache)).To(Equal(1)) - testServer = httptest.NewServer(http.HandlerFunc( - func(w http.ResponseWriter, req *http.Request) { - if req.URL.Path == analyticsBasePathDefault { - saveAnalyticsRecord(w, req) - } - })) + createDeveloperInfoCache() + Expect(len(developerInfoCache)).To(Equal(1)) + + router := apid.API().Router() + router.HandleFunc(analyticsBasePath+"/{bundle_scope_uuid}", func(w http.ResponseWriter, req *http.Request) { + saveAnalyticsRecord(w, req) + }).Methods("POST") + testServer = httptest.NewServer(router) }) func createTables(db apid.DB) {
diff --git a/buffering_manager_test.go b/buffering_manager_test.go new file mode 100644 index 0000000..1789317 --- /dev/null +++ b/buffering_manager_test.go
@@ -0,0 +1,144 @@ +package apidAnalytics + +import ( + "compress/gzip" + "encoding/json" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "os" + "path/filepath" + "time" +) + +var _ = Describe("test getBucketForTimestamp()", func() { + It("should return new bucket or existing bucket if created previously", func() { + t := time.Date(2017, 1, 20, 10, 24, 5, 0, time.Local) + tenant := tenant{Org: "testorg", Env: "testenv", TenantId: "tenantid"} + + bucket, err := getBucketForTimestamp(t, tenant) + Expect(err).ShouldNot(HaveOccurred()) + + Expect(bucket.DirName).To(Equal("testorg~testenv~20170120102400")) + Expect(bucket.FileWriter).ToNot(BeNil()) + + fw := bucket.FileWriter + Expect(fw.file.Name()).To(ContainSubstring("20170120102400.20170120102600")) + + // Should return existing bucket if same interval timestamp is passed + t2 := time.Date(2017, 1, 20, 10, 25, 5, 0, time.Local) + bucket, err = getBucketForTimestamp(t2, tenant) + Expect(err).ShouldNot(HaveOccurred()) + Expect(bucket.DirName).To(Equal("testorg~testenv~20170120102400")) + }) +}) + +var _ = Describe("test getRandomHex()", func() { + It("should return a 4 digit hex", func() { + r1 := getRandomHex() + Expect(len(r1)).To(Equal(4)) + }) + + It("should return differe 4 digit hex each time", func() { + r1 := getRandomHex() + r2 := getRandomHex() + + Expect(r1).NotTo(Equal(r2)) + }) +}) + +var _ = Describe("test createWriteAndCloseFile()", func() { + Context("Cannot create file", func() { + It("should return error", func() { + fileName := "testFile" + fileExtension + completeFilePath := filepath.Join(localAnalyticsTempDir, "fakedir", fileName) + + _, err := createGzipFile(completeFilePath) + Expect(err).To((HaveOccurred())) + }) + + }) + Context("Create file, write to it and close file", func() { + It("should save content to file and read correctly", func() { + fileName := "testFile" + fileExtension + completeFilePath := filepath.Join(localAnalyticsTempDir, fileName) + + fw, err := createGzipFile(completeFilePath) + Expect(err).ToNot((HaveOccurred())) + + var records = []byte(`{ + "records":[{ + "response_status_code": 200, + "client_id":"testapikey", + "client_received_start_timestamp": 1486406248277, + "client_received_end_timestamp": 1486406248290 + }] + }`) + + raw := getRaw(records) + + writeGzipFile(fw, raw["records"].([]interface{})) + closeGzipFile(fw) + + // Verify file was written to properly + f, err := os.Open(completeFilePath) + defer f.Close() + gzReader, err := gzip.NewReader(f) + defer gzReader.Close() + Expect(err).ToNot((HaveOccurred())) + + var record map[string]interface{} + decoder := json.NewDecoder(gzReader) // Decode payload to JSON data + decoder.UseNumber() + err = decoder.Decode(&record) + Expect(err).ToNot((HaveOccurred())) + + Expect(record["client_id"]).To(Equal("testapikey")) + Expect(record["response_status_code"]).To(Equal(json.Number("200"))) + Expect(record["client_received_start_timestamp"]).To(Equal(json.Number("1486406248277"))) + Expect(record["client_received_end_timestamp"]).To(Equal(json.Number("1486406248290"))) + }) + }) +}) + +var _ = Describe("test closeBucketChannel()", func() { + Context("send close bucket event on channel", func() { + It("close file and move to staging dir", func() { + dirName := "testorg~testenv~20160101230000" + dirPath := filepath.Join(localAnalyticsTempDir, dirName) + + err := os.Mkdir(dirPath, os.ModePerm) + Expect(err).ShouldNot(HaveOccurred()) + + fileName := "testFile" + fileExtension + completeFilePath := filepath.Join(dirPath, fileName) + + fw, e := createGzipFile(completeFilePath) + Expect(e).ShouldNot(HaveOccurred()) + + bucket := bucket{DirName: dirName, FileWriter: fw} + closeBucketEvent <- bucket + + // wait for it to close dir and move to staging + time.Sleep(time.Second * 2) + + expectedDirPath := filepath.Join(localAnalyticsStagingDir, dirName) + status, _ := exists(expectedDirPath) + Expect(status).To(BeTrue()) + + expectedfilePath := filepath.Join(localAnalyticsStagingDir, dirName, fileName) + status, _ = exists(expectedfilePath) + Expect(status).To(BeTrue()) + }) + }) +}) + +func exists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return true, err +}
diff --git a/common_helper_test.go b/common_helper_test.go index c691d52..31bdb31 100644 --- a/common_helper_test.go +++ b/common_helper_test.go
@@ -1,48 +1,109 @@ package apidAnalytics import ( + "database/sql" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("test getTenantForScope()", func() { - Context("get tenant for valid scopeuuid", func() { - It("should return testorg and testenv", func() { - tenant, dbError := getTenantForScope("testid") - Expect(dbError.Reason).To(Equal("")) - Expect(tenant.Org).To(Equal("testorg")) - Expect(tenant.Env).To(Equal("testenv")) - Expect(tenant.TenantId).To(Equal("tenantid")) + Context("with usecaching set to true", func() { + Context("get tenant for valid scopeuuid", func() { + It("should return testorg and testenv", func() { + tenant, dbError := getTenantForScope("testid") + Expect(dbError.Reason).To(Equal("")) + Expect(tenant.TenantId).To(Equal("tenantid")) + }) + }) + + Context("get tenant for invalid scopeuuid", func() { + It("should return empty tenant and a db error", func() { + tenant, dbError := getTenantForScope("wrongid") + Expect(tenant.Org).To(Equal("")) + Expect(dbError.ErrorCode).To(Equal("UNKNOWN_SCOPE")) + }) }) }) - Context("get tenant for invalid scopeuuid", func() { - It("should return empty tenant and a db error", func() { - tenant, dbError := getTenantForScope("wrongid") - Expect(tenant.Org).To(Equal("")) - Expect(dbError.ErrorCode).To(Equal("UNKNOWN_SCOPE")) + Context("with usecaching set to false", func() { + BeforeEach(func() { + config.Set(useCaching, false) + }) + AfterEach(func() { + config.Set(useCaching, true) + }) + Context("get tenant for valid scopeuuid", func() { + It("should return testorg and testenv", func() { + tenant, dbError := getTenantForScope("testid") + Expect(dbError.Reason).To(Equal("")) + Expect(tenant.Org).To(Equal("testorg")) + }) + }) + + Context("get tenant for invalid scopeuuid", func() { + It("should return empty tenant and a db error", func() { + tenant, dbError := getTenantForScope("wrongid") + Expect(tenant.Org).To(Equal("")) + Expect(dbError.ErrorCode).To(Equal("UNKNOWN_SCOPE")) + }) }) }) }) var _ = Describe("test getDeveloperInfo()", func() { - Context("get developerInfo for valid tenantId and apikey", func() { - It("should return all right data", func() { - developerInfo := getDeveloperInfo("tenantid", "testapikey") - Expect(developerInfo.ApiProduct).To(Equal("testproduct")) - Expect(developerInfo.Developer).To(Equal("testdeveloper")) - Expect(developerInfo.DeveloperEmail).To(Equal("testdeveloper@test.com")) - Expect(developerInfo.DeveloperApp).To(Equal("testapp")) + Context("with usecaching set to true", func() { + Context("get developerInfo for valid tenantId and apikey", func() { + It("should return all right data", func() { + developerInfo := getDeveloperInfo("tenantid", "testapikey") + Expect(developerInfo.ApiProduct).To(Equal("testproduct")) + Expect(developerInfo.Developer).To(Equal("testdeveloper")) + }) + }) + + Context("get developerInfo for invalid tenantId and apikey", func() { + It("should return all right data", func() { + developerInfo := getDeveloperInfo("wrongid", "wrongapikey") + Expect(developerInfo.ApiProduct).To(Equal("")) + }) }) }) - Context("get developerInfo for invalid tenantId and apikey", func() { - It("should return all right data", func() { - developerInfo := getDeveloperInfo("wrongid", "wrongapikey") - Expect(developerInfo.ApiProduct).To(Equal("")) - Expect(developerInfo.Developer).To(Equal("")) - Expect(developerInfo.DeveloperEmail).To(Equal("")) - Expect(developerInfo.DeveloperApp).To(Equal("")) + Context("with usecaching set to false", func() { + BeforeEach(func() { + config.Set(useCaching, false) + }) + AfterEach(func() { + config.Set(useCaching, true) + }) + Context("get developerInfo for valid tenantId and apikey", func() { + It("should return all right data", func() { + developerInfo := getDeveloperInfo("tenantid", "testapikey") + Expect(developerInfo.ApiProduct).To(Equal("testproduct")) + Expect(developerInfo.Developer).To(Equal("testdeveloper")) + }) + }) + Context("get developerInfo for invalid tenantId and apikey", func() { + It("should return all right data", func() { + developerInfo := getDeveloperInfo("wrongid", "wrongapikey") + Expect(developerInfo.ApiProduct).To(Equal("")) + }) + }) + }) +}) + +var _ = Describe("test getValuesIgnoringNull()", func() { + Context("Null sql value", func() { + It("should return empty string", func() { + a := sql.NullString{String: "null", Valid: false} + res := getValuesIgnoringNull(a) + Expect(res).To(Equal("")) + }) + }) + Context("not null sql value", func() { + It("should return string", func() { + a := sql.NullString{String: "sql", Valid: true} + res := getValuesIgnoringNull(a) + Expect(res).To(Equal("sql")) }) }) })
diff --git a/init_test.go b/init_test.go new file mode 100644 index 0000000..4c3649d --- /dev/null +++ b/init_test.go
@@ -0,0 +1,28 @@ +package apidAnalytics + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "path/filepath" +) + +var _ = Describe("test createDirectories()", func() { + Context("Parent directory exists", func() { + It("should create sub directory", func() { + subDir := filepath.Join(config.GetString("data_path"), "subDir") + directories := []string{subDir} + + err := createDirectories(directories) + Expect(err).NotTo(HaveOccurred()) + }) + }) + Context("Parent directory does not exists", func() { + subDir := filepath.Join("/fakepath", "subDir") + directories := []string{subDir} + + It("sub directory creation should fail", func() { + err := createDirectories(directories) + Expect(err).To(HaveOccurred()) + }) + }) +})
diff --git a/listener_test.go b/listener_test.go new file mode 100644 index 0000000..b792133 --- /dev/null +++ b/listener_test.go
@@ -0,0 +1,140 @@ +package apidAnalytics + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/apigee-labs/transicator/common" +) + +const ( + LISTENER_TABLE_APP_CRED_MAPPER = "kms.app_credential_apiproduct_mapper" + LISTENER_TABLE_DATA_SCOPE = "edgex.data_scope" +) + +var _ = Describe("listener", func() { + Context("Process changeList", func() { + Context(LISTENER_TABLE_DATA_SCOPE, func() { + It("insert/delete event should add/remove to/from cache if usecaching is true", func() { + config.Set(useCaching, true) + txn, err := getDB().Begin() + Expect(err).ShouldNot(HaveOccurred()) + txn.Exec("INSERT INTO DATA_SCOPE (id, _change_selector, apid_cluster_id, scope, org, env) "+ + "VALUES"+ + "($1,$2,$3,$4,$5,$6)", + "i2", + "c2", + "a2", + "s2", + "o2", + "e2", + ) + txn.Commit() + + insert := common.ChangeList{ + LastSequence: "test", + Changes: []common.Change{ + { + Operation: common.Insert, + Table: LISTENER_TABLE_DATA_SCOPE, + NewRow: common.Row{ + "id": &common.ColumnVal{Value: "i2"}, + "_change_selector": &common.ColumnVal{Value: "c2"}, + "apid_cluster_id": &common.ColumnVal{Value: "a2"}, + "scope": &common.ColumnVal{Value: "s2"}, + "org": &common.ColumnVal{Value: "o2"}, + "env": &common.ColumnVal{Value: "e2"}, + "created": &common.ColumnVal{Value: "c2"}, + "created_by": &common.ColumnVal{Value: "c2"}, + "updated": &common.ColumnVal{Value: "u2"}, + "updated_by": &common.ColumnVal{Value: "u2"}, + }, + }, + }, + } + + processChange(&insert) + tenant := tenantCache["i2"] + Expect(tenant.TenantId).To(Equal("s2")) + Expect(tenant.Org).To(Equal("o2")) + Expect(tenant.Env).To(Equal("e2")) + + txn, err = getDB().Begin() + Expect(err).ShouldNot(HaveOccurred()) + txn.Exec("DELETE FROM DATA_SCOPE where id = 'i2'") + txn.Commit() + + delete := common.ChangeList{ + LastSequence: "test", + Changes: []common.Change{ + { + Operation: common.Delete, + Table: LISTENER_TABLE_DATA_SCOPE, + OldRow: insert.Changes[0].NewRow, + }, + }, + } + + processChange(&delete) + _, exists := tenantCache["i2"] + Expect(exists).To(Equal(false)) + + }) + }) + Context(LISTENER_TABLE_APP_CRED_MAPPER, func() { + It("insert/delete event should refresh developer cache if usecaching is true", func() { + config.Set(useCaching, true) + + txn, err := getDB().Begin() + Expect(err).ShouldNot(HaveOccurred()) + txn.Exec("INSERT INTO APP_CREDENTIAL_APIPRODUCT_MAPPER (tenant_id, appcred_id, app_id, apiprdt_id, status, _change_selector) "+ + "VALUES"+ + "($1,$2,$3,$4,$5,$6)", + "tenantid", + "aci", + "ai", + "testproductid", + "APPROVED", + "12345", + ) + + txn.Exec("INSERT INTO APP (id, tenant_id, name, developer_id) "+ + "VALUES"+ + "($1,$2,$3,$4)", + "ai", + "tenantid", + "name", + "testdeveloperid", + ) + txn.Commit() + + insert := common.ChangeList{ + LastSequence: "test", + Changes: []common.Change{ + { + Operation: common.Insert, + Table: LISTENER_TABLE_APP_CRED_MAPPER, + NewRow: common.Row{ + "tenant_id": &common.ColumnVal{Value: "tenantid"}, + "appcred_id": &common.ColumnVal{Value: "aci"}, + "app_id": &common.ColumnVal{Value: "ai"}, + "apiprdt_id": &common.ColumnVal{Value: "api"}, + "status": &common.ColumnVal{Value: "s"}, + "_change_selector": &common.ColumnVal{Value: "c"}, + }, + }, + }, + } + + processChange(&insert) + key := getKeyForDeveloperInfoCache("tenantid", "aci") + developerInfo := developerInfoCache[key] + + Expect(developerInfo.ApiProduct).To(Equal("testproduct")) + Expect(developerInfo.Developer).To(Equal("testdeveloper")) + Expect(developerInfo.DeveloperEmail).To(Equal("testdeveloper@test.com")) + Expect(developerInfo.DeveloperApp).To(Equal("name")) + }) + }) + }) +})