/*
** Copyright (C) 2001-2024 Zabbix SIA
**
** Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
** documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all copies or substantial portions
** of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE.
**/

package metric

import "testing"

var (
	number    = "42"
	notNumber = "foo"
)

func TestNumberValidator_Validate(t *testing.T) {
	type args struct {
		value *string
	}
	tests := []struct {
		name    string
		args    args
		wantErr bool
	}{
		{
			name:    "Must successfully validate a number",
			args:    args{&number},
			wantErr: false,
		},
		{
			name:    "Must successfully validate nil",
			args:    args{nil},
			wantErr: false,
		},
		{
			name:    "Must fail if a given value is not a number",
			args:    args{&notNumber},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			v := NumberValidator{}
			if err := v.Validate(tt.args.value); (err != nil) != tt.wantErr {
				t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

var (
	string1 = "hello123"
	string2 = "hello world"
)

func TestPatternValidator_Validate(t *testing.T) {
	type fields struct {
		Pattern string
	}
	type args struct {
		value *string
	}
	tests := []struct {
		name    string
		fields  fields
		args    args
		wantErr bool
	}{
		{
			name:    "Must successfully validate a string value",
			fields:  fields{"^hello[0-9]+$"},
			args:    args{&string1},
			wantErr: false,
		},
		{
			name:    "Must successfully validate nil",
			args:    args{nil},
			wantErr: false,
		},
		{
			name:    "Must fail if a given value does not match a given pattern",
			fields:  fields{"^hello[0-9]+$"},
			args:    args{&string2},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			v := PatternValidator{
				Pattern: tt.fields.Pattern,
			}
			if err := v.Validate(tt.args.value); (err != nil) != tt.wantErr {
				t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

var (
	valInRange    = "50"
	valNotInRange = "1000"
)

func TestRangeValidator_Validate(t *testing.T) {
	type fields struct {
		Min int
		Max int
	}
	type args struct {
		value *string
	}
	tests := []struct {
		name    string
		fields  fields
		args    args
		wantErr bool
	}{
		{
			name:    "Must successfully validate a value in a range",
			fields:  fields{0, 100},
			args:    args{&valInRange},
			wantErr: false,
		},
		{
			name:    "Must successfully validate nil",
			args:    args{nil},
			wantErr: false,
		},
		{
			name:    "Must fail if a given value is out of a range",
			fields:  fields{0, 100},
			args:    args{&valNotInRange},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			v := RangeValidator{
				Min: tt.fields.Min,
				Max: tt.fields.Max,
			}
			if err := v.Validate(tt.args.value); (err != nil) != tt.wantErr {
				t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestSetValidator_Validate(t *testing.T) {
	type fields struct {
		Set []string
	}
	type args struct {
		value *string
	}
	tests := []struct {
		name    string
		fields  fields
		args    args
		wantErr bool
	}{
		{
			name:    "Must successfully validate a value in a set",
			fields:  fields{[]string{"foo", "42", "100500"}},
			args:    args{&number},
			wantErr: false,
		},
		{
			name:    "Must successfully validate nil",
			args:    args{nil},
			wantErr: false,
		},
		{
			name:    "Must fail if a given value is out of a set",
			fields:  fields{[]string{"foo", "42", "100500"}},
			args:    args{&string1},
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			v := SetValidator{
				Set: tt.fields.Set,
			}
			if err := v.Validate(tt.args.value); (err != nil) != tt.wantErr {
				t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}
