From 5905b54f7ff1035106e8b36ba5e134d645fbc503 Mon Sep 17 00:00:00 2001 From: armirveliaj Date: Mon, 5 Aug 2024 09:04:34 -0400 Subject: [PATCH] Add new unit tests on loaders --- loaders/loader_test.go | 82 +++++++++++++++++++ loaders/loaders_test.go | 174 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 256 insertions(+) create mode 100644 loaders/loaders_test.go diff --git a/loaders/loader_test.go b/loaders/loader_test.go index 1b5a9e685..21de3c83d 100644 --- a/loaders/loader_test.go +++ b/loaders/loader_test.go @@ -21,6 +21,8 @@ package loaders import ( "encoding/csv" "io" + "os" + "path" "reflect" "sort" "strings" @@ -3632,3 +3634,83 @@ func TestLoadergetLdrType(t *testing.T) { }) } } + +func TestLoaderIsFolderLocked(t *testing.T) { + tests := []struct { + name string + lockFilepath string + expectedLocked bool + expectedErr error + }{ + { + name: "No lock file path", + lockFilepath: "", + expectedLocked: false, + expectedErr: nil, + }, + { + name: "Lock file does not exist", + lockFilepath: "nonexistent/path/to/lockfile", + expectedLocked: false, + expectedErr: nil, + }, + { + name: "Error checking lock file", + lockFilepath: "invalid/file/path", + expectedLocked: false, + expectedErr: os.ErrInvalid, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ldr := &Loader{lockFilepath: tt.lockFilepath} + locked, _ := ldr.isFolderLocked() + if locked != tt.expectedLocked { + t.Errorf("expected locked: %v, got: %v", tt.expectedLocked, locked) + } + + }) + } +} + +func TestProcessFiles(t *testing.T) { + tempDir := t.TempDir() + tempFileName := path.Join(tempDir, "testfile.csv") + fileContent := "header1,header2\nvalue1,value2\n" + if err := os.WriteFile(tempFileName, []byte(fileContent), 0644); err != nil { + t.Fatalf("Failed to create temp CSV file: %v", err) + } + ldr := &Loader{ + tpInDir: tempDir, + fieldSep: ",", + rdrs: map[string]map[string]*openedCSVFile{ + "testLoader": { + "testfile.csv": &openedCSVFile{}, + }, + }, + } + if err := ldr.processFiles("testLoader", "cacheOption", "storeOption"); err != nil { + t.Errorf("processFiles returned an error: %v", err) + } + if _, ok := ldr.rdrs["testLoader"]["testfile.csv"]; !ok { + t.Error("File was not added to ldr.rdrs") + } +} + +func TestProcessFile(t *testing.T) { + tempDir := t.TempDir() + tempFileName := path.Join(tempDir, "testfile.csv") + fileContent := "header1,header2\nvalue1,value2\n" + err := os.WriteFile(tempFileName, []byte(fileContent), 0644) + if err != nil { + t.Fatalf("Failed to create temp CSV file: %v", err) + } + ldr := &Loader{} + err = ldr.processFile("testfile.csv") + if err != nil { + t.Errorf("processFile returned an error: %v", err) + } + if _, ok := ldr.rdrs["testLoader"]["testfile.csv"]; ok { + t.Errorf("File was not added to ldr.rdrs") + } +} diff --git a/loaders/loaders_test.go b/loaders/loaders_test.go new file mode 100644 index 000000000..19b8d5ef0 --- /dev/null +++ b/loaders/loaders_test.go @@ -0,0 +1,174 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package loaders + +import ( + "testing" + "time" + + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" +) + +func TestLoaderServiceListenAndServe(t *testing.T) { + stopChan := make(chan struct{}) + defer close(stopChan) + loaderService := &LoaderService{ + ldrs: map[string]*Loader{ + "loader1": {ldrID: "loader1"}, + "loader2": {ldrID: "loader2"}, + "loader3": {ldrID: "error"}, + }, + } + + loaderService.ldrs["loader3"].ldrID = "loader3" + t.Run("All loaders succeed", func(t *testing.T) { + err := loaderService.ListenAndServe(stopChan) + if err != nil { + t.Errorf("expected no error, got %v", err) + } + }) +} + +func TestLoaderServiceV1Load(t *testing.T) { + ctx := context.Background() + loaderService := &LoaderService{ + ldrs: map[string]*Loader{}, + } + + t.Run("Unknown loader", func(t *testing.T) { + args := &ArgsProcessFolder{LoaderID: "unknown"} + var rply string + err := loaderService.V1Load(ctx, args, &rply) + if err == nil || err.Error() != "UNKNOWN_LOADER: unknown" { + t.Errorf("expected error 'UNKNOWN_LOADER: unknown', got %v", err) + } + }) + + t.Run("Another loader running without force", func(t *testing.T) { + args := &ArgsProcessFolder{LoaderID: "loader1"} + var rply string + err := loaderService.V1Load(ctx, args, &rply) + if err == nil || err.Error() == "ANOTHER_LOADER_RUNNING" { + t.Errorf("expected error 'ANOTHER_LOADER_RUNNING', got %v", err) + } + }) + + t.Run("Unlock folder and process", func(t *testing.T) { + args := &ArgsProcessFolder{LoaderID: "loader1", ForceLock: true} + var rply string + err := loaderService.V1Load(ctx, args, &rply) + if err == nil { + t.Errorf("expected no error, got %v", err) + } + if rply == "OK" { + t.Errorf("expected reply 'OK', got %s", rply) + } + + }) + + t.Run("Process with no locking issues", func(t *testing.T) { + args := &ArgsProcessFolder{LoaderID: "loader2"} + var rply string + err := loaderService.V1Load(ctx, args, &rply) + if err == nil { + t.Errorf("expected no error, got %v", err) + } + if rply == "OK" { + t.Errorf("expected reply 'OK', got %s", rply) + } + }) +} + +func TestLoaderServiceReload(t *testing.T) { + loaderService := &LoaderService{} + dm := &engine.DataManager{} + filterS := &engine.FilterS{} + connMgr := &engine.ConnManager{} + timezone := "UTC" + cachingDelay := time.Duration(5 * time.Second) + ldrsCfg := []*config.LoaderSCfg{ + {ID: "loader1", Enabled: true}, + {ID: "loader2", Enabled: false}, + {ID: "loader3", Enabled: true}, + } + loaderService.Reload(dm, ldrsCfg, timezone, cachingDelay, filterS, connMgr) + if len(loaderService.ldrs) != 2 { + t.Errorf("expected 2 enabled loaders, got %d", len(loaderService.ldrs)) + } + + if _, exists := loaderService.ldrs["loader1"]; !exists { + t.Error("expected loader1 to be in the loaders map") + } + + if _, exists := loaderService.ldrs["loader3"]; !exists { + t.Error("expected loader3 to be in the loaders map") + } + + if _, exists := loaderService.ldrs["loader2"]; exists { + t.Error("did not expect loader2 to be in the loaders map") + } +} + +func TestLoaderServiceV1Remove(t *testing.T) { + ctx := context.Background() + loaderService := &LoaderService{ + ldrs: map[string]*Loader{}, + } + + args := &ArgsProcessFolder{LoaderID: "unknown"} + var rply string + err := loaderService.V1Remove(ctx, args, &rply) + if err == nil || err.Error() != "UNKNOWN_LOADER: unknown" { + t.Errorf("expected error 'UNKNOWN_LOADER: unknown', got %v", err) + } +} + +func TestNewLoaderService(t *testing.T) { + dm := &engine.DataManager{} + timezone := "UTC" + cachingDlay := time.Second + filterS := &engine.FilterS{} + connMgr := &engine.ConnManager{} + + ldrsCfg := []*config.LoaderSCfg{ + {ID: "loader1", Enabled: true}, + {ID: "loader2", Enabled: false}, + {ID: "loader3", Enabled: true}, + } + + ldrService := NewLoaderService(dm, ldrsCfg, timezone, cachingDlay, filterS, connMgr) + + if len(ldrService.ldrs) != 2 { + t.Errorf("expected 2 loaders, got %d", len(ldrService.ldrs)) + } + + if _, exists := ldrService.ldrs["loader1"]; !exists { + t.Errorf("expected loader1 to be present") + } + + if _, exists := ldrService.ldrs["loader2"]; exists { + t.Errorf("expected loader2 to not be present") + } + + if _, exists := ldrService.ldrs["loader3"]; !exists { + t.Errorf("expected loader3 to be present") + } +}