func Test_Stats(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) q, err := repo.GetQueue("test") assert.Nil(t, err) q.Enqueue([]byte("1")) err = controller.Stats() statsResponse := "STAT uptime 0\r\n" + fmt.Sprintf("STAT time %d\r\n", time.Now().Unix()) + "STAT version " + repo.Stats.Version + "\r\n" + "STAT curr_connections 1\r\n" + "STAT total_connections 1\r\n" + "STAT cmd_get 0\r\n" + "STAT cmd_set 0\r\n" + fmt.Sprintf("STAT queue_test_items %d\r\n", q.Length()) + "STAT queue_test_open_transactions 0\r\n" + "END\r\n" assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), statsResponse) }
func (self *Service) Serve(listener *net.TCPListener) { defer self.wg.Done() log.Println("initializing...") var err error self.repo, err = repository.Initialize(self.dataDir) log.Println("data directory: ", self.dataDir) if err != nil { log.Fatal(err) } for { select { case <-self.ch: log.Println("stopping listening on", listener.Addr()) listener.Close() return default: } listener.SetDeadline(time.Now().Add(1e9)) conn, err := listener.AcceptTCP() if nil != err { if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() { continue } log.Println(err) } self.wg.Add(1) go self.HandleConnection(conn) } }
func Test_Delete(t *testing.T) { repo, _ := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) q, err := repo.GetQueue("test") assert.Nil(t, err) q.Enqueue([]byte("1")) command := []string{"delete", "test"} err = controller.Delete(command) assert.Nil(t, err) response, err := mockTCPConn.WriteBuffer.ReadString('\n') assert.Nil(t, err) assert.Equal(t, "END\r\n", response) command = []string{"DELETE", "test"} err = controller.Delete(command) assert.Nil(t, err) response, err = mockTCPConn.WriteBuffer.ReadString('\n') assert.Nil(t, err) assert.Equal(t, "END\r\n", response) }
// Initialize test queue with 2 items // gets test/open = value // gets test = error // GETS test/t=10/close/open = value func Test_Gets(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) repo.FlushQueue("test") q, err := repo.GetQueue("test") assert.Nil(t, err) q.Enqueue([]byte("1")) q.Enqueue([]byte("2")) // gets test/open = 1 command := []string{"gets", "test"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 1\r\n1\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // GETS test/t=10/close/open = 2 command = []string{"GETS", "test/t=10/close/open"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 1\r\n2\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() }
// Initialize test queue with 2 items // get test/open = value // FinishSession (disconnect) // NewSession // get test = same value func Test_GetOpen_Disconnect(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) repo.FlushQueue("test") q, err := repo.GetQueue("test") assert.Nil(t, err) q.Enqueue([]byte("1")) q.Enqueue([]byte("2")) // get test/open = value command := []string{"get", "test/open"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 1\r\n1\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() controller.FinishSession() mockTCPConn = NewMockTCPConn() controller = NewSession(mockTCPConn, repo) // get test = same value command = []string{"get", "test"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 1\r\n1\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) }
func Test_Version(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) err = controller.Version() assert.Nil(t, err) assert.Equal(t, "VERSION "+repo.Stats.Version+"\r\n", mockTCPConn.WriteBuffer.String()) }
func Test_SendError(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) controller.SendError("Test error message") assert.Equal(t, "Test error message\r\n", mockTCPConn.WriteBuffer.String()) }
func Test_UnknownCommand(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) err = controller.UnknownCommand() assert.Equal(t, "ERROR Unknown command", err.Error()) assert.Equal(t, "ERROR Unknown command\r\n", mockTCPConn.WriteBuffer.String()) }
func Test_NewSession_FinishSession(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() c := NewSession(mockTCPConn, repo) assert.Equal(t, uint64(1), repo.Stats.CurrentConnections) assert.Equal(t, uint64(1), repo.Stats.TotalConnections) c.FinishSession() assert.Equal(t, uint64(0), repo.Stats.CurrentConnections) }
func Test_FlushAll(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) err = controller.FlushAll() assert.Nil(t, err) response, err := mockTCPConn.WriteBuffer.ReadString('\n') assert.Nil(t, err) assert.Equal(t, response, "END\r\n") }
// Initialize queue 'test' with 1 item // get test = value // get test = empty // get test/close = empty // get test/abort = empty func Test_Get(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) q, err := repo.GetQueue("test") assert.Nil(t, err) q.Enqueue([]byte("0123456789")) // When queue has items // get test = value command := []string{"get", "test"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 10\r\n0123456789\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // When queue is empty // get test = empty command = []string{"get", "test"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "END\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // When queue is empty // get test/close = empty command = []string{"get", "test/close"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "END\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // When queue is empty // get test/abort = empty command = []string{"get", "test/close"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "END\r\n", mockTCPConn.WriteBuffer.String()) }
func Test_ReadFirstMessage(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) fmt.Fprintf(&mockTCPConn.ReadBuffer, "GET work\r\n") message, err := controller.ReadFirstMessage() assert.Nil(t, err) assert.Equal(t, "GET work\r\n", message) fmt.Fprintf(&mockTCPConn.ReadBuffer, "SET work 0 0 10\r\n0123456789\r\n") message, err = controller.ReadFirstMessage() assert.Nil(t, err) assert.Equal(t, "SET work 0 0 10\r\n", message) }
func Test_Set(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) command := []string{"set", "test", "0", "0", "10"} fmt.Fprintf(&mockTCPConn.ReadBuffer, "0123567890\r\n") err = controller.Set(command) assert.Nil(t, err) assert.Equal(t, "STORED\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() command = []string{"set", "test", "0", "1"} fmt.Fprintf(&mockTCPConn.ReadBuffer, "0\r\n") err = controller.Set(command) assert.Equal(t, "ERROR Invalid input", err.Error()) mockTCPConn.WriteBuffer.Reset() command = []string{"set", "test", "0", "0", "invalid"} fmt.Fprintf(&mockTCPConn.ReadBuffer, "0123567890\r\n") err = controller.Set(command) assert.Equal(t, "ERROR Invalid <bytes> number", err.Error()) mockTCPConn.WriteBuffer.Reset() command = []string{"set", "test", "0", "0", "10"} fmt.Fprintf(&mockTCPConn.ReadBuffer, "01235678901234567890\r\n") err = controller.Set(command) assert.Equal(t, "CLIENT_ERROR bad data chunk", err.Error()) }
func Test_Dispatch(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) // Command: set test 0 0 1 // 1 fmt.Fprintf(&mockTCPConn.ReadBuffer, "set test 0 0 1\r\n1\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "STORED\r\n") mockTCPConn.WriteBuffer.Reset() // Command: SET test 0 0 2 // 20 fmt.Fprintf(&mockTCPConn.ReadBuffer, "SET test 0 0 2\r\n") fmt.Fprintf(&mockTCPConn.ReadBuffer, "20\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "STORED\r\n") mockTCPConn.WriteBuffer.Reset() // Command: set test 0 0 10 // 123 // 12 // 1 fmt.Fprintf(&mockTCPConn.ReadBuffer, "set test 0 0 10\r\n") fmt.Fprintf(&mockTCPConn.ReadBuffer, "123\r\n") fmt.Fprintf(&mockTCPConn.ReadBuffer, "12\r\n") fmt.Fprintf(&mockTCPConn.ReadBuffer, "1\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "STORED\r\n") mockTCPConn.WriteBuffer.Reset() // Command: get test fmt.Fprintf(&mockTCPConn.ReadBuffer, "get test\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "VALUE test 0 1\r\n1\r\nEND\r\n") mockTCPConn.WriteBuffer.Reset() // Command: get test/open fmt.Fprintf(&mockTCPConn.ReadBuffer, "get test/open\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "VALUE test 0 2\r\n20\r\nEND\r\n") mockTCPConn.WriteBuffer.Reset() // Command: GET test/abort fmt.Fprintf(&mockTCPConn.ReadBuffer, "GET test/abort\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "END\r\n") mockTCPConn.WriteBuffer.Reset() // Command: get test/open fmt.Fprintf(&mockTCPConn.ReadBuffer, "get test/open\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "VALUE test 0 2\r\n20\r\nEND\r\n") mockTCPConn.WriteBuffer.Reset() // Command: get test/close fmt.Fprintf(&mockTCPConn.ReadBuffer, "get test/close\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "END\r\n") mockTCPConn.WriteBuffer.Reset() // Command: version fmt.Fprintf(&mockTCPConn.ReadBuffer, "version\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "VERSION "+repo.Stats.Version+"\r\n") mockTCPConn.WriteBuffer.Reset() // Command: STATS fmt.Fprintf(&mockTCPConn.ReadBuffer, "STATS\r\n") err = controller.Dispatch() assert.Nil(t, err) response, _ := mockTCPConn.WriteBuffer.ReadString('\n') fmt.Println(response) assert.True(t, strings.HasPrefix(response, "STAT uptime")) mockTCPConn.WriteBuffer.Reset() // Command: flush test fmt.Fprintf(&mockTCPConn.ReadBuffer, "flush test\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "END\r\n") mockTCPConn.WriteBuffer.Reset() // Command: DELETE test fmt.Fprintf(&mockTCPConn.ReadBuffer, "DELETE test\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "END\r\n") mockTCPConn.WriteBuffer.Reset() // Command: flush_all fmt.Fprintf(&mockTCPConn.ReadBuffer, "flush_all\r\n") err = controller.Dispatch() assert.Nil(t, err) assert.Equal(t, mockTCPConn.WriteBuffer.String(), "END\r\n") }
// Initialize test queue with 4 items // get test/open = value // get test = error // get test/close = empty // get test/open = value // get test/open = error // get test/abort = empty // get test/open = value // get test/peek = next value // get test/close = empty func Test_GetOpen(t *testing.T) { repo, err := repository.Initialize(dir) defer repo.CloseAllQueues() assert.Nil(t, err) mockTCPConn := NewMockTCPConn() controller := NewSession(mockTCPConn, repo) q, err := repo.GetQueue("test") assert.Nil(t, err) q.Enqueue([]byte("1")) q.Enqueue([]byte("2")) q.Enqueue([]byte("3")) q.Enqueue([]byte("4")) // get test/open = value command := []string{"get", "test/open"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 1\r\n1\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // get test = error command = []string{"get", "test"} err = controller.Get(command) assert.Equal(t, "CLIENT_ERROR Close current item first", err.Error()) mockTCPConn.WriteBuffer.Reset() // get test/close = value command = []string{"get", "test/close"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "END\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // get test/open = value command = []string{"get", "test/open"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 1\r\n2\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) // get test/open = error command = []string{"get", "test/open"} err = controller.Get(command) assert.Equal(t, err.Error(), "CLIENT_ERROR Close current item first") mockTCPConn.WriteBuffer.Reset() // get test/abort = value command = []string{"get", "test/abort"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "END\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // get test/open = value command = []string{"get", "test/open"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 1\r\n2\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // get test/peek = value command = []string{"get", "test/peek"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "VALUE test 0 1\r\n3\r\nEND\r\n", mockTCPConn.WriteBuffer.String()) mockTCPConn.WriteBuffer.Reset() // get test/close = value command = []string{"get", "test/close"} err = controller.Get(command) assert.Nil(t, err) assert.Equal(t, "END\r\n", mockTCPConn.WriteBuffer.String()) }