Add a lot more testing

This commit is contained in:
IamTheFij 2022-02-23 21:53:48 -08:00
parent 512d924f0c
commit 57afeab4ca
3 changed files with 155 additions and 53 deletions

76
job.go
View File

@ -14,10 +14,11 @@ import (
const WorkDirPerms = 0o666
var (
ErrNoJobsFound = errors.New("no jobs found and at least one job is required")
ErrMissingField = errors.New("missing config field")
ErrMissingBlock = errors.New("missing config block")
ErrMutuallyExclusive = errors.New("mutually exclusive values not valid")
ErrNoJobsFound = errors.New("no jobs found and at least one job is required")
ErrMissingField = errors.New("missing config field")
ErrMissingBlock = errors.New("missing config block")
ErrMutuallyExclusive = errors.New("mutually exclusive values not valid")
ErrInvalidConfigValue = errors.New("invalid config value")
)
type TaskConfig struct {
@ -128,11 +129,20 @@ func (t JobTaskMySQL) Filename() string {
func (t JobTaskMySQL) Validate() error {
if invalidChars := "'\";"; strings.ContainsAny(t.Name, invalidChars) {
return fmt.Errorf("mysql task %s has an invalid name. The name may not contain %s", t.Name, invalidChars)
return fmt.Errorf(
"mysql task %s has an invalid name. The name may not contain %s: %w",
t.Name,
invalidChars,
ErrInvalidConfigValue,
)
}
if len(t.Tables) > 0 && t.Database == "" {
return fmt.Errorf("mysql task %s is invalid. Must specify a database to use tables: %w", t.Name, ErrMissingField)
return fmt.Errorf(
"mysql task %s is invalid. Must specify a database to use tables: %w",
t.Name,
ErrMissingField,
)
}
return nil
@ -206,7 +216,12 @@ func (t JobTaskSqlite) Filename() string {
func (t JobTaskSqlite) Validate() error {
if invalidChars := "'\";"; strings.ContainsAny(t.Name, invalidChars) {
return fmt.Errorf("sqlite task %s has an invalid name. The name may not contain %s", t.Name, invalidChars)
return fmt.Errorf(
"sqlite task %s has an invalid name. The name may not contain %s: %w",
t.Name,
invalidChars,
ErrInvalidConfigValue,
)
}
return nil
@ -217,7 +232,7 @@ func (t JobTaskSqlite) GetPreTask() ExecutableTask {
name: t.Name,
env: nil,
OnBackup: fmt.Sprintf(
"sqlite3 %s '.backup $RESTIC_JOB_DIR/%s'",
"sqlite3 '%s' '.backup $RESTIC_JOB_DIR/%s'",
t.Path, t.Filename(),
),
OnRestore: "",
@ -429,17 +444,6 @@ func (j Job) JobDir() string {
return cwd
}
/*
* func NewTaskConfig(jobDir string, jobLogger *log.Logger, restic *ResticCmd, taskName string) TaskConfig {
* return TaskConfig{
* JobDir: jobDir,
* Logger: GetChildLogger(jobLogger, taskName),
* Restic: restic,
* Env: nil,
* }
* }
*/
func (j Job) RunBackup() error {
logger := GetLogger(j.Name)
restic := j.NewRestic()
@ -524,37 +528,3 @@ func (c Config) Validate() error {
return nil
}
/***
job "My App" {
schedule = "* * * * *"
config {
repo = "s3://..."
passphrase = "foo"
}
task "Dump mysql" {
mysql {
hostname = "foo"
username = "bar"
}
}
task "Create biz file" {
on_backup {
body = <<EOF
echo foo > /biz.txt
EOF
}
}
task "Backup data files" {
files = [
"/foo/bar",
"/biz.txt",
]
}
}
***/

View File

@ -173,3 +173,125 @@ func TestJobTaskScript(t *testing.T) {
})
}
}
func TestJobTaskMySQL(t *testing.T) {
t.Parallel()
type TaskGenerator interface {
Validate() error
GetPreTask() main.ExecutableTask
GetPostTask() main.ExecutableTask
}
cases := []struct {
name string
task TaskGenerator
validationErr error
preBackup string
postBackup string
preRestore string
postRestore string
}{
{
name: "mysql simple",
// nolint:exhaustivestruct
task: main.JobTaskMySQL{Name: "simple"},
validationErr: nil,
preBackup: "mysqldump --result-file './simple.sql'",
postBackup: "",
preRestore: "",
postRestore: "mysql < './simple.sql'",
},
{
name: "mysql invalid name",
// nolint:exhaustivestruct
task: main.JobTaskMySQL{Name: "it's invalid;"},
validationErr: main.ErrInvalidConfigValue,
preBackup: "",
postBackup: "",
preRestore: "",
postRestore: "",
},
{
name: "mysql tables no database",
// nolint:exhaustivestruct
task: main.JobTaskMySQL{
Name: "name",
Tables: []string{"table1", "table2"},
},
validationErr: main.ErrMissingField,
preBackup: "",
postBackup: "",
preRestore: "",
postRestore: "",
},
{
name: "mysql all options",
task: main.JobTaskMySQL{
Name: "simple",
Hostname: "host",
Username: "user",
Password: "pass",
Database: "db",
Tables: []string{"table1", "table2"},
},
validationErr: nil,
preBackup: "mysqldump --result-file './simple.sql' --host host --user user --password pass db table1 table2",
postBackup: "",
preRestore: "",
postRestore: "mysql --host host --user user --password pass < './simple.sql'",
},
// Sqlite
{
name: "sqlite simple",
task: main.JobTaskSqlite{Name: "simple", Path: "database.db"},
validationErr: nil,
preBackup: "sqlite3 'database.db' '.backup $RESTIC_JOB_DIR/simple.db.bak'",
postBackup: "",
preRestore: "",
postRestore: "cp '$RESTIC_JOB_DIR/simple.db.bak' 'database.db'",
},
{
name: "sqlite invalid name",
task: main.JobTaskSqlite{Name: "it's invalid;", Path: "database.db"},
validationErr: main.ErrInvalidConfigValue,
preBackup: "",
postBackup: "",
preRestore: "",
postRestore: "",
},
}
for _, c := range cases {
testCase := c
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()
validateErr := testCase.task.Validate()
if !errors.Is(validateErr, testCase.validationErr) {
t.Errorf("unexpected validation result. expected: %v, actual: %v", testCase.validationErr, validateErr)
}
if validateErr != nil {
return
}
if preTask, ok := testCase.task.GetPreTask().(main.JobTaskScript); ok {
AssertEqual(t, "incorrect pre-backup", testCase.preBackup, preTask.OnBackup)
AssertEqual(t, "incorrect pre-restore", testCase.preRestore, preTask.OnRestore)
} else {
t.Error("pre task was not a JobTaskScript")
}
if postTask, ok := testCase.task.GetPostTask().(main.JobTaskScript); ok {
AssertEqual(t, "incorrect post-backup", testCase.postBackup, postTask.OnBackup)
AssertEqual(t, "incorrect post-restore", testCase.postRestore, postTask.OnRestore)
} else {
t.Error("post task was not a JobTaskScript")
}
})
}
}

View File

@ -7,6 +7,16 @@ import (
"github.com/go-test/deep"
)
func AssertEqual(t *testing.T, message string, expected, actual interface{}) bool {
t.Helper()
if expected != actual {
t.Errorf("%s. expected: %v, actual: %v", message, expected, actual)
}
return true
}
func TestMergeEnvMap(t *testing.T) {
t.Parallel()