2020-09-26 20:23:43 +02:00
package client
2020-10-05 01:49:02 +02:00
import (
2022-03-10 02:53:51 +01:00
"bytes"
2022-05-17 04:19:42 +02:00
"io"
2022-03-10 02:53:51 +01:00
"net/http"
2020-10-05 01:49:02 +02:00
"testing"
2021-01-13 03:26:28 +01:00
"time"
2022-03-10 02:53:51 +01:00
2022-12-06 07:41:09 +01:00
"github.com/TwiN/gatus/v5/test"
2020-10-05 01:49:02 +02:00
)
2020-09-26 20:23:43 +02:00
2020-12-28 23:19:41 +01:00
func TestGetHTTPClient ( t * testing . T ) {
2021-07-30 00:13:37 +02:00
cfg := & Config {
2021-07-29 03:41:26 +02:00
Insecure : false ,
IgnoreRedirect : false ,
Timeout : 0 ,
2022-06-13 00:45:08 +02:00
DNSResolver : "tcp://1.1.1.1:53" ,
2022-03-10 02:53:51 +01:00
OAuth2Config : & OAuth2Config {
ClientID : "00000000-0000-0000-0000-000000000000" ,
ClientSecret : "secretsauce" ,
TokenURL : "https://token-server.local/token" ,
Scopes : [ ] string { "https://application.local/.default" } ,
} ,
2021-07-30 00:13:37 +02:00
}
2022-06-13 00:45:08 +02:00
err := cfg . ValidateAndSetDefaults ( )
if err != nil {
t . Errorf ( "expected error to be nil, but got: `%s`" , err )
}
2021-07-30 00:13:37 +02:00
if GetHTTPClient ( cfg ) == nil {
t . Error ( "expected client to not be nil" )
}
if GetHTTPClient ( nil ) == nil {
t . Error ( "expected client to not be nil" )
}
2020-09-26 20:23:43 +02:00
}
2020-12-25 06:07:18 +01:00
2022-11-16 03:35:22 +01:00
func TestGetDomainExpiration ( t * testing . T ) {
2023-01-08 23:53:37 +01:00
t . Parallel ( )
2022-11-16 03:35:22 +01:00
if domainExpiration , err := GetDomainExpiration ( "example.com" ) ; err != nil {
t . Fatalf ( "expected error to be nil, but got: `%s`" , err )
} else if domainExpiration <= 0 {
t . Error ( "expected domain expiration to be higher than 0" )
}
if domainExpiration , err := GetDomainExpiration ( "example.com" ) ; err != nil {
t . Errorf ( "expected error to be nil, but got: `%s`" , err )
} else if domainExpiration <= 0 {
t . Error ( "expected domain expiration to be higher than 0" )
}
// Hack to pretend like the domain is expiring in 1 hour, which should trigger a refresh
whoisExpirationDateCache . SetWithTTL ( "example.com" , time . Now ( ) . Add ( time . Hour ) , 25 * time . Hour )
if domainExpiration , err := GetDomainExpiration ( "example.com" ) ; err != nil {
t . Errorf ( "expected error to be nil, but got: `%s`" , err )
} else if domainExpiration <= 0 {
t . Error ( "expected domain expiration to be higher than 0" )
}
// Make sure the refresh works when the ttl is <24 hours
whoisExpirationDateCache . SetWithTTL ( "example.com" , time . Now ( ) . Add ( 35 * time . Hour ) , 23 * time . Hour )
if domainExpiration , err := GetDomainExpiration ( "example.com" ) ; err != nil {
t . Errorf ( "expected error to be nil, but got: `%s`" , err )
} else if domainExpiration <= 0 {
t . Error ( "expected domain expiration to be higher than 0" )
}
}
2020-12-27 23:07:50 +01:00
func TestPing ( t * testing . T ) {
2023-01-08 23:53:37 +01:00
t . Parallel ( )
2021-07-29 03:41:26 +02:00
if success , rtt := Ping ( "127.0.0.1" , & Config { Timeout : 500 * time . Millisecond } ) ; ! success {
2020-12-25 06:07:18 +01:00
t . Error ( "expected true" )
2020-12-27 23:07:50 +01:00
if rtt == 0 {
t . Error ( "Round-trip time returned on success should've higher than 0" )
}
2020-12-25 06:07:18 +01:00
}
2021-07-29 03:41:26 +02:00
if success , rtt := Ping ( "256.256.256.256" , & Config { Timeout : 500 * time . Millisecond } ) ; success {
2021-01-13 03:26:28 +01:00
t . Error ( "expected false, because the IP is invalid" )
if rtt != 0 {
t . Error ( "Round-trip time returned on failure should've been 0" )
}
}
2021-07-29 03:41:26 +02:00
if success , rtt := Ping ( "192.168.152.153" , & Config { Timeout : 500 * time . Millisecond } ) ; success {
2021-01-13 03:26:28 +01:00
t . Error ( "expected false, because the IP is valid but the host should be unreachable" )
2020-12-27 23:07:50 +01:00
if rtt != 0 {
t . Error ( "Round-trip time returned on failure should've been 0" )
}
2020-12-25 06:07:18 +01:00
}
}
2021-06-05 21:47:11 +02:00
2021-06-05 22:35:52 +02:00
func TestCanPerformStartTLS ( t * testing . T ) {
2021-06-05 21:47:11 +02:00
type args struct {
address string
insecure bool
}
tests := [ ] struct {
2021-06-05 22:35:52 +02:00
name string
args args
wantConnected bool
wantErr bool
2021-06-05 21:47:11 +02:00
} {
{
name : "invalid address" ,
args : args {
address : "test" ,
} ,
2021-06-05 22:35:52 +02:00
wantConnected : false ,
wantErr : true ,
2021-06-05 21:47:11 +02:00
} ,
{
name : "error dial" ,
args : args {
address : "test:1234" ,
} ,
2021-06-05 22:35:52 +02:00
wantConnected : false ,
wantErr : true ,
2021-06-05 21:47:11 +02:00
} ,
{
name : "valid starttls" ,
args : args {
address : "smtp.gmail.com:587" ,
} ,
wantConnected : true ,
wantErr : false ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
2023-01-08 23:53:37 +01:00
t . Parallel ( )
2021-07-29 03:41:26 +02:00
connected , _ , err := CanPerformStartTLS ( tt . args . address , & Config { Insecure : tt . args . insecure , Timeout : 5 * time . Second } )
2021-06-05 21:47:11 +02:00
if ( err != nil ) != tt . wantErr {
2021-06-05 22:35:52 +02:00
t . Errorf ( "CanPerformStartTLS() err=%v, wantErr=%v" , err , tt . wantErr )
2021-06-05 21:47:11 +02:00
return
}
2021-06-05 22:35:52 +02:00
if connected != tt . wantConnected {
t . Errorf ( "CanPerformStartTLS() connected=%v, wantConnected=%v" , connected , tt . wantConnected )
2021-06-05 21:47:11 +02:00
}
} )
}
}
2021-07-17 03:12:18 +02:00
2021-09-30 22:15:17 +02:00
func TestCanPerformTLS ( t * testing . T ) {
2021-10-01 02:45:47 +02:00
type args struct {
address string
insecure bool
}
tests := [ ] struct {
name string
args args
wantConnected bool
wantErr bool
} {
{
name : "invalid address" ,
args : args {
address : "test" ,
} ,
wantConnected : false ,
wantErr : true ,
} ,
{
name : "error dial" ,
args : args {
address : "test:1234" ,
} ,
wantConnected : false ,
wantErr : true ,
} ,
{
name : "valid tls" ,
args : args {
address : "smtp.gmail.com:465" ,
} ,
wantConnected : true ,
wantErr : false ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
2023-01-08 23:53:37 +01:00
t . Parallel ( )
2021-10-01 02:45:47 +02:00
connected , _ , err := CanPerformTLS ( tt . args . address , & Config { Insecure : tt . args . insecure , Timeout : 5 * time . Second } )
if ( err != nil ) != tt . wantErr {
t . Errorf ( "CanPerformTLS() err=%v, wantErr=%v" , err , tt . wantErr )
return
}
if connected != tt . wantConnected {
t . Errorf ( "CanPerformTLS() connected=%v, wantConnected=%v" , connected , tt . wantConnected )
}
} )
}
2021-09-30 22:15:17 +02:00
}
2021-07-17 03:12:18 +02:00
func TestCanCreateTCPConnection ( t * testing . T ) {
2021-07-29 03:41:26 +02:00
if CanCreateTCPConnection ( "127.0.0.1" , & Config { Timeout : 5 * time . Second } ) {
2021-07-17 03:12:18 +02:00
t . Error ( "should've failed, because there's no port in the address" )
}
}
2022-03-10 02:53:51 +01:00
// This test checks if a HTTP client configured with `configureOAuth2()` automatically
// performs a Client Credentials OAuth2 flow and adds the obtained token as a `Authorization`
// header to all outgoing HTTP calls.
func TestHttpClientProvidesOAuth2BearerToken ( t * testing . T ) {
defer InjectHTTPClient ( nil )
oAuth2Config := & OAuth2Config {
ClientID : "00000000-0000-0000-0000-000000000000" ,
ClientSecret : "secretsauce" ,
TokenURL : "https://token-server.local/token" ,
Scopes : [ ] string { "https://application.local/.default" } ,
}
mockHttpClient := & http . Client {
Transport : test . MockRoundTripper ( func ( r * http . Request ) * http . Response {
// if the mock HTTP client tries to get a token from the `token-server`
// we provide the expected token response
if r . Host == "token-server.local" {
return & http . Response {
StatusCode : http . StatusOK ,
2022-05-17 04:19:42 +02:00
Body : io . NopCloser ( bytes . NewReader (
2022-03-10 02:53:51 +01:00
[ ] byte (
` { "token_type":"Bearer","expires_in":3599,"ext_expires_in":3599,"access_token":"secret-token"} ` ,
) ,
) ) ,
}
}
// to verify the headers were sent as expected, we echo them back in the
// `X-Org-Authorization` header and check if the token value matches our
// mocked `token-server` response
return & http . Response {
StatusCode : http . StatusOK ,
Header : map [ string ] [ ] string {
"X-Org-Authorization" : { r . Header . Get ( "Authorization" ) } ,
} ,
Body : http . NoBody ,
}
} ) ,
}
mockHttpClientWithOAuth := configureOAuth2 ( mockHttpClient , * oAuth2Config )
InjectHTTPClient ( mockHttpClientWithOAuth )
request , err := http . NewRequest ( http . MethodPost , "http://127.0.0.1:8282" , http . NoBody )
if err != nil {
t . Error ( "expected no error, got" , err . Error ( ) )
}
response , err := mockHttpClientWithOAuth . Do ( request )
if err != nil {
t . Error ( "expected no error, got" , err . Error ( ) )
}
if response . Header == nil {
t . Error ( "expected response headers, but got nil" )
}
// the mock response echos the Authorization header used in the request back
// to us as `X-Org-Authorization` header, we check here if the value matches
// our expected token `secret-token`
if response . Header . Get ( "X-Org-Authorization" ) != "Bearer secret-token" {
t . Error ( "exptected `secret-token` as Bearer token in the mocked response header `X-Org-Authorization`, but got" , response . Header . Get ( "X-Org-Authorization" ) )
}
}