From fdfb7cda9ae1877f3312eaa28c02b79964458002 Mon Sep 17 00:00:00 2001
From: thijsheijden <hi@thijsheijden.nl>
Date: Tue, 18 May 2021 13:03:18 +0200
Subject: [PATCH] Added more handleMessage tests

Re-ordered operations in the method as well. Empty database check now
happens before query translation.
---
 internal/usecases/consume/consume_test.go  | 367 +++++++++++++--------
 internal/usecases/consume/handlemessage.go |  18 +-
 2 files changed, 234 insertions(+), 151 deletions(-)

diff --git a/internal/usecases/consume/consume_test.go b/internal/usecases/consume/consume_test.go
index cac617b..ecdf68c 100644
--- a/internal/usecases/consume/consume_test.go
+++ b/internal/usecases/consume/consume_test.go
@@ -27,21 +27,22 @@ type testSuite struct {
 	service              *Service
 }
 
-// Reset all stateful things
-func (ts *testSuite) reset() {
-	// Reset broker messages
-	ts.mockBroker.Messages = make(map[string][]broker.Message)
-}
+var ts *testSuite
+
+func createTestSuite() {
+	if ts != nil {
+		ts.reset()
+		return
+	}
 
-func TestHandleMessages(t *testing.T) {
 	// Create test suite
 	mockBroker := broker.NewMockDriver().(*broker.MockDriver)
 	mockKeyValueStore := keyvaluestore.NewMockDriver()
-	ts := testSuite{
+	ts = &testSuite{
 		mockBroker:           mockBroker,
 		mockKeyValueStore:    mockKeyValueStore,
 		produceService:       produce.NewService(mockBroker, mockKeyValueStore),
-		queryConverter:       aql.NewMockService(),
+		queryConverter:       aql.NewService(),
 		requestSenderService: mockrequest.NewService(),
 		databaseInfoService:  mockdatabaseinfo.NewService(),
 	}
@@ -52,152 +53,234 @@ func TestHandleMessages(t *testing.T) {
 
 	// Start producer
 	ts.produceService.Start()
+}
 
-	// Run tests using the test suite
-	t.Run("correct message", func(t *testing.T) {
-		// Reset possible state
-		ts.reset()
+// Reset all stateful things
+func (ts *testSuite) reset() {
+	// Reset broker messages
+	ts.mockBroker.Messages = make(map[string][]broker.Message)
+}
 
-		// Create a mock message
-		headers := make(map[string]interface{})
-		headers["sessionID"] = "mock-session"
-		headers["clientID"] = "mock-client"
-		mockMessage := broker.Message{
-			Headers: headers,
-			Body: []byte(`{
-				"databaseName": "test",
-				"return": {
-					"entities": [],
-					"relations": []
-				},
-				"entities": [],
-				"relations": [],
-				"limit": 5000
-			}`),
-		}
-
-		// Assert that there have not been any messages sent yet
-		assert.Empty(t, mockBroker.Messages)
-
-		// Send the mock message
-		ts.service.HandleMessage(&mockMessage)
-
-		// Assert that there now are two messages that have been sent with routing key mock-queue
-		assert.Len(t, mockBroker.Messages["mock-queue"], 2)
-
-		// Assert that the first message is of type 'query_translation_result' and has 'Query converted' as value
-		var translationMessage entity.MessageStruct
-		json.Unmarshal(mockBroker.Messages["mock-queue"][0].Body, &translationMessage)
-		assert.Equal(t, "query_translation_result", translationMessage.Type)
-		assert.Equal(t, "Query converted", translationMessage.Value)
-
-		// Assert that the second message is of type 'query_result' and contains no values
-		var resultMessage entity.MessageStruct
-		json.Unmarshal(mockBroker.Messages["mock-queue"][1].Body, &resultMessage)
-		assert.Equal(t, "query_result", resultMessage.Type)
-		assert.Equal(t, "test", resultMessage.Value)
-	})
-
-	t.Run("no session id", func(t *testing.T) {
-		// Reset possible state
-		ts.reset()
+func TestCorrectMessageHandled(t *testing.T) {
+	createTestSuite()
 
-		// Create a mock message
-		headers := make(map[string]interface{})
-		headers["clientID"] = "mock-client"
-		mockMessage := broker.Message{
-			Headers: headers,
-			Body: []byte(`{
-				"databaseName": "test",
-				"return": {
-					"entities": [],
-					"relations": []
-				},
+	// Create a mock message
+	headers := make(map[string]interface{})
+	headers["sessionID"] = "mock-session"
+	headers["clientID"] = "mock-client"
+	mockMessage := broker.Message{
+		Headers: headers,
+		Body: []byte(`{
+			"databaseName": "test",
+			"return": {
 				"entities": [],
-				"relations": [],
-				"limit": 5000
-			}`),
-		}
+				"relations": []
+			},
+			"entities": [],
+			"relations": [],
+			"limit": 5000
+		}`),
+	}
 
-		// Assert that there have not been any messages sent yet
-		assert.Empty(t, mockBroker.Messages)
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, ts.mockBroker.Messages)
 
-		// Send the mock message
-		ts.service.HandleMessage(&mockMessage)
+	// Send the mock message
+	ts.service.HandleMessage(&mockMessage)
 
-		// Assert that there was no message published
-		assert.Empty(t, mockBroker.Messages)
-	})
+	// Assert that there now are two messages that have been sent with routing key mock-queue
+	assert.Len(t, ts.mockBroker.Messages["mock-queue"], 2)
 
-	t.Run("failure to unmarshal JSON query", func(t *testing.T) {
-		// Reset possible state
-		ts.reset()
+	// Assert that the first message is of type 'query_translation_result' and has 'Query converted' as value
+	var translationMessage entity.MessageStruct
+	json.Unmarshal(ts.mockBroker.Messages["mock-queue"][0].Body, &translationMessage)
+	assert.Equal(t, "query_translation_result", translationMessage.Type)
 
-		// Create a mock message
-		headers := make(map[string]interface{})
-		headers["clientID"] = "mock-client"
-		headers["sessionID"] = "mock-session"
-		mockMessage := broker.Message{
-			Headers: headers,
-			Body: []byte(`{
-				"databaseName": "test",
-				"return": {
-					"entities": [],
-					"relations": []
-				},
-				"entities": [],
-				"relations": [],
-				"limit": "test"
-			}`),
-		}
-
-		// Assert that there have not been any messages sent yet
-		assert.Empty(t, mockBroker.Messages)
-
-		// Send the mock message
-		ts.service.HandleMessage(&mockMessage)
-
-		// Assert that there was an error message published
-		var errorMsg entity.MessageStruct
-		json.Unmarshal(mockBroker.Messages["mock-queue"][0].Body, &errorMsg)
-		assert.Equal(t, "query_translation_error", errorMsg.Type)
-	})
-
-	// MARK: test
-	t.Run("database execution error", func(t *testing.T) {
-		// Reset possible state
-		ts.reset()
+	// Assert that the second message is of type 'query_result' and contains no values
+	var resultMessage entity.MessageStruct
+	json.Unmarshal(ts.mockBroker.Messages["mock-queue"][1].Body, &resultMessage)
+	assert.Equal(t, "query_result", resultMessage.Type)
+	assert.Equal(t, "test", resultMessage.Value)
+}
 
-		// Create a mock message
-		headers := make(map[string]interface{})
-		headers["clientID"] = "mock-client"
-		headers["sessionID"] = "mock-session"
-		mockMessage := broker.Message{
-			Headers: headers,
-			Body: []byte(`{
-				"databaseName": "test",
-				"return": {
-					"entities": [],
-					"relations": []
-				},
-				"entities": [],
-				"relations": [],
-				"limit": 5000
-			}`),
-		}
+func TestNoSessionIDHandled(t *testing.T) {
+	createTestSuite()
+
+	// Create a mock message
+	headers := make(map[string]interface{})
+	headers["clientID"] = "mock-client"
+	mockMessage := broker.Message{
+		Headers: headers,
+		Body: []byte(`{
+		"databaseName": "test",
+		"return": {
+			"entities": [],
+			"relations": []
+		},
+		"entities": [],
+		"relations": [],
+		"limit": 5000
+	}`),
+	}
 
-		// Make it so that the request sender service throws an error
-		ts.requestSenderService.ToggleError()
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, ts.mockBroker.Messages)
+
+	// Send the mock message
+	ts.service.HandleMessage(&mockMessage)
+
+	// Assert that there was no message published
+	assert.Empty(t, ts.mockBroker.Messages)
+}
+
+func TestBadIncomingQueryHandled(t *testing.T) {
+	createTestSuite()
+
+	// Create a mock message
+	headers := make(map[string]interface{})
+	headers["clientID"] = "mock-client"
+	headers["sessionID"] = "mock-session"
+	mockMessage := broker.Message{
+		Headers: headers,
+		Body: []byte(`{
+		"databaseName": "test",
+		"return": {
+			"entities": [],
+			"relations": []
+		},
+		"entities": [],
+		"relations": [],
+		"limit": "test"
+	}`),
+	}
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, ts.mockBroker.Messages)
+
+	// Send the mock message
+	ts.service.HandleMessage(&mockMessage)
+
+	// Assert that there was an error message published
+	var errorMsg entity.MessageStruct
+	json.Unmarshal(ts.mockBroker.Messages["mock-queue"][0].Body, &errorMsg)
+	assert.Equal(t, "query_translation_error", errorMsg.Type)
+}
+
+func TestDatabaseErrorHandled(t *testing.T) {
+	createTestSuite()
+
+	// Create a mock message
+	headers := make(map[string]interface{})
+	headers["clientID"] = "mock-client"
+	headers["sessionID"] = "mock-session"
+	mockMessage := broker.Message{
+		Headers: headers,
+		Body: []byte(`{
+		"databaseName": "test",
+		"return": {
+			"entities": [],
+			"relations": []
+		},
+		"entities": [],
+		"relations": [],
+		"limit": 5000
+	}`),
+	}
+
+	// Make it so that the request sender service throws an error
+	ts.requestSenderService.ToggleError()
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, ts.mockBroker.Messages)
+
+	// Send the mock message
+	ts.service.HandleMessage(&mockMessage)
+
+	// Assert that there was an error message published
+	var errorMsg entity.MessageStruct
+	json.Unmarshal(ts.mockBroker.Messages["mock-queue"][1].Body, &errorMsg)
+	assert.Equal(t, "query_database_error", errorMsg.Type)
+
+	// Turn of error throwing in request service
+	ts.requestSenderService.ToggleError()
+}
+
+func TestQueryConversionErrorHandled(t *testing.T) {
+	createTestSuite()
+
+	// Create a mock message
+	headers := make(map[string]interface{})
+	headers["clientID"] = "mock-client"
+	headers["sessionID"] = "mock-session"
+	mockMessage := broker.Message{
+		Headers: headers,
+		Body: []byte(`{
+		"databaseName": "test",
+		"return": {
+			"entities": [
+				1
+			],
+			"relations": []
+		},
+		"entities": [
+			{
+				"type": "airports",
+				"constraints": [
+					{
+						"attribute": "state",
+						"value": "HI",
+						"dataType": "text",
+						"matchType": "exact"
+					}
+				]
+			}
+		],
+		"relations": [],
+		"limit": 5000
+	}`),
+	}
+
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, ts.mockBroker.Messages)
+
+	// Send the mock message
+	ts.service.HandleMessage(&mockMessage)
+
+	// Assert that there was an error message published
+	var errorMsg entity.MessageStruct
+	json.Unmarshal(ts.mockBroker.Messages["mock-queue"][0].Body, &errorMsg)
+	assert.Equal(t, "query_translation_error", errorMsg.Type)
+}
+
+func TestNoDatabaseNameHandled(t *testing.T) {
+	createTestSuite()
+
+	// Create a mock message
+	headers := make(map[string]interface{})
+	headers["clientID"] = "mock-client"
+	headers["sessionID"] = "mock-session"
+	mockMessage := broker.Message{
+		Headers: headers,
+		Body: []byte(`{
+			"return": {
+				"entities": [],
+				"relations": []
+			},
+			"entities": [],
+			"relations": [],
+			"limit": 5000
+		}`),
+	}
 
-		// Assert that there have not been any messages sent yet
-		assert.Empty(t, mockBroker.Messages)
+	// Assert that there have not been any messages sent yet
+	assert.Empty(t, ts.mockBroker.Messages)
 
-		// Send the mock message
-		ts.service.HandleMessage(&mockMessage)
+	// Send the mock message
+	ts.service.HandleMessage(&mockMessage)
 
-		// Assert that there was an error message published
-		var errorMsg entity.MessageStruct
-		json.Unmarshal(mockBroker.Messages["mock-queue"][1].Body, &errorMsg)
-		assert.Equal(t, "query_database_error", errorMsg.Type)
-	})
+	// Assert that there was an error message published
+	var errorMsg entity.MessageStruct
+	json.Unmarshal(ts.mockBroker.Messages["mock-queue"][0].Body, &errorMsg)
+	assert.Equal(t, "query_malformed_request_error", errorMsg.Type)
+	assert.Equal(t, "no database name supplied", errorMsg.Value)
 }
