gatus/storage/memory_test.go

437 lines
16 KiB
Go
Raw Normal View History

2020-12-30 11:57:17 +01:00
package storage
import (
"fmt"
"testing"
"time"
"github.com/TwinProduction/gatus/core"
)
var testService = core.Service{
Name: "Name",
Group: "Group",
URL: "URL",
DNS: &core.DNS{QueryType: "QueryType", QueryName: "QueryName"},
Method: "Method",
Body: "Body",
GraphQL: false,
Headers: nil,
Interval: time.Second * 2,
Conditions: nil,
Alerts: nil,
Insecure: false,
NumberOfFailuresInARow: 0,
NumberOfSuccessesInARow: 0,
}
var memoryStore = NewInMemoryStore()
func TestStorage_GetAllFromEmptyMemoryStoreReturnsNothing(t *testing.T) {
memoryStore.Clear()
results := memoryStore.GetAll()
if len(results) != 0 {
t.Errorf("MemoryStore should've returned 0 results, but actually returned %d", len(results))
}
}
func TestStorage_InsertIntoEmptyMemoryStoreThenGetAllReturnsOneResult(t *testing.T) {
memoryStore.Clear()
result := core.Result{
HTTPStatus: 200,
DNSRCode: "DNSRCode",
Body: nil,
Hostname: "Hostname",
IP: "IP",
Connected: false,
Duration: time.Second * 2,
Errors: nil,
ConditionResults: nil,
Success: false,
Timestamp: time.Now(),
CertificateExpiration: time.Second * 2,
}
memoryStore.Insert(&testService, &result)
results := memoryStore.GetAll()
if len(results) != 1 {
t.Errorf("MemoryStore should've returned 0 results, but actually returned %d", len(results))
}
key := fmt.Sprintf("%s_%s", testService.Group, testService.Name)
storedResult, exists := results[key]
if !exists {
t.Fatalf("In Memory Store should've contained key '%s', but didn't", key)
}
if storedResult.Name != testService.Name {
t.Errorf("Stored Results Name should've been %s, but was %s", testService.Name, storedResult.Name)
}
if storedResult.Group != testService.Group {
t.Errorf("Stored Results Group should've been %s, but was %s", testService.Group, storedResult.Group)
}
if len(storedResult.Results) != 1 {
t.Errorf("Stored Results for service %s should've had 1 result, but actually had %d", storedResult.Name, len(storedResult.Results))
}
if storedResult.Results[0] == &result {
t.Errorf("Returned result is the same reference as result passed to insert. Returned result should be copies only")
}
}
func TestStorage_InsertTwoResultsForSingleServiceIntoEmptyMemoryStore_ThenGetAllReturnsTwoResults(t *testing.T) {
memoryStore.Clear()
result1 := core.Result{
HTTPStatus: 404,
DNSRCode: "DNSRCode",
Body: nil,
Hostname: "Hostname",
IP: "IP",
Connected: false,
Duration: time.Second * 2,
Errors: nil,
ConditionResults: nil,
Success: false,
Timestamp: time.Now(),
CertificateExpiration: time.Second * 2,
}
result2 := core.Result{
HTTPStatus: 200,
DNSRCode: "DNSRCode",
Body: nil,
Hostname: "Hostname",
IP: "IP",
Connected: true,
Duration: time.Second * 2,
Errors: nil,
ConditionResults: nil,
Success: true,
Timestamp: time.Now(),
CertificateExpiration: time.Second * 2,
}
resultsToInsert := []core.Result{result1, result2}
memoryStore.Insert(&testService, &result1)
memoryStore.Insert(&testService, &result2)
results := memoryStore.GetAll()
if len(results) != 1 {
t.Fatalf("MemoryStore should've returned 1 results, but actually returned %d", len(results))
}
key := fmt.Sprintf("%s_%s", testService.Group, testService.Name)
serviceResults, exists := results[key]
if !exists {
t.Fatalf("In Memory Store should've contained key '%s', but didn't", key)
}
if len(serviceResults.Results) != 2 {
t.Fatalf("Service '%s' should've had 2 results, but actually returned %d", serviceResults.Name, len(serviceResults.Results))
}
for i, r := range serviceResults.Results {
expectedResult := resultsToInsert[i]
if r.HTTPStatus != expectedResult.HTTPStatus {
t.Errorf("Result at index %d should've had a HTTPStatus of %d, but was actually %d", i, expectedResult.HTTPStatus, r.HTTPStatus)
}
if r.DNSRCode != expectedResult.DNSRCode {
t.Errorf("Result at index %d should've had a DNSRCode of %s, but was actually %s", i, expectedResult.DNSRCode, r.DNSRCode)
}
if len(r.Body) != len(expectedResult.Body) {
t.Errorf("Result at index %d should've had a body of length %d, but was actually %d", i, len(expectedResult.Body), len(r.Body))
}
if r.Hostname != expectedResult.Hostname {
t.Errorf("Result at index %d should've had a Hostname of %s, but was actually %s", i, expectedResult.Hostname, r.Hostname)
}
if r.IP != expectedResult.IP {
t.Errorf("Result at index %d should've had a IP of %s, but was actually %s", i, expectedResult.IP, r.IP)
}
if r.Connected != expectedResult.Connected {
t.Errorf("Result at index %d should've had a Connected value of %t, but was actually %t", i, expectedResult.Connected, r.Connected)
}
if r.Duration != expectedResult.Duration {
t.Errorf("Result at index %d should've had a Duration of %s, but was actually %s", i, expectedResult.Duration.String(), r.Duration.String())
}
if len(r.Errors) != len(expectedResult.Errors) {
t.Errorf("Result at index %d should've had %d errors, but actually had %d errors", i, len(expectedResult.Errors), len(r.Errors))
}
if len(r.ConditionResults) != len(expectedResult.ConditionResults) {
t.Errorf("Result at index %d should've had %d ConditionResults, but actually had %d ConditionResults", i, len(expectedResult.ConditionResults), len(r.ConditionResults))
}
if r.Success != expectedResult.Success {
t.Errorf("Result at index %d should've had a Success of %t, but was actually %t", i, expectedResult.Success, r.Success)
}
if r.Timestamp != expectedResult.Timestamp {
t.Errorf("Result at index %d should've had a Timestamp of %s, but was actually %s", i, expectedResult.Timestamp.String(), r.Timestamp.String())
}
if r.CertificateExpiration != expectedResult.CertificateExpiration {
t.Errorf("Result at index %d should've had a CertificateExpiration of %s, but was actually %s", i, expectedResult.CertificateExpiration.String(), r.CertificateExpiration.String())
}
}
}
func TestStorage_InsertTwoResultsTwoServicesIntoEmptyMemoryStore_ThenGetAllReturnsTwoServicesWithOneResultEach(t *testing.T) {
memoryStore.Clear()
result1 := core.Result{
HTTPStatus: 404,
DNSRCode: "DNSRCode",
Body: nil,
Hostname: "Hostname",
IP: "IP",
Connected: false,
Duration: time.Second * 2,
Errors: nil,
ConditionResults: nil,
Success: false,
Timestamp: time.Now(),
CertificateExpiration: time.Second * 2,
}
result2 := core.Result{
HTTPStatus: 200,
DNSRCode: "DNSRCode",
Body: nil,
Hostname: "Hostname",
IP: "IP",
Connected: true,
Duration: time.Second * 2,
Errors: nil,
ConditionResults: nil,
Success: true,
Timestamp: time.Now(),
CertificateExpiration: time.Second * 2,
}
testService2 := core.Service{
Name: "Name2",
Group: "Group",
URL: "URL",
DNS: &core.DNS{QueryType: "QueryType", QueryName: "QueryName"},
Method: "Method",
Body: "Body",
GraphQL: false,
Headers: nil,
Interval: time.Second * 2,
Conditions: nil,
Alerts: nil,
Insecure: false,
NumberOfFailuresInARow: 0,
NumberOfSuccessesInARow: 0,
}
memoryStore.Insert(&testService, &result1)
memoryStore.Insert(&testService2, &result2)
results := memoryStore.GetAll()
if len(results) != 2 {
t.Fatalf("MemoryStore should've returned 2 results, but actually returned %d", len(results))
}
key := fmt.Sprintf("%s_%s", testService.Group, testService.Name)
serviceResults1, exists := results[key]
if !exists {
t.Fatalf("In Memory Store should've contained key '%s', but didn't", key)
}
if len(serviceResults1.Results) != 1 {
t.Fatalf("Service '%s' should've had 1 results, but actually returned %d", serviceResults1.Name, len(serviceResults1.Results))
}
key = fmt.Sprintf("%s_%s", testService2.Group, testService2.Name)
serviceResults2, exists := results[key]
if !exists {
t.Fatalf("In Memory Store should've contained key '%s', but didn't", key)
}
if len(serviceResults2.Results) != 1 {
t.Fatalf("Service '%s' should've had 1 results, but actually returned %d", serviceResults1.Name, len(serviceResults1.Results))
}
}
func TestStorage_InsertResultForServiceWithErrorsIntoEmptyMemoryStore_ThenGetAllReturnsOneResultWithErrors(t *testing.T) {
memoryStore.Clear()
errors := []string{
"error1",
"error2",
}
result1 := core.Result{
HTTPStatus: 404,
DNSRCode: "DNSRCode",
Body: nil,
Hostname: "Hostname",
IP: "IP",
Connected: false,
Duration: time.Second * 2,
Errors: errors,
ConditionResults: nil,
Success: false,
Timestamp: time.Now(),
CertificateExpiration: time.Second * 2,
}
memoryStore.Insert(&testService, &result1)
results := memoryStore.GetAll()
if len(results) != 1 {
t.Fatalf("MemoryStore should've returned 1 results, but actually returned %d", len(results))
}
key := fmt.Sprintf("%s_%s", testService.Group, testService.Name)
serviceResults, exists := results[key]
if !exists {
t.Fatalf("In Memory Store should've contained key '%s', but didn't", key)
}
if len(serviceResults.Results) != 1 {
t.Fatalf("Service '%s' should've had 2 results, but actually returned %d", serviceResults.Name, len(serviceResults.Results))
}
actualResult := serviceResults.Results[0]
if len(actualResult.Errors) != len(errors) {
t.Errorf("Service result should've had 2 errors, but actually had %d errors", len(actualResult.Errors))
}
for i, err := range actualResult.Errors {
if err != errors[i] {
t.Errorf("Error at index %d should've been %s, but was actually %s", i, errors[i], err)
}
}
}
func TestStorage_InsertResultForServiceWithConditionResultsIntoEmptyMemoryStore_ThenGetAllReturnsOneResultWithConditionResults(t *testing.T) {
memoryStore.Clear()
crs := []*core.ConditionResult{
{
Condition: "condition1",
Success: true,
},
{
Condition: "condition2",
Success: false,
},
}
result := core.Result{
HTTPStatus: 404,
DNSRCode: "DNSRCode",
Body: nil,
Hostname: "Hostname",
IP: "IP",
Connected: false,
Duration: time.Second * 2,
Errors: nil,
ConditionResults: crs,
Success: false,
Timestamp: time.Now(),
CertificateExpiration: time.Second * 2,
}
memoryStore.Insert(&testService, &result)
results := memoryStore.GetAll()
if len(results) != 1 {
t.Fatalf("MemoryStore should've returned 1 results, but actually returned %d", len(results))
}
key := fmt.Sprintf("%s_%s", testService.Group, testService.Name)
serviceResults, exists := results[key]
if !exists {
t.Fatalf("In Memory Store should've contained key '%s', but didn't", key)
}
if len(serviceResults.Results) != 1 {
t.Fatalf("Service '%s' should've had 2 results, but actually returned %d", serviceResults.Name, len(serviceResults.Results))
}
actualResult := serviceResults.Results[0]
if len(actualResult.ConditionResults) != len(crs) {
t.Errorf("Service result should've had 2 ConditionResults, but actually had %d ConditionResults", len(actualResult.Errors))
}
for i, cr := range actualResult.ConditionResults {
if cr.Condition != crs[i].Condition {
t.Errorf("ConditionResult at index %d should've had condition %s, but was actually %s", i, crs[i].Condition, cr.Condition)
}
if cr.Success != crs[i].Success {
t.Errorf("ConditionResult at index %d should've had success value of %t, but was actually %t", i, crs[i].Success, cr.Success)
}
}
}
func TestStorage_MultipleMemoryStoreInstancesReferToDifferentInternalMaps(t *testing.T) {
2020-12-30 11:57:17 +01:00
memoryStore.Clear()
currentMap := memoryStore.GetAll()
otherMemoryStore := NewInMemoryStore()
otherMemoryStoresMap := otherMemoryStore.GetAll()
if len(currentMap) != len(otherMemoryStoresMap) {
t.Errorf("Multiple memory stores should refer to the different internal maps, but 'memoryStore' returned %d results, and 'otherMemoryStore' returned %d results", len(currentMap), len(otherMemoryStoresMap))
2020-12-30 11:57:17 +01:00
}
memoryStore.Insert(&testService, &core.Result{})
currentMap = memoryStore.GetAll()
otherMemoryStoresMap = otherMemoryStore.GetAll()
if len(currentMap) == len(otherMemoryStoresMap) {
t.Errorf("Multiple memory stores should refer to different internal maps, but 'memoryStore' returned %d results after inserting, and 'otherMemoryStore' returned %d results after inserting", len(currentMap), len(otherMemoryStoresMap))
2020-12-30 11:57:17 +01:00
}
otherMemoryStore.Clear()
currentMap = memoryStore.GetAll()
otherMemoryStoresMap = otherMemoryStore.GetAll()
if len(currentMap) == len(otherMemoryStoresMap) {
t.Errorf("Multiple memory stores should refer to different internal maps, but 'memoryStore' returned %d results after clearing, and 'otherMemoryStore' returned %d results after clearing", len(currentMap), len(otherMemoryStoresMap))
2020-12-30 11:57:17 +01:00
}
}
func TestStorage_ModificationsToReturnedMapDoNotAffectInternalMap(t *testing.T) {
memoryStore.Clear()
memoryStore.Insert(&testService, &core.Result{})
modifiedResults := memoryStore.GetAll()
for k := range modifiedResults {
delete(modifiedResults, k)
}
results := memoryStore.GetAll()
if len(modifiedResults) == len(results) {
t.Errorf("Returned map from GetAll should be free to modify by the caller without affecting internal in-memory map, but length of results from in-memory map (%d) was equal to the length of results in modified map (%d)", len(results), len(modifiedResults))
}
}
2020-12-31 21:43:11 +01:00
func TestStorage_GetServiceStatusForExistingStatusReturnsThatServiceStatus(t *testing.T) {
memoryStore.Clear()
memoryStore.Insert(&testService, &core.Result{})
serviceStatus := memoryStore.GetServiceStatus(testService.Group, testService.Name)
if serviceStatus == nil {
t.Errorf("Returned service status for group '%s' and name '%s' was nil after inserting the service into the store", testService.Group, testService.Name)
}
}
func TestStorage_GetServiceStatusForMissingStatusReturnsNil(t *testing.T) {
memoryStore.Clear()
memoryStore.Insert(&testService, &core.Result{})
serviceStatus := memoryStore.GetServiceStatus("nonexistantgroup", "nonexistantname")
if serviceStatus != nil {
t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", testService.Group, testService.Name)
}
serviceStatus = memoryStore.GetServiceStatus(testService.Group, "nonexistantname")
if serviceStatus != nil {
t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", testService.Group, "nonexistantname")
}
serviceStatus = memoryStore.GetServiceStatus("nonexistantgroup", testService.Name)
if serviceStatus != nil {
t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", "nonexistantgroup", testService.Name)
}
}