2021-07-17 01:12:14 +02:00
package store
import (
2024-05-10 04:56:16 +02:00
"errors"
2023-01-08 23:53:37 +01:00
"path/filepath"
2021-07-17 01:12:14 +02:00
"testing"
"time"
2024-05-10 04:56:16 +02:00
"github.com/TwiN/gatus/v5/config/endpoint"
2022-12-06 07:41:09 +01:00
"github.com/TwiN/gatus/v5/storage"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
"github.com/TwiN/gatus/v5/storage/store/memory"
"github.com/TwiN/gatus/v5/storage/store/sql"
2021-07-17 01:12:14 +02:00
)
var (
2024-05-10 04:56:16 +02:00
firstCondition = endpoint . Condition ( "[STATUS] == 200" )
secondCondition = endpoint . Condition ( "[RESPONSE_TIME] < 500" )
thirdCondition = endpoint . Condition ( "[CERTIFICATE_EXPIRATION] < 72h" )
2021-07-17 01:12:14 +02:00
2021-08-20 05:38:29 +02:00
now = time . Now ( ) . Truncate ( time . Hour )
2021-07-17 01:12:14 +02:00
2024-05-10 04:56:16 +02:00
testEndpoint = endpoint . Endpoint {
2021-07-17 01:12:14 +02:00
Name : "name" ,
Group : "group" ,
URL : "https://example.org/what/ever" ,
Method : "GET" ,
Body : "body" ,
Interval : 30 * time . Second ,
2024-05-10 04:56:16 +02:00
Conditions : [ ] endpoint . Condition { firstCondition , secondCondition , thirdCondition } ,
2021-07-17 01:12:14 +02:00
Alerts : nil ,
NumberOfFailuresInARow : 0 ,
NumberOfSuccessesInARow : 0 ,
}
2024-05-10 04:56:16 +02:00
testSuccessfulResult = endpoint . Result {
2021-07-17 01:12:14 +02:00
Timestamp : now ,
Success : true ,
Hostname : "example.org" ,
IP : "127.0.0.1" ,
HTTPStatus : 200 ,
Errors : nil ,
Connected : true ,
Duration : 150 * time . Millisecond ,
CertificateExpiration : 10 * time . Hour ,
2024-05-10 04:56:16 +02:00
ConditionResults : [ ] * endpoint . ConditionResult {
2021-07-17 01:12:14 +02:00
{
Condition : "[STATUS] == 200" ,
Success : true ,
} ,
{
Condition : "[RESPONSE_TIME] < 500" ,
Success : true ,
} ,
{
Condition : "[CERTIFICATE_EXPIRATION] < 72h" ,
Success : true ,
} ,
} ,
}
2024-05-10 04:56:16 +02:00
testUnsuccessfulResult = endpoint . Result {
2021-07-17 01:12:14 +02:00
Timestamp : now ,
Success : false ,
Hostname : "example.org" ,
IP : "127.0.0.1" ,
HTTPStatus : 200 ,
Errors : [ ] string { "error-1" , "error-2" } ,
Connected : true ,
Duration : 750 * time . Millisecond ,
CertificateExpiration : 10 * time . Hour ,
2024-05-10 04:56:16 +02:00
ConditionResults : [ ] * endpoint . ConditionResult {
2021-07-17 01:12:14 +02:00
{
Condition : "[STATUS] == 200" ,
Success : true ,
} ,
{
Condition : "[RESPONSE_TIME] < 500" ,
Success : false ,
} ,
{
Condition : "[CERTIFICATE_EXPIRATION] < 72h" ,
Success : false ,
} ,
} ,
}
)
2021-07-17 01:24:12 +02:00
type Scenario struct {
Name string
Store Store
}
func initStoresAndBaseScenarios ( t * testing . T , testName string ) [ ] * Scenario {
2022-08-12 02:42:56 +02:00
memoryStore , err := memory . NewStore ( )
2021-07-17 01:12:14 +02:00
if err != nil {
t . Fatal ( "failed to create store:" , err . Error ( ) )
}
2022-08-12 02:47:29 +02:00
sqliteStore , err := sql . NewStore ( "sqlite" , t . TempDir ( ) + "/" + testName + ".db" , false )
if err != nil {
t . Fatal ( "failed to create store:" , err . Error ( ) )
}
sqliteStoreWithCaching , err := sql . NewStore ( "sqlite" , t . TempDir ( ) + "/" + testName + "-with-caching.db" , true )
2021-07-17 01:12:14 +02:00
if err != nil {
t . Fatal ( "failed to create store:" , err . Error ( ) )
}
2021-07-17 01:24:12 +02:00
return [ ] * Scenario {
2021-07-17 01:12:14 +02:00
{
Name : "memory" ,
Store : memoryStore ,
} ,
{
2021-07-18 22:13:05 +02:00
Name : "sqlite" ,
Store : sqliteStore ,
2021-07-17 01:12:14 +02:00
} ,
2022-08-12 02:47:29 +02:00
{
Name : "sqlite-with-caching" ,
Store : sqliteStoreWithCaching ,
} ,
2021-07-17 01:12:14 +02:00
}
2021-07-17 01:24:12 +02:00
}
func cleanUp ( scenarios [ ] * Scenario ) {
for _ , scenario := range scenarios {
scenario . Store . Close ( )
}
}
2021-10-23 22:47:12 +02:00
func TestStore_GetEndpointStatusByKey ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_GetEndpointStatusByKey" )
2021-07-17 01:24:12 +02:00
defer cleanUp ( scenarios )
2021-07-17 01:12:14 +02:00
firstResult := testSuccessfulResult
firstResult . Timestamp = now . Add ( - time . Minute )
secondResult := testUnsuccessfulResult
secondResult . Timestamp = now
2023-07-20 05:07:19 +02:00
thirdResult := testSuccessfulResult
thirdResult . Timestamp = now
2021-07-17 01:12:14 +02:00
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2021-10-23 22:47:12 +02:00
scenario . Store . Insert ( & testEndpoint , & firstResult )
scenario . Store . Insert ( & testEndpoint , & secondResult )
endpointStatus , err := scenario . Store . GetEndpointStatusByKey ( testEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) . WithEvents ( 1 , common . MaximumNumberOfEvents ) . WithResults ( 1 , common . MaximumNumberOfResults ) )
2021-09-11 00:00:04 +02:00
if err != nil {
t . Fatal ( "shouldn't have returned an error, got" , err . Error ( ) )
}
2021-10-23 22:47:12 +02:00
if endpointStatus == nil {
t . Fatalf ( "endpointStatus shouldn't have been nil" )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
if endpointStatus . Name != testEndpoint . Name {
t . Fatalf ( "endpointStatus.Name should've been %s, got %s" , testEndpoint . Name , endpointStatus . Name )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
if endpointStatus . Group != testEndpoint . Group {
t . Fatalf ( "endpointStatus.Group should've been %s, got %s" , testEndpoint . Group , endpointStatus . Group )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
if len ( endpointStatus . Results ) != 2 {
t . Fatalf ( "endpointStatus.Results should've had 2 entries" )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
if endpointStatus . Results [ 0 ] . Timestamp . After ( endpointStatus . Results [ 1 ] . Timestamp ) {
2021-07-17 01:12:14 +02:00
t . Error ( "The result at index 0 should've been older than the result at index 1" )
}
2023-07-20 05:07:19 +02:00
scenario . Store . Insert ( & testEndpoint , & thirdResult )
endpointStatus , err = scenario . Store . GetEndpointStatusByKey ( testEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) . WithEvents ( 1 , common . MaximumNumberOfEvents ) . WithResults ( 1 , common . MaximumNumberOfResults ) )
if err != nil {
t . Fatal ( "shouldn't have returned an error, got" , err . Error ( ) )
}
if len ( endpointStatus . Results ) != 3 {
t . Fatalf ( "endpointStatus.Results should've had 3 entries" )
}
2021-07-17 01:12:14 +02:00
scenario . Store . Clear ( )
} )
}
}
2021-10-23 22:47:12 +02:00
func TestStore_GetEndpointStatusForMissingStatusReturnsNil ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_GetEndpointStatusForMissingStatusReturnsNil" )
2021-07-17 01:24:12 +02:00
defer cleanUp ( scenarios )
2021-07-17 01:12:14 +02:00
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2021-10-23 22:47:12 +02:00
scenario . Store . Insert ( & testEndpoint , & testSuccessfulResult )
endpointStatus , err := scenario . Store . GetEndpointStatus ( "nonexistantgroup" , "nonexistantname" , paging . NewEndpointStatusParams ( ) . WithEvents ( 1 , common . MaximumNumberOfEvents ) . WithResults ( 1 , common . MaximumNumberOfResults ) )
2024-05-10 04:56:16 +02:00
if ! errors . Is ( err , common . ErrEndpointNotFound ) {
2021-10-23 22:47:12 +02:00
t . Error ( "should've returned ErrEndpointNotFound, got" , err )
2021-09-11 00:00:04 +02:00
}
2021-10-23 22:47:12 +02:00
if endpointStatus != nil {
t . Errorf ( "Returned endpoint status for group '%s' and name '%s' not nil after inserting the endpoint into the store" , testEndpoint . Group , testEndpoint . Name )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
endpointStatus , err = scenario . Store . GetEndpointStatus ( testEndpoint . Group , "nonexistantname" , paging . NewEndpointStatusParams ( ) . WithEvents ( 1 , common . MaximumNumberOfEvents ) . WithResults ( 1 , common . MaximumNumberOfResults ) )
2024-05-10 04:56:16 +02:00
if ! errors . Is ( err , common . ErrEndpointNotFound ) {
2021-10-23 22:47:12 +02:00
t . Error ( "should've returned ErrEndpointNotFound, got" , err )
2021-09-11 00:00:04 +02:00
}
2021-10-23 22:47:12 +02:00
if endpointStatus != nil {
t . Errorf ( "Returned endpoint status for group '%s' and name '%s' not nil after inserting the endpoint into the store" , testEndpoint . Group , "nonexistantname" )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
endpointStatus , err = scenario . Store . GetEndpointStatus ( "nonexistantgroup" , testEndpoint . Name , paging . NewEndpointStatusParams ( ) . WithEvents ( 1 , common . MaximumNumberOfEvents ) . WithResults ( 1 , common . MaximumNumberOfResults ) )
2024-05-10 04:56:16 +02:00
if ! errors . Is ( err , common . ErrEndpointNotFound ) {
2021-10-23 22:47:12 +02:00
t . Error ( "should've returned ErrEndpointNotFound, got" , err )
2021-09-11 00:00:04 +02:00
}
2021-10-23 22:47:12 +02:00
if endpointStatus != nil {
t . Errorf ( "Returned endpoint status for group '%s' and name '%s' not nil after inserting the endpoint into the store" , "nonexistantgroup" , testEndpoint . Name )
2021-07-17 01:12:14 +02:00
}
} )
}
}
2021-10-23 22:47:12 +02:00
func TestStore_GetAllEndpointStatuses ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_GetAllEndpointStatuses" )
2021-07-17 01:24:12 +02:00
defer cleanUp ( scenarios )
2021-07-17 01:12:14 +02:00
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2021-11-17 04:56:16 +01:00
scenario . Store . Insert ( & testEndpoint , & testSuccessfulResult )
scenario . Store . Insert ( & testEndpoint , & testUnsuccessfulResult )
2021-10-23 22:47:12 +02:00
endpointStatuses , err := scenario . Store . GetAllEndpointStatuses ( paging . NewEndpointStatusParams ( ) . WithResults ( 1 , 20 ) )
2021-09-11 00:00:04 +02:00
if err != nil {
t . Error ( "shouldn't have returned an error, got" , err . Error ( ) )
}
2021-10-23 22:47:12 +02:00
if len ( endpointStatuses ) != 1 {
t . Fatal ( "expected 1 endpoint status" )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
actual := endpointStatuses [ 0 ]
2021-09-02 20:57:50 +02:00
if actual == nil {
2021-10-23 22:47:12 +02:00
t . Fatal ( "expected endpoint status to exist" )
2021-07-17 01:12:14 +02:00
}
if len ( actual . Results ) != 2 {
t . Error ( "expected 2 results, got" , len ( actual . Results ) )
}
if len ( actual . Events ) != 0 {
t . Error ( "expected 0 events, got" , len ( actual . Events ) )
}
scenario . Store . Clear ( )
} )
2021-11-17 04:56:16 +01:00
t . Run ( scenario . Name + "-page-2" , func ( t * testing . T ) {
otherEndpoint := testEndpoint
otherEndpoint . Name = testEndpoint . Name + "-other"
scenario . Store . Insert ( & testEndpoint , & testSuccessfulResult )
scenario . Store . Insert ( & otherEndpoint , & testSuccessfulResult )
scenario . Store . Insert ( & otherEndpoint , & testSuccessfulResult )
scenario . Store . Insert ( & otherEndpoint , & testSuccessfulResult )
endpointStatuses , err := scenario . Store . GetAllEndpointStatuses ( paging . NewEndpointStatusParams ( ) . WithResults ( 2 , 2 ) )
if err != nil {
t . Error ( "shouldn't have returned an error, got" , err . Error ( ) )
}
if len ( endpointStatuses ) != 2 {
t . Fatal ( "expected 2 endpoint statuses" )
}
if endpointStatuses [ 0 ] == nil || endpointStatuses [ 1 ] == nil {
t . Fatal ( "expected endpoint status to exist" )
}
if len ( endpointStatuses [ 0 ] . Results ) != 0 {
t . Error ( "expected 0 results on the first endpoint, got" , len ( endpointStatuses [ 0 ] . Results ) )
}
if len ( endpointStatuses [ 1 ] . Results ) != 1 {
t . Error ( "expected 1 result on the second endpoint, got" , len ( endpointStatuses [ 1 ] . Results ) )
}
if len ( endpointStatuses [ 0 ] . Events ) != 0 {
t . Error ( "expected 0 events on the first endpoint, got" , len ( endpointStatuses [ 0 ] . Events ) )
}
if len ( endpointStatuses [ 1 ] . Events ) != 0 {
t . Error ( "expected 0 events on the second endpoint, got" , len ( endpointStatuses [ 1 ] . Events ) )
}
scenario . Store . Clear ( )
} )
2021-07-17 01:12:14 +02:00
}
}
2021-10-23 22:47:12 +02:00
func TestStore_GetAllEndpointStatusesWithResultsAndEvents ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_GetAllEndpointStatusesWithResultsAndEvents" )
2021-07-17 01:24:12 +02:00
defer cleanUp ( scenarios )
2021-07-17 01:12:14 +02:00
firstResult := testSuccessfulResult
secondResult := testUnsuccessfulResult
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2021-10-23 22:47:12 +02:00
scenario . Store . Insert ( & testEndpoint , & firstResult )
scenario . Store . Insert ( & testEndpoint , & secondResult )
2021-07-17 01:12:14 +02:00
// Can't be bothered dealing with timezone issues on the worker that runs the automated tests
2021-10-23 22:47:12 +02:00
endpointStatuses , err := scenario . Store . GetAllEndpointStatuses ( paging . NewEndpointStatusParams ( ) . WithResults ( 1 , 20 ) . WithEvents ( 1 , 50 ) )
2021-09-11 00:00:04 +02:00
if err != nil {
t . Error ( "shouldn't have returned an error, got" , err . Error ( ) )
}
2021-10-23 22:47:12 +02:00
if len ( endpointStatuses ) != 1 {
t . Fatal ( "expected 1 endpoint status" )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
actual := endpointStatuses [ 0 ]
2021-09-02 20:57:50 +02:00
if actual == nil {
2021-10-23 22:47:12 +02:00
t . Fatal ( "expected endpoint status to exist" )
2021-07-17 01:12:14 +02:00
}
if len ( actual . Results ) != 2 {
t . Error ( "expected 2 results, got" , len ( actual . Results ) )
}
if len ( actual . Events ) != 3 {
t . Error ( "expected 3 events, got" , len ( actual . Events ) )
}
scenario . Store . Clear ( )
} )
}
}
2021-10-23 22:47:12 +02:00
func TestStore_GetEndpointStatusPage1IsHasMoreRecentResultsThanPage2 ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_GetEndpointStatusPage1IsHasMoreRecentResultsThanPage2" )
2021-07-17 01:24:12 +02:00
defer cleanUp ( scenarios )
2021-07-17 01:12:14 +02:00
firstResult := testSuccessfulResult
firstResult . Timestamp = now . Add ( - time . Minute )
secondResult := testUnsuccessfulResult
secondResult . Timestamp = now
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2021-10-23 22:47:12 +02:00
scenario . Store . Insert ( & testEndpoint , & firstResult )
scenario . Store . Insert ( & testEndpoint , & secondResult )
endpointStatusPage1 , err := scenario . Store . GetEndpointStatusByKey ( testEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) . WithResults ( 1 , 1 ) )
2021-09-11 00:00:04 +02:00
if err != nil {
t . Error ( "shouldn't have returned an error, got" , err . Error ( ) )
}
2021-10-23 22:47:12 +02:00
if endpointStatusPage1 == nil {
t . Fatalf ( "endpointStatusPage1 shouldn't have been nil" )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
if len ( endpointStatusPage1 . Results ) != 1 {
t . Fatalf ( "endpointStatusPage1 should've had 1 result" )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
endpointStatusPage2 , err := scenario . Store . GetEndpointStatusByKey ( testEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) . WithResults ( 2 , 1 ) )
2021-09-11 00:00:04 +02:00
if err != nil {
t . Error ( "shouldn't have returned an error, got" , err . Error ( ) )
}
2021-10-23 22:47:12 +02:00
if endpointStatusPage2 == nil {
t . Fatalf ( "endpointStatusPage2 shouldn't have been nil" )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
if len ( endpointStatusPage2 . Results ) != 1 {
t . Fatalf ( "endpointStatusPage2 should've had 1 result" )
2021-07-17 01:12:14 +02:00
}
// Compare the timestamp of both pages
2021-10-23 22:47:12 +02:00
if ! endpointStatusPage1 . Results [ 0 ] . Timestamp . After ( endpointStatusPage2 . Results [ 0 ] . Timestamp ) {
2021-07-17 01:12:14 +02:00
t . Errorf ( "The result from the first page should've been more recent than the results from the second page" )
}
scenario . Store . Clear ( )
} )
}
}
2021-08-13 03:54:23 +02:00
func TestStore_GetUptimeByKey ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_GetUptimeByKey" )
defer cleanUp ( scenarios )
firstResult := testSuccessfulResult
firstResult . Timestamp = now . Add ( - time . Minute )
secondResult := testUnsuccessfulResult
secondResult . Timestamp = now
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2021-10-23 22:47:12 +02:00
if _ , err := scenario . Store . GetUptimeByKey ( testEndpoint . Key ( ) , time . Now ( ) . Add ( - time . Hour ) , time . Now ( ) ) ; err != common . ErrEndpointNotFound {
2021-08-13 03:54:23 +02:00
t . Errorf ( "should've returned not found because there's nothing yet, got %v" , err )
}
2021-10-23 22:47:12 +02:00
scenario . Store . Insert ( & testEndpoint , & firstResult )
scenario . Store . Insert ( & testEndpoint , & secondResult )
if uptime , _ := scenario . Store . GetUptimeByKey ( testEndpoint . Key ( ) , now . Add ( - time . Hour ) , time . Now ( ) ) ; uptime != 0.5 {
2021-08-13 03:54:23 +02:00
t . Errorf ( "the uptime over the past 1h should've been 0.5, got %f" , uptime )
}
2021-10-23 22:47:12 +02:00
if uptime , _ := scenario . Store . GetUptimeByKey ( testEndpoint . Key ( ) , now . Add ( - time . Hour * 24 ) , time . Now ( ) ) ; uptime != 0.5 {
2021-08-13 03:54:23 +02:00
t . Errorf ( "the uptime over the past 24h should've been 0.5, got %f" , uptime )
}
2021-10-23 22:47:12 +02:00
if uptime , _ := scenario . Store . GetUptimeByKey ( testEndpoint . Key ( ) , now . Add ( - time . Hour * 24 * 7 ) , time . Now ( ) ) ; uptime != 0.5 {
2021-08-13 03:54:23 +02:00
t . Errorf ( "the uptime over the past 7d should've been 0.5, got %f" , uptime )
}
2021-10-23 22:47:12 +02:00
if _ , err := scenario . Store . GetUptimeByKey ( testEndpoint . Key ( ) , now , time . Now ( ) . Add ( - time . Hour ) ) ; err == nil {
2021-08-13 03:54:23 +02:00
t . Error ( "should've returned an error because the parameter 'from' cannot be older than 'to'" )
}
} )
}
}
2021-08-21 17:17:39 +02:00
func TestStore_GetAverageResponseTimeByKey ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_GetAverageResponseTimeByKey" )
defer cleanUp ( scenarios )
firstResult := testSuccessfulResult
firstResult . Timestamp = now . Add ( - ( 2 * time . Hour ) )
firstResult . Duration = 300 * time . Millisecond
secondResult := testSuccessfulResult
secondResult . Duration = 150 * time . Millisecond
secondResult . Timestamp = now . Add ( - ( 1 * time . Hour + 30 * time . Minute ) )
thirdResult := testUnsuccessfulResult
thirdResult . Duration = 200 * time . Millisecond
thirdResult . Timestamp = now . Add ( - ( 1 * time . Hour ) )
fourthResult := testSuccessfulResult
fourthResult . Duration = 500 * time . Millisecond
fourthResult . Timestamp = now
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2021-10-23 22:47:12 +02:00
scenario . Store . Insert ( & testEndpoint , & firstResult )
scenario . Store . Insert ( & testEndpoint , & secondResult )
scenario . Store . Insert ( & testEndpoint , & thirdResult )
scenario . Store . Insert ( & testEndpoint , & fourthResult )
if averageResponseTime , err := scenario . Store . GetAverageResponseTimeByKey ( testEndpoint . Key ( ) , now . Add ( - 48 * time . Hour ) , now . Add ( - 24 * time . Hour ) ) ; err == nil {
2021-08-21 17:17:39 +02:00
if averageResponseTime != 0 {
t . Errorf ( "expected average response time to be 0ms, got %v" , averageResponseTime )
}
} else {
t . Error ( "shouldn't have returned an error, got" , err )
}
2021-10-23 22:47:12 +02:00
if averageResponseTime , err := scenario . Store . GetAverageResponseTimeByKey ( testEndpoint . Key ( ) , now . Add ( - 24 * time . Hour ) , now ) ; err == nil {
2021-08-21 17:17:39 +02:00
if averageResponseTime != 287 {
t . Errorf ( "expected average response time to be 287ms, got %v" , averageResponseTime )
}
} else {
t . Error ( "shouldn't have returned an error, got" , err )
}
2021-10-23 22:47:12 +02:00
if averageResponseTime , err := scenario . Store . GetAverageResponseTimeByKey ( testEndpoint . Key ( ) , now . Add ( - time . Hour ) , now ) ; err == nil {
2021-08-21 17:17:39 +02:00
if averageResponseTime != 350 {
t . Errorf ( "expected average response time to be 350ms, got %v" , averageResponseTime )
}
} else {
t . Error ( "shouldn't have returned an error, got" , err )
}
2021-10-23 22:47:12 +02:00
if averageResponseTime , err := scenario . Store . GetAverageResponseTimeByKey ( testEndpoint . Key ( ) , now . Add ( - 2 * time . Hour ) , now . Add ( - time . Hour ) ) ; err == nil {
2021-08-21 17:17:39 +02:00
if averageResponseTime != 216 {
t . Errorf ( "expected average response time to be 216ms, got %v" , averageResponseTime )
}
} else {
t . Error ( "shouldn't have returned an error, got" , err )
}
2021-10-23 22:47:12 +02:00
if _ , err := scenario . Store . GetAverageResponseTimeByKey ( testEndpoint . Key ( ) , now , now . Add ( - 2 * time . Hour ) ) ; err == nil {
2021-08-21 17:17:39 +02:00
t . Error ( "expected an error because from > to, got nil" )
}
scenario . Store . Clear ( )
} )
}
}
2021-08-20 05:07:21 +02:00
func TestStore_GetHourlyAverageResponseTimeByKey ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_GetHourlyAverageResponseTimeByKey" )
defer cleanUp ( scenarios )
firstResult := testSuccessfulResult
firstResult . Timestamp = now . Add ( - ( 2 * time . Hour ) )
firstResult . Duration = 300 * time . Millisecond
secondResult := testSuccessfulResult
secondResult . Duration = 150 * time . Millisecond
secondResult . Timestamp = now . Add ( - ( 1 * time . Hour + 30 * time . Minute ) )
thirdResult := testUnsuccessfulResult
thirdResult . Duration = 200 * time . Millisecond
thirdResult . Timestamp = now . Add ( - ( 1 * time . Hour ) )
fourthResult := testSuccessfulResult
fourthResult . Duration = 500 * time . Millisecond
fourthResult . Timestamp = now
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2021-10-23 22:47:12 +02:00
scenario . Store . Insert ( & testEndpoint , & firstResult )
scenario . Store . Insert ( & testEndpoint , & secondResult )
scenario . Store . Insert ( & testEndpoint , & thirdResult )
scenario . Store . Insert ( & testEndpoint , & fourthResult )
hourlyAverageResponseTime , err := scenario . Store . GetHourlyAverageResponseTimeByKey ( testEndpoint . Key ( ) , now . Add ( - 24 * time . Hour ) , now )
2021-08-20 05:07:21 +02:00
if err != nil {
t . Error ( "shouldn't have returned an error, got" , err )
}
if key := now . Truncate ( time . Hour ) . Unix ( ) ; hourlyAverageResponseTime [ key ] != 500 {
t . Errorf ( "expected average response time to be 500ms at %d, got %v" , key , hourlyAverageResponseTime [ key ] )
}
2021-08-20 05:38:29 +02:00
if key := now . Truncate ( time . Hour ) . Add ( - time . Hour ) . Unix ( ) ; hourlyAverageResponseTime [ key ] != 200 {
t . Errorf ( "expected average response time to be 200ms at %d, got %v" , key , hourlyAverageResponseTime [ key ] )
2021-08-20 05:07:21 +02:00
}
2021-08-20 05:38:29 +02:00
if key := now . Truncate ( time . Hour ) . Add ( - 2 * time . Hour ) . Unix ( ) ; hourlyAverageResponseTime [ key ] != 225 {
t . Errorf ( "expected average response time to be 225ms at %d, got %v" , key , hourlyAverageResponseTime [ key ] )
2021-08-20 05:07:21 +02:00
}
scenario . Store . Clear ( )
} )
}
}
2021-07-17 01:12:14 +02:00
func TestStore_Insert ( t * testing . T ) {
2021-07-17 01:24:12 +02:00
scenarios := initStoresAndBaseScenarios ( t , "TestStore_Insert" )
defer cleanUp ( scenarios )
2021-07-17 01:12:14 +02:00
firstResult := testSuccessfulResult
firstResult . Timestamp = now . Add ( - time . Minute )
secondResult := testUnsuccessfulResult
secondResult . Timestamp = now
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2023-07-20 05:07:19 +02:00
scenario . Store . Insert ( & testEndpoint , & firstResult )
scenario . Store . Insert ( & testEndpoint , & secondResult )
2021-10-23 22:47:12 +02:00
ss , err := scenario . Store . GetEndpointStatusByKey ( testEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) . WithEvents ( 1 , common . MaximumNumberOfEvents ) . WithResults ( 1 , common . MaximumNumberOfResults ) )
2021-09-11 00:00:04 +02:00
if err != nil {
t . Error ( "shouldn't have returned an error, got" , err )
}
2021-07-19 05:02:27 +02:00
if ss == nil {
2021-10-23 22:47:12 +02:00
t . Fatalf ( "Store should've had key '%s', but didn't" , testEndpoint . Key ( ) )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if len ( ss . Events ) != 3 {
2021-10-23 22:47:12 +02:00
t . Fatalf ( "Endpoint '%s' should've had 3 events, got %d" , ss . Name , len ( ss . Events ) )
2021-07-19 05:02:27 +02:00
}
if len ( ss . Results ) != 2 {
2021-10-23 22:47:12 +02:00
t . Fatalf ( "Endpoint '%s' should've had 2 results, got %d" , ss . Name , len ( ss . Results ) )
2021-07-17 01:12:14 +02:00
}
2024-05-10 04:56:16 +02:00
for i , expectedResult := range [ ] endpoint . Result { firstResult , secondResult } {
2021-07-19 05:02:27 +02:00
if expectedResult . HTTPStatus != ss . Results [ i ] . HTTPStatus {
t . Errorf ( "Result at index %d should've had a HTTPStatus of %d, got %d" , i , ss . Results [ i ] . HTTPStatus , expectedResult . HTTPStatus )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if expectedResult . DNSRCode != ss . Results [ i ] . DNSRCode {
t . Errorf ( "Result at index %d should've had a DNSRCode of %s, got %s" , i , ss . Results [ i ] . DNSRCode , expectedResult . DNSRCode )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if expectedResult . Hostname != ss . Results [ i ] . Hostname {
t . Errorf ( "Result at index %d should've had a Hostname of %s, got %s" , i , ss . Results [ i ] . Hostname , expectedResult . Hostname )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if expectedResult . IP != ss . Results [ i ] . IP {
t . Errorf ( "Result at index %d should've had a IP of %s, got %s" , i , ss . Results [ i ] . IP , expectedResult . IP )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if expectedResult . Connected != ss . Results [ i ] . Connected {
t . Errorf ( "Result at index %d should've had a Connected value of %t, got %t" , i , ss . Results [ i ] . Connected , expectedResult . Connected )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if expectedResult . Duration != ss . Results [ i ] . Duration {
t . Errorf ( "Result at index %d should've had a Duration of %s, got %s" , i , ss . Results [ i ] . Duration . String ( ) , expectedResult . Duration . String ( ) )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if len ( expectedResult . Errors ) != len ( ss . Results [ i ] . Errors ) {
t . Errorf ( "Result at index %d should've had %d errors, but actually had %d errors" , i , len ( ss . Results [ i ] . Errors ) , len ( expectedResult . Errors ) )
} else {
for j := range expectedResult . Errors {
if ss . Results [ i ] . Errors [ j ] != expectedResult . Errors [ j ] {
t . Error ( "should've been the same" )
}
}
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if len ( expectedResult . ConditionResults ) != len ( ss . Results [ i ] . ConditionResults ) {
t . Errorf ( "Result at index %d should've had %d ConditionResults, but actually had %d ConditionResults" , i , len ( ss . Results [ i ] . ConditionResults ) , len ( expectedResult . ConditionResults ) )
} else {
for j := range expectedResult . ConditionResults {
if ss . Results [ i ] . ConditionResults [ j ] . Condition != expectedResult . ConditionResults [ j ] . Condition {
t . Error ( "should've been the same" )
}
if ss . Results [ i ] . ConditionResults [ j ] . Success != expectedResult . ConditionResults [ j ] . Success {
t . Error ( "should've been the same" )
}
}
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if expectedResult . Success != ss . Results [ i ] . Success {
t . Errorf ( "Result at index %d should've had a Success of %t, got %t" , i , ss . Results [ i ] . Success , expectedResult . Success )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if expectedResult . Timestamp . Unix ( ) != ss . Results [ i ] . Timestamp . Unix ( ) {
t . Errorf ( "Result at index %d should've had a Timestamp of %d, got %d" , i , ss . Results [ i ] . Timestamp . Unix ( ) , expectedResult . Timestamp . Unix ( ) )
2021-07-17 01:12:14 +02:00
}
2021-07-19 05:02:27 +02:00
if expectedResult . CertificateExpiration != ss . Results [ i ] . CertificateExpiration {
t . Errorf ( "Result at index %d should've had a CertificateExpiration of %s, got %s" , i , ss . Results [ i ] . CertificateExpiration . String ( ) , expectedResult . CertificateExpiration . String ( ) )
2021-07-17 01:12:14 +02:00
}
}
} )
}
}
2021-10-23 22:47:12 +02:00
func TestStore_DeleteAllEndpointStatusesNotInKeys ( t * testing . T ) {
scenarios := initStoresAndBaseScenarios ( t , "TestStore_DeleteAllEndpointStatusesNotInKeys" )
2021-07-17 01:24:12 +02:00
defer cleanUp ( scenarios )
2024-05-10 04:56:16 +02:00
firstEndpoint := endpoint . Endpoint { Name : "endpoint-1" , Group : "group" }
secondEndpoint := endpoint . Endpoint { Name : "endpoint-2" , Group : "group" }
r := & testSuccessfulResult
2021-07-17 01:12:14 +02:00
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
2024-05-10 04:56:16 +02:00
scenario . Store . Insert ( & firstEndpoint , r )
scenario . Store . Insert ( & secondEndpoint , r )
2021-10-23 22:47:12 +02:00
if ss , _ := scenario . Store . GetEndpointStatusByKey ( firstEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) ) ; ss == nil {
2022-08-12 02:42:56 +02:00
t . Fatal ( "firstEndpoint should exist, got" , ss )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
if ss , _ := scenario . Store . GetEndpointStatusByKey ( secondEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) ) ; ss == nil {
2022-08-12 02:42:56 +02:00
t . Fatal ( "secondEndpoint should exist, got" , ss )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
scenario . Store . DeleteAllEndpointStatusesNotInKeys ( [ ] string { firstEndpoint . Key ( ) } )
if ss , _ := scenario . Store . GetEndpointStatusByKey ( firstEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) ) ; ss == nil {
2022-08-12 02:42:56 +02:00
t . Error ( "secondEndpoint should still exist, got" , ss )
2021-07-17 01:12:14 +02:00
}
2021-10-23 22:47:12 +02:00
if ss , _ := scenario . Store . GetEndpointStatusByKey ( secondEndpoint . Key ( ) , paging . NewEndpointStatusParams ( ) ) ; ss != nil {
2022-08-12 02:42:56 +02:00
t . Error ( "firstEndpoint should have been deleted, got" , ss )
2021-07-17 01:12:14 +02:00
}
2021-07-18 06:34:22 +02:00
// Delete everything
2021-10-23 22:47:12 +02:00
scenario . Store . DeleteAllEndpointStatusesNotInKeys ( [ ] string { } )
endpointStatuses , _ := scenario . Store . GetAllEndpointStatuses ( paging . NewEndpointStatusParams ( ) )
if len ( endpointStatuses ) != 0 {
2021-07-18 06:34:22 +02:00
t . Errorf ( "everything should've been deleted" )
}
2021-07-17 01:12:14 +02:00
} )
}
}
2021-10-29 01:35:46 +02:00
func TestGet ( t * testing . T ) {
store := Get ( )
if store == nil {
t . Error ( "store should've been automatically initialized" )
}
}
func TestInitialize ( t * testing . T ) {
2023-01-08 23:53:37 +01:00
dir := t . TempDir ( )
2021-10-29 01:35:46 +02:00
type Scenario struct {
Name string
Cfg * storage . Config
ExpectedErr error
}
scenarios := [ ] Scenario {
{
Name : "nil" ,
Cfg : nil ,
ExpectedErr : nil ,
} ,
{
Name : "blank" ,
Cfg : & storage . Config { } ,
ExpectedErr : nil ,
} ,
{
2021-11-05 02:40:05 +01:00
Name : "memory-no-path" ,
2021-10-29 01:35:46 +02:00
Cfg : & storage . Config { Type : storage . TypeMemory } ,
ExpectedErr : nil ,
} ,
{
2021-11-05 02:40:05 +01:00
Name : "sqlite-no-path" ,
2021-10-29 01:35:46 +02:00
Cfg : & storage . Config { Type : storage . TypeSQLite } ,
2021-11-05 02:33:13 +01:00
ExpectedErr : sql . ErrPathNotSpecified ,
2021-10-29 01:35:46 +02:00
} ,
{
2021-11-05 02:40:05 +01:00
Name : "sqlite-with-path" ,
2023-01-08 23:53:37 +01:00
Cfg : & storage . Config { Type : storage . TypeSQLite , Path : filepath . Join ( dir , "TestInitialize_sqlite-with-path.db" ) } ,
2021-10-29 01:35:46 +02:00
ExpectedErr : nil ,
} ,
}
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
err := Initialize ( scenario . Cfg )
if err != scenario . ExpectedErr {
t . Errorf ( "expected %v, got %v" , scenario . ExpectedErr , err )
}
if err != nil {
return
}
if cancelFunc == nil {
t . Error ( "cancelFunc shouldn't have been nil" )
}
if ctx == nil {
t . Error ( "ctx shouldn't have been nil" )
}
if store == nil {
t . Fatal ( "provider shouldn't have been nit" )
}
store . Close ( )
// Try to initialize it again
err = Initialize ( scenario . Cfg )
2024-05-10 04:56:16 +02:00
if ! errors . Is ( err , scenario . ExpectedErr ) {
2021-10-29 01:35:46 +02:00
t . Errorf ( "expected %v, got %v" , scenario . ExpectedErr , err )
return
}
store . Close ( )
} )
}
}
func TestAutoSave ( t * testing . T ) {
2023-01-08 23:53:37 +01:00
file := filepath . Join ( t . TempDir ( ) , "/TestAutoSave.db" )
2021-11-05 02:33:13 +01:00
if err := Initialize ( & storage . Config { Path : file } ) ; err != nil {
2021-10-29 01:35:46 +02:00
t . Fatal ( "shouldn't have returned an error" )
}
go autoSave ( ctx , store , 3 * time . Millisecond )
time . Sleep ( 15 * time . Millisecond )
cancelFunc ( )
time . Sleep ( 50 * time . Millisecond )
}