diff --git a/internal/usecases/consume/handlemessage.go b/internal/usecases/consume/handlemessage.go
index 44bd654..7efd3af 100644
--- a/internal/usecases/consume/handlemessage.go
+++ b/internal/usecases/consume/handlemessage.go
@@ -35,23 +35,23 @@ func (s *Service) HandleMessage(msg *broker.Message) {
 		return
 	}
 
-	// Convert the json byte msg to a query string
-	query, err := s.queryConverter.ConvertQuery(JSONQuery)
-	if err != nil {
+	// Check if there was a database name
+	if JSONQuery.DatabaseName == "" {
 		errorMsg := entity.MessageStruct{
-			Type:  "query_translation_error",
-			Value: err.Error(),
+			Type:  "query_malformed_request_error",
+			Value: "no database name supplied",
 		}
 		errorMsgBytes, _ := json.Marshal(errorMsg)
 		s.producer.PublishMessage(&errorMsgBytes, &sessionID)
 		return
 	}
 
-	// Check if there was a database name
-	if JSONQuery.DatabaseName == "" {
+	// Convert the json byte msg to a query string
+	query, err := s.queryConverter.ConvertQuery(JSONQuery)
+	if err != nil {
 		errorMsg := entity.MessageStruct{
-			Type:  "query_malformed_request_error",
-			Value: "no database name supplied",
+			Type:  "query_translation_error",
+			Value: err.Error(),
 		}
 		errorMsgBytes, _ := json.Marshal(errorMsg)
 		s.producer.PublishMessage(&errorMsgBytes, &sessionID)
-- 
GitLab