diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/gobang.go | 614 |
1 files changed, 589 insertions, 25 deletions
diff --git a/tests/gobang.go b/tests/gobang.go index a03e8bc..842b95a 100644 --- a/tests/gobang.go +++ b/tests/gobang.go @@ -1,16 +1,17 @@ package gobang import ( - "bytes" "crypto/sha1" "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" + "errors" "fmt" "hash" "log/slog" "os" + "strings" "time" ) @@ -382,6 +383,10 @@ func test_Hash() { }) } +func test_getV7Time() { + // FIXME +} + func test_newUUIDFrom() { TestStart("newUUIDFrom()") @@ -489,6 +494,458 @@ func test_ParseUUID() { }) } +func test_sourceInfo() { + TestStart("sourceInfo()") + + Testing("sourceInfo() is defined at...", func() { + const FILENAME = "src/gobang.go" + info := sourceInfo(1) + AssertEqual(info.Key, "src") + AssertEqual(len(info.Value.Group()), 3) + + AssertEqual(info.Value.Group()[0].Key, "file") + file := info.Value.Group()[0].Value.String() + AssertEqual(file[len(file) - len(FILENAME):], FILENAME) + + AssertEqual(info.Value.Group()[1].Key, "function") + AssertEqual( + info.Value.Group()[1].Value.String(), + "gobang.sourceInfo", + ) + + AssertEqual(info.Value.Group()[2].Key, "line") + AssertEqual(info.Value.Group()[2].Value.Kind(), slog.KindInt64) + }) + + Testing("we're calling it from...", func() { + const FILENAME = "tests/gobang.go" + info := sourceInfo(2) + AssertEqual(info.Key, "src") + AssertEqual(len(info.Value.Group()), 3) + + AssertEqual(info.Value.Group()[0].Key, "file") + file := info.Value.Group()[0].Value.String() + AssertEqual(file[len(file) - len(FILENAME):], FILENAME) + + AssertEqual(info.Value.Group()[1].Key, "function") + AssertEqual( + info.Value.Group()[1].Value.String(), + "gobang.test_sourceInfo.func2", + ) + + AssertEqual(info.Value.Group()[2].Key, "line") + AssertEqual(info.Value.Group()[2].Value.Kind(), slog.KindInt64) + }) +} + +func test_logArgs() { + TestStart("logArgs()") + + Testing("direct string array return", func() { + args := logArgs("the-type") + AssertEqual(len(args), 6) + AssertEqual(args[0], "id") + + _, err := ParseUUID(args[1]) + ErrorIf(err) + + expected := []string { "kind", "log", "type", "the-type" } + AssertEqual(args[2:], expected) + }) +} + +func test_anyArr() { + TestStart("anyArr()") + + Testing("we can turn []string into []any", func() { + var input []string = []string { "one", "two", "three" } + var given []any = anyArr(input) + var expected []any = []any { "one", "two", "three" } + + AssertEqual(given, expected) + }) +} + +func testLog( + levelName string, + filterLevel logLevel, + fn func(string, string, ...any), +) { + savedLogger := slog.Default() + savedLevel := level + + s := new(strings.Builder) + setLoggerOutput(s) + level = filterLevel + + fn("a-message", "a-type", "a-key", "a-value") + + { + var data map[string]interface{} + err := json.Unmarshal([]byte(s.String()), &data) + ErrorIf(err) + + timeRaw, ok := data["time"] + AssertEqual(ok, true) + timeStr, ok := timeRaw.(string) + AssertEqual(ok, true) + _, err = time.Parse(time.RFC3339, timeStr) + ErrorIf(err) + + levelRaw, ok := data["level"] + AssertEqual(ok, true) + level, ok := levelRaw.(string) + AssertEqual(ok, true) + AssertEqual(level, levelName) + + kindRaw, ok := data["kind"] + AssertEqual(ok, true) + kind, ok := kindRaw.(string) + AssertEqual(ok, true) + AssertEqual(kind, "log") + + msgRaw, ok := data["msg"] + AssertEqual(ok, true) + msg, ok := msgRaw.(string) + AssertEqual(ok, true) + AssertEqual(msg, "a-message") + + typeRaw, ok := data["type"] + AssertEqual(ok, true) + type_, ok := typeRaw.(string) + AssertEqual(ok, true) + AssertEqual(type_, "a-type") + + keyRaw, ok := data["a-key"] + AssertEqual(ok, true) + key, ok := keyRaw.(string) + AssertEqual(ok, true) + AssertEqual(key, "a-value") + } + + slog.SetDefault(savedLogger) + level = savedLevel +} + +func testNoLog(filterLevel logLevel, fn func(string, string, ...any)) { + savedLogger := slog.Default() + savedLevel := level + + s := new(strings.Builder) + setLoggerOutput(s) + level = filterLevel + fn("a-message", "a-type", "a-key", "a-value") + + AssertEqual(s.String(), "") + + slog.SetDefault(savedLogger) + level = savedLevel +} + +func test_Debug() { + TestStart("Debug()") + + Testing("exists in LevelDebug", func() { + testLog("DEBUG", LevelDebug, Debug) + }) + + Testing("doesn't in lower levels", func() { + testNoLog(LevelInfo, Debug) + }) +} + +func test_Info() { + TestStart("Info()") + + Testing("exists in LevelInfo", func() { + testLog("INFO", LevelInfo, Info) + }) + + Testing("doesn't in lower levels", func() { + testNoLog(LevelWarning, Info) + }) +} + +func test_Warning() { + TestStart("Warning()") + + Testing("exists in LevelWarning", func() { + testLog("WARN" /* WARNING */, LevelWarning, Warning) + }) + + Testing("doesn't in lower levels", func() { + testNoLog(LevelError, Warning) + }) +} + +func test_Error() { + TestStart("Error()") + + Testing("exists in LevelError", func() { + testLog("ERROR", LevelError, Error) + }) + + Testing("doesn't in lower levels", func() { + testNoLog(LevelNone, Error) + }) +} + +func test_metric() { + TestStart("metric()") + + Testing("noop when emitMetric is false", func() { + savedLogger := slog.Default() + savedFlag := emitMetric + + s := new(strings.Builder) + setLoggerOutput(s) + emitMetric = false + + metric("", "") + AssertEqual(s.String(), "") + + slog.SetDefault(savedLogger) + emitMetric = savedFlag + }) + + Testing("JSON entry of kind \"metric\"", func() { + savedLogger := slog.Default() + savedFlag := emitMetric + + s := new(strings.Builder) + setLoggerOutput(s) + emitMetric = true + + metric("a-type", "a-label", "count-something", 123) + + var data map[string]interface{} + err := json.Unmarshal([]byte(s.String()), &data) + ErrorIf(err) + + timeRaw, ok := data["time"] + AssertEqual(ok, true) + timeStr, ok := timeRaw.(string) + AssertEqual(ok, true) + _, err = time.Parse(time.RFC3339, timeStr) + ErrorIf(err) + + levelRaw, ok := data["level"] + AssertEqual(ok, true) + level, ok := levelRaw.(string) + AssertEqual(ok, true) + AssertEqual(level, "INFO") + + msgRaw, ok := data["msg"] + AssertEqual(ok, true) + msg, ok := msgRaw.(string) + AssertEqual(ok, true) + AssertEqual(msg, "_") + + idRaw, ok := data["id"] + AssertEqual(ok, true) + id, ok := idRaw.(string) + AssertEqual(ok, true) + _, err = ParseUUID(id) + ErrorIf(err) + + kindRaw, ok := data["kind"] + AssertEqual(ok, true) + kind, ok := kindRaw.(string) + AssertEqual(ok, true) + AssertEqual(kind, "metric") + + typeRaw, ok := data["type"] + AssertEqual(ok, true) + type_, ok := typeRaw.(string) + AssertEqual(ok, true) + AssertEqual(type_, "a-type") + + labelRaw, ok := data["label"] + AssertEqual(ok, true) + label, ok := labelRaw.(string) + AssertEqual(ok, true) + AssertEqual(label, "a-label") + + keyRaw, ok := data["count-something"] + AssertEqual(ok, true) + key, ok := keyRaw.(float64) + AssertEqual(ok, true) + AssertEqual(int(key), 123) + + slog.SetDefault(savedLogger) + emitMetric = savedFlag + }) +} + +func test_MakeCounter() { + TestStart("MakeCounter()") + + Testing("\"value\" is always 1", func() { + savedLogger := slog.Default() + savedFlag := emitMetric + + s := new(strings.Builder) + setLoggerOutput(s) + emitMetric = true + + emitTCPError := MakeCounter("emit-tcp-error") + emitTCPError("more-data", 555) + + var data map[string]interface{} + err := json.Unmarshal([]byte(s.String()), &data) + ErrorIf(err) + + typeRaw, ok := data["type"] + AssertEqual(ok, true) + type_, ok := typeRaw.(string) + AssertEqual(ok, true) + AssertEqual(type_, "counter") + + labelRaw, ok := data["label"] + AssertEqual(ok, true) + label, ok := labelRaw.(string) + AssertEqual(ok, true) + AssertEqual(label, "emit-tcp-error") + + valueRaw, ok := data["value"] + AssertEqual(ok, true) + value, ok := valueRaw.(float64) + AssertEqual(ok, true) + AssertEqual(int(value), 1) + + keyRaw, ok := data["more-data"] + AssertEqual(ok, true) + key, ok := keyRaw.(float64) + AssertEqual(ok, true) + AssertEqual(int(key), 555) + + slog.SetDefault(savedLogger) + emitMetric = savedFlag + }) +} + +func test_MakeGauge() { + TestStart("MakeGauge()") + + Testing("errors on underflow", func() { + savedLogger := slog.Default() + savedLevel := level + + s := new(strings.Builder) + setLoggerOutput(s) + level = LevelError + + activeTCPConnections := MakeGauge("active-tcp-connections") + activeTCPConnections.Dec() + + { + var data map[string]interface{} + err := json.Unmarshal([]byte(s.String()), &data) + ErrorIf(err) + + levelRaw, ok := data["level"] + AssertEqual(ok, true) + level, ok := levelRaw.(string) + AssertEqual(ok, true) + AssertEqual(level, "ERROR") + + msgRaw, ok := data["msg"] + AssertEqual(ok, true) + msg, ok := msgRaw.(string) + AssertEqual(ok, true) + AssertEqual(msg, "Gauge went negative") + + kindRaw, ok := data["kind"] + AssertEqual(ok, true) + kind, ok := kindRaw.(string) + AssertEqual(ok, true) + AssertEqual(kind, "log") + + typeRaw, ok := data["type"] + AssertEqual(ok, true) + type_, ok := typeRaw.(string) + AssertEqual(ok, true) + AssertEqual(type_, "process-metric") + + valueRaw, ok := data["value"] + AssertEqual(ok, true) + value, ok := valueRaw.(float64) + AssertEqual(ok, true) + AssertEqual(int(value), -1) + } + + slog.SetDefault(savedLogger) + level = savedLevel + }) + + Testing("\"value\" grows monotonically", func() { + savedLogger := slog.Default() + savedFlag := emitMetric + + s := new(strings.Builder) + setLoggerOutput(s) + emitMetric = true + + activeTCPConnections := MakeGauge("active-tcp-connections") + activeTCPConnections.Inc() + activeTCPConnections.Inc() + activeTCPConnections.Dec() + activeTCPConnections.Inc() + activeTCPConnections.Inc("more-data", 999) + + strs := strings.Split(s.String(), "\n") + AssertEqual(len(strs), 6) + AssertEqual(strs[5], "") + + var data map[string]interface{} + err := json.Unmarshal([]byte(strs[len(strs) - 2]), &data) + ErrorIf(err) + + typeRaw, ok := data["type"] + AssertEqual(ok, true) + type_, ok := typeRaw.(string) + AssertEqual(ok, true) + AssertEqual(type_, "gauge") + + labelRaw, ok := data["label"] + AssertEqual(ok, true) + label, ok := labelRaw.(string) + AssertEqual(ok, true) + AssertEqual(label, "active-tcp-connections") + + valueRaw, ok := data["value"] + AssertEqual(ok, true) + value, ok := valueRaw.(float64) + AssertEqual(ok, true) + AssertEqual(int(value), 3) + + keyRaw, ok := data["more-data"] + AssertEqual(ok, true) + key, ok := keyRaw.(float64) + AssertEqual(ok, true) + AssertEqual(int(key), 999) + + slog.SetDefault(savedLogger) + emitMetric = savedFlag + }) +} + +func test_ErrorIf() { + TestStart("ErrorIf()") + + Testing("noop on nil value", func() { + ErrorIf(nil) + }) +} + +func test_ErrorNil() { + TestStart("ErrorNil()") + + Testing("noop on thruthy value", func() { + ErrorNil(errors.New("some error")) + }) +} + func test_showColour() { TestStart("showColour()") @@ -513,6 +970,123 @@ func test_showColour() { ErrorIf(os.Setenv(NAME, savedEnvvar)) } +func test_setLoggerOutput() { + TestStart("setLoggerOutput()") + + savedLogger := slog.Default() + + Testing("the output JSON has data under \"src\"", func() { + s := new(strings.Builder) + setLoggerOutput(s) + Info("", "") + + var data map[string]interface{} + err := json.Unmarshal([]byte(s.String()), &data) + ErrorIf(err) + + srcRaw, ok := data["src"] + AssertEqual(ok, true) + src, ok := srcRaw.(map[string]interface{}) + AssertEqual(ok, true) + + fileRaw, ok := src["file"] + AssertEqual(ok, true) + file, ok := fileRaw.(string) + AssertEqual(ok, true) + const FILENAME = "tests/gobang.go" + AssertEqual(file[len(file) - len(FILENAME):], FILENAME) + + functionRaw, ok := src["function"] + AssertEqual(ok, true) + function, ok := functionRaw.(string) + AssertEqual(ok, true) + AssertEqual(function, "gobang.test_setLoggerOutput.func1") + + lineRaw, ok := src["line"] + AssertEqual(ok, true) + _, ok = lineRaw.(float64) + AssertEqual(ok, true) + }) + + Testing("the output JSON has data under \"info\"", func() { + s := new(strings.Builder) + setLoggerOutput(s) + Info("", "") + + var data map[string]interface{} + err := json.Unmarshal([]byte(s.String()), &data) + ErrorIf(err) + + infoRaw, ok := data["info"] + AssertEqual(ok, true) + info, ok := infoRaw.(map[string]interface{}) + AssertEqual(ok, true) + + pidRaw, ok := info["pid"] + AssertEqual(ok, true) + pid, ok := pidRaw.(float64) + AssertEqual(ok, true) + AssertEqual(int(pid), os.Getpid()) + + ppidRaw, ok := info["ppid"] + AssertEqual(ok, true) + ppid, ok := ppidRaw.(float64) + AssertEqual(ok, true) + AssertEqual(int(ppid), os.Getppid()) + + puuidRaw, ok := info["puuid"] + AssertEqual(ok, true) + puuid, ok := puuidRaw.(string) + AssertEqual(ok, true) + _, err = ParseUUID(puuid) + ErrorIf(err) + }) + + Testing("the puuid is the same across calls to the logger", func() { + s := new(strings.Builder) + setLoggerOutput(s) + Info("", "first") + Info("", "second") + + strs := strings.Split(s.String(), "\n") + AssertEqual(len(strs), 3) + AssertEqual(strs[2], "") + + log1 := strs[0] + log2 := strs[1] + + var puuidFromString = func(str string) string { + var data map[string]interface{} + err := json.Unmarshal([]byte(str), &data) + ErrorIf(err) + + infoRaw, ok := data["info"] + AssertEqual(ok, true) + info, ok := infoRaw.(map[string]interface{}) + AssertEqual(ok, true) + + puuidRaw, ok := info["puuid"] + AssertEqual(ok, true) + puuid, ok := puuidRaw.(string) + AssertEqual(ok, true) + + return puuid + } + + puuid1 := puuidFromString(log1) + puuid2 := puuidFromString(log2) + AssertEqual(puuid1, puuid2) + + uuid1, err := ParseUUID(puuid1) + ErrorIf(err) + uuid2, err := ParseUUID(puuid2) + ErrorIf(err) + AssertEqual(uuid1, uuid2) + }) + + slog.SetDefault(savedLogger) +} + func test_levelFromString() { TestStart("levelFromString()") @@ -640,30 +1214,6 @@ func test_setHostname() { }) } -func TestSetLoggerOutput() { - return - type entry struct { - msg string `json:"msg"` - aKey string `json:"a-key"` - } - var e entry - var buf bytes.Buffer - slog.Error("the message", "a-key", "a-value") - - s := buf.String() - // fmt.Println(s) - // fmt.Println(e) - err := json.Unmarshal([]byte(s), &e) - if err != nil { - // t.Fail() - // Mmain() - } - if e.msg != "the message" { - // t.Fail() - } - fmt.Println(1) - // fmt.Println(e) -} func t1() { test__PBKDF() @@ -680,11 +1230,25 @@ func t3() { func t4() { test_Random() test_Salt() + test_getV7Time() test_newUUIDFrom() test_NewUUID() test_UUIDString() test_ParseUUID() + test_sourceInfo() + test_logArgs() + test_anyArr() + test_Debug() + test_Info() + test_Warning() + test_Error() + test_metric() + test_MakeCounter() + test_MakeGauge() + test_ErrorIf() + test_ErrorNil() test_showColour() + test_setLoggerOutput() test_levelFromString() test_setLogLevel() test_setMetric() |