From ebb7f3eb394e3f7694f2745a6104d4818b75b824 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Fri, 7 Feb 2025 17:34:00 +0530 Subject: [PATCH 01/14] chore: add tests for nsqlookupd Signed-off-by: shivamsouravjha <2019145@iiitdmj.ac.in> --- nsqlookupd/http_test.go | 105 +++++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 12 deletions(-) diff --git a/nsqlookupd/http_test.go b/nsqlookupd/http_test.go index 94f17f086..18b836b08 100644 --- a/nsqlookupd/http_test.go +++ b/nsqlookupd/http_test.go @@ -1,18 +1,18 @@ package nsqlookupd import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "strconv" - "testing" - "time" - - "github.com/nsqio/nsq/internal/test" - "github.com/nsqio/nsq/internal/version" - "github.com/nsqio/nsq/nsqd" + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "strconv" + "testing" + "time" + + "github.com/nsqio/nsq/internal/test" + "github.com/nsqio/nsq/internal/version" + "github.com/nsqio/nsq/nsqd" ) type InfoDoc struct { @@ -482,3 +482,84 @@ func TestDeleteChannel(t *testing.T) { t.Logf("%s", body) test.Equal(t, []byte(""), body) } + +// Test generated using Keploy +func TestDoLookup_TopicNotFound(t *testing.T) { + dataPath, nsqds, nsqlookupd1 := bootstrapNSQCluster(t) + defer os.RemoveAll(dataPath) + defer nsqds[0].Exit() + defer nsqlookupd1.Exit() + + client := http.Client{} + topicName := "nonexistentTopic" + url := fmt.Sprintf("http://%s/lookup?topic=%s", nsqlookupd1.RealHTTPAddr(), topicName) + + req, _ := http.NewRequest("GET", url, nil) + req.Header.Add("Accept", "application/vnd.nsq; version=1.0") + resp, err := client.Do(req) + test.Nil(t, err) + test.Equal(t, 404, resp.StatusCode) + body, _ := io.ReadAll(resp.Body) + resp.Body.Close() + + t.Logf("%s", body) + em := ErrMessage{} + err = json.Unmarshal(body, &em) + test.Nil(t, err) + test.Equal(t, "TOPIC_NOT_FOUND", em.Message) +} + + +// Test generated using Keploy +func TestDoTombstoneTopicProducer_MissingNode(t *testing.T) { + dataPath, nsqds, nsqlookupd1 := bootstrapNSQCluster(t) + defer os.RemoveAll(dataPath) + defer nsqds[0].Exit() + defer nsqlookupd1.Exit() + + client := http.Client{} + topicName := "sampletopic" + makeTopic(nsqlookupd1, topicName) + + url := fmt.Sprintf("http://%s/topic/tombstone?topic=%s", nsqlookupd1.RealHTTPAddr(), topicName) + req, _ := http.NewRequest("POST", url, nil) + req.Header.Add("Accept", "application/vnd.nsq; version=1.0") + resp, err := client.Do(req) + test.Nil(t, err) + test.Equal(t, 400, resp.StatusCode) + body, _ := io.ReadAll(resp.Body) + resp.Body.Close() + + t.Logf("%s", body) + em := ErrMessage{} + err = json.Unmarshal(body, &em) + test.Nil(t, err) + test.Equal(t, "MISSING_ARG_NODE", em.Message) +} + + +// Test generated using Keploy +func TestDoDebug_ValidResponse(t *testing.T) { + dataPath, nsqds, nsqlookupd1 := bootstrapNSQCluster(t) + defer os.RemoveAll(dataPath) + defer nsqds[0].Exit() + defer nsqlookupd1.Exit() + + client := http.Client{} + url := fmt.Sprintf("http://%s/debug", nsqlookupd1.RealHTTPAddr()) + + req, _ := http.NewRequest("GET", url, nil) + req.Header.Add("Accept", "application/vnd.nsq; version=1.0") + resp, err := client.Do(req) + test.Nil(t, err) + test.Equal(t, 200, resp.StatusCode) + body, _ := io.ReadAll(resp.Body) + resp.Body.Close() + + t.Logf("%s", body) + var debugData map[string][]map[string]interface{} + err = json.Unmarshal(body, &debugData) + test.Nil(t, err) + test.NotNil(t, debugData) +} + From 3574e3b351f37cef0035c75ce92726d61edf24c5 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Fri, 7 Feb 2025 17:40:33 +0530 Subject: [PATCH 02/14] add: tests for nsq stat --- apps/nsq_stat/nsq_stat_test.go | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 apps/nsq_stat/nsq_stat_test.go diff --git a/apps/nsq_stat/nsq_stat_test.go b/apps/nsq_stat/nsq_stat_test.go new file mode 100644 index 000000000..50ff73f1f --- /dev/null +++ b/apps/nsq_stat/nsq_stat_test.go @@ -0,0 +1,51 @@ +package main + +import ( + "testing" +) + + +// Test generated using Keploy +func TestNumValue_Set_ValidInput(t *testing.T) { + nv := &numValue{} + err := nv.Set("42") + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if nv.value != 42 { + t.Errorf("Expected value to be 42, got %v", nv.value) + } + if !nv.isSet { + t.Errorf("Expected isSet to be true, got %v", nv.isSet) + } +} + +// Test generated using Keploy +func TestNumValue_Set_InvalidInput(t *testing.T) { + nv := &numValue{} + err := nv.Set("invalid") + if err == nil { + t.Errorf("Expected an error, got nil") + } +} + + +// Test generated using Keploy +func TestCheckAddrs_InvalidAddress(t *testing.T) { + addrs := []string{"http://example.com"} + err := checkAddrs(addrs) + if err == nil { + t.Errorf("Expected an error, got nil") + } +} + + +// Test generated using Keploy +func TestCheckAddrs_ValidAddresses(t *testing.T) { + addrs := []string{"example.com", "localhost:8080"} + err := checkAddrs(addrs) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } +} + From ed72025b681fde1f60fe22d064a4008ff34785d1 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Fri, 7 Feb 2025 17:51:45 +0530 Subject: [PATCH 03/14] chore: add test for nsq tail --- apps/nsq_tail/nsq_tail.go | 4 ++- apps/nsq_tail/nsq_tail_test.go | 52 ++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 apps/nsq_tail/nsq_tail_test.go diff --git a/apps/nsq_tail/nsq_tail.go b/apps/nsq_tail/nsq_tail.go index 65470c428..9d666cd8f 100644 --- a/apps/nsq_tail/nsq_tail.go +++ b/apps/nsq_tail/nsq_tail.go @@ -28,6 +28,8 @@ var ( topics = app.StringArray{} ) +var appExit = os.Exit + func init() { flag.Var(&nsqdTCPAddrs, "nsqd-tcp-address", "nsqd TCP address (may be given multiple times)") flag.Var(&lookupdHTTPAddrs, "lookupd-http-address", "lookupd HTTP address (may be given multiple times)") @@ -63,7 +65,7 @@ func (th *TailHandler) HandleMessage(m *nsq.Message) error { log.Fatalf("ERROR: failed to write to os.Stdout - %s", err) } if th.totalMessages > 0 && th.messagesShown >= th.totalMessages { - os.Exit(0) + appExit(0) } return nil } diff --git a/apps/nsq_tail/nsq_tail_test.go b/apps/nsq_tail/nsq_tail_test.go new file mode 100644 index 000000000..b269dad66 --- /dev/null +++ b/apps/nsq_tail/nsq_tail_test.go @@ -0,0 +1,52 @@ +package main + +import ( + "os" + "testing" + "github.com/nsqio/go-nsq" +) + + +// Test generated using Keploy +func TestMain_VersionFlag(t *testing.T) { + os.Args = []string{"cmd", "--version"} + exitCode := 0 + exitFunc := func(code int) { + exitCode = code + } + appExit = exitFunc + defer func() { appExit = os.Exit }() + + main() + + if exitCode != 0 { + t.Errorf("Expected exit code 0, got %d", exitCode) + } +} + +// Test generated using Keploy +func TestTailHandler_HandleMessage_Exit(t *testing.T) { + handler := &TailHandler{ + topicName: "test_topic", + totalMessages: 1, + messagesShown: 0, + } + + message := &nsq.Message{ + Body: []byte("test message"), + } + + exitCode := 0 + exitFunc := func(code int) { + exitCode = code + } + appExit = exitFunc + defer func() { appExit = os.Exit }() + + handler.HandleMessage(message) + + if exitCode != 0 { + t.Errorf("Expected exit code 0, got %d", exitCode) + } +} + From 689d8aabb31c3d7f92ca198049c9e3f726f8acc2 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Fri, 7 Feb 2025 17:53:01 +0530 Subject: [PATCH 04/14] chore: add tests --- apps/nsq_tail/nsq_tail_test.go | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/apps/nsq_tail/nsq_tail_test.go b/apps/nsq_tail/nsq_tail_test.go index b269dad66..4154799a5 100644 --- a/apps/nsq_tail/nsq_tail_test.go +++ b/apps/nsq_tail/nsq_tail_test.go @@ -4,6 +4,7 @@ import ( "os" "testing" "github.com/nsqio/go-nsq" + "bytes" ) @@ -50,3 +51,55 @@ func TestTailHandler_HandleMessage_Exit(t *testing.T) { } } + +// Test generated using Keploy +func TestTailHandler_HandleMessage_PrintTopic(t *testing.T) { + // Set printTopic flag to true + originalPrintTopic := *printTopic + *printTopic = true + defer func() { *printTopic = originalPrintTopic }() + + // Replace os.Stdout with a pipe + r, w, err := os.Pipe() + if err != nil { + t.Fatalf("Failed to create pipe: %v", err) + } + originalStdout := os.Stdout + os.Stdout = w + defer func() { + os.Stdout = originalStdout + w.Close() + r.Close() + }() + + handler := &TailHandler{ + topicName: "test_topic", + totalMessages: 0, + messagesShown: 0, + } + + message := &nsq.Message{ + Body: []byte("test message"), + } + + err = handler.HandleMessage(message) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + // Close writer to allow reading + w.Close() + + // Read output + var buf bytes.Buffer + _, err = buf.ReadFrom(r) + if err != nil { + t.Fatalf("Failed to read from pipe: %v", err) + } + + expectedOutput := "test_topic | test message\n" + if buf.String() != expectedOutput { + t.Errorf("Expected output %q, got %q", expectedOutput, buf.String()) + } +} + From e021d21e7ffec71b2a7ed47dadb01ec9e0fad225 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Fri, 7 Feb 2025 18:59:05 +0530 Subject: [PATCH 05/14] add: tests for nsqadmin --- apps/nsq_to_file/file_logger_test.go | 107 +++++++++++++++++++++++++++ apps/nsq_to_file/nsq_to_file_test.go | 34 +++++++++ apps/nsq_to_http/nsq_to_http_test.go | 17 ++++- internal/app/float_array_test.go | 31 ++++++++ nsqadmin/http_test.go | 34 +++++++++ 5 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 apps/nsq_to_file/file_logger_test.go create mode 100644 apps/nsq_to_file/nsq_to_file_test.go create mode 100644 internal/app/float_array_test.go diff --git a/apps/nsq_to_file/file_logger_test.go b/apps/nsq_to_file/file_logger_test.go new file mode 100644 index 000000000..7c0078047 --- /dev/null +++ b/apps/nsq_to_file/file_logger_test.go @@ -0,0 +1,107 @@ +package main + +import ( + "testing" + + "os" + + "github.com/nsqio/go-nsq" + "github.com/nsqio/nsq/internal/lg" +) + +// Test generated using Keploy +func TestFileLogger_HandleMessage(t *testing.T) { + logChan := make(chan *nsq.Message, 1) + f := &FileLogger{ + logChan: logChan, + } + + msg := &nsq.Message{} + err := f.HandleMessage(msg) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + select { + case receivedMsg := <-logChan: + if receivedMsg != msg { + t.Errorf("Expected message %v, got %v", msg, receivedMsg) + } + default: + t.Errorf("Expected message to be sent to log channel, but it was not") + } +} + +// Test generated using Keploy +func TestNewFileLogger_MissingREVPlaceholder(t *testing.T) { + opts := &Options{ + FilenameFormat: "-", + GZIP: true, + } + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + cfg := nsq.NewConfig() + + _, err := NewFileLogger(logf, opts, "test_topic", cfg) + if err == nil { + t.Errorf("Expected error due to missing in filename format, got nil") + } +} + +// Test generated using Keploy +func TestNewFileLogger_InvalidTopicName(t *testing.T) { + opts := &Options{ + Channel: "test_channel", + } + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + cfg := nsq.NewConfig() + + _, err := NewFileLogger(logf, opts, "", cfg) + if err == nil { + t.Errorf("Expected error due to invalid topic name, got nil") + } +} + +// Test generated using Keploy +func TestExclusiveRename_Success(t *testing.T) { + srcFile, err := os.CreateTemp("", "srcFile") + if err != nil { + t.Fatalf("Failed to create temp source file: %v", err) + } + defer os.Remove(srcFile.Name()) + + dstFileName := srcFile.Name() + "_renamed" + + err = exclusiveRename(srcFile.Name(), dstFileName) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + if _, err := os.Stat(dstFileName); os.IsNotExist(err) { + t.Errorf("Expected destination file %s to exist, but it does not", dstFileName) + } + defer os.Remove(dstFileName) +} + +// Test generated using Keploy + +// Test generated using Keploy +func TestMakeDirFromPath_InvalidPath(t *testing.T) { + path := "/invalid_path/testdir" + + err := makeDirFromPath(func(lvl lg.LogLevel, f string, args ...interface{}) {}, path) + if err == nil { + t.Errorf("Expected error due to invalid path, got nil") + } +} + + + +func TestExclusiveRename_SourceFileNotExist(t *testing.T) { + src := "nonexistent_file" + dst := "destination_file" + + err := exclusiveRename(src, dst) + if err == nil { + t.Errorf("Expected error due to nonexistent source file, got nil") + } +} diff --git a/apps/nsq_to_file/nsq_to_file_test.go b/apps/nsq_to_file/nsq_to_file_test.go new file mode 100644 index 000000000..eccf0172a --- /dev/null +++ b/apps/nsq_to_file/nsq_to_file_test.go @@ -0,0 +1,34 @@ +package main + +import ( + "testing" +) + +// Test generated using Keploy +func TestFlagSetInitialization(t *testing.T) { + fs := flagSet() + + if fs == nil { + t.Fatal("Expected FlagSet to be initialized, got nil") + } + + if fs.Lookup("version") == nil { + t.Error("Expected 'version' flag to be defined") + } + + if fs.Lookup("log-level") == nil { + t.Error("Expected 'log-level' flag to be defined") + } + + if fs.Lookup("channel") == nil { + t.Error("Expected 'channel' flag to be defined") + } + + if fs.Lookup("output-dir") == nil { + t.Error("Expected 'output-dir' flag to be defined") + } + + if fs.Lookup("rotate-size") == nil { + t.Error("Expected 'rotate-size' flag to be defined") + } +} diff --git a/apps/nsq_to_http/nsq_to_http_test.go b/apps/nsq_to_http/nsq_to_http_test.go index b920b536d..f3fe555cc 100644 --- a/apps/nsq_to_http/nsq_to_http_test.go +++ b/apps/nsq_to_http/nsq_to_http_test.go @@ -4,8 +4,9 @@ package main import ( - "reflect" - "testing" + "reflect" + "testing" + "github.com/nsqio/go-nsq" ) func TestParseCustomHeaders(t *testing.T) { @@ -56,3 +57,15 @@ func TestParseCustomHeaders(t *testing.T) { }) } } + +// Test generated using Keploy +func TestPublishHandlerHandleMessage_SampleRateSkip(t *testing.T) { + *sample = 0.0 + handler := &PublishHandler{} + msg := &nsq.Message{} + err := handler.HandleMessage(msg) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + } + diff --git a/internal/app/float_array_test.go b/internal/app/float_array_test.go new file mode 100644 index 000000000..a2b5d6f7b --- /dev/null +++ b/internal/app/float_array_test.go @@ -0,0 +1,31 @@ +package app + +import ( + "testing" + "fmt" +) + + +// Test generated using Keploy +func TestFloatArray_Set_ValidInput(t *testing.T) { + var fa FloatArray + err := fa.Set("1.1,2.2,3.3") + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + expected := FloatArray{3.3, 2.2, 1.1} + if fmt.Sprintf("%v", fa) != fmt.Sprintf("%v", expected) { + t.Errorf("Expected %v, got %v", expected, fa) + } +} + +// Test generated using Keploy +func TestFloatArray_String(t *testing.T) { + fa := FloatArray{3.3, 2.2, 1.1} + expected := "3.300000,2.200000,1.100000" + result := fa.String() + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + diff --git a/nsqadmin/http_test.go b/nsqadmin/http_test.go index adc843073..ec8150352 100644 --- a/nsqadmin/http_test.go +++ b/nsqadmin/http_test.go @@ -12,6 +12,8 @@ import ( "testing" "time" + "net/url" + "github.com/nsqio/nsq/internal/clusterinfo" "github.com/nsqio/nsq/internal/test" "github.com/nsqio/nsq/internal/version" @@ -642,3 +644,35 @@ func TestHTTPconfigCIDR(t *testing.T) { _, _ = io.ReadAll(resp.Body) test.Equal(t, 403, resp.StatusCode) } + +// Test generated using Keploy +func TestMaybeWarnMsgWithMessages(t *testing.T) { + msgs := []string{"message1", "message2"} + expected := "WARNING: message1; message2" + result := maybeWarnMsg(msgs) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + +// Test generated using Keploy +func TestNewSingleHostReverseProxy(t *testing.T) { + target, _ := url.Parse("http://example.com") + proxy := NewSingleHostReverseProxy(target, 5*time.Second, 10*time.Second) + + req := &http.Request{ + URL: &url.URL{}, + Header: make(http.Header), + } + target.User = url.UserPassword("user", "pass") + proxy.Director(req) + + if req.URL.Scheme != "http" || req.URL.Host != "example.com" { + t.Errorf("Expected scheme and host to be set, got %v and %v", req.URL.Scheme, req.URL.Host) + } + + username, password, ok := req.BasicAuth() + if !ok || username != "user" || password != "pass" { + t.Errorf("Expected basic auth to be set, got %v:%v", username, password) + } +} From fbfdd75eb02404e12c4d016956323aaf517659fa Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Fri, 7 Feb 2025 19:33:10 +0530 Subject: [PATCH 06/14] chore: add tests for discover and strtftime --- apps/nsq_to_file/strftime_test.go | 30 +++++ apps/nsq_to_file/topic_discoverer_test.go | 152 ++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 apps/nsq_to_file/strftime_test.go create mode 100644 apps/nsq_to_file/topic_discoverer_test.go diff --git a/apps/nsq_to_file/strftime_test.go b/apps/nsq_to_file/strftime_test.go new file mode 100644 index 000000000..3baadfe17 --- /dev/null +++ b/apps/nsq_to_file/strftime_test.go @@ -0,0 +1,30 @@ +package main + +import ( + "testing" + "time" +) + + +// Test generated using Keploy +func TestStrftime_SimpleFormat(t *testing.T) { + inputTime := time.Date(2023, 10, 1, 12, 0, 0, 0, time.UTC) + format := "Simple format" + expected := "Simple format" + result := strftime(format, inputTime) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + +// Test generated using Keploy +func TestStrftime_SingleSpecifier(t *testing.T) { + inputTime := time.Date(2023, 10, 1, 12, 0, 0, 0, time.UTC) + format := "%Y" + expected := "2023" + result := strftime(format, inputTime) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + diff --git a/apps/nsq_to_file/topic_discoverer_test.go b/apps/nsq_to_file/topic_discoverer_test.go new file mode 100644 index 000000000..88e55ae71 --- /dev/null +++ b/apps/nsq_to_file/topic_discoverer_test.go @@ -0,0 +1,152 @@ +package main + +import ( + "os" + "testing" + "time" + "github.com/nsqio/go-nsq" + "github.com/nsqio/nsq/internal/lg" +) + + +// Test generated using Keploy +func TestNewTopicDiscoverer_Initialization(t *testing.T) { + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + opts := &Options{ + HTTPClientConnectTimeout: 2 * time.Second, + HTTPClientRequestTimeout: 5 * time.Second, + } + cfg := nsq.NewConfig() + hupChan := make(chan os.Signal, 1) + termChan := make(chan os.Signal, 1) + + td := newTopicDiscoverer(logf, opts, cfg, hupChan, termChan) + + if td.logf == nil { + t.Errorf("Expected logf to be initialized, got nil") + } + if td.opts != opts { + t.Errorf("Expected opts to be %v, got %v", opts, td.opts) + } + if td.cfg != cfg { + t.Errorf("Expected cfg to be %v, got %v", cfg, td.cfg) + } + if td.hupChan != hupChan { + t.Errorf("Expected hupChan to be %v, got %v", hupChan, td.hupChan) + } + if td.termChan != termChan { + t.Errorf("Expected termChan to be %v, got %v", termChan, td.termChan) + } + if td.topics == nil { + t.Errorf("Expected topics map to be initialized, got nil") + } +} + +// Test generated using Keploy +func TestUpdateTopics_SkipExistingTopics(t *testing.T) { + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + opts := &Options{} + cfg := nsq.NewConfig() + hupChan := make(chan os.Signal, 1) + termChan := make(chan os.Signal, 1) + + td := newTopicDiscoverer(logf, opts, cfg, hupChan, termChan) + td.topics["existing_topic"] = &FileLogger{} + + td.updateTopics([]string{"existing_topic"}) + + if len(td.topics) != 1 { + t.Errorf("Expected topics map to have 1 entry, got %d", len(td.topics)) + } +} + + +// Test generated using Keploy +func TestIsTopicAllowed_InvalidPattern(t *testing.T) { + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + opts := &Options{TopicPattern: "^allowed.*"} + cfg := nsq.NewConfig() + hupChan := make(chan os.Signal, 1) + termChan := make(chan os.Signal, 1) + + td := newTopicDiscoverer(logf, opts, cfg, hupChan, termChan) + + allowed := td.isTopicAllowed("disallowed_topic") + if allowed { + t.Errorf("Expected isTopicAllowed to return false, got true") + } +} + + +// Test generated using Keploy +func TestRun_HupChanSignal(t *testing.T) { + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + opts := &Options{} + cfg := nsq.NewConfig() + hupChan := make(chan os.Signal, 1) + termChan := make(chan os.Signal, 1) + + td := newTopicDiscoverer(logf, opts, cfg, hupChan, termChan) + mockFileLogger := &FileLogger{ + hupChan: make(chan bool, 1), + } + td.topics["test_topic"] = mockFileLogger + + hupChan <- os.Interrupt + + go func() { + td.run() + }() + + select { + case <-mockFileLogger.hupChan: + // Success + case <-time.After(1 * time.Second): + t.Errorf("Expected hupChan signal to be sent to FileLogger") + } +} + + +// Test generated using Keploy +func TestIsTopicAllowed_InvalidRegex(t *testing.T) { + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + opts := &Options{TopicPattern: "["} // Invalid regex pattern + cfg := nsq.NewConfig() + hupChan := make(chan os.Signal, 1) + termChan := make(chan os.Signal, 1) + + td := newTopicDiscoverer(logf, opts, cfg, hupChan, termChan) + + allowed := td.isTopicAllowed("any_topic") + if allowed { + t.Errorf("Expected isTopicAllowed to return false for invalid regex pattern, got true") + } +} + + +// Test generated using Keploy +func TestRun_TermChanSignal(t *testing.T) { + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + opts := &Options{} + cfg := nsq.NewConfig() + hupChan := make(chan os.Signal, 1) + termChan := make(chan os.Signal, 1) + + td := newTopicDiscoverer(logf, opts, cfg, hupChan, termChan) + + done := make(chan bool) + go func() { + td.run() + done <- true + }() + + termChan <- os.Interrupt + + select { + case <-done: + // Success + case <-time.After(1 * time.Second): + t.Errorf("Expected run to terminate on termChan signal") + } +} + From 8b2faaa47074522abbb85cd293512c451adef92d Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Fri, 7 Feb 2025 19:50:46 +0530 Subject: [PATCH 07/14] add: add tests for nsq_to_nsq and nsqadmin functionality --- apps/nsq_to_nsq/nsq_to_nsq_test.go | 125 +++++++++++++++++++++++++++++ apps/nsqadmin/main_test.go | 41 ++++++++++ apps/nsqadmin/options_test.go | 15 ++++ apps/nsqd/main_test.go | 10 +++ 4 files changed, 191 insertions(+) create mode 100644 apps/nsq_to_nsq/nsq_to_nsq_test.go create mode 100644 apps/nsqadmin/options_test.go diff --git a/apps/nsq_to_nsq/nsq_to_nsq_test.go b/apps/nsq_to_nsq/nsq_to_nsq_test.go new file mode 100644 index 000000000..4abdac88e --- /dev/null +++ b/apps/nsq_to_nsq/nsq_to_nsq_test.go @@ -0,0 +1,125 @@ +package main + +import ( + "testing" + "github.com/nsqio/go-nsq" + "github.com/nsqio/nsq/internal/app" +) + + +// Test generated using Keploy +func TestPublishHandler_ShouldPassMessage(t *testing.T) { + requireJSONField = new(string) + *requireJSONField = "field1" + requireJSONValue = new(string) + *requireJSONValue = "value1" + + ph := &PublishHandler{} + js := map[string]interface{}{ + "field1": "value1", + } + + pass, backoff := ph.shouldPassMessage(js) + if !pass || backoff { + t.Errorf("Expected pass=true and backoff=false, got pass=%v, backoff=%v", pass, backoff) + } + + js = map[string]interface{}{ + "field1": "wrong_value", + } + pass, backoff = ph.shouldPassMessage(js) + if pass || backoff { + t.Errorf("Expected pass=false and backoff=false, got pass=%v, backoff=%v", pass, backoff) + } +} + +// Test generated using Keploy +func TestPublishHandler_HandleMessage_JSONUnmarshalError(t *testing.T) { + requireJSONField = new(string) + *requireJSONField = "field1" + + ph := &PublishHandler{} + msg := &nsq.Message{ + Body: []byte(`invalid json`), + } + + err := ph.HandleMessage(msg, "test_topic") + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } +} + + +// Test generated using Keploy +func TestFilterMessage_WhitelistFields(t *testing.T) { + whitelistJSONFields = app.StringArray{"field1", "field2"} + js := map[string]interface{}{ + "field1": "value1", + "field2": 42, + "field3": "should be removed", + } + rawMsg := []byte(`{"field1":"value1","field2":42,"field3":"should be removed"}`) + + filteredMsg, err := filterMessage(js, rawMsg) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + expectedMsg := `{"field1":"value1","field2":42}` + if string(filteredMsg) != expectedMsg { + t.Errorf("Expected %s, got %s", expectedMsg, string(filteredMsg)) + } +} + + +// Test generated using Keploy +func TestFilterMessage_JSONMarshalError(t *testing.T) { + whitelistJSONFields = app.StringArray{"field1"} + js := map[string]interface{}{ + "field1": func() {}, // Invalid type for JSON marshalling + } + rawMsg := []byte(`{"field1":"invalid"}`) + + _, err := filterMessage(js, rawMsg) + if err == nil { + t.Fatalf("Expected an error, got nil") + } +} + + +// Test generated using Keploy +func TestFilterMessage_NoWhitelistFields(t *testing.T) { + whitelistJSONFields = app.StringArray{} + js := map[string]interface{}{ + "field1": "value1", + "field2": "value2", + } + rawMsg := []byte(`{"field1":"value1","field2":"value2"}`) + + filteredMsg, err := filterMessage(js, rawMsg) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + if string(filteredMsg) != string(rawMsg) { + t.Errorf("Expected message to be unchanged when no whitelist fields, got %s", string(filteredMsg)) + } +} + + +// Test generated using Keploy +func TestPublishHandler_HandleMessage_MissingRequiredField(t *testing.T) { + requireJSONField = new(string) + *requireJSONField = "field1" + + ph := &PublishHandler{} + msg := &nsq.Message{ + Body: []byte(`{"field2": "value2"}`), + } + + err := ph.HandleMessage(msg, "test_topic") + if err == nil { + t.Fatalf("Expected an error due to missing required field, got nil") + } +} + diff --git a/apps/nsqadmin/main_test.go b/apps/nsqadmin/main_test.go index 6c39c8d75..b88040a2c 100644 --- a/apps/nsqadmin/main_test.go +++ b/apps/nsqadmin/main_test.go @@ -3,6 +3,8 @@ package main import ( "testing" + "os" + "github.com/mreiferson/go-options" "github.com/nsqio/nsq/internal/lg" "github.com/nsqio/nsq/internal/test" @@ -24,3 +26,42 @@ func TestConfigFlagParsing(t *testing.T) { t.Fatalf("log level: want debug, got %s", opts.LogLevel.String()) } } + +// Test generated using Keploy +func TestProgramInit_NotWindowsService(t *testing.T) { + // Save the original working directory + originalDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + + // Create a mock environment where IsWindowsService() returns false + mockEnv := &MockEnvironment{windowsService: false} + // Create a new program instance + p := &program{} + + // Call Init method + err = p.Init(mockEnv) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + // Get current working directory + cwd, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + + // Check if working directory has not changed + if cwd != originalDir { + t.Errorf("Expected working directory to remain %s, got %s", originalDir, cwd) + } +} + +type MockEnvironment struct { + windowsService bool +} + +func (m *MockEnvironment) IsWindowsService() bool { + return m.windowsService +} diff --git a/apps/nsqadmin/options_test.go b/apps/nsqadmin/options_test.go new file mode 100644 index 000000000..5fb0f33a6 --- /dev/null +++ b/apps/nsqadmin/options_test.go @@ -0,0 +1,15 @@ +package main + +import ( + "testing" +) + + +// Test generated using Keploy +func TestConfigValidate_NoLogLevel(t *testing.T) { + cfg := config{} + cfg.Validate() + if _, exists := cfg["log_level"]; exists { + t.Errorf("Expected log_level to not exist in the config, but it does") + } +} diff --git a/apps/nsqd/main_test.go b/apps/nsqd/main_test.go index bef345eed..1006bc1e3 100644 --- a/apps/nsqd/main_test.go +++ b/apps/nsqd/main_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/BurntSushi/toml" + "github.com/judwhite/go-svc" "github.com/mreiferson/go-options" "github.com/nsqio/nsq/internal/lg" "github.com/nsqio/nsq/internal/test" @@ -39,3 +40,12 @@ func TestConfigFlagParsing(t *testing.T) { t.Fatalf("log level: want debug, got %s", opts.LogLevel.String()) } } + +// Test generated using Keploy +func TestProgramHandle(t *testing.T) { + p := &program{} + err := p.Handle(os.Interrupt) + if err != svc.ErrStop { + t.Fatalf("Expected svc.ErrStop, got %v", err) + } +} From 69843400673b2fdd1a3d8918430ea0e6ffd133e7 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Fri, 7 Feb 2025 20:59:28 +0530 Subject: [PATCH 08/14] chore: add tests for options --- apps/nsqd/options_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 apps/nsqd/options_test.go diff --git a/apps/nsqd/options_test.go b/apps/nsqd/options_test.go new file mode 100644 index 000000000..5fb0a0f69 --- /dev/null +++ b/apps/nsqd/options_test.go @@ -0,0 +1,39 @@ +package main + +import ( + "crypto/tls" + "testing" +) + + +// Test generated using Keploy +func TestTLSMinVersionOption_Set_ValidInput(t *testing.T) { + var tmo tlsMinVersionOption + err := tmo.Set("tls1.2") + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if uint16(tmo) != tls.VersionTLS12 { + t.Errorf("Expected %v, got %v", tls.VersionTLS12, uint16(tmo)) + } +} + +// Test generated using Keploy +func TestTLSMinVersionOption_Set_InvalidInput(t *testing.T) { + var tmo tlsMinVersionOption + err := tmo.Set("invalid") + if err == nil { + t.Errorf("Expected an error, got nil") + } +} + + +// Test generated using Keploy +func TestTLSMinVersionOption_String_UnknownVersion(t *testing.T) { + var tmo tlsMinVersionOption = tlsMinVersionOption(9999) + result := tmo.String() + if result != "9999" { + t.Errorf("Expected '9999', got %v", result) + } +} + From f15f56a6ac451c8c15023318e0d4e3b66dbb9306 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Sat, 8 Feb 2025 01:08:58 +0530 Subject: [PATCH 09/14] chore: adding tests --- apps/nsq_to_file/options_test.go | 14 ++ apps/nsq_to_file/topic_discoverer_test.go | 18 +++ apps/nsqadmin/options_test.go | 13 +- apps/nsqd/options_test.go | 67 ++++++--- apps/to_nsq/to_nsq_test.go | 45 ++++++ bench/bench_channels/bench_channels_test.go | 18 +++ bench/bench_writer/bench_writer_test.go | 59 ++++++++ internal/auth/authorizations_test.go | 67 +++++++++ internal/clusterinfo/types_test.go | 71 +++++++++ internal/http_api/compress_test.go | 101 +++++++++++++ internal/http_api/http_server_test.go | 147 +++++++++++++++++++ internal/http_api/req_params_test.go | 139 ++++++++++++++++++ internal/http_api/topic_channel_args_test.go | 101 +++++++++++++ internal/lg/lg_test.go | 59 ++++++++ 14 files changed, 890 insertions(+), 29 deletions(-) create mode 100644 apps/nsq_to_file/options_test.go create mode 100644 apps/to_nsq/to_nsq_test.go create mode 100644 bench/bench_channels/bench_channels_test.go create mode 100644 bench/bench_writer/bench_writer_test.go create mode 100644 internal/auth/authorizations_test.go create mode 100644 internal/clusterinfo/types_test.go create mode 100644 internal/http_api/compress_test.go create mode 100644 internal/http_api/http_server_test.go create mode 100644 internal/http_api/req_params_test.go create mode 100644 internal/http_api/topic_channel_args_test.go diff --git a/apps/nsq_to_file/options_test.go b/apps/nsq_to_file/options_test.go new file mode 100644 index 000000000..fb6cdbea4 --- /dev/null +++ b/apps/nsq_to_file/options_test.go @@ -0,0 +1,14 @@ +package main + +import ( + "testing" +) + + +// Test generated using Keploy +func TestNewOptions_NotNil(t *testing.T) { + opts := NewOptions() + if opts == nil { + t.Errorf("Expected NewOptions() to return a non-nil pointer.") + } +} diff --git a/apps/nsq_to_file/topic_discoverer_test.go b/apps/nsq_to_file/topic_discoverer_test.go index 88e55ae71..6d38c6b7b 100644 --- a/apps/nsq_to_file/topic_discoverer_test.go +++ b/apps/nsq_to_file/topic_discoverer_test.go @@ -150,3 +150,21 @@ func TestRun_TermChanSignal(t *testing.T) { } } +// Test generated using Keploy +func TestUpdateTopics_SkipDisallowedTopic(t *testing.T) { + logf := func(lvl lg.LogLevel, f string, args ...interface{}) {} + opts := &Options{TopicPattern: "^allowed.*"} + cfg := nsq.NewConfig() + hupChan := make(chan os.Signal, 1) + termChan := make(chan os.Signal, 1) + + td := newTopicDiscoverer(logf, opts, cfg, hupChan, termChan) + + td.updateTopics([]string{"disallowed_topic"}) + + if _, exists := td.topics["disallowed_topic"]; exists { + t.Errorf("Expected topic 'disallowed_topic' to not be added to topics map") + } +} + + diff --git a/apps/nsqadmin/options_test.go b/apps/nsqadmin/options_test.go index 5fb0f33a6..a3008f1d7 100644 --- a/apps/nsqadmin/options_test.go +++ b/apps/nsqadmin/options_test.go @@ -1,15 +1,14 @@ package main import ( - "testing" + "testing" ) - // Test generated using Keploy func TestConfigValidate_NoLogLevel(t *testing.T) { - cfg := config{} - cfg.Validate() - if _, exists := cfg["log_level"]; exists { - t.Errorf("Expected log_level to not exist in the config, but it does") - } + cfg := config{} + cfg.Validate() + if _, exists := cfg["log_level"]; exists { + t.Errorf("Expected log_level to not exist in the config, but it does") + } } diff --git a/apps/nsqd/options_test.go b/apps/nsqd/options_test.go index 5fb0a0f69..c4da4a63f 100644 --- a/apps/nsqd/options_test.go +++ b/apps/nsqd/options_test.go @@ -1,39 +1,62 @@ package main import ( - "crypto/tls" - "testing" -) + "crypto/tls" + "testing" + "github.com/nsqio/nsq/nsqd" +) // Test generated using Keploy func TestTLSMinVersionOption_Set_ValidInput(t *testing.T) { - var tmo tlsMinVersionOption - err := tmo.Set("tls1.2") - if err != nil { - t.Errorf("Expected no error, got %v", err) - } - if uint16(tmo) != tls.VersionTLS12 { - t.Errorf("Expected %v, got %v", tls.VersionTLS12, uint16(tmo)) - } + var tmo tlsMinVersionOption + err := tmo.Set("tls1.2") + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if uint16(tmo) != tls.VersionTLS12 { + t.Errorf("Expected %v, got %v", tls.VersionTLS12, uint16(tmo)) + } } // Test generated using Keploy func TestTLSMinVersionOption_Set_InvalidInput(t *testing.T) { - var tmo tlsMinVersionOption - err := tmo.Set("invalid") - if err == nil { - t.Errorf("Expected an error, got nil") - } + var tmo tlsMinVersionOption + err := tmo.Set("invalid") + if err == nil { + t.Errorf("Expected an error, got nil") + } } - // Test generated using Keploy func TestTLSMinVersionOption_String_UnknownVersion(t *testing.T) { - var tmo tlsMinVersionOption = tlsMinVersionOption(9999) - result := tmo.String() - if result != "9999" { - t.Errorf("Expected '9999', got %v", result) - } + var tmo tlsMinVersionOption = tlsMinVersionOption(9999) + result := tmo.String() + if result != "9999" { + t.Errorf("Expected '9999', got %v", result) + } +} + +// Test generated using Keploy +func TestTLSRequiredOption_Set_TCPHTTPS(t *testing.T) { + var tro tlsRequiredOption + err := tro.Set("tcp-https") + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if int(tro) != int(nsqd.TLSRequiredExceptHTTP) { + t.Errorf("Expected %v, got %v", nsqd.TLSRequiredExceptHTTP, tro) + } } +// Test generated using Keploy +func TestTLSRequiredOption_Set_True(t *testing.T) { + var tro tlsRequiredOption + err := tro.Set("true") + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if int(tro) != int(nsqd.TLSRequired) { + t.Errorf("Expected %v, got %v", nsqd.TLSRequired, tro) + } +} diff --git a/apps/to_nsq/to_nsq_test.go b/apps/to_nsq/to_nsq_test.go new file mode 100644 index 000000000..b1b2e8cd2 --- /dev/null +++ b/apps/to_nsq/to_nsq_test.go @@ -0,0 +1,45 @@ +package main + +import ( + "bufio" + "os" + "strings" + "testing" + "time" + + "github.com/nsqio/go-nsq" +) + +// Test generated using Keploy +func TestMain_RateThrottling(t *testing.T) { + os.Args = []string{"cmd", "--topic=test", "--nsqd-tcp-address=127.0.0.1:4150", "--rate=1"} + go func() { + defer func() { + if r := recover(); r != nil { + t.Errorf("Unexpected panic: %v", r) + } + }() + main() + }() + time.Sleep(2 * time.Second) // Allow throttling to occur +} + +// Test generated using Keploy +func TestReadAndPublish_OnlyDelimiter(t *testing.T) { + r := bufio.NewReader(strings.NewReader("\n")) + producers := make(map[string]*nsq.Producer) + err := readAndPublish(r, '\n', producers) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } +} + +// Test generated using Keploy +func TestReadAndPublish_NoDelimiter(t *testing.T) { + r := bufio.NewReader(strings.NewReader("test_message")) + producers := make(map[string]*nsq.Producer) + err := readAndPublish(r, '\n', producers) + if err == nil { + t.Errorf("Expected an error for missing delimiter, got nil") + } +} diff --git a/bench/bench_channels/bench_channels_test.go b/bench/bench_channels/bench_channels_test.go new file mode 100644 index 000000000..188c36a75 --- /dev/null +++ b/bench/bench_channels/bench_channels_test.go @@ -0,0 +1,18 @@ +package main + +import ( + "testing" +) + + +// Test generated using Keploy +func TestSubWorkerConnectionError(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("Expected subWorker to panic on connection error, but it did not") + } + }() + + // Call subWorker with an invalid TCP address + subWorker(1, "invalid:address", "test_topic", "test_channel", make(chan int), make(chan int), 1) +} diff --git a/bench/bench_writer/bench_writer_test.go b/bench/bench_writer/bench_writer_test.go new file mode 100644 index 000000000..603ea9180 --- /dev/null +++ b/bench/bench_writer/bench_writer_test.go @@ -0,0 +1,59 @@ +package main + +import ( + "testing" + "time" + "net" + "sync/atomic" +) + + +// Test generated using Keploy +func TestPubWorker_TCPConnectionError(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("Expected pubWorker to panic on TCP connection error") + } + }() + + // Call pubWorker with an invalid TCP address + pubWorker(1*time.Second, "invalid_address", 10, nil, "test_topic", make(chan int), make(chan int)) +} + +// Test generated using Keploy +func TestPubWorker_EmptyBatch(t *testing.T) { + // Mock data + batch := [][]byte{} + rdyChan := make(chan int, 1) + goChan := make(chan int, 1) + + // Mock TCP server + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("Failed to start mock server: %v", err) + } + defer listener.Close() + + go func() { + conn, err := listener.Accept() + if err != nil { + t.Errorf("Failed to accept connection: %v", err) + return + } + defer conn.Close() + }() + + // Run pubWorker + go func() { + pubWorker(1*time.Second, listener.Addr().String(), 1, batch, "test_topic", rdyChan, goChan) + }() + + // Allow some time for the worker to execute + time.Sleep(2 * time.Second) + + // Validate totalMsgCount + if atomic.LoadInt64(&totalMsgCount) != 0 { + t.Errorf("Expected totalMsgCount to remain 0 for an empty batch") + } +} + diff --git a/internal/auth/authorizations_test.go b/internal/auth/authorizations_test.go new file mode 100644 index 000000000..a1855c262 --- /dev/null +++ b/internal/auth/authorizations_test.go @@ -0,0 +1,67 @@ +package auth + +import ( + "testing" + "time" +) + + +// Test generated using Keploy +func TestAuthorization_HasPermission_ValidPermission(t *testing.T) { + auth := Authorization{ + Permissions: []string{"publish", "subscribe"}, + } + if !auth.HasPermission("publish") { + t.Errorf("Expected HasPermission to return true for 'publish', got false") + } +} + +// Test generated using Keploy +func TestState_IsExpired_Expired(t *testing.T) { + state := State{ + Expires: time.Now().Add(-1 * time.Hour), + } + if !state.IsExpired() { + t.Errorf("Expected IsExpired to return true for expired state, got false") + } +} + + +// Test generated using Keploy +func TestAuthorization_HasPermission_InvalidPermission(t *testing.T) { + auth := Authorization{ + Permissions: []string{"publish", "subscribe"}, + } + if auth.HasPermission("delete") { + t.Errorf("Expected HasPermission to return false for 'delete', got true") + } +} + + +// Test generated using Keploy +func TestAuthorization_IsAllowed_InvalidTopic(t *testing.T) { + auth := Authorization{ + Topic: "test-topic", + Channels: []string{"test-channel"}, + } + if auth.IsAllowed("invalid-topic", "test-channel") { + t.Errorf("Expected IsAllowed to return false for invalid topic, got true") + } +} + + +// Test generated using Keploy +func TestState_IsAllowed_InvalidTopic(t *testing.T) { + state := State{ + Authorizations: []Authorization{ + { + Topic: "test-topic", + Channels: []string{"test-channel"}, + }, + }, + } + if state.IsAllowed("invalid-topic", "test-channel") { + t.Errorf("Expected IsAllowed to return false for unauthorized topic, got true") + } +} + diff --git a/internal/clusterinfo/types_test.go b/internal/clusterinfo/types_test.go new file mode 100644 index 000000000..477602daa --- /dev/null +++ b/internal/clusterinfo/types_test.go @@ -0,0 +1,71 @@ +package clusterinfo + +import ( + "testing" +) + + +// Test generated using Keploy +func TestClientStats_HasUserAgent_ReturnsTrue(t *testing.T) { + cs := &ClientStats{ + UserAgent: "test-agent", + } + + if !cs.HasUserAgent() { + t.Errorf("Expected HasUserAgent to return true when UserAgent is not empty") + } +} + +// Test generated using Keploy +func TestClientStats_HasSampleRate_ReturnsTrue(t *testing.T) { + cs := &ClientStats{ + SampleRate: 50, + } + + if !cs.HasSampleRate() { + t.Errorf("Expected HasSampleRate to return true when SampleRate > 0") + } +} + + +// Test generated using Keploy +func TestProducers_HTTPAddrs_ReturnsCorrectAddresses(t *testing.T) { + producers := Producers{ + &Producer{ + BroadcastAddress: "127.0.0.1", + HTTPPort: 4151, + }, + &Producer{ + BroadcastAddress: "192.168.1.1", + HTTPPort: 4151, + }, + } + + addrs := producers.HTTPAddrs() + expectedAddrs := []string{"127.0.0.1:4151", "192.168.1.1:4151"} + + for i, addr := range addrs { + if addr != expectedAddrs[i] { + t.Errorf("Expected address %s, got %s", expectedAddrs[i], addr) + } + } +} + + +// Test generated using Keploy +func TestProducers_Search_FindsProducer(t *testing.T) { + producer := &Producer{ + BroadcastAddress: "127.0.0.1", + HTTPPort: 4151, + } + producers := Producers{producer} + + found := producers.Search("127.0.0.1:4151") + if found == nil { + t.Fatalf("Expected to find producer, got nil") + } + if found != producer { + t.Errorf("Expected to find the correct producer, got a different one") + } +} + diff --git a/internal/http_api/compress_test.go b/internal/http_api/compress_test.go new file mode 100644 index 000000000..dc2fd9f77 --- /dev/null +++ b/internal/http_api/compress_test.go @@ -0,0 +1,101 @@ +package http_api + +import ( + "net/http/httptest" + "testing" + "net/http" +) + + +// Test generated using Keploy +func TestCompressResponseWriterHeader(t *testing.T) { + mockResponseWriter := httptest.NewRecorder() + compressWriter := &compressResponseWriter{ + ResponseWriter: mockResponseWriter, + } + + compressWriter.Header().Set("Content-Type", "application/json") + if compressWriter.Header().Get("Content-Type") != "application/json" { + t.Errorf("Expected Content-Type to be 'application/json', got %v", compressWriter.Header().Get("Content-Type")) + } +} + +// Test generated using Keploy +func TestCompressResponseWriterWriteHeader(t *testing.T) { + mockResponseWriter := httptest.NewRecorder() + compressWriter := &compressResponseWriter{ + ResponseWriter: mockResponseWriter, + } + + compressWriter.Header().Set("Content-Length", "123") + compressWriter.WriteHeader(http.StatusOK) + + if compressWriter.Header().Get("Content-Length") != "" { + t.Errorf("Expected Content-Length to be removed, but it was not") + } + if mockResponseWriter.Code != http.StatusOK { + t.Errorf("Expected status code to be %v, got %v", http.StatusOK, mockResponseWriter.Code) + } +} + + +// Test generated using Keploy +func TestCompressResponseWriterWrite(t *testing.T) { + mockResponseWriter := httptest.NewRecorder() + compressWriter := &compressResponseWriter{ + ResponseWriter: mockResponseWriter, + Writer: mockResponseWriter, + } + + data := []byte("test data") + _, err := compressWriter.Write(data) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + if compressWriter.Header().Get("Content-Type") == "" { + t.Errorf("Expected Content-Type to be set, but it was not") + } + if compressWriter.Header().Get("Content-Length") != "" { + t.Errorf("Expected Content-Length to be removed, but it was not") + } +} + + +// Test generated using Keploy +func TestCompressHandlerGzip(t *testing.T) { + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("test data")) + }) + compressHandler := CompressHandler(handler) + + req := httptest.NewRequest("GET", "/", nil) + req.Header.Set("Accept-Encoding", "gzip") + rec := httptest.NewRecorder() + + compressHandler.ServeHTTP(rec, req) + + if rec.Header().Get("Content-Encoding") != "gzip" { + t.Errorf("Expected Content-Encoding to be 'gzip', got %v", rec.Header().Get("Content-Encoding")) + } +} + + +// Test generated using Keploy +func TestCompressHandlerDeflate(t *testing.T) { + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("test data")) + }) + compressHandler := CompressHandler(handler) + + req := httptest.NewRequest("GET", "/", nil) + req.Header.Set("Accept-Encoding", "deflate") + rec := httptest.NewRecorder() + + compressHandler.ServeHTTP(rec, req) + + if rec.Header().Get("Content-Encoding") != "deflate" { + t.Errorf("Expected Content-Encoding to be 'deflate', got %v", rec.Header().Get("Content-Encoding")) + } +} + diff --git a/internal/http_api/http_server_test.go b/internal/http_api/http_server_test.go new file mode 100644 index 000000000..e07436763 --- /dev/null +++ b/internal/http_api/http_server_test.go @@ -0,0 +1,147 @@ +package http_api + +import ( + "testing" + "github.com/nsqio/nsq/internal/lg" + "fmt" + "net" + "net/http" + "time" +) + + +// Test generated using Keploy +func TestLogWriter_Write(t *testing.T) { + var loggedLevel lg.LogLevel + var loggedFormat string + var loggedArgs []interface{} + + mockLogFunc := func(lvl lg.LogLevel, f string, args ...interface{}) { + loggedLevel = lvl + loggedFormat = f + loggedArgs = args + } + + lw := logWriter{logf: mockLogFunc} + message := "test message" + n, err := lw.Write([]byte(message)) + + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + if n != len(message) { + t.Errorf("Expected %d bytes written, got %d", n, len(message)) + } + + if loggedLevel != lg.WARN { + t.Errorf("Expected log level WARN, got %v", loggedLevel) + } + + if loggedFormat != "%s" { + t.Errorf("Expected log format '%%s', got %s", loggedFormat) + } + + if len(loggedArgs) != 1 || loggedArgs[0].(string) != message { + t.Errorf("Expected logged args [%s], got %v", message, loggedArgs) + } +} + +// Test generated using Keploy +func TestServe_NormalOperation(t *testing.T) { + var logMessages []string + + mockLogFunc := func(lvl lg.LogLevel, f string, args ...interface{}) { + logMessages = append(logMessages, fmt.Sprintf(f, args...)) + } + + listener, err := net.Listen("tcp", "localhost:0") + if err != nil { + t.Fatalf("Failed to create listener: %v", err) + } + defer listener.Close() + + handler := http.NewServeMux() + + // Run Serve in a separate goroutine because it blocks + done := make(chan error) + go func() { + err := Serve(listener, handler, "test_proto", mockLogFunc) + done <- err + }() + + // Wait a bit to let the server start + time.Sleep(100 * time.Millisecond) + + // Make a simple HTTP request to ensure the server is running + resp, err := http.Get(fmt.Sprintf("http://%s", listener.Addr().String())) + if err != nil { + t.Errorf("Failed to connect to server: %v", err) + } else { + resp.Body.Close() + } + + // Close the listener to stop the server + listener.Close() + + // Wait for Serve to finish + err = <-done + if err != nil { + t.Errorf("Serve returned error: %v", err) + } + + // Check that appropriate log messages were logged + expectedStartMessage := fmt.Sprintf("test_proto: listening on %s", listener.Addr()) + expectedCloseMessage := fmt.Sprintf("test_proto: closing %s", listener.Addr()) + if len(logMessages) < 2 { + t.Errorf("Expected at least 2 log messages, got %d", len(logMessages)) + } else { + if logMessages[0] != expectedStartMessage { + t.Errorf("Expected log message '%s', got '%s'", expectedStartMessage, logMessages[0]) + } + if logMessages[len(logMessages)-1] != expectedCloseMessage { + t.Errorf("Expected log message '%s', got '%s'", expectedCloseMessage, logMessages[len(logMessages)-1]) + } + } +} + + +// Test generated using Keploy +func TestServe_ServerError(t *testing.T) { + var logMessages []string + + mockLogFunc := func(lvl lg.LogLevel, f string, args ...interface{}) { + logMessages = append(logMessages, fmt.Sprintf(f, args...)) + } + + handler := http.NewServeMux() + + // Create a faulty listener that returns an error on Accept + faultyListener := &FaultyListener{} + + err := Serve(faultyListener, handler, "test_proto", mockLogFunc) + if err == nil { + t.Errorf("Expected error from Serve, got nil") + } else if err.Error() != "http.Serve() error - forced error" { + t.Errorf("Unexpected error message: %v", err) + } +} + +// FaultyListener is a net.Listener that returns an error on Accept +type FaultyListener struct{} + +func (fl *FaultyListener) Accept() (net.Conn, error) { + return nil, fmt.Errorf("forced error") +} + +func (fl *FaultyListener) Close() error { + return nil +} + +func (fl *FaultyListener) Addr() net.Addr { + return &net.TCPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: 0, + } +} + diff --git a/internal/http_api/req_params_test.go b/internal/http_api/req_params_test.go new file mode 100644 index 000000000..e65139213 --- /dev/null +++ b/internal/http_api/req_params_test.go @@ -0,0 +1,139 @@ +package http_api + +import ( + "io" + "net/http" + "net/url" + "strings" + "testing" + "errors" +) + + +// Test generated using Keploy +func TestNewReqParams_ValidRequest(t *testing.T) { + reqBody := "key1=value1&key2=value2" + req := &http.Request{ + URL: &url.URL{ + RawQuery: "param1=value1¶m2=value2", + }, + Body: io.NopCloser(strings.NewReader(reqBody)), + } + + reqParams, err := NewReqParams(req) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + if reqParams.Values.Get("param1") != "value1" { + t.Errorf("Expected param1 to be 'value1', got %v", reqParams.Values.Get("param1")) + } + + if string(reqParams.Body) != reqBody { + t.Errorf("Expected body to be '%v', got %v", reqBody, string(reqParams.Body)) + } +} + +// Test generated using Keploy +func TestNewReqParams_InvalidQuery(t *testing.T) { + req := &http.Request{ + URL: &url.URL{ + RawQuery: "%zz", // Invalid query + }, + Body: io.NopCloser(strings.NewReader("")), + } + + _, err := NewReqParams(req) + if err == nil { + t.Fatalf("Expected an error, got nil") + } +} + + +// Test generated using Keploy +type errorReader struct{} + +func (e *errorReader) Read(p []byte) (n int, err error) { + return 0, errors.New("read error") +} + +func TestNewReqParams_BodyReadError(t *testing.T) { + req := &http.Request{ + URL: &url.URL{ + RawQuery: "param1=value1", + }, + Body: io.NopCloser(&errorReader{}), + } + + _, err := NewReqParams(req) + if err == nil { + t.Fatalf("Expected an error, got nil") + } +} + + +// Test generated using Keploy +func TestReqParams_Get_ExistingKey(t *testing.T) { + reqParams := &ReqParams{ + Values: url.Values{ + "key1": {"value1"}, + }, + } + + value, err := reqParams.Get("key1") + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + if value != "value1" { + t.Errorf("Expected value to be 'value1', got %v", value) + } +} + + +// Test generated using Keploy +func TestReqParams_Get_NonExistingKey(t *testing.T) { + reqParams := &ReqParams{ + Values: url.Values{}, + } + + _, err := reqParams.Get("key1") + if err == nil { + t.Fatalf("Expected an error, got nil") + } +} + + +// Test generated using Keploy +func TestReqParams_GetAll_ExistingKey(t *testing.T) { + reqParams := &ReqParams{ + Values: url.Values{ + "key1": {"value1", "value2"}, + }, + } + + values, err := reqParams.GetAll("key1") + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + if len(values) != 2 || values[0] != "value1" || values[1] != "value2" { + t.Errorf("Expected values to be ['value1', 'value2'], got %v", values) + } +} + + +// Test generated using Keploy +func TestReqParams_GetAll_InvalidKey(t *testing.T) { + reqParams := &ReqParams{ + Values: url.Values{ + "key1": {"value1", "value2"}, + }, + } + + _, err := reqParams.GetAll("key@1") + if err == nil { + t.Fatalf("Expected an error, got nil") + } +} + diff --git a/internal/http_api/topic_channel_args_test.go b/internal/http_api/topic_channel_args_test.go new file mode 100644 index 000000000..cbd372d2c --- /dev/null +++ b/internal/http_api/topic_channel_args_test.go @@ -0,0 +1,101 @@ +package http_api + +import ( + "errors" + "testing" +) + + +// Test generated using Keploy +type MockGetter struct { + values map[string]string + errors map[string]error +} + +func (m *MockGetter) Get(key string) (string, error) { + if err, ok := m.errors[key]; ok { + return "", err + } + if val, ok := m.values[key]; ok { + return val, nil + } + return "", errors.New("key not found") +} + +func TestGetTopicChannelArgs_MissingTopic(t *testing.T) { + mockGetter := &MockGetter{ + errors: map[string]error{ + "topic": errors.New("missing"), + }, + } + + topic, channel, err := GetTopicChannelArgs(mockGetter) + if topic != "" || channel != "" || err == nil || err.Error() != "MISSING_ARG_TOPIC" { + t.Errorf("Expected error 'MISSING_ARG_TOPIC', got topic: '%v', channel: '%v', err: %v", topic, channel, err) + } +} + +// Test generated using Keploy +func TestGetTopicChannelArgs_InvalidTopic(t *testing.T) { + mockGetter := &MockGetter{ + values: map[string]string{ + "topic": "invalid_topic!", // invalid topic name + }, + } + + topic, channel, err := GetTopicChannelArgs(mockGetter) + if topic != "" || channel != "" || err == nil || err.Error() != "INVALID_ARG_TOPIC" { + t.Errorf("Expected error 'INVALID_ARG_TOPIC', got topic: '%v', channel: '%v', err: %v", topic, channel, err) + } +} + + +// Test generated using Keploy +func TestGetTopicChannelArgs_MissingChannel(t *testing.T) { + mockGetter := &MockGetter{ + values: map[string]string{ + "topic": "valid_topic", + }, + errors: map[string]error{ + "channel": errors.New("missing"), + }, + } + + topic, channel, err := GetTopicChannelArgs(mockGetter) + if topic != "" || channel != "" || err == nil || err.Error() != "MISSING_ARG_CHANNEL" { + t.Errorf("Expected error 'MISSING_ARG_CHANNEL', got topic: '%v', channel: '%v', err: %v", topic, channel, err) + } +} + + +// Test generated using Keploy +func TestGetTopicChannelArgs_InvalidChannel(t *testing.T) { + mockGetter := &MockGetter{ + values: map[string]string{ + "topic": "valid_topic", + "channel": "invalid_channel#", // invalid channel name + }, + } + + topic, channel, err := GetTopicChannelArgs(mockGetter) + if topic != "" || channel != "" || err == nil || err.Error() != "INVALID_ARG_CHANNEL" { + t.Errorf("Expected error 'INVALID_ARG_CHANNEL', got topic: '%v', channel: '%v', err: %v", topic, channel, err) + } +} + + +// Test generated using Keploy +func TestGetTopicChannelArgs_ValidArgs(t *testing.T) { + mockGetter := &MockGetter{ + values: map[string]string{ + "topic": "valid_topic", + "channel": "valid_channel", + }, + } + + topic, channel, err := GetTopicChannelArgs(mockGetter) + if topic != "valid_topic" || channel != "valid_channel" || err != nil { + t.Errorf("Expected topic: 'valid_topic', channel: 'valid_channel', got topic: '%v', channel: '%v', err: %v", topic, channel, err) + } +} + diff --git a/internal/lg/lg_test.go b/internal/lg/lg_test.go index 2d8e506cc..a7bca100a 100644 --- a/internal/lg/lg_test.go +++ b/internal/lg/lg_test.go @@ -39,3 +39,62 @@ func TestLogging(t *testing.T) { } test.Equal(t, 5, logger.Count) } + +// Test generated using Keploy +func TestNilLoggerOutput(t *testing.T) { + logger := NilLogger{} + err := logger.Output(1, "test message") + if err != nil { + t.Errorf("Expected nil, got %v", err) + } +} + +// Test generated using Keploy +func TestLogLevelGet(t *testing.T) { + level := LogLevel(INFO) + result := level.Get() + if result != INFO { + t.Errorf("Expected %v, got %v", INFO, result) + } +} + +// Test generated using Keploy +func TestLogLevelSetValid(t *testing.T) { + var level LogLevel + err := level.Set("debug") + if err != nil { + t.Errorf("Expected nil, got %v", err) + } + if level != DEBUG { + t.Errorf("Expected %v, got %v", DEBUG, level) + } +} + +// Test generated using Keploy +func TestLogLevelSetInvalid(t *testing.T) { + var level LogLevel + err := level.Set("invalid") + if err == nil { + t.Errorf("Expected an error, got nil") + } +} + +// Test generated using Keploy +func TestParseLogLevelValid(t *testing.T) { + tests := map[string]LogLevel{ + "debug": DEBUG, + "info": INFO, + "warn": WARN, + "error": ERROR, + "fatal": FATAL, + } + for input, expected := range tests { + result, err := ParseLogLevel(input) + if err != nil { + t.Errorf("Expected nil, got %v", err) + } + if result != expected { + t.Errorf("For input %s, expected %v, got %v", input, expected, result) + } + } +} From 21d33091c336fabe93a9220a63e4dff364b07973 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Sat, 8 Feb 2025 01:20:07 +0530 Subject: [PATCH 10/14] chore: add tests for protocol --- internal/protocol/byte_base10_test.go | 30 +++++- internal/protocol/errors_test.go | 95 +++++++++++++++++++ internal/protocol/names_test.go | 35 +++++++ internal/protocol/protocol_test.go | 127 ++++++++++++++++++++++++++ 4 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 internal/protocol/errors_test.go create mode 100644 internal/protocol/names_test.go create mode 100644 internal/protocol/protocol_test.go diff --git a/internal/protocol/byte_base10_test.go b/internal/protocol/byte_base10_test.go index 5fd4715b9..776d4b012 100644 --- a/internal/protocol/byte_base10_test.go +++ b/internal/protocol/byte_base10_test.go @@ -1,7 +1,7 @@ package protocol import ( - "testing" + "testing" ) var result uint64 @@ -23,3 +23,31 @@ func BenchmarkByteToBase10Invalid(b *testing.B) { } result = n } + +// Test generated using Keploy +func TestByteToBase10ValidInput(t *testing.T) { + input := []byte{'1', '2', '3', '4', '5'} + expected := uint64(12345) + result, err := ByteToBase10(input) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + + +// Test generated using Keploy +func TestByteToBase10InvalidInput(t *testing.T) { + input := []byte{'1', '2', 'a', '4', '5'} + expected := uint64(0) + result, err := ByteToBase10(input) + if err == nil { + t.Errorf("Expected an error, got nil") + } + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + diff --git a/internal/protocol/errors_test.go b/internal/protocol/errors_test.go new file mode 100644 index 000000000..020d4f023 --- /dev/null +++ b/internal/protocol/errors_test.go @@ -0,0 +1,95 @@ +package protocol + +import ( + "testing" +) + + +// Test generated using Keploy +func TestClientErr_Error(t *testing.T) { + err := &ClientErr{ + Code: "E100", + Desc: "Invalid request", + } + expected := "E100 Invalid request" + result := err.Error() + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + +// Test generated using Keploy +func TestClientErr_Parent(t *testing.T) { + parentErr := &ClientErr{ + Code: "E101", + Desc: "Parent error", + } + err := &ClientErr{ + ParentErr: parentErr, + } + result := err.Parent() + if result != parentErr { + t.Errorf("Expected %v, got %v", parentErr, result) + } +} + + +// Test generated using Keploy +func TestNewClientErr(t *testing.T) { + parentErr := &ClientErr{ + Code: "E102", + Desc: "Parent error", + } + code := "E103" + desc := "New error" + err := NewClientErr(parentErr, code, desc) + if err.ParentErr != parentErr || err.Code != code || err.Desc != desc { + t.Errorf("Expected ParentErr: %v, Code: %v, Desc: %v, got ParentErr: %v, Code: %v, Desc: %v", parentErr, code, desc, err.ParentErr, err.Code, err.Desc) + } +} + + +// Test generated using Keploy +func TestFatalClientErr_Error(t *testing.T) { + err := &FatalClientErr{ + Code: "F100", + Desc: "Fatal error occurred", + } + expected := "F100 Fatal error occurred" + result := err.Error() + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + + +// Test generated using Keploy +func TestFatalClientErr_Parent(t *testing.T) { + parentErr := &FatalClientErr{ + Code: "F101", + Desc: "Parent fatal error", + } + err := &FatalClientErr{ + ParentErr: parentErr, + } + result := err.Parent() + if result != parentErr { + t.Errorf("Expected %v, got %v", parentErr, result) + } +} + + +// Test generated using Keploy +func TestNewFatalClientErr(t *testing.T) { + parentErr := &FatalClientErr{ + Code: "F102", + Desc: "Parent fatal error", + } + code := "F103" + desc := "New fatal error" + err := NewFatalClientErr(parentErr, code, desc) + if err.ParentErr != parentErr || err.Code != code || err.Desc != desc { + t.Errorf("Expected ParentErr: %v, Code: %v, Desc: %v, got ParentErr: %v, Code: %v, Desc: %v", parentErr, code, desc, err.ParentErr, err.Code, err.Desc) + } +} + diff --git a/internal/protocol/names_test.go b/internal/protocol/names_test.go new file mode 100644 index 000000000..8e81c7d16 --- /dev/null +++ b/internal/protocol/names_test.go @@ -0,0 +1,35 @@ +package protocol + +import ( + "testing" +) + + +// Test generated using Keploy +func TestIsValidTopicName_ValidName_ReturnsTrue(t *testing.T) { + validName := "valid_topic_name" + result := IsValidTopicName(validName) + if !result { + t.Errorf("Expected true, got false for valid topic name: %s", validName) + } +} + +// Test generated using Keploy +func TestIsValidTopicName_TooLongName_ReturnsFalse(t *testing.T) { + longName := "this_is_a_very_long_topic_name_that_exceeds_the_sixty_four_character_limit" + result := IsValidTopicName(longName) + if result { + t.Errorf("Expected false, got true for too long topic name: %s", longName) + } +} + + +// Test generated using Keploy +func TestIsValidChannelName_ValidName_ReturnsTrue(t *testing.T) { + validName := "valid_channel_name" + result := IsValidChannelName(validName) + if !result { + t.Errorf("Expected true, got false for valid channel name: %s", validName) + } +} + diff --git a/internal/protocol/protocol_test.go b/internal/protocol/protocol_test.go new file mode 100644 index 000000000..f900dc5f8 --- /dev/null +++ b/internal/protocol/protocol_test.go @@ -0,0 +1,127 @@ +package protocol + +import ( + "bytes" + "testing" + "io" +) + + +// Test generated using Keploy +func TestSendResponse_HappyPath(t *testing.T) { + data := []byte("test data") + buf := &bytes.Buffer{} + + n, err := SendResponse(buf, data) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + expectedLength := len(data) + 4 + if n != expectedLength { + t.Errorf("Expected %d bytes written, got %d", expectedLength, n) + } + + expectedOutput := append([]byte{0, 0, 0, byte(len(data))}, data...) + if !bytes.Equal(buf.Bytes(), expectedOutput) { + t.Errorf("Expected output %v, got %v", expectedOutput, buf.Bytes()) + } +} + +// Test generated using Keploy +type FailingWriter struct{} + +func (f *FailingWriter) Write(p []byte) (n int, err error) { + return 0, io.ErrClosedPipe +} + +func TestSendResponse_WriteLengthError(t *testing.T) { + data := []byte("test data") + writer := &FailingWriter{} + + n, err := SendResponse(writer, data) + if err == nil { + t.Fatalf("Expected an error, got nil") + } + + if n != 0 { + t.Errorf("Expected 0 bytes written, got %d", n) + } +} + + +// Test generated using Keploy +func TestSendFramedResponse_HappyPath(t *testing.T) { + data := []byte("test data") + frameType := int32(1) + buf := &bytes.Buffer{} + + n, err := SendFramedResponse(buf, frameType, data) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + expectedLength := len(data) + 8 + if n != expectedLength { + t.Errorf("Expected %d bytes written, got %d", expectedLength, n) + } + + expectedOutput := append([]byte{0, 0, 0, byte(len(data) + 4)}, []byte{0, 0, 0, byte(frameType)}...) + expectedOutput = append(expectedOutput, data...) + if !bytes.Equal(buf.Bytes(), expectedOutput) { + t.Errorf("Expected output %v, got %v", expectedOutput, buf.Bytes()) + } +} + + +// Test generated using Keploy +type PartialHeaderWriter struct { + writeCount int +} + +func (p *PartialHeaderWriter) Write(b []byte) (int, error) { + if p.writeCount == 0 { + p.writeCount++ + return len(b) / 2, nil + } + return 0, io.ErrClosedPipe +} + +func TestSendFramedResponse_PartialFrameHeaderWrite(t *testing.T) { + data := []byte("test data") + frameType := int32(1) + writer := &PartialHeaderWriter{} + + n, err := SendFramedResponse(writer, frameType, data) + if err == nil { + t.Fatalf("Expected an error, got nil") + } + + if n != len(data)/2 { + t.Errorf("Expected %d bytes written, got %d", len(data)/2, n) + } +} + + +// Test generated using Keploy +type AlwaysErrorWriter struct{} + +func (a *AlwaysErrorWriter) Write(p []byte) (n int, err error) { + return 0, io.ErrClosedPipe +} + +func TestSendFramedResponse_ErrorWriter(t *testing.T) { + data := []byte("test data") + frameType := int32(1) + writer := &AlwaysErrorWriter{} + + n, err := SendFramedResponse(writer, frameType, data) + if err == nil { + t.Fatalf("Expected an error, got nil") + } + + if n != 0 { + t.Errorf("Expected 0 bytes written, got %d", n) + } +} + From 56fc963c8746201233eb88f9eb7709c4db48ea01 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Sat, 8 Feb 2025 01:54:55 +0530 Subject: [PATCH 11/14] add: test for internal functions --- internal/quantile/aggregate_test.go | 187 ++++++++++++++++ internal/quantile/quantile_test.go | 127 +++++++++++ internal/statsd/client_test.go | 74 +++++++ internal/statsd/host_test.go | 16 ++ internal/stringy/slice_test.go | 33 +++ internal/stringy/template_test.go | 50 +++++ internal/test/assertions_test.go | 35 +++ internal/test/fakes_test.go | 203 ++++++++++++++++++ internal/test/logger_test.go | 39 ++++ internal/util/wait_group_wrapper_test.go | 21 ++ internal/version/binary_test.go | 18 ++ .../writers/boundary_buffered_writer_test.go | 67 ++++++ internal/writers/spread_writer_test.go | 102 +++++++++ 13 files changed, 972 insertions(+) create mode 100644 internal/quantile/aggregate_test.go create mode 100644 internal/quantile/quantile_test.go create mode 100644 internal/statsd/client_test.go create mode 100644 internal/statsd/host_test.go create mode 100644 internal/stringy/template_test.go create mode 100644 internal/test/assertions_test.go create mode 100644 internal/test/fakes_test.go create mode 100644 internal/test/logger_test.go create mode 100644 internal/util/wait_group_wrapper_test.go create mode 100644 internal/version/binary_test.go create mode 100644 internal/writers/boundary_buffered_writer_test.go create mode 100644 internal/writers/spread_writer_test.go diff --git a/internal/quantile/aggregate_test.go b/internal/quantile/aggregate_test.go new file mode 100644 index 000000000..2415cece5 --- /dev/null +++ b/internal/quantile/aggregate_test.go @@ -0,0 +1,187 @@ +package quantile + +import ( + "testing" +) + + +// Test generated using Keploy +func TestUnmarshalJSON_ValidInput(t *testing.T) { + jsonData := `{ + "count": 10, + "percentiles": [ + {"value": 1.0, "quantile": 0.5}, + {"value": 2.0, "quantile": 0.9} + ], + "topic": "test_topic", + "channel": "test_channel", + "host": "test_host" + }` + + var aggregate E2eProcessingLatencyAggregate + err := aggregate.UnmarshalJSON([]byte(jsonData)) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + if aggregate.Count != 10 { + t.Errorf("Expected Count to be 10, got %d", aggregate.Count) + } + if len(aggregate.Percentiles) != 2 { + t.Errorf("Expected 2 percentiles, got %d", len(aggregate.Percentiles)) + } + if aggregate.Topic != "test_topic" { + t.Errorf("Expected Topic to be 'test_topic', got %s", aggregate.Topic) + } + if aggregate.Channel != "test_channel" { + t.Errorf("Expected Channel to be 'test_channel', got %s", aggregate.Channel) + } + if aggregate.Addr != "test_host" { + t.Errorf("Expected Addr to be 'test_host', got %s", aggregate.Addr) + } +} + +// Test generated using Keploy +func TestUnmarshalJSON_InvalidInput(t *testing.T) { + invalidJSON := `{"count": "invalid_count"}` + + var aggregate E2eProcessingLatencyAggregate + err := aggregate.UnmarshalJSON([]byte(invalidJSON)) + if err == nil { + t.Fatalf("Expected an error, got nil") + } +} + + +// Test generated using Keploy +func TestLen_CorrectCount(t *testing.T) { + aggregate := &E2eProcessingLatencyAggregate{ + Percentiles: []map[string]float64{ + {"quantile": 0.5}, + {"quantile": 0.9}, + }, + } + + if aggregate.Len() != 2 { + t.Errorf("Expected Len to be 2, got %d", aggregate.Len()) + } +} + + +// Test generated using Keploy +func TestLess_CorrectComparison(t *testing.T) { + aggregate := &E2eProcessingLatencyAggregate{ + Percentiles: []map[string]float64{ + {"percentile": 0.9}, + {"percentile": 0.5}, + }, + } + + if !aggregate.Less(0, 1) { + t.Errorf("Expected Less(0, 1) to return true, got false") + } + if aggregate.Less(1, 0) { + t.Errorf("Expected Less(1, 0) to return false, got true") + } +} + + +// Test generated using Keploy +func TestSwap_CorrectSwapping(t *testing.T) { + aggregate := &E2eProcessingLatencyAggregate{ + Percentiles: []map[string]float64{ + {"percentile": 0.9}, + {"percentile": 0.5}, + }, + } + + aggregate.Swap(0, 1) + + if aggregate.Percentiles[0]["percentile"] != 0.5 { + t.Errorf("Expected first element to be 0.5, got %f", aggregate.Percentiles[0]["percentile"]) + } + if aggregate.Percentiles[1]["percentile"] != 0.9 { + t.Errorf("Expected second element to be 0.9, got %f", aggregate.Percentiles[1]["percentile"]) + } +} + + +// Test generated using Keploy +func TestAdd_WithEmptyPercentiles(t *testing.T) { + aggregate1 := &E2eProcessingLatencyAggregate{ + Count: 5, + Percentiles: []map[string]float64{ + {"quantile": 0.5, "max": 2.0, "min": 1.0, "average": 1.5, "count": 5}, + }, + Topic: "test_topic", + Channel: "test_channel", + Addr: "test_host", + } + aggregate2 := &E2eProcessingLatencyAggregate{ + Count: 10, + Percentiles: []map[string]float64{}, + } + + aggregate1.Add(aggregate2) + + if aggregate1.Count != 15 { + t.Errorf("Expected Count to be 15, got %d", aggregate1.Count) + } + if len(aggregate1.Percentiles) != 1 { + t.Errorf("Expected 1 percentile, got %d", len(aggregate1.Percentiles)) + } + + // Verify that Percentiles remain unchanged + p0 := aggregate1.Percentiles[0] + if p0["count"] != 5 { + t.Errorf("Expected count 5 for the percentile, got %f", p0["count"]) + } +} + + +// Test generated using Keploy +func TestAdd_NonOverlappingQuantiles(t *testing.T) { + aggregate1 := &E2eProcessingLatencyAggregate{ + Count: 5, + Percentiles: []map[string]float64{ + {"quantile": 0.5, "max": 2.0, "min": 1.0, "average": 1.5, "count": 5}, + }, + Topic: "test_topic", + Channel: "test_channel", + Addr: "test_host", + } + aggregate2 := &E2eProcessingLatencyAggregate{ + Count: 5, + Percentiles: []map[string]float64{ + {"quantile": 0.9, "max": 4.0, "min": 3.0, "average": 3.5, "count": 5}, + }, + } + + aggregate1.Add(aggregate2) + + if aggregate1.Count != 10 { + t.Errorf("Expected Count to be 10, got %d", aggregate1.Count) + } + if len(aggregate1.Percentiles) != 2 { + t.Errorf("Expected 2 percentiles, got %d", len(aggregate1.Percentiles)) + } + + // Check first percentile + p0 := aggregate1.Percentiles[0] + if p0["quantile"] != 0.5 { + t.Errorf("Expected first quantile to be 0.5, got %f", p0["quantile"]) + } + if p0["count"] != 5 { + t.Errorf("Expected count 5 for quantile 0.5, got %f", p0["count"]) + } + + // Check second percentile + p1 := aggregate1.Percentiles[1] + if p1["quantile"] != 0.9 { + t.Errorf("Expected second quantile to be 0.9, got %f", p1["quantile"]) + } + if p1["count"] != 5 { + t.Errorf("Expected count 5 for quantile 0.9, got %f", p1["count"]) + } +} + diff --git a/internal/quantile/quantile_test.go b/internal/quantile/quantile_test.go new file mode 100644 index 000000000..18afd7602 --- /dev/null +++ b/internal/quantile/quantile_test.go @@ -0,0 +1,127 @@ +package quantile + +import ( + "testing" + "time" +) + + +// Test generated using Keploy +func TestNewQuantileInitialization(t *testing.T) { + windowTime := 10 * time.Second + percentiles := []float64{0.5, 0.9, 0.99} + q := New(windowTime, percentiles) + + if q == nil { + t.Fatal("Expected Quantile object, got nil") + } + + if q.MoveWindowTime != windowTime/2 { + t.Errorf("Expected MoveWindowTime %v, got %v", windowTime/2, q.MoveWindowTime) + } + + if len(q.Percentiles) != len(percentiles) { + t.Errorf("Expected Percentiles length %d, got %d", len(percentiles), len(q.Percentiles)) + } + + for i, p := range percentiles { + if q.Percentiles[i] != p { + t.Errorf("Expected Percentile %v at index %d, got %v", p, i, q.Percentiles[i]) + } + } +} + +// Test generated using Keploy +func TestResultOnNilQuantile(t *testing.T) { + var q *Quantile + result := q.Result() + + if result == nil { + t.Fatal("Expected Result object, got nil") + } + + if result.Count != 0 { + t.Errorf("Expected Count 0, got %d", result.Count) + } + + if len(result.Percentiles) != 0 { + t.Errorf("Expected Percentiles length 0, got %d", len(result.Percentiles)) + } +} + + +// Test generated using Keploy +func TestInsertAddsValue(t *testing.T) { + windowTime := 10 * time.Second + percentiles := []float64{0.5, 0.9, 0.99} + q := New(windowTime, percentiles) + + msgStartTime := time.Now().Add(-1 * time.Second).UnixNano() + q.Insert(msgStartTime) + + if q.currentStream.Count() != 1 { + t.Errorf("Expected currentStream count 1, got %d", q.currentStream.Count()) + } +} + + +// Test generated using Keploy +func TestMergeQuantiles(t *testing.T) { + windowTime := 10 * time.Second + percentiles := []float64{0.5, 0.9, 0.99} + q1 := New(windowTime, percentiles) + q2 := New(windowTime, percentiles) + + q1.Insert(time.Now().Add(-1 * time.Second).UnixNano()) + q2.Insert(time.Now().Add(-2 * time.Second).UnixNano()) + + q1.Merge(q2) + + if q1.streams[q1.currentIndex].Count() != 2 { + t.Errorf("Expected merged stream count 2, got %d", q1.streams[q1.currentIndex].Count()) + } +} + + +// Test generated using Keploy +func TestMoveWindow(t *testing.T) { + windowTime := 10 * time.Second + percentiles := []float64{0.5, 0.9, 0.99} + q := New(windowTime, percentiles) + + q.currentStream.Insert(1.0) + q.moveWindow() + + if q.currentStream.Count() != 0 { + t.Errorf("Expected currentStream count 0 after moveWindow, got %d", q.currentStream.Count()) + } + + if q.currentIndex != 1 { + t.Errorf("Expected currentIndex 1, got %d", q.currentIndex) + } +} + + +// Test generated using Keploy +func TestResultAggregation(t *testing.T) { + windowTime := 10 * time.Second + percentiles := []float64{0.5, 0.9, 0.99} + q := New(windowTime, percentiles) + + q.Insert(time.Now().Add(-1 * time.Second).UnixNano()) + q.Insert(time.Now().Add(-2 * time.Second).UnixNano()) + + result := q.Result() + if result == nil { + t.Fatal("Expected Result object, got nil") + } + + if result.Count != 2 { + t.Errorf("Expected Count 2, got %d", result.Count) + } + + if len(result.Percentiles) != len(percentiles) { + t.Errorf("Expected Percentiles length %d, got %d", len(percentiles), len(result.Percentiles)) + } +} + diff --git a/internal/statsd/client_test.go b/internal/statsd/client_test.go new file mode 100644 index 000000000..451538e9e --- /dev/null +++ b/internal/statsd/client_test.go @@ -0,0 +1,74 @@ +package statsd + +import ( + "bytes" + "testing" +) + + +// Test generated using Keploy +func TestClient_Incr_ValidInput(t *testing.T) { + var buf bytes.Buffer + client := NewClient(&buf, "test.prefix.") + + err := client.Incr("test_stat", 1) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + expected := "test.prefix.test_stat:1|c\n" + if buf.String() != expected { + t.Errorf("Expected %q, got %q", expected, buf.String()) + } +} + +// Test generated using Keploy +func TestClient_Decr_ValidInput(t *testing.T) { + var buf bytes.Buffer + client := NewClient(&buf, "test.prefix.") + + err := client.Decr("test_stat", 1) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + expected := "test.prefix.test_stat:-1|c\n" + if buf.String() != expected { + t.Errorf("Expected %q, got %q", expected, buf.String()) + } +} + + +// Test generated using Keploy +func TestClient_Timing_ValidInput(t *testing.T) { + var buf bytes.Buffer + client := NewClient(&buf, "test.prefix.") + + err := client.Timing("test_stat", 123) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + expected := "test.prefix.test_stat:123|ms\n" + if buf.String() != expected { + t.Errorf("Expected %q, got %q", expected, buf.String()) + } +} + + +// Test generated using Keploy +func TestClient_Gauge_ValidInput(t *testing.T) { + var buf bytes.Buffer + client := NewClient(&buf, "test.prefix.") + + err := client.Gauge("test_stat", 456) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + expected := "test.prefix.test_stat:456|g\n" + if buf.String() != expected { + t.Errorf("Expected %q, got %q", expected, buf.String()) + } +} + diff --git a/internal/statsd/host_test.go b/internal/statsd/host_test.go new file mode 100644 index 000000000..e225d78e6 --- /dev/null +++ b/internal/statsd/host_test.go @@ -0,0 +1,16 @@ +package statsd + +import ( + "testing" +) + + +// Test generated using Keploy +func TestHostKey_ReplacesDotsAndColons(t *testing.T) { + input := "example.com:8080" + expected := "example_com_8080" + result := HostKey(input) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} diff --git a/internal/stringy/slice_test.go b/internal/stringy/slice_test.go index cd5b1224f..6578fc7e1 100644 --- a/internal/stringy/slice_test.go +++ b/internal/stringy/slice_test.go @@ -3,6 +3,8 @@ package stringy_test import ( "testing" + "reflect" + "github.com/nsqio/nsq/internal/stringy" ) @@ -23,3 +25,34 @@ func TestUniq(t *testing.T) { t.Fatal("values len is incorrect") } } + +// Test generated using Keploy +func TestAdd_NewStringAppended(t *testing.T) { + input := []string{"a", "b", "c"} + result := stringy.Add(input, "d") + expected := []string{"a", "b", "c", "d"} + if !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %v, got %v", expected, result) + } +} + +// Test generated using Keploy +func TestAdd_ExistingStringNotAppended(t *testing.T) { + input := []string{"a", "b", "c"} + result := stringy.Add(input, "b") + expected := []string{"a", "b", "c"} + if !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %v, got %v", expected, result) + } +} + +// Test generated using Keploy +func TestUnion_CombineSlicesNoDuplicates(t *testing.T) { + input1 := []string{"a", "b", "c"} + input2 := []string{"b", "c", "d"} + result := stringy.Union(input1, input2) + expected := []string{"a", "b", "c", "d"} + if !reflect.DeepEqual(result, expected) { + t.Errorf("Expected %v, got %v", expected, result) + } +} diff --git a/internal/stringy/template_test.go b/internal/stringy/template_test.go new file mode 100644 index 000000000..0d873167e --- /dev/null +++ b/internal/stringy/template_test.go @@ -0,0 +1,50 @@ +package stringy + +import ( + "testing" +) + + +// Test generated using Keploy +func TestNanoSecondToHuman_SecondsConversion(t *testing.T) { + input := 1500000000.0 + expected := "1.5s" + result := NanoSecondToHuman(input) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + +// Test generated using Keploy +func TestNanoSecondToHuman_MillisecondsConversion(t *testing.T) { + input := 1500000.0 + expected := "1.5ms" + result := NanoSecondToHuman(input) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + + +// Test generated using Keploy +func TestNanoSecondToHuman_MicrosecondsConversion(t *testing.T) { + input := 1500.0 + expected := "1.5us" + result := NanoSecondToHuman(input) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + + +// Test generated using Keploy +func TestNanoSecondToHuman_NanosecondsConversion(t *testing.T) { + input := 500.0 + expected := "500.0ns" + result := NanoSecondToHuman(input) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} + + diff --git a/internal/test/assertions_test.go b/internal/test/assertions_test.go new file mode 100644 index 000000000..670994dab --- /dev/null +++ b/internal/test/assertions_test.go @@ -0,0 +1,35 @@ +package test + +import ( + "testing" +) + + +// Test generated using Keploy +func TestEqual_DeeplyEqualValues_NoFail(t *testing.T) { + expected := map[string]int{"key1": 1, "key2": 2} + actual := map[string]int{"key1": 1, "key2": 2} + Equal(t, expected, actual) +} + +// Test generated using Keploy +func TestNotEqual_NotDeeplyEqualValues_NoFail(t *testing.T) { + expected := map[string]int{"key1": 1, "key2": 2} + actual := map[string]int{"key1": 1, "key2": 3} + NotEqual(t, expected, actual) +} + + +// Test generated using Keploy +func TestNil_NilValue_NoFail(t *testing.T) { + var object interface{} = nil + Nil(t, object) +} + + +// Test generated using Keploy +func TestNotNil_NonNilValue_NoFail(t *testing.T) { + object := "not nil" + NotNil(t, object) +} + diff --git a/internal/test/fakes_test.go b/internal/test/fakes_test.go new file mode 100644 index 000000000..16b8f4dd2 --- /dev/null +++ b/internal/test/fakes_test.go @@ -0,0 +1,203 @@ +package test + +import ( + "testing" + "net" + "time" + "fmt" +) + + +// Test generated using Keploy +func TestFakeNetConn_Read(t *testing.T) { + expectedData := []byte("test data") + expectedLen := len(expectedData) + expectedErr := error(nil) + + fakeConn := FakeNetConn{ + ReadFunc: func(b []byte) (int, error) { + copy(b, expectedData) + return expectedLen, expectedErr + }, + } + + buffer := make([]byte, 10) + n, err := fakeConn.Read(buffer) + + if n != expectedLen { + t.Errorf("Expected length %d, got %d", expectedLen, n) + } + if err != expectedErr { + t.Errorf("Expected error %v, got %v", expectedErr, err) + } + if string(buffer[:n]) != string(expectedData) { + t.Errorf("Expected data %s, got %s", expectedData, buffer[:n]) + } +} + +// Test generated using Keploy +func TestFakeNetConn_Write(t *testing.T) { + inputData := []byte("test data") + expectedLen := len(inputData) + expectedErr := error(nil) + + fakeConn := FakeNetConn{ + WriteFunc: func(b []byte) (int, error) { + if string(b) != string(inputData) { + t.Errorf("Expected data %s, got %s", inputData, b) + } + return expectedLen, expectedErr + }, + } + + n, err := fakeConn.Write(inputData) + + if n != expectedLen { + t.Errorf("Expected length %d, got %d", expectedLen, n) + } + if err != expectedErr { + t.Errorf("Expected error %v, got %v", expectedErr, err) + } +} + + +// Test generated using Keploy +func TestFakeNetConn_Close(t *testing.T) { + expectedErr := error(nil) + + fakeConn := FakeNetConn{ + CloseFunc: func() error { + return expectedErr + }, + } + + err := fakeConn.Close() + + if err != expectedErr { + t.Errorf("Expected error %v, got %v", expectedErr, err) + } +} + + +// Test generated using Keploy +func TestFakeNetConn_LocalAddr(t *testing.T) { + expectedAddr := fakeNetAddr{} + + fakeConn := FakeNetConn{ + LocalAddrFunc: func() net.Addr { + return expectedAddr + }, + } + + addr := fakeConn.LocalAddr() + + if addr != expectedAddr { + t.Errorf("Expected address %v, got %v", expectedAddr, addr) + } +} + + +// Test generated using Keploy +func TestFakeNetConn_RemoteAddr(t *testing.T) { + expectedAddr := fakeNetAddr{} + + fakeConn := FakeNetConn{ + RemoteAddrFunc: func() net.Addr { + return expectedAddr + }, + } + + addr := fakeConn.RemoteAddr() + + if addr != expectedAddr { + t.Errorf("Expected address %v, got %v", expectedAddr, addr) + } +} + + +// Test generated using Keploy +func TestFakeNetConn_SetDeadline(t *testing.T) { + expectedErr := error(nil) + expectedTime := time.Now() + + fakeConn := FakeNetConn{ + SetDeadlineFunc: func(t time.Time) error { + if !t.Equal(expectedTime) { + return fmt.Errorf("Expected time %v, got %v", expectedTime, t) + } + return expectedErr + }, + } + + // Test with valid time + err := fakeConn.SetDeadline(expectedTime) + if err != expectedErr { + t.Errorf("Expected error %v, got %v", expectedErr, err) + } + + // Test with zero time (invalid case) + zeroTime := time.Time{} + err = fakeConn.SetDeadline(zeroTime) + if err == nil { + t.Errorf("Expected an error for zero time, got nil") + } +} + + +// Test generated using Keploy +func TestFakeNetConn_SetReadDeadline(t *testing.T) { + expectedErr := error(nil) + expectedTime := time.Now() + + fakeConn := FakeNetConn{ + SetReadDeadlineFunc: func(t time.Time) error { + if !t.Equal(expectedTime) { + return fmt.Errorf("Expected time %v, got %v", expectedTime, t) + } + return expectedErr + }, + } + + // Test with valid time + err := fakeConn.SetReadDeadline(expectedTime) + if err != expectedErr { + t.Errorf("Expected error %v, got %v", expectedErr, err) + } + + // Test with zero time (invalid case) + zeroTime := time.Time{} + err = fakeConn.SetReadDeadline(zeroTime) + if err == nil { + t.Errorf("Expected an error for zero time, got nil") + } +} + + +// Test generated using Keploy +func TestFakeNetConn_SetWriteDeadline(t *testing.T) { + expectedErr := error(nil) + expectedTime := time.Now() + + fakeConn := FakeNetConn{ + SetWriteDeadlineFunc: func(t time.Time) error { + if !t.Equal(expectedTime) { + return fmt.Errorf("Expected time %v, got %v", expectedTime, t) + } + return expectedErr + }, + } + + // Test with valid time + err := fakeConn.SetWriteDeadline(expectedTime) + if err != expectedErr { + t.Errorf("Expected error %v, got %v", expectedErr, err) + } + + // Test with zero time (invalid case) + zeroTime := time.Time{} + err = fakeConn.SetWriteDeadline(zeroTime) + if err == nil { + t.Errorf("Expected an error for zero time, got nil") + } +} + diff --git a/internal/test/logger_test.go b/internal/test/logger_test.go new file mode 100644 index 000000000..1733435da --- /dev/null +++ b/internal/test/logger_test.go @@ -0,0 +1,39 @@ +package test + +import ( + "testing" +) + + +// Test generated using Keploy +// Mock implementation of tbLog +type mockTbLog struct { + loggedMessages []string +} + +func (m *mockTbLog) Log(args ...interface{}) { + for _, arg := range args { + if msg, ok := arg.(string); ok { + m.loggedMessages = append(m.loggedMessages, msg) + } + } +} + +func TestNewTestLogger_OutputCallsLog(t *testing.T) { + mockLog := &mockTbLog{} + logger := NewTestLogger(mockLog) + + testMessage := "test log message" + err := logger.Output(1, testMessage) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + if len(mockLog.loggedMessages) != 1 { + t.Errorf("Expected 1 logged message, got %d", len(mockLog.loggedMessages)) + } + + if mockLog.loggedMessages[0] != testMessage { + t.Errorf("Expected logged message to be '%s', got '%s'", testMessage, mockLog.loggedMessages[0]) + } +} diff --git a/internal/util/wait_group_wrapper_test.go b/internal/util/wait_group_wrapper_test.go new file mode 100644 index 000000000..dce55d2d1 --- /dev/null +++ b/internal/util/wait_group_wrapper_test.go @@ -0,0 +1,21 @@ +package util + +import ( + "testing" +) + +// Test generated using Keploy +func TestWaitGroupWrapper_Wrap_CallbackExecution(t *testing.T) { + var wgWrapper WaitGroupWrapper + executed := false + + wgWrapper.Wrap(func() { + executed = true + }) + + wgWrapper.Wait() + + if !executed { + t.Errorf("Expected callback to be executed, but it was not") + } +} diff --git a/internal/version/binary_test.go b/internal/version/binary_test.go new file mode 100644 index 000000000..b88cad659 --- /dev/null +++ b/internal/version/binary_test.go @@ -0,0 +1,18 @@ +package version + +import ( + "fmt" + "runtime" + "testing" +) + + +// Test generated using Keploy +func TestStringFunction_NormalInput(t *testing.T) { + appName := "TestApp" + expected := fmt.Sprintf("%s v%s (built w/%s)", appName, Binary, runtime.Version()) + result := String(appName) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} diff --git a/internal/writers/boundary_buffered_writer_test.go b/internal/writers/boundary_buffered_writer_test.go new file mode 100644 index 000000000..328fea6ae --- /dev/null +++ b/internal/writers/boundary_buffered_writer_test.go @@ -0,0 +1,67 @@ +package writers + +import ( + "bytes" + "io" + "testing" +) + + +// Test generated using Keploy +func TestNewBoundaryBufferedWriter_Initialization(t *testing.T) { + var writer io.Writer = &bytes.Buffer{} + size := 1024 + b := NewBoundaryBufferedWriter(writer, size) + + if b == nil { + t.Fatalf("Expected BoundaryBufferedWriter to be initialized, got nil") + } + + if b.bw.Size() != size { + t.Errorf("Expected buffer size %d, got %d", size, b.bw.Size()) + } +} + +// Test generated using Keploy +func TestBoundaryBufferedWriter_Write_BufferFlush(t *testing.T) { + var buf bytes.Buffer + writer := NewBoundaryBufferedWriter(&buf, 10) + + data := []byte("12345678901") // Exceeds buffer size of 10 + n, err := writer.Write(data) + + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + if n != len(data) { + t.Errorf("Expected %d bytes written, got %d", len(data), n) + } + + if buf.String() != string(data) { + t.Errorf("Expected buffer content %q, got %q", string(data), buf.String()) + } +} + + +// Test generated using Keploy +func TestBoundaryBufferedWriter_Flush(t *testing.T) { + var buf bytes.Buffer + writer := NewBoundaryBufferedWriter(&buf, 10) + + data := []byte("12345") + _, err := writer.Write(data) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + err = writer.Flush() + if err != nil { + t.Fatalf("Expected no error on flush, got %v", err) + } + + if buf.String() != string(data) { + t.Errorf("Expected buffer content %q, got %q", string(data), buf.String()) + } +} + diff --git a/internal/writers/spread_writer_test.go b/internal/writers/spread_writer_test.go new file mode 100644 index 000000000..a79adffae --- /dev/null +++ b/internal/writers/spread_writer_test.go @@ -0,0 +1,102 @@ +package writers + +import ( + "testing" + "time" +) + + +// Test generated using Keploy +type MockWriter struct { + WrittenData [][]byte +} + +func (m *MockWriter) Write(p []byte) (n int, err error) { + b := make([]byte, len(p)) + copy(b, p) + m.WrittenData = append(m.WrittenData, b) + return len(p), nil +} + +func TestNewSpreadWriter_Initialization(t *testing.T) { + exitCh := make(chan int) + mockWriter := &MockWriter{} + interval := time.Second + spreadWriter := NewSpreadWriter(mockWriter, interval, exitCh) + + if spreadWriter.w != mockWriter { + t.Errorf("Expected writer to be initialized") + } + if spreadWriter.interval != interval { + t.Errorf("Expected interval to be initialized") + } + if spreadWriter.buf == nil || len(spreadWriter.buf) != 0 { + t.Errorf("Expected buffer to be initialized and empty") + } + if spreadWriter.exitCh != exitCh { + t.Errorf("Expected exitCh to be initialized") + } +} + +// Test generated using Keploy +func TestWrite_AppendsToBuffer(t *testing.T) { + exitCh := make(chan int) + mockWriter := &MockWriter{} + spreadWriter := NewSpreadWriter(mockWriter, time.Second, exitCh) + + input := []byte("test data") + n, err := spreadWriter.Write(input) + + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + if n != len(input) { + t.Errorf("Expected %d bytes written, got %d", len(input), n) + } + if len(spreadWriter.buf) != 1 || string(spreadWriter.buf[0]) != "test data" { + t.Errorf("Buffer does not contain the expected data") + } +} + + +// Test generated using Keploy +func TestFlush_EmptyBuffer_WaitsInterval(t *testing.T) { + exitCh := make(chan int) + mockWriter := &MockWriter{} + spreadWriter := NewSpreadWriter(mockWriter, 100*time.Millisecond, exitCh) + + start := time.Now() + spreadWriter.Flush() + elapsed := time.Since(start) + + if elapsed < 100*time.Millisecond { + t.Errorf("Flush did not wait for the interval") + } + if len(mockWriter.WrittenData) != 0 { + t.Errorf("Expected no data to be written") + } +} + + +// Test generated using Keploy +func TestFlush_WritesAndClearsBuffer(t *testing.T) { + exitCh := make(chan int) + mockWriter := &MockWriter{} + spreadWriter := NewSpreadWriter(mockWriter, time.Second, exitCh) + + spreadWriter.Write([]byte("data1")) + spreadWriter.Write([]byte("data2")) + + spreadWriter.Flush() + + if len(mockWriter.WrittenData) != 2 { + t.Errorf("Expected 2 writes, got %d", len(mockWriter.WrittenData)) + } + if string(mockWriter.WrittenData[0]) != "data1" || string(mockWriter.WrittenData[1]) != "data2" { + t.Errorf("Written data does not match expected values") + } + if len(spreadWriter.buf) != 0 { + t.Errorf("Buffer was not cleared after flush") + } +} + From a653738276b4a97116c392d2a17066cf0ec853b3 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Sat, 8 Feb 2025 02:24:05 +0530 Subject: [PATCH 12/14] chore: add tests for nsqd --- nsqadmin/notify_test.go | 64 ++++++++++++++++++++++++++++++++ nsqd/channel_test.go | 24 ++++++++++++ nsqd/client_v2_test.go | 31 ++++++++++++++++ nsqd/dummy_backend_queue_test.go | 35 +++++++++++++++++ nsqd/guid_test.go | 41 +++++++++++++++++++- 5 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 nsqadmin/notify_test.go create mode 100644 nsqd/client_v2_test.go create mode 100644 nsqd/dummy_backend_queue_test.go diff --git a/nsqadmin/notify_test.go b/nsqadmin/notify_test.go new file mode 100644 index 000000000..e78b44725 --- /dev/null +++ b/nsqadmin/notify_test.go @@ -0,0 +1,64 @@ +package nsqadmin + +import ( + "net/http" + "testing" + "encoding/base64" +) + + +// Test generated using Keploy +func TestBasicAuthUser_EmptyAuthorizationHeader(t *testing.T) { + req := &http.Request{ + Header: http.Header{}, + } + user := basicAuthUser(req) + if user != "" { + t.Errorf("Expected empty string, got %v", user) + } +} + +// Test generated using Keploy +func TestBasicAuthUser_InvalidBase64(t *testing.T) { + req := &http.Request{ + Header: http.Header{ + "Authorization": []string{"Basic invalid_base64"}, + }, + } + user := basicAuthUser(req) + if user != "" { + t.Errorf("Expected empty string, got %v", user) + } +} + + +// Test generated using Keploy +func TestBasicAuthUser_NoColonInDecodedString(t *testing.T) { + req := &http.Request{ + Header: http.Header{ + "Authorization": []string{"Basic " + base64.StdEncoding.EncodeToString([]byte("invalidstring"))}, + }, + } + user := basicAuthUser(req) + if user != "" { + t.Errorf("Expected empty string, got %v", user) + } +} + + +// Test generated using Keploy +func TestBasicAuthUser_ValidAuthorizationHeader(t *testing.T) { + username := "testuser" + password := "testpass" + auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password)) + req := &http.Request{ + Header: http.Header{ + "Authorization": []string{auth}, + }, + } + user := basicAuthUser(req) + if user != username { + t.Errorf("Expected %v, got %v", username, user) + } +} + diff --git a/nsqd/channel_test.go b/nsqd/channel_test.go index f629aecb0..db6d9fb50 100644 --- a/nsqd/channel_test.go +++ b/nsqd/channel_test.go @@ -9,6 +9,8 @@ import ( "testing" "time" + "sync/atomic" + "github.com/nsqio/nsq/internal/test" ) @@ -248,3 +250,25 @@ func TestChannelHealth(t *testing.T) { resp.Body.Close() test.Equal(t, "OK", string(body)) } + +// Test generated using Keploy +func TestPutMessage_ChannelExiting(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + _, _, nsqd := mustStartNSQD(opts) + defer os.RemoveAll(opts.DataPath) + defer nsqd.Exit() + + topicName := "test_put_message_exiting" + strconv.Itoa(int(time.Now().Unix())) + topic := nsqd.GetTopic(topicName) + channel := topic.GetChannel("ch") + + // Simulate channel exiting + atomic.StoreInt32(&channel.exitFlag, 1) + + msg := NewMessage(topic.GenerateID(), []byte("test")) + err := channel.PutMessage(msg) + + test.NotNil(t, err) + test.Equal(t, "exiting", err.Error()) +} diff --git a/nsqd/client_v2_test.go b/nsqd/client_v2_test.go new file mode 100644 index 000000000..1fd87adea --- /dev/null +++ b/nsqd/client_v2_test.go @@ -0,0 +1,31 @@ +package nsqd + +import ( + "strings" + "testing" + "time" +) + + +// Test generated using Keploy +func TestClientV2Stats_String_Consumer(t *testing.T) { + currentTime := time.Now().Add(-5 * time.Minute) + stats := ClientV2Stats{ + ClientID: "test-client", + Hostname: "test-host", + Version: "1.0", + RemoteAddress: "127.0.0.1:4150", + State: stateConnected, + ReadyCount: 10, + InFlightCount: 2, + FinishCount: 100, + RequeueCount: 5, + MessageCount: 150, + ConnectTime: currentTime.Unix(), + } + + result := stats.String() + if !strings.Contains(result, "state: 2") { + t.Errorf("Expected result to contain 'state: 2', got %s", result) + } +} diff --git a/nsqd/dummy_backend_queue_test.go b/nsqd/dummy_backend_queue_test.go new file mode 100644 index 000000000..18952347c --- /dev/null +++ b/nsqd/dummy_backend_queue_test.go @@ -0,0 +1,35 @@ +package nsqd + +import ( + "testing" +) + + +// Test generated using Keploy +func TestDummyBackendQueue_Put_ReturnsNil(t *testing.T) { + queue := newDummyBackendQueue() + err := queue.Put([]byte("test")) + if err != nil { + t.Errorf("Expected nil, got %v", err) + } +} + +// Test generated using Keploy +func TestDummyBackendQueue_Close_ReturnsNil(t *testing.T) { + queue := newDummyBackendQueue() + err := queue.Close() + if err != nil { + t.Errorf("Expected nil, got %v", err) + } +} + + +// Test generated using Keploy +func TestDummyBackendQueue_Depth_ReturnsZero(t *testing.T) { + queue := newDummyBackendQueue() + depth := queue.Depth() + if depth != 0 { + t.Errorf("Expected 0, got %v", depth) + } +} + diff --git a/nsqd/guid_test.go b/nsqd/guid_test.go index dd98d9638..b1a95309d 100644 --- a/nsqd/guid_test.go +++ b/nsqd/guid_test.go @@ -1,8 +1,9 @@ package nsqd import ( - "testing" - "unsafe" + "testing" + "unsafe" + "time" ) func BenchmarkGUIDCopy(b *testing.B) { @@ -40,3 +41,39 @@ func BenchmarkGUID(b *testing.B) { } b.Logf("okays=%d errors=%d bads=%d", okays, errors, fails) } + +// Test generated using Keploy +func TestNewGUIDFactoryInitialization(t *testing.T) { + nodeID := int64(123) + factory := NewGUIDFactory(nodeID) + if factory.nodeID != nodeID { + t.Errorf("Expected nodeID %d, got %d", nodeID, factory.nodeID) + } +} + + +// Test generated using Keploy +func TestNewGUID_TimeBackwards(t *testing.T) { + factory := NewGUIDFactory(1) + factory.lastTimestamp = time.Now().UnixNano() >> 20 + factory.lastTimestamp += 1 // Simulate a future timestamp + + _, err := factory.NewGUID() + if err != ErrTimeBackwards { + t.Errorf("Expected error %v, got %v", ErrTimeBackwards, err) + } +} + + +// Test generated using Keploy +func TestNewGUID_SequenceExpired(t *testing.T) { + factory := NewGUIDFactory(1) + factory.lastTimestamp = time.Now().UnixNano() >> 20 + factory.sequence = sequenceMask // Simulate sequence reaching its limit + + _, err := factory.NewGUID() + if err != ErrSequenceExpired { + t.Errorf("Expected error %v, got %v", ErrSequenceExpired, err) + } +} + From 29304eb14f87bb88dcbd833888d67d613c664899 Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Sat, 8 Feb 2025 03:03:26 +0530 Subject: [PATCH 13/14] chore: add tests for nsqd --- nsqd/message_test.go | 31 +++++++++++++++++++++ nsqd/nsqd_test.go | 40 +++++++++++++++++++++++++++ nsqd/options_test.go | 17 ++++++++++++ nsqd/protocol_v2_test.go | 46 +++++++++++++++++++++++++++++++ nsqd/stats_test.go | 44 ++++++++++++++++++++++++++++++ nsqd/statsd_test.go | 17 ++++++++++++ nsqd/topic_test.go | 59 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 254 insertions(+) create mode 100644 nsqd/message_test.go create mode 100644 nsqd/options_test.go create mode 100644 nsqd/statsd_test.go diff --git a/nsqd/message_test.go b/nsqd/message_test.go new file mode 100644 index 000000000..f10db8e54 --- /dev/null +++ b/nsqd/message_test.go @@ -0,0 +1,31 @@ +package nsqd + +import ( + "bytes" + "testing" +) + + +// Test generated using Keploy +func TestMessage_WriteTo(t *testing.T) { + id := MessageID{} + body := []byte("test body") + msg := NewMessage(id, body) + msg.Attempts = 5 + + var buf bytes.Buffer + n, err := msg.WriteTo(&buf) + if err != nil { + t.Fatalf("WriteTo failed: %v", err) + } + + expectedSize := int64(10 + len(id) + len(body)) // 10 bytes for Timestamp + Attempts, 16 bytes for ID, len(body) for Body + if n != expectedSize { + t.Errorf("Expected written size %v, got %v", expectedSize, n) + } + + writtenData := buf.Bytes() + if len(writtenData) != int(expectedSize) { + t.Errorf("Expected buffer size %v, got %v", expectedSize, len(writtenData)) + } +} diff --git a/nsqd/nsqd_test.go b/nsqd/nsqd_test.go index 2351854c8..e6387cf8e 100644 --- a/nsqd/nsqd_test.go +++ b/nsqd/nsqd_test.go @@ -459,3 +459,43 @@ func TestUnixSocketStartup(t *testing.T) { test.Equal(t, isSocket(opts.TCPAddress), true) test.Equal(t, isSocket(opts.HTTPAddress), true) } + +// Test generated using Keploy +func TestIsAuthEnabled_NoAuthAddresses(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + nsqd, err := New(opts) + test.Nil(t, err) + defer nsqd.Exit() + + test.Equal(t, false, nsqd.IsAuthEnabled()) +} + +// Test generated using Keploy +func TestLoadMetadata_MissingFile(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + _, _, nsqd := mustStartNSQD(opts) + defer os.RemoveAll(opts.DataPath) + defer nsqd.Exit() + + err := nsqd.LoadMetadata() + test.Nil(t, err) +} + +// Test generated using Keploy +func TestDeleteExistingTopic_RemovesTopic(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + _, _, nsqd := mustStartNSQD(opts) + defer os.RemoveAll(opts.DataPath) + defer nsqd.Exit() + + topicName := "test_topic" + nsqd.GetTopic(topicName) // Create the topic + err := nsqd.DeleteExistingTopic(topicName) + test.Nil(t, err) + + _, err = nsqd.GetExistingTopic(topicName) + test.NotNil(t, err) // Ensure the topic no longer exists +} diff --git a/nsqd/options_test.go b/nsqd/options_test.go new file mode 100644 index 000000000..ce7707b43 --- /dev/null +++ b/nsqd/options_test.go @@ -0,0 +1,17 @@ +package nsqd + +import ( + "testing" +) + + +// Test generated using Keploy +func TestHasExperiment_ExperimentExists_ReturnsTrue(t *testing.T) { + options := Options{ + Experiments: []string{"topology-aware-consumption"}, + } + result := options.HasExperiment(TopologyAwareConsumption) + if !result { + t.Errorf("Expected true, got false") + } +} diff --git a/nsqd/protocol_v2_test.go b/nsqd/protocol_v2_test.go index e7d9f20e3..110cd50ca 100644 --- a/nsqd/protocol_v2_test.go +++ b/nsqd/protocol_v2_test.go @@ -2019,3 +2019,49 @@ func BenchmarkProtocolV2MultiSub2(b *testing.B) { benchmarkProtocolV2MultiSub(b func BenchmarkProtocolV2MultiSub4(b *testing.B) { benchmarkProtocolV2MultiSub(b, 4) } func BenchmarkProtocolV2MultiSub8(b *testing.B) { benchmarkProtocolV2MultiSub(b, 8) } func BenchmarkProtocolV2MultiSub16(b *testing.B) { benchmarkProtocolV2MultiSub(b, 16) } + +// Test generated using Keploy +func TestIdentifyInvalidJSON(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + tcpAddr, _, nsqd := mustStartNSQD(opts) + defer os.RemoveAll(opts.DataPath) + defer nsqd.Exit() + + conn, err := mustConnectNSQD(tcpAddr) + test.Nil(t, err) + defer conn.Close() + + // Send IDENTIFY command with invalid JSON data + _, err = conn.Write([]byte("IDENTIFY\n")) + test.Nil(t, err) + _, err = conn.Write([]byte{0, 0, 0, 5}) // Invalid JSON length + test.Nil(t, err) + _, err = conn.Write([]byte("abcde")) // Invalid JSON data + test.Nil(t, err) + + resp, err := nsq.ReadResponse(conn) + test.Nil(t, err) + frameType, data, err := nsq.UnpackResponse(resp) + test.Nil(t, err) + test.Equal(t, frameTypeError, frameType) + test.Equal(t, "E_BAD_BODY IDENTIFY failed to decode JSON body", string(data)) +} + +// Test generated using Keploy +func TestExecInvalidCommand(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + nsqd, err := New(opts) + test.Nil(t, err) + defer nsqd.Exit() + + prot := &protocolV2{nsqd: nsqd} + client := &clientV2{ID: 1} + + // Test invalid command + params := [][]byte{[]byte("INVALID_COMMAND")} + _, err = prot.Exec(client, params) + test.NotNil(t, err) + test.Equal(t, "E_INVALID invalid command INVALID_COMMAND", err.Error()) +} diff --git a/nsqd/stats_test.go b/nsqd/stats_test.go index dd41d641b..9f7bdc565 100644 --- a/nsqd/stats_test.go +++ b/nsqd/stats_test.go @@ -9,6 +9,8 @@ import ( "testing" "time" + "sort" + "github.com/golang/snappy" "github.com/nsqio/nsq/internal/http_api" "github.com/nsqio/nsq/internal/test" @@ -158,3 +160,45 @@ func TestStatsChannelLocking(t *testing.T) { test.Equal(t, 1, len(stats[0].Channels)) test.Equal(t, 25, stats[0].Channels[0].InFlightCount) } + +// Test generated using Keploy +func TestTopicsByNameSorting(t *testing.T) { + topic1 := &Topic{name: "topicA"} + topic2 := &Topic{name: "topicB"} + topic3 := &Topic{name: "topicC"} + + topics := TopicsByName{Topics: []*Topic{topic3, topic1, topic2}} + sort.Sort(topics) + + if topics.Topics[0].name != "topicA" || topics.Topics[1].name != "topicB" || topics.Topics[2].name != "topicC" { + t.Errorf("Expected topics to be sorted by name, got: %v", topics) + } +} + +// Test generated using Keploy +func TestChannelsByNameSorting(t *testing.T) { + channel1 := &Channel{name: "channelA"} + channel2 := &Channel{name: "channelB"} + channel3 := &Channel{name: "channelC"} + + channels := ChannelsByName{Channels: []*Channel{channel3, channel1, channel2}} + sort.Sort(channels) + + if channels.Channels[0].name != "channelA" || channels.Channels[1].name != "channelB" || channels.Channels[2].name != "channelC" { + t.Errorf("Expected channels to be sorted by name, got: %v", channels) + } +} + +// Test generated using Keploy +func TestGetStatsNoTopics(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + _, _, nsqd := mustStartNSQD(opts) + defer os.RemoveAll(opts.DataPath) + defer nsqd.Exit() + + stats := nsqd.GetStats("", "", false) + if len(stats.Topics) != 0 { + t.Errorf("Expected no topics, got: %v", stats.Topics) + } +} diff --git a/nsqd/statsd_test.go b/nsqd/statsd_test.go new file mode 100644 index 000000000..2abfeb811 --- /dev/null +++ b/nsqd/statsd_test.go @@ -0,0 +1,17 @@ +package nsqd + +import ( + "testing" +) + + + +// Test generated using Keploy +func TestPercentile_EmptyArray(t *testing.T) { + data := []uint64{} + result := percentile(50, data, len(data)) + expected := uint64(0) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } +} diff --git a/nsqd/topic_test.go b/nsqd/topic_test.go index d78fceae9..14cb8b20c 100644 --- a/nsqd/topic_test.go +++ b/nsqd/topic_test.go @@ -11,6 +11,8 @@ import ( "testing" "time" + "sync/atomic" + "github.com/nsqio/nsq/internal/test" ) @@ -239,3 +241,60 @@ func BenchmarkTopicToChannelPut(b *testing.B) { runtime.Gosched() } } + +// Test generated using Keploy +func TestDeleteExistingChannel_NonExistentChannel_ReturnsError(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + _, _, nsqd := mustStartNSQD(opts) + defer os.RemoveAll(opts.DataPath) + defer nsqd.Exit() + + topic := nsqd.GetTopic("test") + err := topic.DeleteExistingChannel("nonexistent_channel") + test.NotNil(t, err) + test.Equal(t, "channel does not exist", err.Error()) +} + +// Test generated using Keploy +func TestPutMessage_ExitingTopic_ReturnsError(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + _, _, nsqd := mustStartNSQD(opts) + defer os.RemoveAll(opts.DataPath) + defer nsqd.Exit() + + topic := nsqd.GetTopic("test") + atomic.StoreInt32(&topic.exitFlag, 1) + + msg := NewMessage(topic.GenerateID(), []byte("test message")) + err := topic.PutMessage(msg) + test.NotNil(t, err) + test.Equal(t, "exiting", err.Error()) +} + +// Test generated using Keploy +func TestPause_TopicPaused_PreventsMessageProcessing(t *testing.T) { + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + _, _, nsqd := mustStartNSQD(opts) + defer os.RemoveAll(opts.DataPath) + defer nsqd.Exit() + + topic := nsqd.GetTopic("test") + err := topic.Pause() + test.Nil(t, err) + test.Equal(t, true, topic.IsPaused()) + + channel := topic.GetChannel("ch1") + test.NotNil(t, channel) + + msg := NewMessage(topic.GenerateID(), []byte("test message")) + err = topic.PutMessage(msg) + test.Nil(t, err) + + time.Sleep(15 * time.Millisecond) + + test.Equal(t, int64(1), topic.Depth()) + test.Equal(t, int64(0), channel.Depth()) +} From e9758fd1e38771da6ba24c3b0f2762a63d6428ab Mon Sep 17 00:00:00 2001 From: shivamsouravjha <2019145@iiitdmj.ac.in> Date: Sat, 8 Feb 2025 03:20:28 +0530 Subject: [PATCH 14/14] chore: add test for nsqlookupd --- nsqd/statsd_test.go | 16 +++++----- nsqlookupd/lookup_protocol_v1_test.go | 41 +++++++++++++++++++++++++ nsqlookupd/nsqlookupd_test.go | 43 +++++++++++++++++++++++++++ nsqlookupd/options_test.go | 33 ++++++++++++++++++++ 4 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 nsqlookupd/options_test.go diff --git a/nsqd/statsd_test.go b/nsqd/statsd_test.go index 2abfeb811..45f8aabaf 100644 --- a/nsqd/statsd_test.go +++ b/nsqd/statsd_test.go @@ -1,17 +1,15 @@ package nsqd import ( - "testing" + "testing" ) - - // Test generated using Keploy func TestPercentile_EmptyArray(t *testing.T) { - data := []uint64{} - result := percentile(50, data, len(data)) - expected := uint64(0) - if result != expected { - t.Errorf("Expected %v, got %v", expected, result) - } + data := []uint64{} + result := percentile(50, data, len(data)) + expected := uint64(0) + if result != expected { + t.Errorf("Expected %v, got %v", expected, result) + } } diff --git a/nsqlookupd/lookup_protocol_v1_test.go b/nsqlookupd/lookup_protocol_v1_test.go index af9f3a7e5..bd40dceec 100644 --- a/nsqlookupd/lookup_protocol_v1_test.go +++ b/nsqlookupd/lookup_protocol_v1_test.go @@ -27,6 +27,47 @@ func TestIOLoopReturnsClientErrWhenSendSucceeds(t *testing.T) { testIOLoopReturnsClientErr(t, fakeConn) } +// Test generated using Keploy +func TestIOLoopSendResponseError(t *testing.T) { + fakeConn := test.NewFakeNetConn() + + // Simulate a valid command that will cause a response + fakeConn.ReadFunc = func(b []byte) (int, error) { + return copy(b, []byte("PING\n")), nil + } + + // Simulate an error on write to cause SendResponse to fail + firstWrite := true + fakeConn.WriteFunc = func(b []byte) (int, error) { + if firstWrite { + firstWrite = false + return len(b), nil + } + return 0, errors.New("write error") + } + + opts := NewOptions() + opts.Logger = test.NewTestLogger(t) + nsqlookupd, err := New(opts) + test.Nil(t, err) + prot := &LookupProtocolV1{nsqlookupd: nsqlookupd} + client := prot.NewClient(fakeConn) + + errChan := make(chan error) + go func() { + errChan <- prot.IOLoop(client) + }() + + // Wait for IOLoop to exit + var ioLoopErr error + select { + case ioLoopErr = <-errChan: + case <-time.After(time.Second): + t.Fatal("IOLoop didn't exit") + } + test.NotNil(t, ioLoopErr) +} + func testIOLoopReturnsClientErr(t *testing.T, fakeConn test.FakeNetConn) { fakeConn.ReadFunc = func(b []byte) (int, error) { return copy(b, []byte("INVALID_COMMAND\n")), nil diff --git a/nsqlookupd/nsqlookupd_test.go b/nsqlookupd/nsqlookupd_test.go index 6afb18906..4f86b6633 100644 --- a/nsqlookupd/nsqlookupd_test.go +++ b/nsqlookupd/nsqlookupd_test.go @@ -357,3 +357,46 @@ func TestTombstonedNodes(t *testing.T) { test.Equal(t, topicName, producers[0].Topics[0].Topic) test.Equal(t, true, producers[0].Topics[0].Tombstoned) } + +// Test generated using Keploy +func TestNew_NilLogger(t *testing.T) { + opts := NewOptions() + opts.Logger = nil + opts.LogPrefix = "[TEST] " + opts.TCPAddress = "127.0.0.1:0" + opts.HTTPAddress = "127.0.0.1:0" + + nsqlookupd, err := New(opts) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer nsqlookupd.Exit() + + if nsqlookupd.opts.Logger == nil { + t.Fatalf("expected logger to be initialized, but it was nil") + } +} + +// Test generated using Keploy +func TestNew_TCPListenerError(t *testing.T) { + opts := NewOptions() + opts.TCPAddress = "invalid_address" + opts.HTTPAddress = "127.0.0.1:0" + + _, err := New(opts) + if err == nil { + t.Fatalf("expected error but got nil") + } +} + +// Test generated using Keploy +func TestNew_HTTPListenerError(t *testing.T) { + opts := NewOptions() + opts.TCPAddress = "127.0.0.1:0" + opts.HTTPAddress = "invalid_address" + + _, err := New(opts) + if err == nil { + t.Fatalf("expected error but got nil") + } +} diff --git a/nsqlookupd/options_test.go b/nsqlookupd/options_test.go new file mode 100644 index 000000000..aebf8a8af --- /dev/null +++ b/nsqlookupd/options_test.go @@ -0,0 +1,33 @@ +package nsqlookupd + +import ( + "testing" + "time" + + "github.com/nsqio/nsq/internal/lg" +) + +// Test generated using Keploy +func TestNewOptions_DefaultValues_ValidHostname(t *testing.T) { + + opts := NewOptions() + + if opts.LogPrefix != "[nsqlookupd] " { + t.Errorf("Expected LogPrefix to be '[nsqlookupd] ', got %v", opts.LogPrefix) + } + if opts.LogLevel != lg.INFO { + t.Errorf("Expected LogLevel to be lg.INFO, got %v", opts.LogLevel) + } + if opts.TCPAddress != "0.0.0.0:4160" { + t.Errorf("Expected TCPAddress to be '0.0.0.0:4160', got %v", opts.TCPAddress) + } + if opts.HTTPAddress != "0.0.0.0:4161" { + t.Errorf("Expected HTTPAddress to be '0.0.0.0:4161', got %v", opts.HTTPAddress) + } + if opts.InactiveProducerTimeout != 300*time.Second { + t.Errorf("Expected InactiveProducerTimeout to be 300 seconds, got %v", opts.InactiveProducerTimeout) + } + if opts.TombstoneLifetime != 45*time.Second { + t.Errorf("Expected TombstoneLifetime to be 45 seconds, got %v", opts.TombstoneLifetime) + } +}