2020-04-15 01:20:00 +02:00
package core
import (
2020-12-19 00:40:11 +01:00
"io/ioutil"
"strings"
2020-04-15 01:20:00 +02:00
"testing"
2020-10-22 03:56:07 +02:00
"time"
2021-05-19 04:29:15 +02:00
"github.com/TwinProduction/gatus/alerting/alert"
2021-07-29 03:41:26 +02:00
"github.com/TwinProduction/gatus/client"
2020-04-15 01:20:00 +02:00
)
2021-09-18 17:52:11 +02:00
func TestService_IsEnabled ( t * testing . T ) {
if ! ( Service { Enabled : nil } ) . IsEnabled ( ) {
t . Error ( "service.IsEnabled() should've returned true, because Enabled was set to nil" )
}
if value := false ; ( Service { Enabled : & value } ) . IsEnabled ( ) {
t . Error ( "service.IsEnabled() should've returned false, because Enabled was set to false" )
}
if value := true ; ! ( Service { Enabled : & value } ) . IsEnabled ( ) {
t . Error ( "Service.IsEnabled() should've returned true, because Enabled was set to true" )
}
}
2020-10-22 04:21:51 +02:00
func TestService_ValidateAndSetDefaults ( t * testing . T ) {
condition := Condition ( "[STATUS] == 200" )
service := Service {
2021-09-18 18:42:11 +02:00
Name : "website-health" ,
URL : "https://twin.sh/health" ,
2020-10-22 04:21:51 +02:00
Conditions : [ ] * Condition { & condition } ,
2021-05-19 04:29:15 +02:00
Alerts : [ ] * alert . Alert { { Type : alert . TypePagerDuty } } ,
2020-10-22 04:21:51 +02:00
}
service . ValidateAndSetDefaults ( )
2021-07-29 03:41:26 +02:00
if service . ClientConfig == nil {
t . Error ( "client configuration should've been set to the default configuration" )
} else {
if service . ClientConfig . Insecure != client . GetDefaultConfig ( ) . Insecure {
t . Errorf ( "Default client configuration should've set Insecure to %v, got %v" , client . GetDefaultConfig ( ) . Insecure , service . ClientConfig . Insecure )
}
if service . ClientConfig . IgnoreRedirect != client . GetDefaultConfig ( ) . IgnoreRedirect {
t . Errorf ( "Default client configuration should've set IgnoreRedirect to %v, got %v" , client . GetDefaultConfig ( ) . IgnoreRedirect , service . ClientConfig . IgnoreRedirect )
}
if service . ClientConfig . Timeout != client . GetDefaultConfig ( ) . Timeout {
t . Errorf ( "Default client configuration should've set Timeout to %v, got %v" , client . GetDefaultConfig ( ) . Timeout , service . ClientConfig . Timeout )
}
}
2020-10-22 04:21:51 +02:00
if service . Method != "GET" {
t . Error ( "Service method should've defaulted to GET" )
}
if service . Interval != time . Minute {
t . Error ( "Service interval should've defaulted to 1 minute" )
}
if service . Headers == nil {
t . Error ( "Service headers should've defaulted to an empty map" )
}
if len ( service . Alerts ) != 1 {
t . Error ( "Service should've had 1 alert" )
}
2021-05-16 03:31:32 +02:00
if service . Alerts [ 0 ] . IsEnabled ( ) {
2020-10-22 04:21:51 +02:00
t . Error ( "Service alert should've defaulted to disabled" )
}
if service . Alerts [ 0 ] . SuccessThreshold != 2 {
t . Error ( "Service alert should've defaulted to a success threshold of 2" )
}
if service . Alerts [ 0 ] . FailureThreshold != 3 {
t . Error ( "Service alert should've defaulted to a failure threshold of 3" )
}
}
2021-07-29 03:41:26 +02:00
func TestService_ValidateAndSetDefaultsWithClientConfig ( t * testing . T ) {
condition := Condition ( "[STATUS] == 200" )
service := Service {
2021-09-18 18:42:11 +02:00
Name : "website-health" ,
URL : "https://twin.sh/health" ,
2021-07-29 03:41:26 +02:00
Conditions : [ ] * Condition { & condition } ,
ClientConfig : & client . Config {
Insecure : true ,
IgnoreRedirect : true ,
Timeout : 0 ,
} ,
}
service . ValidateAndSetDefaults ( )
if service . ClientConfig == nil {
t . Error ( "client configuration should've been set to the default configuration" )
} else {
if ! service . ClientConfig . Insecure {
t . Error ( "service.ClientConfig.Insecure should've been set to true" )
}
if ! service . ClientConfig . IgnoreRedirect {
t . Error ( "service.ClientConfig.IgnoreRedirect should've been set to true" )
}
if service . ClientConfig . Timeout != client . GetDefaultConfig ( ) . Timeout {
t . Error ( "service.ClientConfig.Timeout should've been set to 10s, because the timeout value entered is not set or invalid" )
}
}
}
2020-10-22 04:56:35 +02:00
func TestService_ValidateAndSetDefaultsWithNoName ( t * testing . T ) {
defer func ( ) { recover ( ) } ( )
condition := Condition ( "[STATUS] == 200" )
service := & Service {
Name : "" ,
2020-10-23 22:29:20 +02:00
URL : "http://example.com" ,
2020-10-22 04:56:35 +02:00
Conditions : [ ] * Condition { & condition } ,
}
2021-05-19 05:27:43 +02:00
err := service . ValidateAndSetDefaults ( )
if err == nil {
t . Fatal ( "Should've returned an error because service didn't have a name, which is a mandatory field" )
}
2020-10-22 04:56:35 +02:00
}
func TestService_ValidateAndSetDefaultsWithNoUrl ( t * testing . T ) {
defer func ( ) { recover ( ) } ( )
condition := Condition ( "[STATUS] == 200" )
service := & Service {
Name : "example" ,
2020-10-23 22:29:20 +02:00
URL : "" ,
2020-10-22 04:56:35 +02:00
Conditions : [ ] * Condition { & condition } ,
}
2021-05-19 05:27:43 +02:00
err := service . ValidateAndSetDefaults ( )
if err == nil {
t . Fatal ( "Should've returned an error because service didn't have an url, which is a mandatory field" )
}
2020-10-22 04:56:35 +02:00
}
func TestService_ValidateAndSetDefaultsWithNoConditions ( t * testing . T ) {
defer func ( ) { recover ( ) } ( )
service := & Service {
Name : "example" ,
2020-10-23 22:29:20 +02:00
URL : "http://example.com" ,
2020-10-22 04:56:35 +02:00
Conditions : nil ,
}
2021-05-19 05:27:43 +02:00
err := service . ValidateAndSetDefaults ( )
if err == nil {
t . Fatal ( "Should've returned an error because service didn't have at least 1 condition" )
}
2020-10-22 04:56:35 +02:00
}
2020-11-18 00:55:31 +01:00
func TestService_ValidateAndSetDefaultsWithDNS ( t * testing . T ) {
2020-11-18 01:00:16 +01:00
conditionSuccess := Condition ( "[DNS_RCODE] == NOERROR" )
2020-11-18 00:55:31 +01:00
service := & Service {
2020-11-18 01:00:16 +01:00
Name : "dns-test" ,
2020-11-18 00:55:31 +01:00
URL : "http://example.com" ,
DNS : & DNS {
QueryType : "A" ,
QueryName : "example.com" ,
} ,
2020-11-18 01:00:16 +01:00
Conditions : [ ] * Condition { & conditionSuccess } ,
2020-11-18 00:55:31 +01:00
}
2021-05-19 05:27:43 +02:00
err := service . ValidateAndSetDefaults ( )
if err != nil {
}
2020-11-18 01:00:16 +01:00
if service . DNS . QueryName != "example.com." {
2020-11-18 00:55:31 +01:00
t . Error ( "Service.dns.query-name should be formatted with . suffix" )
}
}
2020-12-19 00:06:57 +01:00
func TestService_buildHTTPRequest ( t * testing . T ) {
condition := Condition ( "[STATUS] == 200" )
service := Service {
2021-09-18 18:42:11 +02:00
Name : "website-health" ,
URL : "https://twin.sh/health" ,
2020-12-19 00:06:57 +01:00
Conditions : [ ] * Condition { & condition } ,
}
service . ValidateAndSetDefaults ( )
request := service . buildHTTPRequest ( )
2020-12-19 00:40:11 +01:00
if request . Method != "GET" {
t . Error ( "request.Method should've been GET, but was" , request . Method )
}
2021-09-18 18:42:11 +02:00
if request . Host != "twin.sh" {
t . Error ( "request.Host should've been twin.sh, but was" , request . Host )
2020-12-19 00:06:57 +01:00
}
2020-12-31 01:56:12 +01:00
if userAgent := request . Header . Get ( "User-Agent" ) ; userAgent != GatusUserAgent {
t . Errorf ( "request.Header.Get(User-Agent) should've been %s, but was %s" , GatusUserAgent , userAgent )
}
}
func TestService_buildHTTPRequestWithCustomUserAgent ( t * testing . T ) {
condition := Condition ( "[STATUS] == 200" )
service := Service {
2021-09-18 18:42:11 +02:00
Name : "website-health" ,
URL : "https://twin.sh/health" ,
2020-12-31 01:56:12 +01:00
Conditions : [ ] * Condition { & condition } ,
Headers : map [ string ] string {
"User-Agent" : "Test/2.0" ,
} ,
}
service . ValidateAndSetDefaults ( )
request := service . buildHTTPRequest ( )
if request . Method != "GET" {
t . Error ( "request.Method should've been GET, but was" , request . Method )
}
2021-09-18 18:42:11 +02:00
if request . Host != "twin.sh" {
t . Error ( "request.Host should've been twin.sh, but was" , request . Host )
2020-12-31 01:56:12 +01:00
}
if userAgent := request . Header . Get ( "User-Agent" ) ; userAgent != "Test/2.0" {
t . Errorf ( "request.Header.Get(User-Agent) should've been %s, but was %s" , "Test/2.0" , userAgent )
}
2020-12-19 00:06:57 +01:00
}
func TestService_buildHTTPRequestWithHostHeader ( t * testing . T ) {
condition := Condition ( "[STATUS] == 200" )
service := Service {
2021-09-18 18:42:11 +02:00
Name : "website-health" ,
URL : "https://twin.sh/health" ,
2020-12-19 00:40:11 +01:00
Method : "POST" ,
2020-12-19 00:06:57 +01:00
Conditions : [ ] * Condition { & condition } ,
Headers : map [ string ] string {
"Host" : "example.com" ,
} ,
}
service . ValidateAndSetDefaults ( )
request := service . buildHTTPRequest ( )
2020-12-19 00:40:11 +01:00
if request . Method != "POST" {
t . Error ( "request.Method should've been POST, but was" , request . Method )
}
2020-12-19 00:06:57 +01:00
if request . Host != "example.com" {
2020-12-19 00:40:11 +01:00
t . Error ( "request.Host should've been example.com, but was" , request . Host )
}
}
func TestService_buildHTTPRequestWithGraphQLEnabled ( t * testing . T ) {
condition := Condition ( "[STATUS] == 200" )
service := Service {
2021-09-18 18:42:11 +02:00
Name : "website-graphql" ,
URL : "https://twin.sh/graphql" ,
2020-12-19 00:40:11 +01:00
Method : "POST" ,
Conditions : [ ] * Condition { & condition } ,
GraphQL : true ,
Body : ` {
2021-03-06 02:33:06 +01:00
users ( gender : "female" ) {
2020-12-19 00:40:11 +01:00
id
name
gender
avatar
}
} ` ,
}
service . ValidateAndSetDefaults ( )
request := service . buildHTTPRequest ( )
if request . Method != "POST" {
t . Error ( "request.Method should've been POST, but was" , request . Method )
}
if contentType := request . Header . Get ( ContentTypeHeader ) ; contentType != "application/json" {
t . Error ( "request.Header.Content-Type should've been application/json, but was" , contentType )
}
body , _ := ioutil . ReadAll ( request . Body )
if ! strings . HasPrefix ( string ( body ) , "{\"query\":" ) {
2021-03-09 03:30:11 +01:00
t . Error ( "request.body should've started with '{\"query\":', but it didn't:" , string ( body ) )
2020-12-19 00:06:57 +01:00
}
}
2020-09-25 01:49:32 +02:00
func TestIntegrationEvaluateHealth ( t * testing . T ) {
2020-04-15 01:20:00 +02:00
condition := Condition ( "[STATUS] == 200" )
2021-03-09 03:30:11 +01:00
bodyCondition := Condition ( "[BODY].status == UP" )
2020-04-15 01:20:00 +02:00
service := Service {
2021-09-18 18:42:11 +02:00
Name : "website-health" ,
URL : "https://twin.sh/health" ,
2021-03-09 03:30:11 +01:00
Conditions : [ ] * Condition { & condition , & bodyCondition } ,
2020-04-15 01:20:00 +02:00
}
2021-07-29 03:41:26 +02:00
service . ValidateAndSetDefaults ( )
2020-09-25 01:49:32 +02:00
result := service . EvaluateHealth ( )
2020-04-15 01:20:00 +02:00
if ! result . ConditionResults [ 0 ] . Success {
t . Errorf ( "Condition '%s' should have been a success" , condition )
}
2020-10-05 01:55:19 +02:00
if ! result . Connected {
t . Error ( "Because the connection has been established, result.Connected should've been true" )
}
2020-04-15 01:20:00 +02:00
if ! result . Success {
t . Error ( "Because all conditions passed, this should have been a success" )
}
}
2020-12-25 06:07:18 +01:00
func TestIntegrationEvaluateHealthWithFailure ( t * testing . T ) {
condition := Condition ( "[STATUS] == 500" )
service := Service {
2021-09-18 18:42:11 +02:00
Name : "website-health" ,
URL : "https://twin.sh/health" ,
2020-12-25 06:07:18 +01:00
Conditions : [ ] * Condition { & condition } ,
}
2021-07-29 03:41:26 +02:00
service . ValidateAndSetDefaults ( )
2020-12-25 06:07:18 +01:00
result := service . EvaluateHealth ( )
if result . ConditionResults [ 0 ] . Success {
t . Errorf ( "Condition '%s' should have been a failure" , condition )
}
if ! result . Connected {
t . Error ( "Because the connection has been established, result.Connected should've been true" )
}
if result . Success {
t . Error ( "Because one of the conditions failed, success should have been false" )
}
}
2020-11-18 00:55:31 +01:00
func TestIntegrationEvaluateHealthForDNS ( t * testing . T ) {
conditionSuccess := Condition ( "[DNS_RCODE] == NOERROR" )
conditionBody := Condition ( "[BODY] == 93.184.216.34" )
service := Service {
2021-03-09 03:30:11 +01:00
Name : "example" ,
2020-11-18 00:55:31 +01:00
URL : "8.8.8.8" ,
DNS : & DNS {
QueryType : "A" ,
QueryName : "example.com." ,
} ,
Conditions : [ ] * Condition { & conditionSuccess , & conditionBody } ,
}
2021-07-29 03:41:26 +02:00
service . ValidateAndSetDefaults ( )
2020-11-18 00:55:31 +01:00
result := service . EvaluateHealth ( )
if ! result . ConditionResults [ 0 ] . Success {
t . Errorf ( "Conditions '%s' and %s should have been a success" , conditionSuccess , conditionBody )
}
if ! result . Connected {
t . Error ( "Because the connection has been established, result.Connected should've been true" )
}
if ! result . Success {
t . Error ( "Because all conditions passed, this should have been a success" )
}
}
2020-12-25 06:07:18 +01:00
func TestIntegrationEvaluateHealthForICMP ( t * testing . T ) {
conditionSuccess := Condition ( "[CONNECTED] == true" )
2020-04-15 01:20:00 +02:00
service := Service {
2021-03-09 03:30:11 +01:00
Name : "icmp-test" ,
2020-12-25 09:05:47 +01:00
URL : "icmp://127.0.0.1" ,
2020-12-25 06:07:18 +01:00
Conditions : [ ] * Condition { & conditionSuccess } ,
2020-04-15 01:20:00 +02:00
}
2021-07-29 03:41:26 +02:00
service . ValidateAndSetDefaults ( )
2020-09-25 01:49:32 +02:00
result := service . EvaluateHealth ( )
2020-12-25 06:07:18 +01:00
if ! result . ConditionResults [ 0 ] . Success {
t . Errorf ( "Conditions '%s' should have been a success" , conditionSuccess )
2020-04-15 01:20:00 +02:00
}
2020-10-05 01:55:19 +02:00
if ! result . Connected {
t . Error ( "Because the connection has been established, result.Connected should've been true" )
}
2020-12-25 06:07:18 +01:00
if ! result . Success {
t . Error ( "Because all conditions passed, this should have been a success" )
2020-04-15 01:20:00 +02:00
}
}
2020-12-29 23:27:58 +01:00
func TestService_getIP ( t * testing . T ) {
conditionSuccess := Condition ( "[CONNECTED] == true" )
service := Service {
2021-03-09 03:30:11 +01:00
Name : "invalid-url-test" ,
2020-12-29 23:27:58 +01:00
URL : "" ,
Conditions : [ ] * Condition { & conditionSuccess } ,
}
result := & Result { }
service . getIP ( result )
if len ( result . Errors ) == 0 {
t . Error ( "service.getIP(result) should've thrown an error because the URL is invalid, thus cannot be parsed" )
}
}
2021-03-09 03:30:11 +01:00
func TestService_NeedsToReadBody ( t * testing . T ) {
statusCondition := Condition ( "[STATUS] == 200" )
bodyCondition := Condition ( "[BODY].status == UP" )
bodyConditionWithLength := Condition ( "len([BODY].tags) > 0" )
if ( & Service { Conditions : [ ] * Condition { & statusCondition } } ) . needsToReadBody ( ) {
t . Error ( "expected false, got true" )
}
if ! ( & Service { Conditions : [ ] * Condition { & bodyCondition } } ) . needsToReadBody ( ) {
t . Error ( "expected true, got false" )
}
if ! ( & Service { Conditions : [ ] * Condition { & bodyConditionWithLength } } ) . needsToReadBody ( ) {
t . Error ( "expected true, got false" )
}
if ! ( & Service { Conditions : [ ] * Condition { & statusCondition , & bodyCondition } } ) . needsToReadBody ( ) {
t . Error ( "expected true, got false" )
}
if ! ( & Service { Conditions : [ ] * Condition { & bodyCondition , & statusCondition } } ) . needsToReadBody ( ) {
t . Error ( "expected true, got false" )
}
if ! ( & Service { Conditions : [ ] * Condition { & bodyConditionWithLength , & statusCondition } } ) . needsToReadBody ( ) {
t . Error ( "expected true, got false" )
}
}