From 93b09eea4001af3e4c523d8b1d6b0e9ccebca585 Mon Sep 17 00:00:00 2001 From: Kyal Lanum <48729516+kyallanum@users.noreply.github.com> Date: Sun, 14 Jan 2024 11:41:15 -0700 Subject: [PATCH] Improve testing (#15) * Added some more table tests, refactored some other tests. Fixed a bug --- cmd/cmd_test.go | 157 ++++++++++------ cmd/root.go | 2 +- models/config/configuration_test.go | 204 ++++++++++++--------- models/config/regex_utils_test.go | 156 +++++++++------- models/config/source_config_test.go | 99 +++++------ models/config/source_file_test.go | 72 ++++++-- models/config/source_web_test.go | 39 ++-- models/library/library.go | 1 + models/library/library_test.go | 237 +++++++++++++++++-------- models/library/operation_count_test.go | 129 ++++++++------ models/library/operation_print_test.go | 134 +++++++++----- models/library/searchtermdata_test.go | 185 +++++++++++++------ 12 files changed, 893 insertions(+), 522 deletions(-) diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index ced4462..787563a 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -1,89 +1,132 @@ package cmd import ( + "fmt" "io" - "os" + "reflect" + "strings" "testing" config "github.com/kyallanum/athena/models/config" + models "github.com/kyallanum/athena/models/library" logs "github.com/kyallanum/athena/models/logs" "github.com/sirupsen/logrus" ) -func TestResolveFile(t *testing.T) { - logger := logrus.New() - logger.SetOutput(io.Discard) - - os.Stdout, _ = os.Open(os.DevNull) - defer os.Stdout.Close() - logFile, _ := logs.LoadLogFile("../examples/apt-term.log") - configuration, _ := config.CreateConfiguration("../examples/apt-term-config.json") - - _, err := resolveLogFile(logFile, configuration, logger) - - if err != nil { - t.Errorf("An error occurred while resolving log file: %s", err) +func checkExpectedError(actualError, expectedError any) bool { + if actualError == nil && expectedError == nil { + return true } -} - -func TestResolveLogFileBadLog(t *testing.T) { - os.Stdout, _ = os.Open(os.DevNull) - defer os.Stdout.Close() - - logFile, _ := logs.LoadLogFile("../examples/apt-term-bad.log") - configuration, _ := config.CreateConfiguration("../examples/apt-term-config.json") - _, err := resolveLogFile(logFile, configuration, nil) - - if err.Error() != "log file contains no contents" { - t.Errorf("Error was not properly returned when checking log file contents") + if actualError != nil { + if expectedError != nil { + if strings.Contains(actualError.(error).Error(), expectedError.(error).Error()) { + return true + } + } } + return false } -func TestResolveLogFileBadConfig(t *testing.T) { +func TestResolveFile(t *testing.T) { logger := logrus.New() logger.SetOutput(io.Discard) - os.Stdout, _ = os.Open(os.DevNull) - defer os.Stdout.Close() - - logFile, _ := logs.LoadLogFile("../examples/apt-term.log") - configuration, _ := config.CreateConfiguration("../examples/apt-term-config-bad.json") - - _, err := resolveLogFile(logFile, configuration, logger) + testTable := []struct { + name string + fileName string + configFile string + expectedReturn *models.Library + expectedLogFileError error + expectedConfigFileError error + expectedResolveError error + }{ + { + name: "Test_Good_Log_And_Configuration_File", + fileName: "../examples/apt-term.log", + configFile: "../examples/apt-term-config.json", + expectedReturn: &models.Library{}, + expectedLogFileError: nil, + expectedConfigFileError: nil, + expectedResolveError: nil, + }, + { + name: "Test_Bad_Log_File", + fileName: "../examples/apt-term-bad.log", + configFile: "../examples/apt-term-config.json", + expectedReturn: nil, + expectedLogFileError: fmt.Errorf("../examples/apt-term-bad.log: no such file or directory"), + expectedConfigFileError: nil, + expectedResolveError: fmt.Errorf("log file contains no contents"), + }, + { + name: "Test_Bad_Config_File", + fileName: "../examples/apt-term.log", + configFile: "../examples/apt-term-config-bad.json", + expectedReturn: nil, + expectedLogFileError: nil, + expectedConfigFileError: fmt.Errorf("../examples/apt-term-config-bad.json: no such file or directory"), + expectedResolveError: fmt.Errorf("configuration file has no contents"), + }, + } - if err.Error() != "configuration file has no contents" { - t.Errorf("Error was not properly returned when checking configuration contents") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + logFile, err := logs.LoadLogFile(test.fileName) + if !checkExpectedError(err, test.expectedLogFileError) { + t.Errorf("Error was incorrectly thrown while loading log file when it shouldn't have: \n\tExpected: %v\n\tReceived: %v", test.expectedLogFileError, err) + } + configFile, err := config.CreateConfiguration(test.configFile) + if !checkExpectedError(err, test.expectedConfigFileError) { + t.Errorf("Error was incorrectly thrown while loading configuration file when it shouldn't have: \n\tExpected: %v\n\tReceived: %v", test.expectedConfigFileError, err) + } + + library, err := resolveLogFile(logFile, configFile, logger) + if !checkExpectedError(err, test.expectedResolveError) { + t.Errorf("Error was incorrectly thrown while resolving log file: \n\tExpected: %v\n\tReceived: %v", test.expectedResolveError, err) + } + + if reflect.TypeOf(library).String() != reflect.TypeOf(test.expectedReturn).String() { + t.Errorf("Log file resolution did not return the proper type: Expected: %v\n\tReceived: %v", reflect.TypeOf(test.expectedReturn).String(), reflect.TypeOf(library).String()) + } + }) } } -func TestResolveLogFileNoConfigName(t *testing.T) { +func TestConfigErrors(t *testing.T) { logger := logrus.New() logger.SetOutput(io.Discard) - logFile, _ := logs.LoadLogFile("../examples/apt-term.log") - configuration := &config.Configuration{ - Rules: make([]config.Rule, 1), - } - - _, err := resolveLogFile(logFile, configuration, logger) - - if err.Error() != "configuration file contains no log name" { - t.Errorf("Error was not properly returned when checking configuration name") + testTable := []struct { + name string + configuration *config.Configuration + expectedError error + }{ + { + name: "Test_No_Config_Name", + configuration: &config.Configuration{ + Rules: make([]config.Rule, 1), + }, + expectedError: fmt.Errorf("configuration file contains no log name"), + }, + { + name: "Test_No_Config_Rules", + configuration: &config.Configuration{ + Name: "test", + }, + expectedError: fmt.Errorf("configuration does not have any rules"), + }, } -} -func TestResolveLogFileNoConfigRules(t *testing.T) { - logger := logrus.New() - logger.SetOutput(io.Discard) + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + logFile, _ := logs.LoadLogFile("../examples/apt-term.log") - logFile, _ := logs.LoadLogFile("../examples/apt-term.log") - configuration := &config.Configuration{ - Name: "test", - } + _, err := resolveLogFile(logFile, test.configuration, logger) - _, err := resolveLogFile(logFile, configuration, logger) - if err.Error() != "configuration does not have any rules" { - t.Errorf("Error was not properly returned when checking configuration rules") + if !checkExpectedError(err, test.expectedError) { + t.Errorf("Error was not properly returned when checking configuration: \n\tExpected: %v\n\tReceived: %v", test.expectedError, err) + } + }) } } diff --git a/cmd/root.go b/cmd/root.go index 6f354a3..37cd645 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -130,7 +130,7 @@ func printSummary(library *library.Library, logger *logrus.Logger) error { logger.Infof("\n--------------- %s Log File Summary ---------------\n", libraryName) libraryKeys := library.LibraryKeys() for _, rule := range libraryKeys { - logger.Infof("Rule: %s\n", rule) + logger.Infof("Rule: %s", rule) ruleData, _ := library.RuleData(rule) summaryDataLen := ruleData.SummaryDataLen() if summaryDataLen == 0 { diff --git a/models/config/configuration_test.go b/models/config/configuration_test.go index 510ad6c..d072d58 100644 --- a/models/config/configuration_test.go +++ b/models/config/configuration_test.go @@ -3,6 +3,7 @@ package models import ( "bufio" "encoding/json" + "fmt" "io" "net/http" "net/http/httptest" @@ -11,29 +12,60 @@ import ( "strings" "testing" + models "github.com/kyallanum/athena/models/library" logs "github.com/kyallanum/athena/models/logs" "github.com/sirupsen/logrus" ) -func TestTranslateRegex(t *testing.T) { - regexToTranslate := "(?)" - err := translateConfigurationNamedGroups(®exToTranslate) - - if err != nil { - t.Errorf("An error occurred while attempting to translate regex: \n\t%v", err) +func checkExpectedError(actualError, expectedError any) bool { + if actualError == nil && expectedError == nil { + return true } - if regexToTranslate != "(?P)" { - t.Errorf("Regex was not translated properly.") + if actualError != nil { + if expectedError != nil { + if strings.Contains(actualError.(error).Error(), expectedError.(error).Error()) { + return true + } + } } + return false } -func TestTranslateRegexEmptyString(t *testing.T) { - regexToTranslate := "" - err := translateConfigurationNamedGroups(®exToTranslate) +func TestTranslateRegex(t *testing.T) { + testTable := []struct { + name string + regex string + expectedOutput string + expectedError error + }{ + { + name: "Test_Good_Regex", + regex: `(?)`, + expectedOutput: `(?P)`, + expectedError: nil, + }, { + name: "Test_Empty_Regex", + regex: "", + expectedOutput: "", + expectedError: fmt.Errorf("empty search terms are not allowed"), + }, + } + + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + regexToTranslate := test.regex + + err := translateConfigurationNamedGroups(®exToTranslate) + + if !checkExpectedError(err, test.expectedError) { + t.Errorf("An error occurred while attempting to translate regex: \n\tExpected: %v\n\tReceived: %v\n\t", test.expectedError, err) + } - if err.Error() != "empty search terms are not allowed" { - t.Errorf("Error was not properly returned when checking for empty string.") + if regexToTranslate != test.expectedOutput { + t.Errorf("Regex was not translated properly \n\tExpected: %v\n\tReceived: %v", test.expectedOutput, regexToTranslate) + } + }) } } @@ -60,29 +92,39 @@ func TestTranslateConfiguration(t *testing.T) { configObject.TranslateConfiguration() } -func TestCreateConfigurationFromFile(t *testing.T) { - config, err := CreateConfiguration("../../examples/apt-term-config.json") - if err != nil { - t.Errorf("Error returned during CreateConfiguration when there shouldn't have.") - } - - if config.Name != "Apt Terminal" { - t.Errorf("Name improperly returned from CreateConfiguration") +func TestCreateConfiguration(t *testing.T) { + testTable := []struct { + name string + source string + expectedOutput *Configuration + expectedError error + }{ + { + name: "Test_From_Good_File", + source: "../../examples/apt-term-config.json", + expectedOutput: &Configuration{}, + expectedError: nil, + }, + { + name: "Test_From_Bad_File", + source: "bad_file_name", + expectedOutput: nil, + expectedError: fmt.Errorf("unable to create configuration object: \n\tunable to get file information for file: bad_file_name. error: stat bad_file_name: no such file or directory"), + }, } - if reflect.TypeOf(config).String() != "*models.Configuration" { - t.Errorf("Improper type returned when running CreateConfiguration") - } -} + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + config, err := CreateConfiguration(test.source) -func TestCreateConfigurationFromFileBadFile(t *testing.T) { - _, err := CreateConfiguration("bad_file_name") - if err == nil { - t.Errorf("Error not returned when it should have after calling CreateConfiguration") - } + if !checkExpectedError(err, test.expectedError) { + t.Errorf("Error was improperly returned from CreateConfiguration: \n\tExpected: %v\n\tReceived: %v", test.expectedError.Error(), err.Error()) + } - if err.Error() != "unable to create configuration object: \n\tunable to get file information for file: bad_file_name. error: stat bad_file_name: no such file or directory" { - t.Errorf("Error improperly returned when it should have. \nError: %s", err.Error()) + if reflect.TypeOf(config).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Improper type returned from CreateConfiguration: \n\tExpected: %v\n\tReceived: %v", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(config).String()) + } + }) } } @@ -97,10 +139,10 @@ func TestCreateConfigurationFromWeb(t *testing.T) { } testTable := []struct { - name string - server *httptest.Server - expectedOutputType string - expectedErr string + name string + server *httptest.Server + expectedOutput *Configuration + expectedError error }{ { name: "good-test-create-web-config", @@ -108,34 +150,31 @@ func TestCreateConfigurationFromWeb(t *testing.T) { w.WriteHeader(http.StatusOK) w.Write(configFileBytes) })), - expectedOutputType: "*models.Configuration", - expectedErr: "", + expectedOutput: &Configuration{}, + expectedError: nil, }, { name: "bad-test-create-web-config-404", server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) })), - expectedOutputType: "*models.Configuration", - expectedErr: "received status code 404 when attempting to get file", + expectedOutput: &Configuration{}, + expectedError: fmt.Errorf("received status code 404 when attempting to get file"), }, } - for _, testServer := range testTable { - t.Run(testServer.name, func(t *testing.T) { - defer testServer.server.Close() - testWebSource, err := CreateConfiguration(testServer.server.URL) + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + defer test.server.Close() + testWebSource, err := CreateConfiguration(test.server.URL) - if reflect.TypeOf(testWebSource).String() != testServer.expectedOutputType { - t.Errorf("Create Configuration returned the wrong output type for web configuration") + if reflect.TypeOf(testWebSource).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Create Configuration returned the wrong output type for web configuration: \n\tExpected: %v\n\tReceived: %v", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(testWebSource).String()) } - if (err != nil) && (testServer.expectedErr != "") { - if !strings.Contains(err.Error(), testServer.expectedErr) { - t.Errorf("Create Configuration returned an improper error when using incorrect web URL") - } + if !checkExpectedError(err, test.expectedError) { + t.Errorf("Create Configuration returned an improper error when using incorrect web URL: \n\tExpected: %v\n\tReceived: %v", test.expectedError.Error(), err.Error()) } - }) } } @@ -144,43 +183,42 @@ func TestResolveRule(t *testing.T) { logger := logrus.New() logger.SetOutput(io.Discard) - os.Stdout, _ = os.Open(os.DevNull) - defer os.Stdout.Close() - logFile, _ := logs.LoadLogFile("../../examples/apt-term.log") - currentConfig, _ := CreateConfiguration("../../examples/apt-term-config.json") - currentRule := currentConfig.Rules[0] - - ruleData, err := ResolveRule(logFile, ¤tRule, logger) - if err != nil { - t.Errorf("An error was returned when one should not have been: \n\t%s", err.Error()) - } - - if reflect.TypeOf(ruleData).String() != "*models.RuleData" { - t.Errorf("The incorrect datatype was not returned: \n\t%s", reflect.TypeOf(ruleData).String()) + testTable := []struct { + name string + currentRule *Rule + expectedOutput *models.RuleData + expectedError error + }{ + { + name: "Test_Good_Rule", + currentRule: ¤tConfig.Rules[0], + expectedOutput: &models.RuleData{}, + expectedError: nil, + }, + { + name: "Test_Bad_Rule", + currentRule: &Rule{}, + expectedOutput: nil, + expectedError: fmt.Errorf("unable to resolve search terms for rule : \n\truntime error: index out of range [0] with length 0"), + }, } -} - -func TestResolveRuleBadRule(t *testing.T) { - defer func() { - if err := recover(); err == nil { - t.Errorf("An error was not returned when one should have been.") - } else if (err.(error)).Error() != "unable to resolve search terms for rule : \n\truntime error: index out of range [0] with length 0" { - t.Errorf("%s", err.(error).Error()) - } - }() - - logger := logrus.New() - logger.SetOutput(io.Discard) - os.Stdout, _ = os.Open(os.DevNull) - defer os.Stdout.Close() - - logFile, _ := logs.LoadLogFile("../examples/apt-term.log") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + defer func() { + if err := recover(); !checkExpectedError(err, test.expectedError) { + t.Errorf("The expected error was not returned: \n\tExpected: %v\n\tReceived: %v", test.expectedError.Error(), err.(error).Error()) + } + }() - currentRule := &Rule{} + ruleData, _ := ResolveRule(logFile, test.currentRule, logger) - ResolveRule(logFile, currentRule, logger) + if reflect.TypeOf(ruleData).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("The incorrect datatype was not returned: \n\tExpected: %v\n\tReceived: %v", reflect.TypeOf(test.currentRule).String(), reflect.TypeOf(ruleData).String()) + } + }) + } } diff --git a/models/config/regex_utils_test.go b/models/config/regex_utils_test.go index e3fc7b0..1679005 100644 --- a/models/config/regex_utils_test.go +++ b/models/config/regex_utils_test.go @@ -1,88 +1,112 @@ package models import ( + "fmt" "reflect" "testing" library "github.com/kyallanum/athena/models/library" ) -func TestResolveLine(t *testing.T) { - defer func() { - if err := recover(); err != nil { - t.Errorf("An error was returned improperly when calling resolveLine: \n\t%s", (err.(error)).Error()) - } - }() - line := "test line 1" - regex := "stuff" - - result := resolveLine(line, regex) - if result != nil { - t.Errorf("An incorrect object was returned when calling resolveLine") - } - - regex = `(?Pline \d+)` - result = resolveLine(line, regex) - - if reflect.TypeOf(result).String() != "*map[string]string" { - t.Errorf("resolveLine did not return the proper data type: \n\t%s", reflect.TypeOf(result).String()) - } -} - -func TestResolveLineBadRegex(t *testing.T) { - defer func() { - if err := recover(); err == nil { - t.Errorf("An error was not returned properly when it should have") - } else if (err.(error)).Error() != "the provided regular expression cannot be compiled: \n\tregexp: Compile(`(stuff`): error parsing regexp: missing closing ): `(stuff`" { - t.Errorf("The improper error was returned when calling with a bad regex: \n\t%s", (err.(error)).Error()) - } - }() - - line := "test line 1" - regex := "(stuff" - - _ = resolveLine(line, regex) +func createSearchTermTestData(reference, replace string) *library.SearchTermData { + st_data := library.NewSearchTermData() + st_data.AddValue(reference, replace) + return st_data } -func TestTranslateSearchTermReference(t *testing.T) { - defer func() { - if err := recover(); err != nil { - t.Errorf("An error was returned when it shouldn't have: \n\t%s", (err.(error).Error())) - } - }() +func TestResolveLine(t *testing.T) { + testTable := []struct { + name string + line string + regex string + expectedOutput *map[string]string + expectedError any + }{ + { + name: "Test_Good_Regex_No_Match", + line: "test line 1", + regex: "stuff", + expectedOutput: nil, + expectedError: nil, + }, + { + name: "Test_Good_Regex_With_Match", + line: "test line 1", + regex: `(?Pline \d+)`, + expectedOutput: &map[string]string{}, + expectedError: nil, + }, + { + name: "Test_Bad_Regex", + line: "test line 1", + regex: `(stuff`, + expectedOutput: nil, + expectedError: fmt.Errorf("the provided regular expression cannot be compiled: \n\tregexp: Compile(`(stuff`): error parsing regexp: missing closing ): `(stuff`"), + }, + } - regex := `Testing {{test}}` - st_data := library.NewSearchTermData() - st_data.AddValue("test", "Test1") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + defer func() { + if err := recover(); !checkExpectedError(err, test.expectedError) { + t.Errorf("An error was returned improperly when calling resolveLine: \n\tExpected: %s\n\tReceived: %s", test.expectedError.(error).Error(), err.(error).Error()) + } + }() - newRegex, err := translateSearchTermReference(regex, st_data) - if err != nil { - t.Errorf("An error was returned when it shouldn't have: \n\t%s", err.Error()) - } + result := resolveLine(test.line, test.regex) - if newRegex != "Testing Test1" { - t.Errorf("TranslateSearchTermReference returned the wrong value: \n\t%s", newRegex) + if reflect.TypeOf(result).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("resolveLine returned unexpected output type: \n\tExpected: %s\n\tReceived: %s", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(test.expectedError).String()) + } + }) } } -func TestTranslateSearchTermReferenceBadReference(t *testing.T) { - defer func() { - if err := recover(); err != nil { - t.Errorf("An error was returned when it shouldn't have: \n\t%s", (err.(error).Error())) - } - }() - - regex := `Testing {{test}}` - st_data := library.NewSearchTermData() - st_data.AddValue("bad_test", "testing") - - _, err := translateSearchTermReference(regex, st_data) - if err == nil { - t.Errorf("An error was not returned when it should have.") +func TestTranslateSearchTermReference(t *testing.T) { + testTable := []struct { + name string + regex string + st_data *library.SearchTermData + expectedOutput string + expectedError error + }{ + { + name: "Test_Good_Search_Term", + regex: `Testing {{test}}`, + st_data: createSearchTermTestData("test", "test1"), + expectedOutput: "Testing test1", + expectedError: nil, + }, + { + name: "Test_Bad_Search_Term", + regex: `Testing {{test}}`, + st_data: createSearchTermTestData("bad_test", "test"), + expectedOutput: "", + expectedError: fmt.Errorf("an error occurred when translating a search term reference. \n\tthe following key was not registered in a previous search term: test"), + }, } - if err.Error() != "an error occurred when translating a search term reference. \n\tthe following key was not registered in a previous search term: test" { - t.Errorf("An improper error was returned when attempting to translate search term reference: \n\t%s", err.Error()) + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + defer func() { + if err := recover(); !checkExpectedError(err, test.expectedError) { + t.Errorf("An incorrect error was returned: \n\tExpected: %s\n\tReceived: %s", test.expectedError.Error(), err.(error).Error()) + } + }() + + newRegex, err := translateSearchTermReference(test.regex, test.st_data) + if err != nil { + panic(err) + } + + if reflect.TypeOf(newRegex).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("TranslateSearchTermReference did not output the correct data type: \n\tExpected: %s\n\tReceived: %s", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(newRegex).String()) + } + + if newRegex != test.expectedOutput { + t.Errorf("TranslateSearchTermReference did not output the correct result: \n\tExpected: %s\n\tReceived: %s", test.expectedOutput, newRegex) + } + }) } } diff --git a/models/config/source_config_test.go b/models/config/source_config_test.go index 5e7f5a2..86a5b77 100644 --- a/models/config/source_config_test.go +++ b/models/config/source_config_test.go @@ -6,57 +6,52 @@ import ( "testing" ) -func TestGetSourceFile(t *testing.T) { - source := "../../examples/apt-term-config.json" - - configSource, err := Source(source) - fmt.Println(reflect.TypeOf(configSource).String()) - if err != nil { - t.Errorf("Error returned from getSource when it shouldn't have: \n\t%s", err.Error()) - } - - if reflect.TypeOf(configSource).String() != "*models.FileSource" { - t.Errorf("Correct data type not returned from GetSource") - } -} - -func TestGetSourceFileBadFile(t *testing.T) { - source := "../../examples/apt-term.json" - - _, err := Source(source) - - if err == nil { - t.Errorf("No error was returned when one should have been.") - } - - if err.Error() != "unable to get file information for file: ../../examples/apt-term.json. error: stat ../../examples/apt-term.json: no such file or directory" { - t.Errorf("Incorrect error returned when attempting to stat a non-existant file.") - } -} - -func TestGetSourceWeb(t *testing.T) { - source := "http://example.org" - - configWeb, err := Source(source) - if err != nil { - t.Errorf("Error returned from getSource when it shouldn't have: \n\t%s", err.Error()) - } - - if reflect.TypeOf(configWeb).String() != "*models.WebSource" { - t.Errorf("Correct data type not returned from GetSource: \n\t%s", reflect.TypeOf(configWeb).String()) - } -} - -func TestGetSourceWebBadAddress(t *testing.T) { - source := "http://192.168.0.1/index.html" - - _, err := Source(source) - - if err == nil { - t.Errorf("Error not returned from getSource when one should have") - } - - if err.Error() != "url provided is not reachable. please check the URL and try again" { - t.Errorf("Error not returned properly from getSource when one should have: \n\t%s", err.Error()) +func TestGetSource(t *testing.T) { + testTable := []struct { + name string + source string + expectedOutput IConfigurationSource + expectedError error + }{ + { + name: "Test_Good_Source_File", + source: "../../examples/apt-term-config.json", + expectedOutput: &FileSource{}, + expectedError: nil, + }, + { + name: "Test_Bad_Source_File", + source: "../../examples/apt-term-bad.json", + expectedOutput: nil, + expectedError: fmt.Errorf("unable to get file information for file: ../../examples/apt-term-bad.json. error: stat ../../examples/apt-term-bad.json: no such file or directory"), + }, + { + name: "Test_Good_Web_Source", + source: "https://raw.githubusercontent.com/kyallanum/athena/main/examples/apt-term-config.json", + expectedOutput: &WebSource{}, + expectedError: nil, + }, + { + name: "Test_Bad_Web_Source", + source: "http://192.168.0.1", + expectedOutput: nil, + expectedError: fmt.Errorf("url provided is not reachable. please check the URL and try again"), + }, + } + + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + configSource, err := Source(test.source) + + if !checkExpectedError(err, test.expectedError) { + t.Errorf("Error immproperly returned from Source function: \n\tExpected: %s\n\tReceived: %s", test.expectedError.Error(), err.Error()) + } + + if configSource != test.expectedOutput { + if reflect.TypeOf(configSource).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Object returned is not of the right type: \n\tExpected: %s\n\tReceived: %s", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(test.expectedOutput).String()) + } + } + }) } } diff --git a/models/config/source_file_test.go b/models/config/source_file_test.go index c0a861c..f483c3d 100644 --- a/models/config/source_file_test.go +++ b/models/config/source_file_test.go @@ -1,37 +1,73 @@ package models import ( - "fmt" "reflect" "testing" ) -func TestNewFileConfig(t *testing.T) { - source := "./examples/apt-term-config.json" +func TestNewConfigFile(t *testing.T) { + testTable := []struct { + name string + source string + expectedOutput IConfigurationSource + expectedError error + }{ + { + name: "Test_New_File_Config", + source: "../../examples/apt-term-config.json", + expectedOutput: &FileSource{ + ConfigurationSource: ConfigurationSource{ + source_type: "file", + source: "", + }, + }, + expectedError: nil, + }, + } - fileSource := NewFileSource(source) + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + fileSource := NewFileSource(test.source) - if fileSource.SourceType() != "file" { - t.Errorf("Configuration source type not set properly") - } + if fileSource.SourceType() != test.expectedOutput.SourceType() { + t.Errorf("Source Type was not set properly. \n\tExpected: %s\n\tReceived: %s", test.expectedOutput.SourceType(), fileSource.SourceType()) + } - if reflect.TypeOf(fileSource).String() != "*models.FileSource" { - t.Errorf("Configuration source not of the right type") + if reflect.TypeOf(fileSource).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Configuration source not of the right type. \n\tExpected: %s\n\tReceived: %s", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(fileSource).String()) + } + }) } } func TestLoadFileConfig(t *testing.T) { - source := "../../examples/apt-term-config.json" - fileSource := NewFileSource(source) - - fileConfig, err := fileSource.Config() - if err != nil { - t.Errorf("Configuration Load created an error:\n\t%v", err) + testTable := []struct { + name string + source string + expectedOutput []byte + expectedError error + }{ + { + name: "Test_Bad_String", + source: "../../examples/apt-term-config.json", + expectedOutput: []byte{}, + expectedError: nil, + }, } - fmt.Printf("t: %v", reflect.TypeOf(fileConfig)) + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + fileSource := NewFileSource(test.source) + + fileConfig, err := fileSource.Config() + + if !checkExpectedError(err, test.expectedError) { + t.Errorf("Configuration Load created an unexpected error: \n\tExpected: %s\n\tReceived: %s", test.expectedError.Error(), err.Error()) + } - if reflect.TypeOf(fileConfig).String() != "[]uint8" { - t.Errorf("LoadConfig did not return the correct type") + if reflect.TypeOf(fileConfig).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Configuration Load returned the wrong object type: \n\tExpected: %s\n\tReceived: %s", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(fileConfig).String()) + } + }) } } diff --git a/models/config/source_web_test.go b/models/config/source_web_test.go index 810c7cf..3fc2101 100644 --- a/models/config/source_web_test.go +++ b/models/config/source_web_test.go @@ -5,7 +5,6 @@ import ( "net/http" "net/http/httptest" "reflect" - "strings" "testing" ) @@ -27,14 +26,16 @@ func TestNewWebSource(t *testing.T) { } for _, testServer := range testTable { - testWebSource := NewWebSource(testServer.server.URL) - if testWebSource.SourceType() != "web" { - t.Errorf("Config source type not set properly.") - } + t.Run(testServer.name, func(t *testing.T) { + testWebSource := NewWebSource(testServer.server.URL) + if testWebSource.SourceType() != "web" { + t.Errorf("Config source type not set properly.") + } - if reflect.TypeOf(testWebSource).String() != "*models.WebSource" { - t.Errorf("Config source not of the right type.") - } + if reflect.TypeOf(testWebSource).String() != "*models.WebSource" { + t.Errorf("Config source not of the right type.") + } + }) } } @@ -68,28 +69,22 @@ func TestLoadWebConfig(t *testing.T) { }, } - for _, testServer := range testTable { - t.Run(testServer.name, func(t *testing.T) { - defer testServer.server.Close() - testWebSource := NewWebSource(testServer.server.URL) + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + defer test.server.Close() + testWebSource := NewWebSource(test.server.URL) configFileString, err := testWebSource.Config() - if reflect.TypeOf(configFileString).String() != reflect.TypeOf(testServer.expectedOutput).String() { + if reflect.TypeOf(configFileString).String() != reflect.TypeOf(test.expectedOutput).String() { t.Errorf("LoadConfig does not return the correct type.") } - if !reflect.DeepEqual(configFileString, testServer.expectedOutput) { + if !reflect.DeepEqual(configFileString, test.expectedOutput) { t.Errorf("LoadConfig did not output the expected data.") } - if !(err == nil && testServer.expectedErr == nil) { - if reflect.TypeOf(err.Error()).String() != reflect.TypeOf(testServer.expectedErr.Error()).String() { - t.Errorf("Error not of the same type as expected error.") - } - } - - if err != nil && !strings.Contains(err.Error(), testServer.expectedErr.Error()) { - t.Errorf("Error improperly created when loading config.") + if !checkExpectedError(err, test.expectedErr) { + t.Errorf("Error returned improperly: \n\tExpected: %s\n\tReceived: %s", test.expectedErr.Error(), err.Error()) } }) diff --git a/models/library/library.go b/models/library/library.go index e2c8b44..eff7a05 100644 --- a/models/library/library.go +++ b/models/library/library.go @@ -34,6 +34,7 @@ func (library *Library) LibraryKeys() (rule_data_keys []string) { rule_data_index := 0 for key := range library.rule_data_collection { rule_data_keys[rule_data_index] = key + rule_data_index++ } return rule_data_keys diff --git a/models/library/library_test.go b/models/library/library_test.go index 994e66d..1e20e82 100644 --- a/models/library/library_test.go +++ b/models/library/library_test.go @@ -1,110 +1,199 @@ package models import ( + "fmt" "reflect" + "sort" + "strings" "testing" ) -func TestLibraryGetName(t *testing.T) { - current_library := New("test_stuff") - library_name, err := current_library.Name() - if err != nil { - t.Errorf("an error occurred when getting name for library") +func checkExpectedError(actualError, expectedError any) bool { + if actualError == nil && expectedError == nil { + return true } - if library_name != "test_stuff" { - t.Errorf("library name returned improperly") + if actualError != nil { + if expectedError != nil { + if strings.Contains(actualError.(error).Error(), expectedError.(error).Error()) { + return true + } + } } + return false } -func TestLibraryGetNameNoName(t *testing.T) { - current_library := New("") - _, err := current_library.Name() - - if err == nil { - t.Errorf("Error not returned when Library name is nil") +func TestLibraryGetName(t *testing.T) { + testTable := []struct { + name string + library_name string + expectedOutput string + expectedError error + }{ + { + name: "Test_Library_With_Name", + library_name: "test_library", + expectedOutput: "test_library", + expectedError: nil, + }, + { + name: "Test_Library_No_Name", + library_name: "", + expectedOutput: "", + expectedError: fmt.Errorf("Library does not have a name assigned"), + }, } - if err.Error() != "Library does not have a name assigned" { - t.Errorf("Error not returned properly when Library name is nil") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + current_library := New(test.library_name) + current_library_name, err := current_library.Name() + + if !checkExpectedError(err, test.expectedError) { + t.Errorf("An unexpected error occurred when getting the name for the Library: \n\tExpected: %v\n\tReceived: %v", test.expectedError.Error(), err.Error()) + } + + if current_library_name != test.expectedOutput { + t.Errorf("Library name was not returned properly: \n\tExpected: %v\n\tReceived: %v", test.expectedOutput, current_library_name) + } + }) } } func TestGetLibraryKeys(t *testing.T) { - ruleData1 := NewRuleData() - ruleData2 := NewRuleData() - - library := New("test_library") - library.AddRuleData("ruleData1", &ruleData1) - library.AddRuleData("ruleData2", &ruleData2) - - libraryKeys := library.LibraryKeys() - - if len(libraryKeys) != 2 { - t.Errorf("Library did not return the correct number of keys") + testTable := []struct { + name string + library *Library + expectedOutput []string + expectedError error + }{ + { + name: "Test_No_Keys", + library: New("test_library_no_keys"), + expectedOutput: nil, + }, + { + name: "Test_With_Keys", + library: &Library{ + name: "test_library_with_keys", + rule_data_collection: map[string]RuleData{ + "ruleData1": NewRuleData(), + "ruleData2": NewRuleData(), + }, + }, + expectedOutput: []string{"ruleData1", "ruleData2"}, + }, } - if reflect.TypeOf(libraryKeys).String() != "[]string" { - t.Errorf("Library did not return the correct datatype") - } -} + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + libraryKeys := test.library.LibraryKeys() -func TestGetLibraryKeysNoKeys(t *testing.T) { - library := New("testing") + sort.Strings(libraryKeys) + sort.Strings(test.expectedOutput) - libraryKeys := library.LibraryKeys() + if !reflect.DeepEqual(libraryKeys, test.expectedOutput) { - if libraryKeys != nil { - t.Errorf("Returned the incorrect value when there are no library keys") + t.Errorf("Unexpected return from getting library keys: \n\tExpected: %v\n\tReceived: %v", libraryKeys, test.expectedOutput) + } + }) } } func TestGetRuleData(t *testing.T) { - ruleData1 := NewRuleData() - - library := New("testing") - library.AddRuleData("ruleData1", &ruleData1) - - newRuleData, err := library.RuleData("ruleData1") - if err != nil { - t.Errorf("Library did not return any rule data when it should have") + testTable := []struct { + name string + ruleToExtract string + library *Library + expectedOutput RuleData + expectedError error + }{ + { + name: "Test_Get_Good_Rule_Data", + ruleToExtract: "ruleData1", + library: &Library{ + name: "testing", + rule_data_collection: map[string]RuleData{ + "ruleData1": NewRuleData(), + }, + }, + expectedOutput: RuleData{}, + expectedError: nil, + }, + { + name: "Test_Get_Rule_Data_No_Keys", + ruleToExtract: "badRuleData", + library: &Library{ + name: "testing", + rule_data_collection: map[string]RuleData{}, + }, + expectedOutput: RuleData{}, + expectedError: fmt.Errorf("could not find key: badRuleData in library"), + }, } - if reflect.TypeOf(newRuleData).String() != "models.RuleData" { - t.Errorf("Library did not return the proper object") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + newRuleData, err := test.library.RuleData(test.ruleToExtract) + if !checkExpectedError(err, test.expectedError) { + t.Errorf("Library did not return the right error data: \n\tExpected: %v\n\tReceived: %v", test.expectedError, err) + } + + if reflect.TypeOf(newRuleData).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Library did not return the proper data type: \n\tExpected: %v\n\tReceived: %v", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(newRuleData).String()) + } + }) } } -func TestGetRuleDataNoKeys(t *testing.T) { - library := New("testing") - - _, err := library.RuleData("testingData") - - if err.Error() != "could not find key: testingData in library" { - t.Errorf("Error improperly returned when testing getRuleData without a proper key") +func TestAddRuleDatas(t *testing.T) { + testTable := []struct { + name string + library *Library + keysToAdd []string + rulesToAdd []RuleData + expectedError error + }{ + { + name: "Add_Good_Rule_Data", + library: &Library{ + name: "test_library", + rule_data_collection: map[string]RuleData{}, + }, + keysToAdd: []string{"ruleData1"}, + rulesToAdd: []RuleData{ + NewRuleData(), + }, + expectedError: nil, + }, + { + name: "Add_Rule_Data_Overwrite", + library: &Library{ + name: "test_library", + rule_data_collection: map[string]RuleData{}, + }, + keysToAdd: []string{"ruleData1", "ruleData1"}, + rulesToAdd: []RuleData{ + NewRuleData(), + NewRuleData(), + }, + expectedError: fmt.Errorf("could not set ruledata for key: ruleData1 - data is readonly"), + }, } -} - -func TestAddRuleData(t *testing.T) { - ruleData1 := NewRuleData() - - library := New("testing") - err := library.AddRuleData("ruleData1", &ruleData1) - - if err != nil { - t.Errorf("Adding rule data returned an error when it shouldn't have") - } -} - -func TestAddRuleDataOverwrite(t *testing.T) { - ruleData1 := NewRuleData() - ruleData2 := NewRuleData() - - library := New("testing") - library.AddRuleData("ruleData1", &ruleData1) - err := library.AddRuleData("ruleData1", &ruleData2) - if err.Error() != "could not set ruledata for key: ruleData1 - data is readonly" { - t.Errorf("Error improperly returned when overwriting data") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + var err error + for index, keyToAdd := range test.keysToAdd { + err = test.library.AddRuleData(keyToAdd, &test.rulesToAdd[index]) + if err != nil { + break + } + } + + if !checkExpectedError(err, test.expectedError) { + t.Errorf("AddRuleData returned an unexpected error: \n\tExpected: %v\n\tReceived: %v", test.expectedError.Error(), err.Error()) + } + }) } } diff --git a/models/library/operation_count_test.go b/models/library/operation_count_test.go index a57f1d0..cd3a835 100644 --- a/models/library/operation_count_test.go +++ b/models/library/operation_count_test.go @@ -1,70 +1,99 @@ package models import ( + "fmt" "reflect" "testing" ) -func TestCreateNewCount(t *testing.T) { - testCountOperation := NewCountOperation("test") - - if testCountOperation.Operation() != "count" { - t.Errorf("Operation type is not correct for count.") - } - - if reflect.TypeOf(testCountOperation).String() != "*models.Count" { - t.Errorf("Creating new operation did not return the appropriate type.") +func TestCreateNewCounts(t *testing.T) { + testTable := []struct { + name string + key string + expectedOutput ISummaryOperation + }{ + { + name: "Test_New_Count", + key: "test", + expectedOutput: &Count{ + SummaryOperation{ + operation: "count", + }, + }, + }, } -} - -func TestCountCalculateOperation(t *testing.T) { - st_data1 := NewSearchTermData() - st_data1.AddValue("test", "testing 1") - - st_data2 := NewSearchTermData() - st_data2.AddValue("test", "testing 2") - - testRuleData := NewRuleData() - testRuleData.AppendSearchTermData(st_data1) - testRuleData.AppendSearchTermData(st_data2) - testCountOperation := NewCountOperation("test") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + testCountOperation := NewCountOperation(test.key) - numTests, err := testCountOperation.CalculateOperation(testRuleData) + if testCountOperation.Operation() != test.expectedOutput.Operation() { + t.Errorf("Operation did not return properly: Expected: %s\n\tReceived: %s\n\t", test.expectedOutput.Operation(), testCountOperation.Operation()) + } - if err != nil { - t.Errorf("An error occurred when calculating for operation: count %v", err) - } - - if numTests[0] != "2" { - t.Errorf("An issue occurred when calculating for operation: count") - } - - if reflect.TypeOf(numTests).String() != "[]string" { - t.Errorf("Calculate Operation returned the wrong value type") + if reflect.TypeOf(testCountOperation).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Operation did not return the correct data type: Expected: %s\n\tReceived: %s\n\t", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(testCountOperation).String()) + } + }) } } -func TestCountCalculateOperationEmptyRuleData(t *testing.T) { - testRuleData := NewRuleData() - testCountOperation := NewCountOperation("test") - _, err := testCountOperation.CalculateOperation(testRuleData) - - if err.Error() != "rule does not have any search term data stored" { - t.Errorf("Error not returned properly for empty RuleData") +func TestCountCalculateOperations(t *testing.T) { + testTable := []struct { + name string + ruleData RuleData + expectedOutput []string + expectedError error + }{ + { + name: "Test_Count_Good_Data", + ruleData: RuleData{ + st_data_collection: []SearchTermData{ + { + data: map[string]string{ + "test": "testing 1", + }, + }, + { + data: map[string]string{ + "test": "testing 2", + }, + }, + }, + }, + expectedOutput: []string{"2"}, + expectedError: nil, + }, + { + name: "Test_Count_No_RuleData", + ruleData: RuleData{ + st_data_collection: []SearchTermData{ + { + data: map[string]string{}, + }, + }, + }, + expectedOutput: nil, + expectedError: fmt.Errorf("this value was never extracted during search phase"), + }, } -} -func TestCountCalculateOperationSearchTermNotExist(t *testing.T) { - st_data1 := NewSearchTermData() - st_data1.AddValue("bad_test", "testing") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + testCountOperation := NewCountOperation("test") + numReturned, err := testCountOperation.CalculateOperation(test.ruleData) + + if !checkExpectedError(err, test.expectedError) { + t.Errorf("An error occurred when calculating operation: Count\n\tExpected: %v, Received: %v", err, test.expectedError) + } - testRuleData := NewRuleData() - testRuleData.AppendSearchTermData(st_data1) + if reflect.TypeOf(numReturned).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("The calculation did not return the proper datatype: \n\tExpected: %s, Received: %s", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(numReturned).String()) + } - testCountOperation := NewCountOperation("test") - _, err := testCountOperation.CalculateOperation(testRuleData) - if err.Error() != "this value was never extracted during search phase" { - t.Errorf("Error not returned properly for search term data that was never created") + if !reflect.DeepEqual(numReturned, test.expectedOutput) { + t.Errorf("Count did not return the expected value: \n\tExpected: %s\n\tReceived: %s", numReturned[0], test.expectedOutput[0]) + } + }) } } diff --git a/models/library/operation_print_test.go b/models/library/operation_print_test.go index 33126ff..cc1afad 100644 --- a/models/library/operation_print_test.go +++ b/models/library/operation_print_test.go @@ -1,69 +1,111 @@ package models import ( + "fmt" "reflect" + "sort" "testing" ) func TestCreateNewPrint(t *testing.T) { - testPrint := NewPrintOperation("testing") - - if testPrint.Operation() != "print" { - t.Errorf("Returned object does not have the right operation") + testTable := []struct { + name string + key string + expectedOutput ISummaryOperation + }{ + { + name: "Test_Create_New_Print_Operation", + key: "testing", + expectedOutput: &Print{ + SummaryOperation: SummaryOperation{ + operation: "print", + key: "testing", + }, + }, + }, } - if reflect.TypeOf(testPrint).String() != "*models.Print" { - t.Errorf("Returned object not of the correct type") - } -} + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + testPrint := NewPrintOperation(test.key) -func TestPrintCalculateOperation(t *testing.T) { - st_data1 := NewSearchTermData() - st_data1.AddValue("testing", "test 1") + if testPrint.Operation() != test.expectedOutput.Operation() { + t.Errorf("Creating new Operation object returned improper operation: \n\tExpected: %s\n\tReceived: %s", test.expectedOutput.Operation(), testPrint.Operation()) + } - st_data2 := NewSearchTermData() - st_data2.AddValue("testing", "test 2") - - testRuleData := NewRuleData() - testRuleData.AppendSearchTermData(st_data1) - testRuleData.AppendSearchTermData(st_data2) - - testOperation := NewPrintOperation("testing") - printOutput, err := testOperation.CalculateOperation(testRuleData) - if err != nil { - t.Errorf("An error occurred when attempting to resolve lines to print: \n\t%s", err.Error()) - } + if testPrint.Key() != test.expectedOutput.Key() { + t.Errorf("Creating new Operation object does not assign the proper key: \n\tExpected: %s\n\tReceived: %s", test.expectedOutput.Key(), testPrint.Key()) + } - if len(printOutput) != 2 { - t.Errorf("Returned incorrect input length for print statement") - } - - if reflect.TypeOf(printOutput).String() != "[]string" { - t.Errorf("Returned object of incorrect type") + if reflect.TypeOf(testPrint).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Operation that was created is not of the right type: \n\tExpected: %s\n\tReceived: %s", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(testPrint).String()) + } + }) } } -func TestPrintCalculateOperationEmptyRuleData(t *testing.T) { - testRuleData := NewRuleData() - testPrintOperation := NewPrintOperation("testing") - - _, err := testPrintOperation.CalculateOperation(testRuleData) - if err.Error() != "rule does not have any search term data stored" { - t.Errorf("error not properly returned when ruledata is empty") +func TestPrintCalculateOperation(t *testing.T) { + testTable := []struct { + name string + keyToAdd string + testRuleData RuleData + expectedOutput []string + expectedError error + }{ + { + name: "Test_Print_Calculate_Operation_Good_Data", + keyToAdd: "testing", + testRuleData: RuleData{ + st_data_collection: []SearchTermData{ + { + data: map[string]string{ + "testing": "test 1", + }, + }, + { + data: map[string]string{ + "testing": "test 2", + }, + }, + }, + }, + expectedOutput: []string{"test 1", "test 2"}, + expectedError: nil, + }, + { + name: "Test_Print_Calculate_Operation_No_Rule_Data", + keyToAdd: "testing", + testRuleData: RuleData{ + st_data_collection: []SearchTermData{ + { + data: map[string]string{}, + }, + }, + }, + expectedOutput: nil, + expectedError: fmt.Errorf("this value was never extracted during search phase"), + }, } -} -func TestPrintCalculateOperationSearchTermNotExist(t *testing.T) { - st_data1 := NewSearchTermData() - st_data1.AddValue("bad_test", "test 1") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + testOperation := NewPrintOperation("testing") + printOutput, err := testOperation.CalculateOperation(test.testRuleData) + + if !checkExpectedError(err, test.expectedError) { + t.Errorf("An error occurred when attempting to resolve lines to print: \n\tExpected: %v\n\tReceived: %v", test.expectedError, err) + } - testRuleData := NewRuleData() - testRuleData.AppendSearchTermData(st_data1) + if reflect.TypeOf(printOutput).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Print Operation did not return the proper output datatype: \n\tExpected: %s\n\tReceived: %s", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(printOutput).String()) + } - testPrintOperation := NewPrintOperation("testing") - _, err := testPrintOperation.CalculateOperation(testRuleData) + sort.Strings(printOutput) + sort.Strings(test.expectedOutput) - if err.Error() != "this value was never extracted during search phase" { - t.Errorf("Error was not properly returned for search term data that was never created") + if !reflect.DeepEqual(printOutput, test.expectedOutput) { + t.Errorf("Print Operation did not return the proper output: \n\tExpected: %v\n\tReceived: %v", test.expectedOutput, printOutput) + } + }) } } diff --git a/models/library/searchtermdata_test.go b/models/library/searchtermdata_test.go index 2cb5938..1e6e16c 100644 --- a/models/library/searchtermdata_test.go +++ b/models/library/searchtermdata_test.go @@ -1,86 +1,165 @@ package models import ( + "fmt" "reflect" + "sort" "testing" ) -func TestCreateNewSearchTermData(t *testing.T) { - st_data := NewSearchTermData() +func TestCreateNewSearchTermDatas(t *testing.T) { + testTable := []struct { + name string + expectedOutput *SearchTermData + }{ + { + name: "Test_New_Search_Term_Data", + expectedOutput: &SearchTermData{ + data: map[string]string{}, + }, + }, + } - if reflect.TypeOf(st_data).String() != "*models.SearchTermData" { - t.Errorf("Creating new SearchTermData returned the wrong type") + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + stData := NewSearchTermData() + if reflect.TypeOf(stData).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Creating new SearchTermData returned the wrong data type: \n\tExpected: %v\n\tReceived: %v", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(stData).String()) + } + + if !reflect.DeepEqual(stData.data, test.expectedOutput.data) { + t.Errorf("Creating new SearchTermData returned the wrong data: \n\tExpected: %v\n\tReceived: %v", test.expectedOutput.data, stData.data) + } + }) } } func TestSearchTermDataGetKeys(t *testing.T) { - st_data := NewSearchTermData() - st_data.AddValue("test1", "testing") - st_data.AddValue("test2", "testing") - - keys_returned := st_data.Keys() - - if len(keys_returned) != 2 { - t.Errorf("Get Keys returned the wrong number of keys") + testTable := []struct { + name string + searchTermData *SearchTermData + expectedOutput []string + }{ + { + name: "Test_Get_Keys_Good_Data", + searchTermData: &SearchTermData{ + data: map[string]string{ + "test1": "Testing 1", + "test2": "Testing 2", + }, + }, + expectedOutput: []string{"test1", "test2"}, + }, + { + name: "Test_Get_Keys_No_Keys", + searchTermData: &SearchTermData{ + data: map[string]string{}, + }, + expectedOutput: nil, + }, } - if reflect.TypeOf(keys_returned).String() != "[]string" { - t.Errorf("Get Keys returned the wrong datatype") - } -} + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + keysReturned := test.searchTermData.Keys() -func TestSearchTermDataGetKeysNoKeys(t *testing.T) { - st_data := NewSearchTermData() + if reflect.TypeOf(keysReturned).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Get Keys returned the wrong data type: \n\tExpected: %v\n\tReceived: %v", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(keysReturned).String()) + } - keys_returned := st_data.Keys() + sort.Strings(keysReturned) + sort.Strings(test.expectedOutput) - if keys_returned != nil { - t.Errorf("Get Keys returned the wrong answer with no keys") + if !reflect.DeepEqual(keysReturned, test.expectedOutput) { + t.Errorf("Get Keys returned the wrong data: \n\tExpected: %v\n\tReceived: %v", test.expectedOutput, keysReturned) + } + }) } } -func TestGetValue(t *testing.T) { - st_data := NewSearchTermData() - st_data.AddValue("test1", "testing") - - currentValue, err := st_data.Value("test1") - if err != nil { - t.Errorf("Error improperly returned when getting value.") +func TestGetValues(t *testing.T) { + testTable := []struct { + name string + key string + searchTermData *SearchTermData + expectedOutput string + expectedError error + }{ + { + name: "Test_Get_Valuee_Good_Data", + key: "test1", + searchTermData: &SearchTermData{ + data: map[string]string{ + "test1": "testing", + }, + }, + expectedOutput: "testing", + expectedError: nil, + }, + { + name: "Test_Get_Value_Wrong_Key", + key: "test1", + searchTermData: &SearchTermData{ + data: map[string]string{}, + }, + expectedOutput: "", + expectedError: fmt.Errorf("could not find key: test1 in searchtermdata"), + }, } - if currentValue != "testing" { - t.Errorf("Value improperly returned when getting value.") - } + for _, test := range testTable { + currentValue, err := test.searchTermData.Value(test.key) + if !checkExpectedError(err, test.expectedError) { + t.Errorf("Get Value returned an unexpected error: \n\tExpected: %v\n\tReceived: %v", test.expectedError, err) + } - if reflect.TypeOf(currentValue).String() != "string" { - t.Errorf("GetValue returned improper datatype") + if reflect.TypeOf(currentValue).String() != reflect.TypeOf(test.expectedOutput).String() { + t.Errorf("Get Value returned unexpected data type: \n\tExpected: %v\n\tReceived: %v", reflect.TypeOf(test.expectedOutput).String(), reflect.TypeOf(currentValue).String()) + } + + if currentValue != test.expectedOutput { + t.Errorf("Get Value returned incorrect data: \n\tExpected: %v\n\tReceived: %v", test.expectedOutput, currentValue) + } } } -func TestGetValueWrongValue(t *testing.T) { - st_data := NewSearchTermData() - - _, err := st_data.Value("test1") - - if err == nil { - t.Errorf("Error not returned when it should have.") +func TestAddValues(t *testing.T) { + testTable := []struct { + name string + keysToAdd []string + valuesToAdd []string + expectedError error + }{ + { + name: "Test_Good_Values", + keysToAdd: []string{"test1"}, + valuesToAdd: []string{"testing"}, + expectedError: nil, + }, + { + name: "Test_Overwrite_Error", + keysToAdd: []string{"test1", "test1"}, + valuesToAdd: []string{"testing", "another test"}, + expectedError: fmt.Errorf("unable to set value: another test for key: test1 - data is readonly"), + }, } - if err.Error() != "could not find key: test1 in searchtermdata" { - t.Errorf("Error improperly returned when getting new searchtermdata") - } -} + for _, test := range testTable { + t.Run(test.name, func(t *testing.T) { + var err error + st_data := NewSearchTermData() -func TestAddValue(t *testing.T) { - st_data := NewSearchTermData() + for index, keyToAdd := range test.keysToAdd { + err = st_data.AddValue(keyToAdd, test.valuesToAdd[index]) - err := st_data.AddValue("test1", "testing") - if err != nil { - t.Errorf("Error returned when there should not have been") - } + if err != nil { + break + } + } - err = st_data.AddValue("test1", "another test") - if err.Error() != "unable to set value: another test for key: test1 - data is readonly" { - t.Errorf("Error improperly returned when attempting to overwrite data") + if !checkExpectedError(err, test.expectedError) { + t.Errorf("SearchTermData.AddValue did not return the expected error: \n\tExpected: %v\n\tReceived: %v", test.expectedError, err) + } + }) } }