1ff17c429b
* Add file parsing for targets & fix multi targets in docker * Remove deprecated info in README & update examples
409 lines
9.0 KiB
Go
409 lines
9.0 KiB
Go
package cmrdr
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
// Setup Mock
|
|
type mockedFS struct {
|
|
osFS
|
|
|
|
fileExists bool
|
|
openError bool
|
|
|
|
fileMock *fileMock
|
|
|
|
fileSize int64
|
|
}
|
|
|
|
// fileMock mocks a file
|
|
type fileMock struct {
|
|
mock.Mock
|
|
|
|
readError bool
|
|
|
|
bytes.Buffer
|
|
}
|
|
|
|
type mockedFileInfo struct {
|
|
os.FileInfo
|
|
}
|
|
|
|
func (m mockedFileInfo) Size() int64 { return 1 }
|
|
|
|
func (m mockedFS) Stat(name string) (os.FileInfo, error) {
|
|
if !m.fileExists {
|
|
return nil, os.ErrNotExist
|
|
}
|
|
return mockedFileInfo{}, nil
|
|
}
|
|
|
|
func (m mockedFS) Open(name string) (file, error) {
|
|
if m.openError {
|
|
return nil, os.ErrNotExist
|
|
}
|
|
|
|
return m.fileMock, nil
|
|
}
|
|
|
|
func (m *fileMock) Read(p []byte) (n int, err error) {
|
|
if m.readError {
|
|
return 0, os.ErrNotExist
|
|
}
|
|
return m.Buffer.Read(p)
|
|
}
|
|
|
|
func (m *fileMock) ReadAt(p []byte, off int64) (n int, err error) {
|
|
return 1, nil
|
|
}
|
|
|
|
func (m *fileMock) Seek(offset int64, whence int) (int64, error) {
|
|
return offset, nil
|
|
}
|
|
|
|
func (m *fileMock) Stat() (os.FileInfo, error) {
|
|
return mockedFileInfo{}, nil
|
|
}
|
|
|
|
// Close mock
|
|
func (m *fileMock) Close() error {
|
|
args := m.Called()
|
|
return args.Error(0)
|
|
}
|
|
|
|
// Sync mock
|
|
func (m *fileMock) Sync() error {
|
|
args := m.Called()
|
|
return args.Error(0)
|
|
}
|
|
|
|
func TestLoadCredentials(t *testing.T) {
|
|
credentialsJSONString := []byte("{\"usernames\":[\"admin\",\"root\"],\"passwords\":[\"12345\",\"root\"]}")
|
|
validCredentials := Credentials{
|
|
Usernames: []string{"admin", "root"},
|
|
Passwords: []string{"12345", "root"},
|
|
}
|
|
|
|
testCases := []struct {
|
|
input []byte
|
|
fileExists bool
|
|
|
|
expectedOutput Credentials
|
|
expectedErrMsg string
|
|
}{
|
|
// Valid baseline
|
|
{
|
|
fileExists: true,
|
|
input: credentialsJSONString,
|
|
expectedOutput: validCredentials,
|
|
},
|
|
// File does not exist
|
|
{
|
|
fileExists: false,
|
|
input: credentialsJSONString,
|
|
expectedErrMsg: "could not read credentials dictionary file at",
|
|
},
|
|
// Invalid format
|
|
{
|
|
fileExists: true,
|
|
input: []byte("not json"),
|
|
expectedErrMsg: "invalid character",
|
|
},
|
|
// No streams in dictionary
|
|
{
|
|
fileExists: true,
|
|
input: []byte("{\"invalid\":\"json\"}"),
|
|
},
|
|
}
|
|
for i, test := range testCases {
|
|
filePath := "/tmp/cameradar_test_load_credentials_" + fmt.Sprint(i) + ".xml"
|
|
// create file
|
|
if test.fileExists {
|
|
_, err := os.Create(filePath)
|
|
if err != nil {
|
|
fmt.Printf("could not create xml file for LoadCredentials: %v. iteration: %d. file path: %s\n", err, i, filePath)
|
|
os.Exit(1)
|
|
}
|
|
|
|
err = ioutil.WriteFile(filePath, test.input, 0644)
|
|
if err != nil {
|
|
fmt.Printf("could not write xml file for LoadCredentials: %v. iteration: %d. file path: %s\n", err, i, filePath)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
result, err := LoadCredentials(filePath)
|
|
if len(test.expectedErrMsg) > 0 {
|
|
if err == nil {
|
|
fmt.Printf("unexpected success in LoadCredentials test, iteration %d. expected error: %s\n", i, test.expectedErrMsg)
|
|
os.Exit(1)
|
|
}
|
|
assert.Contains(t, err.Error(), test.expectedErrMsg, "wrong error message")
|
|
} else {
|
|
if err != nil {
|
|
fmt.Printf("unexpected error in LoadCredentials test, iteration %d: %v\n", i, err)
|
|
os.Exit(1)
|
|
}
|
|
for _, expectedUsername := range test.expectedOutput.Usernames {
|
|
foundUsername := false
|
|
for _, username := range result.Usernames {
|
|
if username == expectedUsername {
|
|
foundUsername = true
|
|
}
|
|
}
|
|
assert.Equal(t, true, foundUsername, "wrong usernames parsed")
|
|
}
|
|
for _, expectedPassword := range test.expectedOutput.Passwords {
|
|
foundPassword := false
|
|
for _, password := range result.Passwords {
|
|
if password == expectedPassword {
|
|
foundPassword = true
|
|
}
|
|
}
|
|
assert.Equal(t, true, foundPassword, "wrong passwords parsed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadRoutes(t *testing.T) {
|
|
routesJSONString := []byte("admin\nroot")
|
|
validRoutes := Routes{"admin", "root"}
|
|
|
|
testCases := []struct {
|
|
input []byte
|
|
fileExists bool
|
|
|
|
expectedOutput Routes
|
|
expectedErrMsg string
|
|
}{
|
|
// Valid baseline
|
|
{
|
|
fileExists: true,
|
|
input: routesJSONString,
|
|
expectedOutput: validRoutes,
|
|
},
|
|
// File does not exist
|
|
{
|
|
fileExists: false,
|
|
input: routesJSONString,
|
|
expectedErrMsg: "no such file or directory",
|
|
},
|
|
// No streams in dictionary
|
|
{
|
|
fileExists: true,
|
|
input: []byte(""),
|
|
},
|
|
}
|
|
for i, test := range testCases {
|
|
filePath := "/tmp/cameradar_test_load_routes_" + fmt.Sprint(i) + ".xml"
|
|
// create file
|
|
if test.fileExists {
|
|
_, err := os.Create(filePath)
|
|
if err != nil {
|
|
fmt.Printf("could not create xml file for LoadRoutes: %v. iteration: %d. file path: %s\n", err, i, filePath)
|
|
os.Exit(1)
|
|
}
|
|
|
|
err = ioutil.WriteFile(filePath, test.input, 0644)
|
|
if err != nil {
|
|
fmt.Printf("could not write xml file for LoadRoutes: %v. iteration: %d. file path: %s\n", err, i, filePath)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
result, err := LoadRoutes(filePath)
|
|
if len(test.expectedErrMsg) > 0 {
|
|
if err == nil {
|
|
fmt.Printf("unexpected success in LoadRoutes test, iteration %d. expected error: %s\n", i, test.expectedErrMsg)
|
|
os.Exit(1)
|
|
}
|
|
assert.Contains(t, err.Error(), test.expectedErrMsg, "wrong error message")
|
|
} else {
|
|
if err != nil {
|
|
fmt.Printf("unexpected error in LoadRoutes test, iteration %d: %v\n", i, err)
|
|
os.Exit(1)
|
|
}
|
|
for _, expectedRoute := range test.expectedOutput {
|
|
foundRoute := false
|
|
for _, route := range result {
|
|
if route == expectedRoute {
|
|
foundRoute = true
|
|
}
|
|
}
|
|
assert.Equal(t, true, foundRoute, "wrong routes parsed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseCredentialsFromString(t *testing.T) {
|
|
defaultCredentials := Credentials{
|
|
Usernames: []string{
|
|
"",
|
|
"admin",
|
|
"Admin",
|
|
"Administrator",
|
|
"root",
|
|
"supervisor",
|
|
"ubnt",
|
|
"service",
|
|
"Dinion",
|
|
"administrator",
|
|
"admin1",
|
|
},
|
|
Passwords: []string{
|
|
"",
|
|
"admin",
|
|
"9999",
|
|
"123456",
|
|
"pass",
|
|
"camera",
|
|
"1234",
|
|
"12345",
|
|
"fliradmin",
|
|
"system",
|
|
"jvc",
|
|
"meinsm",
|
|
"root",
|
|
"4321",
|
|
"111111",
|
|
"1111111",
|
|
"password",
|
|
"ikwd",
|
|
"supervisor",
|
|
"ubnt",
|
|
"wbox123",
|
|
"service",
|
|
},
|
|
}
|
|
|
|
testCases := []struct {
|
|
str string
|
|
expectedResult Credentials
|
|
}{
|
|
{
|
|
str: "{\"usernames\":[\"\",\"admin\",\"Admin\",\"Administrator\",\"root\",\"supervisor\",\"ubnt\",\"service\",\"Dinion\",\"administrator\",\"admin1\"],\"passwords\":[\"\",\"admin\",\"9999\",\"123456\",\"pass\",\"camera\",\"1234\",\"12345\",\"fliradmin\",\"system\",\"jvc\",\"meinsm\",\"root\",\"4321\",\"111111\",\"1111111\",\"password\",\"ikwd\",\"supervisor\",\"ubnt\",\"wbox123\",\"service\"]}",
|
|
expectedResult: defaultCredentials,
|
|
},
|
|
{
|
|
str: "{}",
|
|
expectedResult: Credentials{},
|
|
},
|
|
{
|
|
str: "{\"invalid_field\":42}",
|
|
expectedResult: Credentials{},
|
|
},
|
|
{
|
|
str: "not json",
|
|
expectedResult: Credentials{},
|
|
},
|
|
}
|
|
for _, test := range testCases {
|
|
parsedCredentials, _ := ParseCredentialsFromString(test.str)
|
|
assert.Equal(t, test.expectedResult, parsedCredentials, "unexpected result, parse error")
|
|
}
|
|
}
|
|
|
|
func TestParseRoutesFromString(t *testing.T) {
|
|
testCases := []struct {
|
|
str string
|
|
expectedResult Routes
|
|
}{
|
|
{
|
|
str: "a\nb\nc",
|
|
expectedResult: []string{"a", "b", "c"},
|
|
},
|
|
{
|
|
str: "a",
|
|
expectedResult: []string{"a"},
|
|
},
|
|
{
|
|
str: "",
|
|
expectedResult: []string{""},
|
|
},
|
|
}
|
|
for _, test := range testCases {
|
|
parsedRoutes := ParseRoutesFromString(test.str)
|
|
assert.Equal(t, test.expectedResult, parsedRoutes, "unexpected result, parse error")
|
|
}
|
|
}
|
|
|
|
func TestParseTargetsFile(t *testing.T) {
|
|
|
|
oldFS := fs
|
|
mfs := &mockedFS{}
|
|
fs = mfs
|
|
defer func() {
|
|
fs = oldFS
|
|
}()
|
|
|
|
testCases := []struct {
|
|
input string
|
|
|
|
fileExists bool
|
|
openError bool
|
|
readError bool
|
|
|
|
expectedResult string
|
|
expectedError error
|
|
}{
|
|
{
|
|
input: "0.0.0.0",
|
|
|
|
fileExists: false,
|
|
|
|
expectedResult: "0.0.0.0",
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
input: "test_does_not_really_exist",
|
|
|
|
fileExists: true,
|
|
|
|
expectedResult: "0.0.0.0 localhost 192.17.0.0/16 192.168.1.140-255 192.168.2-3.0-255",
|
|
expectedError: nil,
|
|
},
|
|
{
|
|
input: "test_does_not_really_exist",
|
|
|
|
fileExists: true,
|
|
openError: true,
|
|
|
|
expectedResult: "test_does_not_really_exist",
|
|
expectedError: os.ErrNotExist,
|
|
},
|
|
{
|
|
input: "test_does_not_really_exist",
|
|
|
|
fileExists: true,
|
|
readError: true,
|
|
|
|
expectedResult: "test_does_not_really_exist",
|
|
expectedError: os.ErrNotExist,
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
mfs.fileExists = test.fileExists
|
|
mfs.openError = test.openError
|
|
|
|
mfs.fileMock = &fileMock{
|
|
readError: test.readError,
|
|
}
|
|
mfs.fileMock.On("Close").Return(nil)
|
|
mfs.fileMock.WriteString("0.0.0.0 localhost 192.17.0.0/16 192.168.1.140-255 192.168.2-3.0-255")
|
|
|
|
result, err := ParseTargetsFile(test.input)
|
|
assert.Equal(t, test.expectedResult, result, "unexpected result, parse error")
|
|
assert.Equal(t, test.expectedError, err, "unexpected error")
|
|
}
|
|
}
|