Files
cameradar/loaders_test.go
T
Brendan Le Glaunec 212ac2f0d5 Cameradar v4 (#212)
* Refactor of cameradar library

* Old unit tests updated & improved. New unit tests inc

* Update documentation & issue template

* Update dependencies

* Update TravisCI build script to reflect argument change

* Remove outdated contributing guide

* Update README with more examples and remove part on library

* Add second camera to Travis build script & improve error detection

* Fix typo in travis script & add missing image to readme

* Remember that travis uses bash syntax not fish

* Use relative paths for images in the README
2019-05-26 08:33:08 +02:00

441 lines
9.8 KiB
Go

package cameradar
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"testing"
"github.com/ullaakut/disgo"
"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"},
}
tests := []struct {
description string
input []byte
fileExists bool
expectedCredentials Credentials
expectedErr error
}{
{
description: "Valid baseline",
fileExists: true,
input: credentialsJSONString,
expectedCredentials: validCredentials,
},
{
description: "File does not exist",
fileExists: false,
input: credentialsJSONString,
expectedErr: errors.New("could not read credentials dictionary file at \"/tmp/cameradar_test_load_credentials_1.xml\": open /tmp/cameradar_test_load_credentials_1.xml: no such file or directory"),
},
{
description: "Invalid format",
fileExists: true,
input: []byte("not json"),
expectedErr: errors.New("unable to unmarshal dictionary contents: invalid character 'o' in literal null (expecting 'u')"),
},
{
description: "No streams in dictionary",
fileExists: true,
input: []byte("{\"invalid\":\"json\"}"),
},
}
for i, test := range tests {
t.Run(test.description, func(t *testing.T) {
filePath := "/tmp/cameradar_test_load_credentials_" + fmt.Sprint(i) + ".xml"
// create file.
if test.fileExists {
_, err := os.Create(filePath)
if err != nil {
t.Fatalf("could not create xml file for LoadCredentials: %v. iteration: %d. file path: %s\n", err, i, filePath)
}
err = ioutil.WriteFile(filePath, test.input, 0644)
if err != nil {
t.Fatalf("could not write xml file for LoadCredentials: %v. iteration: %d. file path: %s\n", err, i, filePath)
}
}
scanner := &Scanner{
term: disgo.NewTerminal(disgo.WithDefaultOutput(ioutil.Discard)),
credentialDictionaryPath: filePath,
}
err := scanner.LoadCredentials()
assert.Equal(t, test.expectedErr, err)
assert.Len(t, scanner.credentials.Usernames, len(test.expectedCredentials.Usernames))
for _, expectedUsername := range test.expectedCredentials.Usernames {
assert.Contains(t, scanner.credentials.Usernames, expectedUsername)
}
assert.Len(t, scanner.credentials.Passwords, len(test.expectedCredentials.Passwords))
for _, expectedPassword := range test.expectedCredentials.Passwords {
assert.Contains(t, scanner.credentials.Passwords, expectedPassword)
}
})
}
}
func TestLoadRoutes(t *testing.T) {
routesJSONString := []byte("admin\nroot")
validRoutes := Routes{"admin", "root"}
tests := []struct {
description string
input []byte
fileExists bool
expectedRoutes Routes
expectedErr error
}{
{
description: "Valid baseline",
fileExists: true,
input: routesJSONString,
expectedRoutes: validRoutes,
},
{
description: "File does not exist",
fileExists: false,
input: routesJSONString,
expectedErr: errors.New("unable to open dictionary: open /tmp/cameradar_test_load_routes_1.xml: no such file or directory"),
},
{
description: "No streams in dictionary",
fileExists: true,
input: []byte(""),
},
}
for i, test := range tests {
t.Run(test.description, func(t *testing.T) {
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)
}
}
scanner := &Scanner{
term: disgo.NewTerminal(disgo.WithDefaultOutput(ioutil.Discard)),
routeDictionaryPath: filePath,
}
err := scanner.LoadRoutes()
assert.Equal(t, test.expectedErr, err)
assert.Len(t, scanner.routes, len(test.expectedRoutes))
for _, expectedRoute := range test.expectedRoutes {
assert.Contains(t, scanner.routes, expectedRoute)
}
})
}
}
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",
},
}
tests := []struct {
str string
expectedCredentials 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\"]}",
expectedCredentials: defaultCredentials,
},
{
str: "{}",
expectedCredentials: Credentials{},
},
{
str: "{\"invalid_field\":42}",
expectedCredentials: Credentials{},
},
{
str: "not json",
expectedCredentials: Credentials{},
},
}
for _, test := range tests {
parsedCredentials, _ := ParseCredentialsFromString(test.str)
assert.Equal(t, test.expectedCredentials, parsedCredentials)
}
}
func TestParseRoutesFromString(t *testing.T) {
tests := []struct {
str string
expectedRoutes Routes
}{
{
str: "a\nb\nc",
expectedRoutes: []string{"a", "b", "c"},
},
{
str: "a",
expectedRoutes: []string{"a"},
},
{
str: "",
expectedRoutes: []string{""},
},
}
for _, test := range tests {
assert.Equal(t, test.expectedRoutes, ParseRoutesFromString(test.str))
}
}
func TestLoadTargets(t *testing.T) {
oldFS := fs
mfs := &mockedFS{}
fs = mfs
defer func() {
fs = oldFS
}()
tests := []struct {
description string
targets []string
fileExists bool
openError bool
readError bool
expectedTargets []string
expectedError error
}{
{
description: "not a file",
targets: []string{"0.0.0.0"},
fileExists: false,
expectedTargets: []string{"0.0.0.0"},
expectedError: nil,
},
{
description: "not file targets",
targets: []string{"0.0.0.0", "1.2.3.4/24"},
expectedTargets: []string{"0.0.0.0", "1.2.3.4/24"},
expectedError: nil,
},
{
description: "file contains targets",
targets: []string{"test_does_not_really_exist"},
fileExists: true,
expectedTargets: []string{"0.0.0.0", "localhost", "192.17.0.0/16", "192.168.1.140-255", "192.168.2-3.0-255"},
expectedError: nil,
},
{
description: "open error",
targets: []string{"test_does_not_really_exist"},
fileExists: true,
openError: true,
expectedTargets: []string{"test_does_not_really_exist"},
expectedError: errors.New("unable to open targets file \"test_does_not_really_exist\": file does not exist"),
},
{
description: "read error",
targets: []string{"test_does_not_really_exist"},
fileExists: true,
readError: true,
expectedTargets: []string{"test_does_not_really_exist"},
expectedError: errors.New("unable to read targets file \"test_does_not_really_exist\": file does not exist"),
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
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\nlocalhost\n192.17.0.0/16\n192.168.1.140-255\n192.168.2-3.0-255")
scanner := &Scanner{
term: disgo.NewTerminal(disgo.WithDefaultOutput(ioutil.Discard)),
targets: test.targets,
}
err := scanner.LoadTargets()
assert.Equal(t, test.expectedTargets, scanner.targets)
assert.Equal(t, test.expectedError, err)
})
}
}
// This is completely useless and just lets me
// not look at these two red lines on the coverage
// any longer.
func TestFS(t *testing.T) {
fs := osFS{}
fs.Open("test")
fs.Stat("test")
}