Skip to content

Commit

Permalink
extract context creation for unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
creativeprojects committed Nov 12, 2023
1 parent c7775a4 commit 4e4bebb
Show file tree
Hide file tree
Showing 4 changed files with 276 additions and 53 deletions.
2 changes: 1 addition & 1 deletion codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ coverage:
threshold: "2%"
patch:
default:
target: "80%"
target: "70%"
threshold: "2%"
52 changes: 52 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,58 @@ type Context struct {
lockWait time.Duration // wait up to duration to acquire a lock
}

func CreateContext(flags commandLineFlags, global *config.Global, cfg *config.Config, ownCommands *OwnCommands) (*Context, error) {
// The remaining arguments are going to be sent to the restic command line
command := global.DefaultCommand
resticArguments := flags.resticArgs
if len(resticArguments) > 0 {
command = resticArguments[0]
resticArguments = resticArguments[1:]
}

ctx := &Context{
request: Request{
command: command,
arguments: resticArguments,
profile: flags.name,
group: "",
schedule: "",
},
flags: flags,
global: global,
config: cfg,
binary: "",
command: "",
profile: nil,
schedule: nil,
sigChan: nil,
logTarget: global.Log, // default to global (which can be empty)
}
// own commands can check the context before running
if ownCommands.Exists(command, true) {
err := ownCommands.Pre(ctx)
if err != nil {
return ctx, err
}

Check warning on line 69 in context.go

View check run for this annotation

Codecov / codecov/patch

context.go#L68-L69

Added lines #L68 - L69 were not covered by tests
}
// command line flag supersedes any configuration
if flags.log != "" {
ctx.logTarget = flags.log
}
// same for battery configuration
if flags.ignoreOnBattery > 0 {
ctx.stopOnBattery = flags.ignoreOnBattery
}
// also lock configuration
if flags.noLock {
ctx.noLock = true
}
if flags.lockWait > 0 {
ctx.lockWait = flags.lockWait
}
return ctx, nil
}

