| // Licensed to the Apache Software Foundation (ASF) under one or more | |
| // contributor license agreements. See the NOTICE file distributed with | |
| // this work for additional information regarding copyright ownership. | |
| // The ASF licenses this file to You under the Apache License, Version 2.0 | |
| // (the "License"); you may not use this file except in compliance with | |
| // the License. You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package components | |
| import ( | |
| "context" | |
| "os" | |
| "reflect" | |
| "testing" | |
| "time" | |
| pb "beam.apache.org/playground/backend/internal/api/v1" | |
| "beam.apache.org/playground/backend/internal/cache" | |
| "beam.apache.org/playground/backend/internal/cache/local" | |
| "beam.apache.org/playground/backend/internal/constants" | |
| db "beam.apache.org/playground/backend/internal/db/datastore" | |
| "beam.apache.org/playground/backend/internal/db/entity" | |
| "beam.apache.org/playground/backend/internal/tests/test_cleaner" | |
| "beam.apache.org/playground/backend/internal/utils" | |
| ) | |
| var datastoreDb *db.EmulatedDatastore | |
| var ctx context.Context | |
| var cacheComponent *CacheComponent | |
| var cacheService cache.Cache | |
| var defaultCacheRequestTimeout = 10 * time.Second | |
| func TestMain(m *testing.M) { | |
| setup() | |
| code := m.Run() | |
| teardown() | |
| os.Exit(code) | |
| } | |
| func setup() { | |
| ctx = context.Background() | |
| ctx = context.WithValue(ctx, constants.DatastoreNamespaceKey, "components") | |
| cacheService = local.New(ctx) | |
| var err error | |
| datastoreDb, err = db.NewEmulated(ctx) | |
| if err != nil { | |
| panic(err) | |
| } | |
| cacheComponent = NewService(cacheService, datastoreDb) | |
| } | |
| func teardown() { | |
| clientCloseErr := datastoreDb.Close() | |
| if clientCloseErr != nil { | |
| panic(clientCloseErr) | |
| } | |
| } | |
| func TestCacheComponent_GetSdkCatalogFromCacheOrDatastore(t *testing.T) { | |
| sdks := getSDKs() | |
| tests := []struct { | |
| name string | |
| prepare func() | |
| wantErr bool | |
| }{ | |
| { | |
| name: "Getting sdk catalog from cache in the usual case", | |
| prepare: func() { | |
| _ = cacheService.SetSdkCatalog(ctx, sdks) | |
| }, | |
| wantErr: false, | |
| }, | |
| { | |
| name: "Getting sdk catalog from datastore in the usual case", | |
| prepare: func() { | |
| _ = datastoreDb.PutSDKs(ctx, sdks) | |
| }, | |
| wantErr: false, | |
| }, | |
| } | |
| for _, tt := range tests { | |
| t.Run(tt.name, func(t *testing.T) { | |
| tt.prepare() | |
| result, err := cacheComponent.GetSdkCatalogFromCacheOrDatastore(ctx, defaultCacheRequestTimeout) | |
| if (err != nil) != tt.wantErr { | |
| t.Error("GetSdkCatalogFromCacheOrDatastore() unexpected error") | |
| return | |
| } | |
| if !reflect.DeepEqual(sdks, result) { | |
| t.Error("GetSdkCatalogFromCacheOrDatastore() unexpected result") | |
| } | |
| }) | |
| } | |
| } | |
| func TestCacheComponent_GetCatalogFromCacheOrDatastore(t *testing.T) { | |
| catalog := getCatalog() | |
| tests := []struct { | |
| name string | |
| storeType string | |
| prepare func() | |
| wantErr bool | |
| clean func() | |
| }{ | |
| { | |
| name: "Getting catalog from cache in the usual case", | |
| storeType: "CACHE", | |
| prepare: func() { | |
| _ = cacheService.SetCatalog(ctx, catalog) | |
| }, | |
| wantErr: false, | |
| clean: func() { | |
| _ = cacheService.SetCatalog(ctx, nil) | |
| }, | |
| }, | |
| { | |
| name: "Getting catalog from datastore in the usual case", | |
| storeType: "DB", | |
| prepare: func() { | |
| _ = cacheService.SetSdkCatalog(ctx, getSDKs()) | |
| exampleId := utils.GetIDWithDelimiter(pb.Sdk_SDK_JAVA.String(), "MOCK_EXAMPLE") | |
| saveExample("MOCK_EXAMPLE", pb.Sdk_SDK_JAVA.String()) | |
| saveSnippet(exampleId, pb.Sdk_SDK_JAVA.String()) | |
| savePCObjs(exampleId) | |
| }, | |
| wantErr: false, | |
| clean: func() { | |
| exampleId := utils.GetIDWithDelimiter(pb.Sdk_SDK_JAVA.String(), "MOCK_EXAMPLE") | |
| test_cleaner.CleanPCObjs(ctx, t, exampleId) | |
| test_cleaner.CleanFiles(ctx, t, exampleId, 1) | |
| test_cleaner.CleanSnippet(ctx, t, exampleId) | |
| test_cleaner.CleanExample(ctx, t, exampleId) | |
| }, | |
| }, | |
| } | |
| for _, tt := range tests { | |
| t.Run(tt.name, func(t *testing.T) { | |
| tt.prepare() | |
| result, err := cacheComponent.GetCatalogFromCacheOrDatastore(ctx, defaultCacheRequestTimeout) | |
| if (err != nil) != tt.wantErr { | |
| t.Error("GetCatalogFromCacheOrDatastore() unexpected error") | |
| return | |
| } | |
| switch tt.storeType { | |
| case "CACHE": | |
| if !reflect.DeepEqual(result, catalog) { | |
| t.Error("GetCatalogFromCacheOrDatastore() unexpected result") | |
| } | |
| tt.clean() | |
| case "DB": | |
| if result[0].GetSdk() != pb.Sdk_SDK_JAVA { | |
| t.Error("GetCatalogFromCacheOrDatastore() unexpected result: wrong sdk") | |
| } | |
| actualCatName := result[0].GetCategories()[0].GetCategoryName() | |
| actualPCObj := result[0].GetCategories()[0].GetPrecompiledObjects()[0] | |
| if actualCatName != "MOCK_CATEGORY" { | |
| t.Error("GetCatalogFromCacheOrDatastore() unexpected result: wrong category") | |
| } | |
| if actualPCObj.DefaultExample != false || | |
| actualPCObj.Multifile != false || | |
| actualPCObj.Name != "MOCK_EXAMPLE" || | |
| actualPCObj.Type.String() != "PRECOMPILED_OBJECT_TYPE_EXAMPLE" || | |
| actualPCObj.CloudPath != "SDK_JAVA_MOCK_EXAMPLE" || | |
| actualPCObj.PipelineOptions != "MOCK_OPTIONS" || | |
| actualPCObj.Description != "MOCK_DESCR" || | |
| actualPCObj.Link != "MOCK_PATH" || | |
| actualPCObj.ContextLine != 32 || | |
| actualPCObj.Complexity != pb.Complexity_COMPLEXITY_MEDIUM { | |
| t.Error("GetCatalogFromCacheOrDatastore() unexpected result: wrong precompiled obj") | |
| } | |
| tt.clean() | |
| } | |
| }) | |
| } | |
| } | |
| func TestCacheComponent_GetDefaultPrecompiledObjectFromCacheOrDatastore(t *testing.T) { | |
| pcObj := getPCObj() | |
| tests := []struct { | |
| name string | |
| prepare func() | |
| wantErr bool | |
| }{ | |
| { | |
| name: "Getting default precompiled object from cache in the usual case", | |
| prepare: func() { | |
| _ = cacheService.SetDefaultPrecompiledObject(ctx, pb.Sdk_SDK_JAVA, pcObj) | |
| }, | |
| wantErr: false, | |
| }, | |
| } | |
| for _, tt := range tests { | |
| t.Run(tt.name, func(t *testing.T) { | |
| tt.prepare() | |
| result, err := cacheComponent.GetDefaultPrecompiledObjectFromCacheOrDatastore(ctx, pb.Sdk_SDK_JAVA, defaultCacheRequestTimeout) | |
| if (err != nil) != tt.wantErr { | |
| t.Error("GetDefaultPrecompiledObjectFromCacheOrDatastore() unexpected error") | |
| return | |
| } | |
| if !reflect.DeepEqual(pcObj, result) { | |
| t.Error("GetDefaultPrecompiledObjectFromCacheOrDatastore() unexpected result") | |
| } | |
| }) | |
| } | |
| } | |
| func getSDKs() []*entity.SDKEntity { | |
| var sdkEntities []*entity.SDKEntity | |
| for _, sdk := range pb.Sdk_name { | |
| if sdk == pb.Sdk_SDK_UNSPECIFIED.String() { | |
| continue | |
| } | |
| sdkEntities = append(sdkEntities, &entity.SDKEntity{ | |
| Name: sdk, | |
| DefaultExample: "MOCK_DEFAULT_EXAMPLE", | |
| }) | |
| } | |
| return sdkEntities | |
| } | |
| func getPCObj() *pb.PrecompiledObject { | |
| return &pb.PrecompiledObject{ | |
| CloudPath: "MOCK_PATH", | |
| Name: "MOCK_NAME", | |
| Description: "MOCK_DESCR", | |
| Type: 1, | |
| PipelineOptions: "MOCK_OPTIONS", | |
| Link: "MOCK_LINK", | |
| Multifile: false, | |
| ContextLine: 32, | |
| DefaultExample: true, | |
| } | |
| } | |
| func getCatalog() []*pb.Categories { | |
| return []*pb.Categories{ | |
| { | |
| Sdk: pb.Sdk_SDK_JAVA, | |
| Categories: []*pb.Categories_Category{ | |
| { | |
| CategoryName: "TestCategory", PrecompiledObjects: []*pb.PrecompiledObject{ | |
| { | |
| CloudPath: "SDK_JAVA/TestCategory/TestName.java", | |
| Name: "TestName", | |
| Description: "TestDescription", | |
| Type: pb.PrecompiledObjectType_PRECOMPILED_OBJECT_TYPE_EXAMPLE, | |
| }, | |
| }, | |
| }, | |
| { | |
| CategoryName: "AnotherTestCategory", PrecompiledObjects: []*pb.PrecompiledObject{ | |
| { | |
| CloudPath: "SDK_JAVA/AnotherTestCategory/TestName.java", | |
| Name: "TestName", | |
| Description: "TestDescription", | |
| Type: pb.PrecompiledObjectType_PRECOMPILED_OBJECT_TYPE_EXAMPLE, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| { | |
| Sdk: pb.Sdk_SDK_PYTHON, | |
| Categories: []*pb.Categories_Category{ | |
| { | |
| CategoryName: "TestCategory", PrecompiledObjects: []*pb.PrecompiledObject{ | |
| { | |
| CloudPath: "SDK_PYTHON/TestCategory/TestName.java", | |
| Name: "TestName", | |
| Description: "TestDescription", | |
| Type: pb.PrecompiledObjectType_PRECOMPILED_OBJECT_TYPE_EXAMPLE, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| } | |
| } | |
| func saveExample(name, sdk string) { | |
| _, _ = datastoreDb.Client.Put(ctx, utils.GetExampleKey(ctx, sdk, name), &entity.ExampleEntity{ | |
| Name: name, | |
| Sdk: utils.GetSdkKey(ctx, sdk), | |
| Descr: "MOCK_DESCR", | |
| Cats: []string{"MOCK_CATEGORY"}, | |
| Path: "MOCK_PATH", | |
| UrlVCS: "MOCK_URL_VCS", | |
| UrlNotebook: "MOCK_URL_NOTEBOOK", | |
| Type: pb.PrecompiledObjectType_PRECOMPILED_OBJECT_TYPE_EXAMPLE.String(), | |
| Origin: constants.ExampleOrigin, | |
| SchVer: utils.GetSchemaVerKey(ctx, "MOCK_VERSION"), | |
| }) | |
| } | |
| func saveSnippet(snipId, sdk string) { | |
| _ = datastoreDb.PutSnippet(ctx, snipId, &entity.Snippet{ | |
| IDMeta: &entity.IDMeta{ | |
| Salt: "MOCK_SALT", | |
| IdLength: 11, | |
| }, | |
| Snippet: &entity.SnippetEntity{ | |
| Sdk: utils.GetSdkKey(ctx, sdk), | |
| PipeOpts: "MOCK_OPTIONS", | |
| Origin: constants.ExampleOrigin, | |
| NumberOfFiles: 1, | |
| Complexity: pb.Complexity_COMPLEXITY_MEDIUM.String(), | |
| }, | |
| Files: []*entity.FileEntity{{ | |
| Name: "MOCK_NAME", | |
| Content: "MOCK_CONTENT", | |
| CntxLine: 32, | |
| IsMain: true, | |
| }}, | |
| }) | |
| } | |
| func savePCObjs(exampleId string) { | |
| pcTypes := []string{constants.PCOutputType, constants.PCLogType, constants.PCGraphType} | |
| for _, pcType := range pcTypes { | |
| _, _ = datastoreDb.Client.Put( | |
| ctx, | |
| utils.GetPCObjectKey(ctx, exampleId, pcType), | |
| &entity.PrecompiledObjectEntity{Content: "MOCK_CONTENT_" + pcType}) | |
| } | |
| } |