github.com/nsqio/nsq@v1.3.0/nsqd/topic_test.go (about)

     1  package nsqd
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"os"
     9  	"runtime"
    10  	"strconv"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/nsqio/nsq/internal/test"
    15  )
    16  
    17  func TestGetTopic(t *testing.T) {
    18  	opts := NewOptions()
    19  	opts.Logger = test.NewTestLogger(t)
    20  	_, _, nsqd := mustStartNSQD(opts)
    21  	defer os.RemoveAll(opts.DataPath)
    22  	defer nsqd.Exit()
    23  
    24  	topic1 := nsqd.GetTopic("test")
    25  	test.NotNil(t, topic1)
    26  	test.Equal(t, "test", topic1.name)
    27  
    28  	topic2 := nsqd.GetTopic("test")
    29  	test.Equal(t, topic1, topic2)
    30  
    31  	topic3 := nsqd.GetTopic("test2")
    32  	test.Equal(t, "test2", topic3.name)
    33  	test.NotEqual(t, topic2, topic3)
    34  }
    35  
    36  func TestGetChannel(t *testing.T) {
    37  	opts := NewOptions()
    38  	opts.Logger = test.NewTestLogger(t)
    39  	_, _, nsqd := mustStartNSQD(opts)
    40  	defer os.RemoveAll(opts.DataPath)
    41  	defer nsqd.Exit()
    42  
    43  	topic := nsqd.GetTopic("test")
    44  
    45  	channel1 := topic.GetChannel("ch1")
    46  	test.NotNil(t, channel1)
    47  	test.Equal(t, "ch1", channel1.name)
    48  
    49  	channel2 := topic.GetChannel("ch2")
    50  
    51  	test.Equal(t, channel1, topic.channelMap["ch1"])
    52  	test.Equal(t, channel2, topic.channelMap["ch2"])
    53  }
    54  
    55  type errorBackendQueue struct{}
    56  
    57  func (d *errorBackendQueue) Put([]byte) error        { return errors.New("never gonna happen") }
    58  func (d *errorBackendQueue) ReadChan() <-chan []byte { return nil }
    59  func (d *errorBackendQueue) Close() error            { return nil }
    60  func (d *errorBackendQueue) Delete() error           { return nil }
    61  func (d *errorBackendQueue) Depth() int64            { return 0 }
    62  func (d *errorBackendQueue) Empty() error            { return nil }
    63  
    64  type errorRecoveredBackendQueue struct{ errorBackendQueue }
    65  
    66  func (d *errorRecoveredBackendQueue) Put([]byte) error { return nil }
    67  
    68  func TestHealth(t *testing.T) {
    69  	opts := NewOptions()
    70  	opts.Logger = test.NewTestLogger(t)
    71  	opts.MemQueueSize = 2
    72  	_, httpAddr, nsqd := mustStartNSQD(opts)
    73  	defer os.RemoveAll(opts.DataPath)
    74  	defer nsqd.Exit()
    75  
    76  	topic := nsqd.GetTopic("test")
    77  	topic.backend = &errorBackendQueue{}
    78  
    79  	msg := NewMessage(topic.GenerateID(), make([]byte, 100))
    80  	err := topic.PutMessage(msg)
    81  	test.Nil(t, err)
    82  
    83  	msg = NewMessage(topic.GenerateID(), make([]byte, 100))
    84  	err = topic.PutMessages([]*Message{msg})
    85  	test.Nil(t, err)
    86  
    87  	msg = NewMessage(topic.GenerateID(), make([]byte, 100))
    88  	err = topic.PutMessage(msg)
    89  	test.NotNil(t, err)
    90  
    91  	msg = NewMessage(topic.GenerateID(), make([]byte, 100))
    92  	err = topic.PutMessages([]*Message{msg})
    93  	test.NotNil(t, err)
    94  
    95  	url := fmt.Sprintf("http://%s/ping", httpAddr)
    96  	resp, err := http.Get(url)
    97  	test.Nil(t, err)
    98  	test.Equal(t, 500, resp.StatusCode)
    99  	body, _ := io.ReadAll(resp.Body)
   100  	resp.Body.Close()
   101  	test.Equal(t, "NOK - never gonna happen", string(body))
   102  
   103  	topic.backend = &errorRecoveredBackendQueue{}
   104  
   105  	msg = NewMessage(topic.GenerateID(), make([]byte, 100))
   106  	err = topic.PutMessages([]*Message{msg})
   107  	test.Nil(t, err)
   108  
   109  	resp, err = http.Get(url)
   110  	test.Nil(t, err)
   111  	test.Equal(t, 200, resp.StatusCode)
   112  	body, _ = io.ReadAll(resp.Body)
   113  	resp.Body.Close()
   114  	test.Equal(t, "OK", string(body))
   115  }
   116  
   117  func TestDeletes(t *testing.T) {
   118  	opts := NewOptions()
   119  	opts.Logger = test.NewTestLogger(t)
   120  	_, _, nsqd := mustStartNSQD(opts)
   121  	defer os.RemoveAll(opts.DataPath)
   122  	defer nsqd.Exit()
   123  
   124  	topic := nsqd.GetTopic("test")
   125  
   126  	channel1 := topic.GetChannel("ch1")
   127  	test.NotNil(t, channel1)
   128  
   129  	err := topic.DeleteExistingChannel("ch1")
   130  	test.Nil(t, err)
   131  	test.Equal(t, 0, len(topic.channelMap))
   132  
   133  	channel2 := topic.GetChannel("ch2")
   134  	test.NotNil(t, channel2)
   135  
   136  	err = nsqd.DeleteExistingTopic("test")
   137  	test.Nil(t, err)
   138  	test.Equal(t, 0, len(topic.channelMap))
   139  	test.Equal(t, 0, len(nsqd.topicMap))
   140  }
   141  
   142  func TestDeleteLast(t *testing.T) {
   143  	opts := NewOptions()
   144  	opts.Logger = test.NewTestLogger(t)
   145  	_, _, nsqd := mustStartNSQD(opts)
   146  	defer os.RemoveAll(opts.DataPath)
   147  	defer nsqd.Exit()
   148  
   149  	topic := nsqd.GetTopic("test")
   150  
   151  	channel1 := topic.GetChannel("ch1")
   152  	test.NotNil(t, channel1)
   153  
   154  	err := topic.DeleteExistingChannel("ch1")
   155  	test.Nil(t, err)
   156  	test.Equal(t, 0, len(topic.channelMap))
   157  
   158  	msg := NewMessage(topic.GenerateID(), []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaa"))
   159  	err = topic.PutMessage(msg)
   160  	time.Sleep(100 * time.Millisecond)
   161  	test.Nil(t, err)
   162  	test.Equal(t, int64(1), topic.Depth())
   163  }
   164  
   165  func TestPause(t *testing.T) {
   166  	opts := NewOptions()
   167  	opts.Logger = test.NewTestLogger(t)
   168  	_, _, nsqd := mustStartNSQD(opts)
   169  	defer os.RemoveAll(opts.DataPath)
   170  	defer nsqd.Exit()
   171  
   172  	topicName := "test_topic_pause" + strconv.Itoa(int(time.Now().Unix()))
   173  	topic := nsqd.GetTopic(topicName)
   174  	err := topic.Pause()
   175  	test.Nil(t, err)
   176  
   177  	channel := topic.GetChannel("ch1")
   178  	test.NotNil(t, channel)
   179  
   180  	msg := NewMessage(topic.GenerateID(), []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaa"))
   181  	err = topic.PutMessage(msg)
   182  	test.Nil(t, err)
   183  
   184  	time.Sleep(15 * time.Millisecond)
   185  
   186  	test.Equal(t, int64(1), topic.Depth())
   187  	test.Equal(t, int64(0), channel.Depth())
   188  
   189  	err = topic.UnPause()
   190  	test.Nil(t, err)
   191  
   192  	time.Sleep(15 * time.Millisecond)
   193  
   194  	test.Equal(t, int64(0), topic.Depth())
   195  	test.Equal(t, int64(1), channel.Depth())
   196  }
   197  
   198  func BenchmarkTopicPut(b *testing.B) {
   199  	b.StopTimer()
   200  	topicName := "bench_topic_put" + strconv.Itoa(b.N)
   201  	opts := NewOptions()
   202  	opts.Logger = test.NewTestLogger(b)
   203  	opts.MemQueueSize = int64(b.N)
   204  	_, _, nsqd := mustStartNSQD(opts)
   205  	defer os.RemoveAll(opts.DataPath)
   206  	defer nsqd.Exit()
   207  	b.StartTimer()
   208  
   209  	for i := 0; i <= b.N; i++ {
   210  		topic := nsqd.GetTopic(topicName)
   211  		msg := NewMessage(topic.GenerateID(), []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaa"))
   212  		topic.PutMessage(msg)
   213  	}
   214  }
   215  
   216  func BenchmarkTopicToChannelPut(b *testing.B) {
   217  	b.StopTimer()
   218  	topicName := "bench_topic_to_channel_put" + strconv.Itoa(b.N)
   219  	channelName := "bench"
   220  	opts := NewOptions()
   221  	opts.Logger = test.NewTestLogger(b)
   222  	opts.MemQueueSize = int64(b.N)
   223  	_, _, nsqd := mustStartNSQD(opts)
   224  	defer os.RemoveAll(opts.DataPath)
   225  	defer nsqd.Exit()
   226  	channel := nsqd.GetTopic(topicName).GetChannel(channelName)
   227  	b.StartTimer()
   228  
   229  	for i := 0; i <= b.N; i++ {
   230  		topic := nsqd.GetTopic(topicName)
   231  		msg := NewMessage(topic.GenerateID(), []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaa"))
   232  		topic.PutMessage(msg)
   233  	}
   234  
   235  	for {
   236  		if len(channel.memoryMsgChan) == b.N {
   237  			break
   238  		}
   239  		runtime.Gosched()
   240  	}
   241  }