// WithConfig sets the configuration and global values. A new copy of the context is returned.
func (c *Context) WithConfig(cfg *config.Config, global *config.Global) *Context {
newContext := c.clone()
Expand Down
219 changes: 219 additions & 0 deletions context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,222 @@ func TestContextWithProfile(t *testing.T) {
assert.Nil(t, ctx.profile)
assert.Nil(t, ctx.schedule)
}

func TestCreateContext(t *testing.T) {
fixtures := []struct {
description string
flags commandLineFlags
global *config.Global
cfg *config.Config
ownCommands *OwnCommands
context *Context
}{
{
description: "empty config with default command only",
flags: commandLineFlags{},
global: &config.Global{
DefaultCommand: "test",
},
cfg: &config.Config{},
ownCommands: &OwnCommands{},
context: &Context{
request: Request{
command: "test",
},
global: &config.Global{
DefaultCommand: "test",
},
config: &config.Config{},
},
},
{
description: "command and arguments",
flags: commandLineFlags{
resticArgs: []string{"arg1", "arg2"},
},
global: &config.Global{
DefaultCommand: "test",
},
cfg: &config.Config{},
ownCommands: &OwnCommands{},
context: &Context{
flags: commandLineFlags{
resticArgs: []string{"arg1", "arg2"},
},
request: Request{
command: "arg1",
arguments: []string{"arg2"},
},
global: &config.Global{
DefaultCommand: "test",
},
config: &config.Config{},
},
},
{
description: "global log target",
flags: commandLineFlags{},
global: &config.Global{Log: "global"},
cfg: &config.Config{},
ownCommands: &OwnCommands{},
context: &Context{
flags: commandLineFlags{},
request: Request{},
global: &config.Global{Log: "global"},
config: &config.Config{},
logTarget: "global",
},
},
{
description: "log target on the command line",
flags: commandLineFlags{log: "cmdline"},
global: &config.Global{Log: "global"},
cfg: &config.Config{},
ownCommands: &OwnCommands{},
context: &Context{
flags: commandLineFlags{log: "cmdline"},
request: Request{},
global: &config.Global{Log: "global"},
config: &config.Config{},
logTarget: "cmdline",
},
},
{
description: "log target from command",
flags: commandLineFlags{},
global: &config.Global{Log: "global", DefaultCommand: "test"},
cfg: &config.Config{},
ownCommands: &OwnCommands{
commands: []ownCommand{
{
name: "test",
needConfiguration: true,
pre: func(ctx *Context) error {
ctx.logTarget = "command"
return nil
},
},
},
},
context: &Context{
flags: commandLineFlags{},
request: Request{command: "test"},
global: &config.Global{Log: "global", DefaultCommand: "test"},
config: &config.Config{},
logTarget: "command",
},
},
{
description: "log target from command line",
flags: commandLineFlags{
log: "cmdline",
resticArgs: []string{"test"},
},
global: &config.Global{},
cfg: &config.Config{},
ownCommands: &OwnCommands{
commands: []ownCommand{
{
name: "test",
needConfiguration: true,
pre: func(ctx *Context) error {
ctx.logTarget = "command"
return nil
},
},
},
},
context: &Context{
flags: commandLineFlags{
log: "cmdline",
resticArgs: []string{"test"},
},
request: Request{
command: "test",
arguments: []string{},
},
global: &config.Global{},
config: &config.Config{},
logTarget: "cmdline",
},
},
{
description: "battery and lock from command",
flags: commandLineFlags{},
global: &config.Global{DefaultCommand: "test"},
cfg: &config.Config{},
ownCommands: &OwnCommands{
commands: []ownCommand{
{
name: "test",
needConfiguration: true,
pre: func(ctx *Context) error {
ctx.stopOnBattery = 10
ctx.lockWait = 20
ctx.noLock = true
return nil
},
},
},
},
context: &Context{
flags: commandLineFlags{},
request: Request{command: "test"},
global: &config.Global{DefaultCommand: "test"},
config: &config.Config{},
stopOnBattery: 10,
lockWait: 20,
noLock: true,
},
},
{
description: "battery and lock from command line",
flags: commandLineFlags{
resticArgs: []string{"test"},
ignoreOnBattery: 80,
lockWait: 30,
noLock: true,
},
global: &config.Global{},
cfg: &config.Config{},
ownCommands: &OwnCommands{
commands: []ownCommand{
{
name: "test",
needConfiguration: true,
pre: func(ctx *Context) error {
ctx.stopOnBattery = 10
ctx.lockWait = 20
return nil
},
},
},
},
context: &Context{
flags: commandLineFlags{
resticArgs: []string{"test"},
ignoreOnBattery: 80,
lockWait: 30,
noLock: true,
},
request: Request{
command: "test",
arguments: []string{},
},
global: &config.Global{},
config: &config.Config{},
stopOnBattery: 80,
lockWait: 30,
noLock: true,
},
},
}

for _, fixture := range fixtures {
t.Run(fixture.description, func(t *testing.T) {
ctx, err := CreateContext(fixture.flags, fixture.global, fixture.cfg, fixture.ownCommands)
assert.NoError(t, err)
assert.Equal(t, fixture.context, ctx)
})
}
}
56 changes: 4 additions & 52 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func main() {
}

// Load the now mandatory configuration and setup logging (before returning an error)
ctx, err := loadContext(flags, false)
ctx, err := loadContext(flags)
closeLogger := setupLogging(ctx)
defer closeLogger()
if err != nil {
Expand Down Expand Up @@ -290,60 +290,12 @@ func loadConfig(flags commandLineFlags, silent bool) (cfg *config.Config, global
}

// loadContext loads the configuration and creates a context.
func loadContext(flags commandLineFlags, silent bool) (*Context, error) {
cfg, global, err := loadConfig(flags, silent)
func loadContext(flags commandLineFlags) (*Context, error) {
cfg, global, err := loadConfig(flags, false)
if err != nil {
return nil, err
}
// The remaining arguments are going to be sent to the restic command line
command := global.DefaultCommand
resticArguments := flags.resticArgs
if len(resticArguments) > 0 {
command = resticArguments[0]
resticArguments = resticArguments[1:]
}

ctx := &Context{
request: Request{
command: command,
arguments: resticArguments,
profile: flags.name,
group: "",
schedule: "",
},
flags: flags,
global: global,
config: cfg,
binary: "",
command: "",
profile: nil,
schedule: nil,
sigChan: nil,
logTarget: global.Log, // default to global (which can be empty)
}
// own commands can check the context before running
if ownCommands.Exists(command, true) {
err = ownCommands.Pre(ctx)
if err != nil {
return ctx, err
}
}
// command line flag supersedes any configuration
if flags.log != "" {
ctx.logTarget = flags.log
}
// same for battery configuration
if flags.ignoreOnBattery > 0 {
ctx.stopOnBattery = flags.ignoreOnBattery
}
// also lock configuration
if flags.noLock {
ctx.noLock = true
}
if flags.lockWait > 0 {
ctx.lockWait = flags.lockWait
}
return ctx, nil
return CreateContext(flags, global, cfg, ownCommands)
}

func setPriority(nice int, class string) error {
Expand Down

0 comments on commit 4e4bebb

Please sign in to comment.