package settings import ( "bytes" "errors" "fmt" "log" "maps" "os" "strings" "testing" "time" ) const ( TheTestFilename = "settings_test.settings" ) var ( AdditionalKeyValuePairs = map[string]string{ "D": "d", "E": "e", "F": "f", } ) func TestSettings(t *testing.T) { err := os.Remove(TheTestFilename) if err != nil && !errors.Is(err, os.ErrNotExist) { t.Fatalf("error cleaning up %s from previous run: %v\n", TheTestFilename, err) } var buffer bytes.Buffer err = WriteMapToWriter(&buffer, KeyValuePairs) if err != nil { t.Fatalf("error writing test data to *bytes.Buffer: %v\n", err) } err = os.WriteFile(TheTestFilename, buffer.Bytes(), 0664) if err != nil { t.Fatalf("error writing %s: %v\n", TheTestFilename, err) } defer func() { if err := os.Remove(TheTestFilename); err != nil { t.Fatalf("error cleaning up %s from this run: %v\n", TheTestFilename, err) } }() settings := NewSettingsWithContext(t.Context(), TheTestFilename, false) if want, got := TheTestFilename, settings.GetFilename(); want != got { t.Fatalf("error: wanted '%s'; got '%s'\n", want, got) } else if got := settings.modtime; got.Equal(time.Time{}) { t.Fatalf("error: modtime == (time.Time{}) - not updated when initialized") } else { for k, v := range KeyValuePairs { if !settings.ContainsKey(k) { t.Fatalf("error: key '%s' not found\n", k) } else if want, got := v, settings.GetKeyValue(k); want != got { t.Fatalf("error: wanted '%s' for key '%s'; got '%s'\n", want, k, got) } } } // change the filename TheNewTestFilename := fmt.Sprintf("New%s", TheTestFilename) buffer.Reset() err = WriteMapToWriter(&buffer, AdditionalKeyValuePairs) if err != nil { t.Fatalf("error writing new map to *bytes.Buffer: %v\n", err) } err = os.WriteFile(TheNewTestFilename, buffer.Bytes(), 0664) if err != nil { t.Fatalf("error writing new test file %s: %v\n", TheNewTestFilename, err) } defer func() { if err := os.Remove(TheNewTestFilename); err != nil { t.Fatalf("error deleting %s: %v", TheNewTestFilename, err) } }() if updated := settings.SetFilename(TheNewTestFilename); !updated { t.Fatalf("error: SetFilename() indicated the filename was not updated...\n") } else if updated := settings.SetFilename(settings.GetFilename()); updated { t.Fatalf("error: setting filename to itself still resulted in updated=true\n") } for k, v := range AdditionalKeyValuePairs { if !settings.ContainsKey(k) { t.Fatalf("error: key '%s' not found\n", k) } else if want, got := v, settings.GetKeyValue(k); want != got { t.Fatalf("error: wanted '%s' for key '%s'; got '%s'\n", want, k, got) } } // update the file, wait, then try again newKeyValuePairs := make(map[string]string) maps.Copy(newKeyValuePairs, KeyValuePairs) maps.Copy(newKeyValuePairs, AdditionalKeyValuePairs) newKeyValuePairs["G"] = "g" buffer.Reset() err = WriteMapToWriter(&buffer, newKeyValuePairs) if err != nil { t.Fatalf("error writing new key value pairs to *bytes.Buffer: %v\n", err) } err = os.WriteFile(TheNewTestFilename, buffer.Bytes(), 0664) if err != nil { t.Fatalf("error writing updates to %s: %v\n", TheNewTestFilename, err) } select { case <-t.Context().Done(): t.Fatalf("error: timed out before finishing wait") case <-time.After(time.Duration(float64(MaintenanceRoutinePace.Nanoseconds()) * 1.1)): } for k, v := range newKeyValuePairs { if !settings.ContainsKey(k) { t.Fatalf("error: key '%s' not found in settings\n", k) } else if want, got := v, settings.GetKeyValue(k); want != got { t.Fatalf("error: wanted '%s' for key '%s'; got '%s'\n", want, k, got) } } buffer.Reset() defaultLogWriter := log.Writer() log.SetOutput(&buffer) // set settings to a fake filename WarnIfFileNotFound = true if updated := settings.SetFilename("fakefilename.txt"); !updated { t.Fatalf("failed to update filename to fake filename...\n") } log.SetOutput(defaultLogWriter) WarnIfFileNotFound = false if !strings.Contains(buffer.String(), "no such file or directory") { t.Fatalf("error: wanted error indicating 'no such file or directory'; got %v\n", err) } }