Add more unit tests

This commit is contained in:
Jamie Curnow
2024-11-07 13:00:07 +10:00
parent 208037946f
commit 3774a40498
14 changed files with 810 additions and 24 deletions

View File

@ -9,6 +9,12 @@ import (
"github.com/rotisserie/eris"
)
var (
certificateGetByID = certificate.GetByID
upstreamGetByID = upstream.GetByID
nginxtemplateGetByID = nginxtemplate.GetByID
)
// ValidateHost will check if associated objects exist and other checks
// will return a nil error if things are OK
func ValidateHost(h host.Model) error {
@ -16,14 +22,14 @@ func ValidateHost(h host.Model) error {
// Check certificate exists and is valid
// This will not determine if the certificate is Ready to use,
// as this validation only cares that the row exists.
if _, cErr := certificate.GetByID(h.CertificateID.Uint); cErr != nil {
if _, cErr := certificateGetByID(h.CertificateID.Uint); cErr != nil {
return eris.Wrapf(cErr, "Certificate #%d does not exist", h.CertificateID.Uint)
}
}
if h.UpstreamID.Uint > 0 {
// Check upstream exists
if _, uErr := upstream.GetByID(h.UpstreamID.Uint); uErr != nil {
if _, uErr := upstreamGetByID(h.UpstreamID.Uint); uErr != nil {
return eris.Wrapf(uErr, "Upstream #%d does not exist", h.UpstreamID.Uint)
}
}
@ -37,7 +43,7 @@ func ValidateHost(h host.Model) error {
}
// Check the nginx template exists and has the same type.
nginxTemplate, tErr := nginxtemplate.GetByID(h.NginxTemplateID)
nginxTemplate, tErr := nginxtemplateGetByID(h.NginxTemplateID)
if tErr != nil {
return eris.Wrapf(tErr, "Host Template #%d does not exist", h.NginxTemplateID)
}

View File

@ -0,0 +1,145 @@
package validator
import (
"testing"
"npm/internal/entity/certificate"
"npm/internal/entity/host"
"npm/internal/entity/nginxtemplate"
"npm/internal/entity/upstream"
"npm/internal/types"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
)
// Mocking the dependencies
type MockCertificate struct {
mock.Mock
}
func (m *MockCertificate) GetByID(id uint) (certificate.Model, error) {
args := m.Called(id)
return args.Get(0).(certificate.Model), args.Error(1)
}
type MockUpstream struct {
mock.Mock
}
func (m *MockUpstream) GetByID(id uint) (upstream.Model, error) {
args := m.Called(id)
return args.Get(0).(upstream.Model), args.Error(1)
}
type MockNginxTemplate struct {
mock.Mock
}
func (m *MockNginxTemplate) GetByID(id uint) (nginxtemplate.Model, error) {
args := m.Called(id)
return args.Get(0).(nginxtemplate.Model), args.Error(1)
}
func TestValidateHost(t *testing.T) {
tests := []struct {
name string
host host.Model
wantErr string
}{
{
name: "valid host with certificate and upstream",
host: host.Model{
CertificateID: types.NullableDBUint{Uint: 1},
UpstreamID: types.NullableDBUint{Uint: 1},
NginxTemplateID: 1,
Type: "some-type",
},
wantErr: "",
},
{
name: "certificate does not exist",
host: host.Model{
CertificateID: types.NullableDBUint{Uint: 9},
},
wantErr: "Certificate #9 does not exist: record not found",
},
{
name: "upstream does not exist",
host: host.Model{
UpstreamID: types.NullableDBUint{Uint: 9},
},
wantErr: "Upstream #9 does not exist: record not found",
},
{
name: "proxy host and port set with upstream",
host: host.Model{
UpstreamID: types.NullableDBUint{Uint: 1},
ProxyHost: "proxy",
ProxyPort: 8080,
},
wantErr: "Proxy Host or Port cannot be set when using an Upstream",
},
{
name: "proxy host and port not set without upstream",
host: host.Model{
ProxyHost: "",
ProxyPort: 0,
},
wantErr: "Proxy Host and Port must be specified, unless using an Upstream",
},
{
name: "nginx template does not exist",
host: host.Model{
ProxyHost: "proxy",
ProxyPort: 8080,
NginxTemplateID: 9,
},
wantErr: "Host Template #9 does not exist: record not found",
},
{
name: "nginx template type mismatch",
host: host.Model{
ProxyHost: "proxy",
ProxyPort: 8080,
NginxTemplateID: 8,
Type: "some-type",
},
wantErr: "Host Template #8 is not valid for this host type",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockCert := new(MockCertificate)
mockUpstream := new(MockUpstream)
mockNginxTemplate := new(MockNginxTemplate)
certificateGetByID = mockCert.GetByID
upstreamGetByID = mockUpstream.GetByID
nginxtemplateGetByID = mockNginxTemplate.GetByID
// id 1 is valid
mockCert.On("GetByID", uint(1)).Return(certificate.Model{}, nil)
mockUpstream.On("GetByID", uint(1)).Return(upstream.Model{}, nil)
mockNginxTemplate.On("GetByID", uint(1)).Return(nginxtemplate.Model{Type: "some-type"}, nil)
// id 9 is errors
mockCert.On("GetByID", uint(9)).Return(certificate.Model{}, gorm.ErrRecordNotFound)
mockUpstream.On("GetByID", uint(9)).Return(upstream.Model{}, gorm.ErrRecordNotFound)
mockNginxTemplate.On("GetByID", uint(9)).Return(nginxtemplate.Model{}, gorm.ErrRecordNotFound)
// 8 is special
mockNginxTemplate.On("GetByID", uint(8)).Return(nginxtemplate.Model{Type: "different-type"}, nil)
err := ValidateHost(tt.host)
if tt.wantErr != "" {
require.NotNil(t, err)
require.Equal(t, tt.wantErr, err.Error())
} else {
require.Nil(t, err)
}
})
}
}

View File

@ -1,7 +1,6 @@
package validator
import (
"npm/internal/entity/nginxtemplate"
"npm/internal/entity/upstream"
"github.com/rotisserie/eris"
@ -26,7 +25,7 @@ func ValidateUpstream(u upstream.Model) error {
}
// Check the nginx template exists and has the same type.
nginxTemplate, err := nginxtemplate.GetByID(u.NginxTemplateID)
nginxTemplate, err := nginxtemplateGetByID(u.NginxTemplateID)
if err != nil {
return eris.Errorf("Nginx Template #%d does not exist", u.NginxTemplateID)
}

View File

@ -0,0 +1,93 @@
package validator
import (
"npm/internal/entity/nginxtemplate"
"npm/internal/entity/upstream"
"npm/internal/entity/upstreamserver"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
)
func TestValidateUpstream(t *testing.T) {
tests := []struct {
name string
upstreamModel upstream.Model
expectedError string
}{
{
name: "less than 2 servers",
upstreamModel: upstream.Model{
Servers: []upstreamserver.Model{
{Server: "192.168.1.1"},
},
},
expectedError: "Upstreams require at least 2 servers",
},
{
name: "backup server with IP hash",
upstreamModel: upstream.Model{
Servers: []upstreamserver.Model{
{Server: "192.168.1.1", Backup: true},
{Server: "192.168.1.2"},
},
IPHash: true,
},
expectedError: "Backup servers cannot be used with hash balancing",
},
{
name: "nginx template does not exist",
upstreamModel: upstream.Model{
Servers: []upstreamserver.Model{
{Server: "192.168.1.1"},
{Server: "192.168.1.2"},
},
NginxTemplateID: 999,
},
expectedError: "Nginx Template #999 does not exist",
},
{
name: "nginx template type mismatch",
upstreamModel: upstream.Model{
Servers: []upstreamserver.Model{
{Server: "192.168.1.1"},
{Server: "192.168.1.2"},
},
NginxTemplateID: 2,
},
expectedError: "Host Template #2 is not valid for this upstream",
},
{
name: "valid upstream",
upstreamModel: upstream.Model{
Servers: []upstreamserver.Model{
{Server: "192.168.1.1"},
{Server: "192.168.1.2"},
},
NginxTemplateID: 1,
},
expectedError: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockNginxTemplate := new(MockNginxTemplate)
nginxtemplateGetByID = mockNginxTemplate.GetByID
mockNginxTemplate.On("GetByID", uint(1)).Return(nginxtemplate.Model{Type: "upstream"}, nil)
mockNginxTemplate.On("GetByID", uint(2)).Return(nginxtemplate.Model{Type: "redirect"}, nil)
mockNginxTemplate.On("GetByID", uint(999)).Return(nginxtemplate.Model{}, gorm.ErrRecordNotFound)
err := ValidateUpstream(tt.upstreamModel)
if tt.expectedError != "" {
require.NotNil(t, err)
assert.Equal(t, tt.expectedError, err.Error())
} else {
assert.NoError(t, err)
}
})
}
}