diff --git a/pkg/gotenberg/cmd.go b/pkg/gotenberg/cmd.go index 54799f47..d6be6e7f 100644 --- a/pkg/gotenberg/cmd.go +++ b/pkg/gotenberg/cmd.go @@ -25,11 +25,11 @@ type Cmd struct { // children without creating orphans. // // See https://medium.com/@felixge/killing-a-child-process-and-all-of-its-children-in-go-54079af94773. -func Command(logger *zap.Logger, binPath string, args ...string) Cmd { +func Command(logger *zap.Logger, binPath string, args ...string) *Cmd { cmd := exec.Command(binPath, args...) cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - return Cmd{ + return &Cmd{ ctx: nil, logger: logger.Named(strings.ReplaceAll(binPath, "/", "")), process: cmd, @@ -41,15 +41,15 @@ func Command(logger *zap.Logger, binPath string, args ...string) Cmd { // children without creating orphans. // // See https://medium.com/@felixge/killing-a-child-process-and-all-of-its-children-in-go-54079af94773. -func CommandContext(ctx context.Context, logger *zap.Logger, binPath string, args ...string) (Cmd, error) { +func CommandContext(ctx context.Context, logger *zap.Logger, binPath string, args ...string) (*Cmd, error) { if ctx == nil { - return Cmd{}, errors.New("nil context") + return nil, errors.New("nil context") } cmd := exec.CommandContext(ctx, binPath, args...) cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - return Cmd{ + return &Cmd{ ctx: ctx, logger: logger.Named(strings.ReplaceAll(binPath, "/", "")), process: cmd, @@ -57,7 +57,7 @@ func CommandContext(ctx context.Context, logger *zap.Logger, binPath string, arg } // Start starts the command but does not wait for its completion. -func (cmd Cmd) Start() error { +func (cmd *Cmd) Start() error { err := cmd.pipeOutput() if err != nil { return fmt.Errorf("pipe unix process output: %w", err) @@ -75,7 +75,7 @@ func (cmd Cmd) Start() error { // Wait waits for the command to complete. It should be called when using the // Start method, so that the command does not leak zombies. -func (cmd Cmd) Wait() error { +func (cmd *Cmd) Wait() error { err := cmd.process.Wait() if err != nil { return fmt.Errorf("wait for unix process: %w", err) @@ -86,7 +86,7 @@ func (cmd Cmd) Wait() error { // Exec executes the command and wait for its completion or until the context // is done. In any case, it kills the unix process and all its children. -func (cmd Cmd) Exec() (int, error) { +func (cmd *Cmd) Exec() (int, error) { if cmd.ctx == nil { return 10, errors.New("nil context") } @@ -134,7 +134,7 @@ func (cmd Cmd) Exec() (int, error) { // pipeOutput creates logs entries according to the process stdout and stderr. // It does nothing if the logging level is not debug. -func (cmd Cmd) pipeOutput() error { +func (cmd *Cmd) pipeOutput() error { checkedEntry := cmd.logger.Check(zap.DebugLevel, "check for debug level before piping unix process output") if checkedEntry == nil { return nil @@ -154,7 +154,12 @@ func (cmd Cmd) pipeOutput() error { // (either stdout or stderr). logCommandOutput := func(logger *zap.Logger, reader io.ReadCloser) { r := bufio.NewReader(reader) - defer reader.Close() + defer func(reader io.ReadCloser) { + err := reader.Close() + if err != nil { + logger.Error(fmt.Sprintf("close reader: %s", err)) + } + }(reader) for { line, _, err := r.ReadLine() @@ -181,7 +186,7 @@ func (cmd Cmd) pipeOutput() error { // Kill kills the unix process and all its children without creating orphans. // // See https://medium.com/@felixge/killing-a-child-process-and-all-of-its-children-in-go-54079af94773. -func (cmd Cmd) Kill() error { +func (cmd *Cmd) Kill() error { if cmd.process == nil { // We cannot use the logger here, because for whatever reason using it // result to a panic. diff --git a/pkg/gotenberg/cmd_test.go b/pkg/gotenberg/cmd_test.go index 69b54d93..7ccbe703 100644 --- a/pkg/gotenberg/cmd_test.go +++ b/pkg/gotenberg/cmd_test.go @@ -10,7 +10,6 @@ import ( func TestCommand(t *testing.T) { cmd := Command(zap.NewNop(), "foo") - if !cmd.process.SysProcAttr.Setpgid { t.Error("expected cmd.process.SysProcAttr.Setpgid to be true") } @@ -18,34 +17,36 @@ func TestCommand(t *testing.T) { func TestCommandContext(t *testing.T) { tests := []struct { - name string - ctx context.Context - expectCommandContextErr bool + scenario string + ctx context.Context + expectCommandContextError bool }{ { - name: "nominal behavior", - ctx: context.Background(), + scenario: "nominal behavior", + ctx: context.Background(), + expectCommandContextError: false, }, { - name: "nil context", - expectCommandContextErr: true, + scenario: "nil context", + ctx: nil, + expectCommandContextError: true, }, } for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { + t.Run(tc.scenario, func(t *testing.T) { cmd, err := CommandContext(tc.ctx, zap.NewNop(), "foo") if err == nil && !cmd.process.SysProcAttr.Setpgid { t.Fatal("expected cmd.process.SysProcAttr.Setpgid to be true") } - if tc.expectCommandContextErr && err == nil { - t.Error("expected error from CommandContext(), but got none") + if !tc.expectCommandContextError && err != nil { + t.Fatalf("expected no error but got: %v", err) } - if !tc.expectCommandContextErr && err != nil { - t.Errorf("expected no error from CommandContext(), but got: %v", err) + if tc.expectCommandContextError && err == nil { + t.Fatal("expected error but got none") } }) } @@ -53,31 +54,32 @@ func TestCommandContext(t *testing.T) { func TestCmd_Start(t *testing.T) { tests := []struct { - name string - cmd Cmd - expectStartErr bool + scenario string + cmd *Cmd + expectStartError bool }{ { - name: "nominal behavior", - cmd: Command(zap.NewNop(), "echo", "Hello", "World"), + scenario: "nominal behavior", + cmd: Command(zap.NewNop(), "echo", "Hello", "World"), + expectStartError: false, }, { - name: "start error", - cmd: Command(zap.NewNop(), "foo"), - expectStartErr: true, + scenario: "start error", + cmd: Command(zap.NewNop(), "foo"), + expectStartError: true, }, } for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { + t.Run(tc.scenario, func(t *testing.T) { err := tc.cmd.Start() - if tc.expectStartErr && err == nil { - t.Error("expected error from cmd.Start(), but got none") + if !tc.expectStartError && err != nil { + t.Fatalf("expected no error but got: %v", err) } - if !tc.expectStartErr && err != nil { - t.Errorf("expected no error from cmd.Start(), but got: %v", err) + if tc.expectStartError && err == nil { + t.Fatal("expected error but got none") } }) } @@ -85,54 +87,50 @@ func TestCmd_Start(t *testing.T) { func TestCmd_Wait(t *testing.T) { tests := []struct { - name string - cmd Cmd - expectWaitErr bool + scenario string + cmd *Cmd + expectWaitError bool }{ { - name: "nominal behavior", - cmd: func() Cmd { + scenario: "nominal behavior", + cmd: func() *Cmd { cmd := Command(zap.NewNop(), "echo", "Hello", "World") - err := cmd.Start() if err != nil { - t.Fatalf("expected no error from cmd.Start(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - return cmd }(), + expectWaitError: false, }, { - name: "wait error", - cmd: func() Cmd { + scenario: "wait error", + cmd: func() *Cmd { cmd := Command(zap.NewNop(), "echo", "Hello", "World") - err := cmd.Start() if err != nil { - t.Fatalf("expected no error from cmd.Start(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - err = cmd.Kill() if err != nil { - t.Fatalf("expected no error from cmd.Kill(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - return cmd }(), - expectWaitErr: true, + expectWaitError: true, }, } for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { + t.Run(tc.scenario, func(t *testing.T) { err := tc.cmd.Wait() - if tc.expectWaitErr && err == nil { - t.Error("expected error from cmd.Wait(), but got none") + if !tc.expectWaitError && err != nil { + t.Fatalf("expected no error but got: %v", err) } - if !tc.expectWaitErr && err != nil { - t.Errorf("expected no error from cmd.Wait(), but got: %v", err) + if tc.expectWaitError && err == nil { + t.Fatal("expected error but got none") } }) } @@ -140,49 +138,48 @@ func TestCmd_Wait(t *testing.T) { func TestCmd_Exec(t *testing.T) { tests := []struct { - name string - cmd Cmd - timeout time.Duration - expectExecErr bool + scenario string + cmd *Cmd + timeout time.Duration + expectExecError bool }{ { - name: "nominal behavior", - cmd: func() Cmd { + scenario: "nominal behavior", + cmd: func() *Cmd { cmd, err := CommandContext(context.Background(), zap.NewNop(), "echo", "Hello", "World") if err != nil { t.Fatalf("expected no error from CommandContext(), but got: %v", err) } - return cmd }(), + expectExecError: false, }, { - name: "nil context", - cmd: Command(zap.NewNop(), "echo", "Hello", "World"), - expectExecErr: true, + scenario: "nil context", + cmd: Command(zap.NewNop(), "echo", "Hello", "World"), + expectExecError: true, }, { - name: "start error", - cmd: func() Cmd { + scenario: "start error", + cmd: func() *Cmd { cmd, err := CommandContext(context.Background(), zap.NewNop(), "foo") if err != nil { - t.Fatalf("expected no error from CommandContext(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - return cmd }(), - expectExecErr: true, + expectExecError: true, }, { - name: "context done", - cmd: Command(zap.NewNop(), "sleep", "2"), - timeout: time.Duration(1) * time.Second, - expectExecErr: true, + scenario: "context done", + cmd: Command(zap.NewNop(), "sleep", "2"), + timeout: time.Duration(1) * time.Second, + expectExecError: true, }, } for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { + t.Run(tc.scenario, func(t *testing.T) { if tc.timeout > 0 { ctx, cancel := context.WithTimeout(context.TODO(), tc.timeout) defer cancel() @@ -192,12 +189,12 @@ func TestCmd_Exec(t *testing.T) { _, err := tc.cmd.Exec() - if tc.expectExecErr && err == nil { - t.Error("expected error from cmd.Exec(), but got none") + if !tc.expectExecError && err != nil { + t.Fatalf("expected no error but got: %v", err) } - if !tc.expectExecErr && err != nil { - t.Errorf("expected no error from cmd.Exec(), but got: %v", err) + if tc.expectExecError && err == nil { + t.Fatal("expected error but got none") } }) } @@ -205,67 +202,68 @@ func TestCmd_Exec(t *testing.T) { func TestCmd_pipeOutput(t *testing.T) { tests := []struct { - name string - cmd Cmd - run bool - expectPipeOutputErr bool + scenario string + cmd *Cmd + run bool + expectPipeOutputError bool }{ { - name: "nominal behavior", - cmd: Command(zap.NewExample(), "echo", "Hello", "World"), - run: true, + scenario: "nominal behavior", + cmd: Command(zap.NewExample(), "echo", "Hello", "World"), + run: true, + expectPipeOutputError: false, }, { - name: "no debug, no pipe", - cmd: Command(zap.NewNop(), "echo", "Hello", "World"), + scenario: "no debug, no pipe", + cmd: Command(zap.NewNop(), "echo", "Hello", "World"), + run: false, + expectPipeOutputError: false, }, { - name: "stdout already piped", - cmd: func() Cmd { + scenario: "stdout already piped", + cmd: func() *Cmd { cmd := Command(zap.NewExample(), "echo", "Hello", "World") - _, err := cmd.process.StdoutPipe() if err != nil { - t.Fatalf("expected no error from cmd.process.StdoutPipe(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - return cmd }(), - expectPipeOutputErr: true, + run: false, + expectPipeOutputError: true, }, { - name: "stderr already piped", - cmd: func() Cmd { + scenario: "stderr already piped", + cmd: func() *Cmd { cmd := Command(zap.NewExample(), "echo", "Hello", "World") - _, err := cmd.process.StderrPipe() if err != nil { - t.Fatalf("expected no error from cmd.process.StderrPipe(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - return cmd }(), - expectPipeOutputErr: true, + run: false, + expectPipeOutputError: true, }, } for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { + t.Run(tc.scenario, func(t *testing.T) { err := tc.cmd.pipeOutput() if tc.run { errStart := tc.cmd.process.Start() if errStart != nil { - t.Fatalf("expected no error from tc.cmd.process.Start(), but got: %v", errStart) + t.Fatalf("expected no error but got: %v", err) } } - if tc.expectPipeOutputErr && err == nil { - t.Error("expected error from cmd.pipeOutput(), but got none") + if !tc.expectPipeOutputError && err != nil { + t.Fatalf("expected no error but got: %v", err) } - if !tc.expectPipeOutputErr && err != nil { - t.Errorf("expected no error from cmd.pipeOutput(), but got: %v", err) + if tc.expectPipeOutputError && err == nil { + t.Fatal("expected error but got none") } }) } @@ -273,51 +271,46 @@ func TestCmd_pipeOutput(t *testing.T) { func TestCmd_Kill(t *testing.T) { tests := []struct { - name string - cmd Cmd + scenario string + cmd *Cmd }{ { - name: "nominal behavior", - cmd: func() Cmd { + scenario: "nominal behavior", + cmd: func() *Cmd { cmd := Command(zap.NewNop(), "sleep", "60") - err := cmd.process.Start() if err != nil { - t.Fatalf("expected no error from cmd.process.Start(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - return cmd }(), }, { - name: "no process", - cmd: Cmd{logger: zap.NewNop()}, + scenario: "no process", + cmd: &Cmd{logger: zap.NewNop()}, }, { - name: "process already killed", - cmd: func() Cmd { + scenario: "process already killed", + cmd: func() *Cmd { cmd := Command(zap.NewNop(), "sleep", "60") - err := cmd.process.Start() if err != nil { - t.Fatalf("expected no error from cmd.process.Start(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - err = cmd.Kill() if err != nil { - t.Fatalf("expected no error from cmd.Kill(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } - return cmd }(), }, } for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { + t.Run(tc.scenario, func(t *testing.T) { err := tc.cmd.Kill() if err != nil { - t.Errorf("expected no error from cmd.Kill(), but got: %v", err) + t.Fatalf("expected no error but got: %v", err) } }) } diff --git a/pkg/gotenberg/context_test.go b/pkg/gotenberg/context_test.go index 9c53c20b..9b48cfd2 100644 --- a/pkg/gotenberg/context_test.go +++ b/pkg/gotenberg/context_test.go @@ -23,173 +23,212 @@ func TestContext_ParsedFlags(t *testing.T) { } func TestContext_Module(t *testing.T) { - for i, tc := range []struct { - mods []ModuleDescriptor - kind interface{} - expectErr bool + for _, tc := range []struct { + scenario string + mods []ModuleDescriptor + kind interface{} + expectError bool }{ { + scenario: "module with error on provision", mods: func() []ModuleDescriptor { - mod := struct{ ProtoProvisioner }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ProvisionerMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.provision = func(ctx *Context) error { return errors.New("foo") } - + mod.ProvisionMock = func(ctx *Context) error { return errors.New("foo") } return []ModuleDescriptor{mod.Descriptor()} }(), - kind: new(Provisioner), - expectErr: true, + kind: new(Provisioner), + expectError: true, }, { + scenario: "two modules instead of one", mods: func() []ModuleDescriptor { - mod := struct{ ProtoProvisioner }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ProvisionerMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.provision = func(ctx *Context) error { return nil } - + mod.ProvisionMock = func(ctx *Context) error { return nil } return []ModuleDescriptor{mod.Descriptor(), mod.Descriptor()} }(), - kind: new(Provisioner), - expectErr: true, + kind: new(Provisioner), + expectError: true, }, { + scenario: "success", mods: func() []ModuleDescriptor { - mod := struct{ ProtoProvisioner }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ProvisionerMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.provision = func(ctx *Context) error { return nil } - + mod.ProvisionMock = func(ctx *Context) error { return nil } return []ModuleDescriptor{mod.Descriptor()} }(), - kind: new(Provisioner), + kind: new(Provisioner), + expectError: false, }, } { + t.Run(tc.scenario, func(t *testing.T) { + ctx := NewContext(ParsedFlags{}, tc.mods) + _, err := ctx.Module(tc.kind) - ctx := NewContext(ParsedFlags{}, tc.mods) - _, err := ctx.Module(tc.kind) + if !tc.expectError && err != nil { + t.Fatalf("expected no error but got: %v", err) + } - if tc.expectErr && err == nil { - t.Errorf("test %d: expected error but got: %v", i, err) - } - - if !tc.expectErr && err != nil { - t.Errorf("test %d: expected no error but got: %v", i, err) - } + if tc.expectError && err == nil { + t.Fatal("expected error but got none") + } + }) } } func TestContext_Modules(t *testing.T) { - for i, tc := range []struct { - mods []ModuleDescriptor - kind interface{} - expectErr bool + for _, tc := range []struct { + scenario string + mods []ModuleDescriptor + kind interface{} + expectError bool }{ { + scenario: "module with error on provision", mods: func() []ModuleDescriptor { - mod := struct{ ProtoProvisioner }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ProvisionerMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.provision = func(ctx *Context) error { return errors.New("foo") } - + mod.ProvisionMock = func(ctx *Context) error { return errors.New("foo") } return []ModuleDescriptor{mod.Descriptor()} }(), - kind: new(Provisioner), - expectErr: true, + kind: new(Provisioner), + expectError: true, }, { + scenario: "success (module)", mods: func() []ModuleDescriptor { - mod := struct{ ProtoProvisioner }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ProvisionerMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.provision = func(ctx *Context) error { return nil } - + mod.ProvisionMock = func(ctx *Context) error { return nil } return []ModuleDescriptor{mod.Descriptor(), mod.Descriptor()} }(), - kind: new(Provisioner), + kind: new(Provisioner), + expectError: false, }, { + scenario: "success (one module)", mods: func() []ModuleDescriptor { - mod := struct{ ProtoProvisioner }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ProvisionerMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.provision = func(ctx *Context) error { return nil } + mod.ProvisionMock = func(ctx *Context) error { return nil } return []ModuleDescriptor{mod.Descriptor()} }(), - kind: new(Provisioner), + kind: new(Provisioner), + expectError: false, }, } { + t.Run(tc.scenario, func(t *testing.T) { + ctx := NewContext(ParsedFlags{}, tc.mods) + _, err := ctx.Modules(tc.kind) - ctx := NewContext(ParsedFlags{}, tc.mods) - _, err := ctx.Modules(tc.kind) + if !tc.expectError && err != nil { + t.Fatalf("expected no error but got: %v", err) + } - if tc.expectErr && err == nil { - t.Errorf("test %d: expected error but got: %v", i, err) - } - - if !tc.expectErr && err != nil { - t.Errorf("test %d: expected no error but got: %v", i, err) - } + if tc.expectError && err == nil { + t.Fatal("expected error but got none") + } + }) } } func TestContext_loadModule(t *testing.T) { - for i, tc := range []struct { - instance interface{} - expectErr bool + for _, tc := range []struct { + scenario string + instance interface{} + expectError bool }{ { + scenario: "module with error on provision", instance: func() interface{} { - mod := struct{ ProtoProvisioner }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ProvisionerMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.provision = func(ctx *Context) error { return errors.New("foo") } - + mod.ProvisionMock = func(ctx *Context) error { return errors.New("foo") } return mod }(), - expectErr: true, + expectError: true, }, { + scenario: "module with error on validation", instance: func() interface{} { - mod := struct{ ProtoValidator }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ValidatorMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.validate = func() error { return errors.New("foo") } - + mod.ValidateMock = func() error { return errors.New("foo") } return mod }(), - expectErr: true, + expectError: true, }, { + scenario: "success", instance: func() interface{} { - mod := struct{ ProtoValidator }{} - mod.descriptor = func() ModuleDescriptor { + mod := &struct { + ModuleMock + ValidatorMock + }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: "foo", New: func() Module { return mod }} } - mod.validate = func() error { return nil } + mod.ValidateMock = func() error { return nil } return mod }(), + expectError: false, }, } { + t.Run(tc.scenario, func(t *testing.T) { + ctx := NewContext(ParsedFlags{}, nil) + err := ctx.loadModule("foo", tc.instance) - ctx := NewContext(ParsedFlags{}, nil) - err := ctx.loadModule("foo", tc.instance) + if !tc.expectError && err != nil { + t.Fatalf("expected no error but got: %v", err) + } - if tc.expectErr && err == nil { - t.Errorf("test %d: expected error but got: %v", i, err) - } - - if !tc.expectErr && err != nil { - t.Errorf("test %d: expected no error but got: %v", i, err) - } + if tc.expectError && err == nil { + t.Fatal("expected error but got none") + } + }) } } diff --git a/pkg/gotenberg/flags_test.go b/pkg/gotenberg/flags_test.go index a5ff9d94..bf524001 100644 --- a/pkg/gotenberg/flags_test.go +++ b/pkg/gotenberg/flags_test.go @@ -20,23 +20,27 @@ func TestParsedFlags_MustString(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -44,49 +48,55 @@ func TestParsedFlags_MustString(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustString(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedString(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue string }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=foo"}, expectValue: "foo", }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=bar"}, expectValue: "bar", }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=foo", "--bar=bar"}, expectValue: "foo", }, } { - fs := flag.NewFlagSet("tests", flag.ContinueOnError) - fs.String("foo", "", "") - fs.String("bar", "", "") + t.Run(tc.scenario, func(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.String("foo", "", "") + fs.String("bar", "", "") - parsedFlags := ParsedFlags{FlagSet: fs} + parsedFlags := ParsedFlags{FlagSet: fs} - err := parsedFlags.Parse(tc.rawFlags) - if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) - } + err := parsedFlags.Parse(tc.rawFlags) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } - actual := parsedFlags.MustDeprecatedString("foo", "bar") - if actual != tc.expectValue { - t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expectValue, actual) - } + actual := parsedFlags.MustDeprecatedString("foo", "bar") + if actual != tc.expectValue { + t.Errorf("expected '%s' but got '%s'", tc.expectValue, actual) + } + }) } } @@ -101,23 +111,27 @@ func TestParsedFlags_MustStringSlice(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -125,49 +139,55 @@ func TestParsedFlags_MustStringSlice(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustStringSlice(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedStringSlice(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue []string }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=foo"}, expectValue: []string{"foo"}, }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=bar"}, expectValue: []string{"bar"}, }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=foo", "--bar=bar"}, expectValue: []string{"foo"}, }, } { - fs := flag.NewFlagSet("tests", flag.ContinueOnError) - fs.StringSlice("foo", make([]string, 0), "") - fs.StringSlice("bar", make([]string, 0), "") + t.Run(tc.scenario, func(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.StringSlice("foo", make([]string, 0), "") + fs.StringSlice("bar", make([]string, 0), "") - parsedFlags := ParsedFlags{FlagSet: fs} + parsedFlags := ParsedFlags{FlagSet: fs} - err := parsedFlags.Parse(tc.rawFlags) - if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) - } + err := parsedFlags.Parse(tc.rawFlags) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } - actual := parsedFlags.MustDeprecatedStringSlice("foo", "bar") - if !reflect.DeepEqual(actual, tc.expectValue) { - t.Errorf("test %d: expected %+v but got %+v", i, tc.expectValue, actual) - } + actual := parsedFlags.MustDeprecatedStringSlice("foo", "bar") + if !reflect.DeepEqual(actual, tc.expectValue) { + t.Errorf("expected %+v but got %+v", tc.expectValue, actual) + } + }) } } @@ -182,23 +202,27 @@ func TestParsedFlags_MustBool(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -206,49 +230,55 @@ func TestParsedFlags_MustBool(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustBool(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedBool(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue bool }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=true"}, expectValue: true, }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=false"}, expectValue: false, }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=true", "--bar=false"}, expectValue: true, }, } { - fs := flag.NewFlagSet("tests", flag.ContinueOnError) - fs.Bool("foo", false, "") - fs.Bool("bar", true, "") + t.Run(tc.scenario, func(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.Bool("foo", false, "") + fs.Bool("bar", true, "") - parsedFlags := ParsedFlags{FlagSet: fs} + parsedFlags := ParsedFlags{FlagSet: fs} - err := parsedFlags.Parse(tc.rawFlags) - if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) - } + err := parsedFlags.Parse(tc.rawFlags) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } - actual := parsedFlags.MustDeprecatedBool("foo", "bar") - if actual != tc.expectValue { - t.Errorf("test %d: expected %v but got %v", i, tc.expectValue, actual) - } + actual := parsedFlags.MustDeprecatedBool("foo", "bar") + if actual != tc.expectValue { + t.Errorf("expected %v but got %v", tc.expectValue, actual) + } + }) } } @@ -263,23 +293,27 @@ func TestParsedFlags_MustInt64(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -287,30 +321,34 @@ func TestParsedFlags_MustInt64(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustInt64(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedInt64(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue int64 }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=1"}, expectValue: 1, }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=2"}, expectValue: 2, }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=1", "--bar=2"}, expectValue: 1, }, @@ -323,12 +361,12 @@ func TestParsedFlags_MustDeprecatedInt64(t *testing.T) { err := parsedFlags.Parse(tc.rawFlags) if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) + t.Fatalf("expected no error but got: %v", err) } actual := parsedFlags.MustDeprecatedInt64("foo", "bar") if actual != tc.expectValue { - t.Errorf("test %d: expected %d but got %d", i, tc.expectValue, actual) + t.Errorf("expected %d but got %d", tc.expectValue, actual) } } } @@ -344,23 +382,27 @@ func TestParsedFlags_MustInt(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -368,49 +410,55 @@ func TestParsedFlags_MustInt(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustInt(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedInt(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue int }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=1"}, expectValue: 1, }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=2"}, expectValue: 2, }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=1", "--bar=2"}, expectValue: 1, }, } { - fs := flag.NewFlagSet("tests", flag.ContinueOnError) - fs.Int("foo", 0, "") - fs.Int("bar", 0, "") + t.Run(tc.scenario, func(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.Int("foo", 0, "") + fs.Int("bar", 0, "") - parsedFlags := ParsedFlags{FlagSet: fs} + parsedFlags := ParsedFlags{FlagSet: fs} - err := parsedFlags.Parse(tc.rawFlags) - if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) - } + err := parsedFlags.Parse(tc.rawFlags) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } - actual := parsedFlags.MustDeprecatedInt("foo", "bar") - if actual != tc.expectValue { - t.Errorf("test %d: expected %d but got %d", i, tc.expectValue, actual) - } + actual := parsedFlags.MustDeprecatedInt("foo", "bar") + if actual != tc.expectValue { + t.Errorf("expected %d but got %d", tc.expectValue, actual) + } + }) } } @@ -425,23 +473,27 @@ func TestParsedFlags_MustFloat64(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -449,49 +501,55 @@ func TestParsedFlags_MustFloat64(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustFloat64(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedFloat64(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue float64 }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=1.0"}, expectValue: 1.0, }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=2.0"}, expectValue: 2.0, }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=1.0", "--bar=2.0"}, expectValue: 1.0, }, } { - fs := flag.NewFlagSet("tests", flag.ContinueOnError) - fs.Float64("foo", 0, "") - fs.Float64("bar", 0, "") + t.Run(tc.scenario, func(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.Float64("foo", 0, "") + fs.Float64("bar", 0, "") - parsedFlags := ParsedFlags{FlagSet: fs} + parsedFlags := ParsedFlags{FlagSet: fs} - err := parsedFlags.Parse(tc.rawFlags) - if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) - } + err := parsedFlags.Parse(tc.rawFlags) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } - actual := parsedFlags.MustDeprecatedFloat64("foo", "bar") - if actual != tc.expectValue { - t.Errorf("test %d: expected %f but got %f", i, tc.expectValue, actual) - } + actual := parsedFlags.MustDeprecatedFloat64("foo", "bar") + if actual != tc.expectValue { + t.Errorf("expected %f but got %f", tc.expectValue, actual) + } + }) } } @@ -506,23 +564,27 @@ func TestParsedFlags_MustDuration(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -530,49 +592,55 @@ func TestParsedFlags_MustDuration(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustDuration(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedDuration(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue time.Duration }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=1s"}, expectValue: time.Duration(1) * time.Second, }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=2s"}, expectValue: time.Duration(2) * time.Second, }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=1s", "--bar=2s"}, expectValue: time.Duration(1) * time.Second, }, } { - fs := flag.NewFlagSet("tests", flag.ContinueOnError) - fs.Duration("foo", 0, "") - fs.Duration("bar", 0, "") + t.Run(tc.scenario, func(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.Duration("foo", 0, "") + fs.Duration("bar", 0, "") - parsedFlags := ParsedFlags{FlagSet: fs} + parsedFlags := ParsedFlags{FlagSet: fs} - err := parsedFlags.Parse(tc.rawFlags) - if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) - } + err := parsedFlags.Parse(tc.rawFlags) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } - actual := parsedFlags.MustDeprecatedDuration("foo", "bar") - if actual != tc.expectValue { - t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expectValue, actual) - } + actual := parsedFlags.MustDeprecatedDuration("foo", "bar") + if actual != tc.expectValue { + t.Errorf("expected '%s' but got '%s'", tc.expectValue, actual) + } + }) } } @@ -588,27 +656,27 @@ func TestParsedFlags_MustHumanReadableBytesString(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, - { - name: "baz", - expectPanic: true, - }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -616,49 +684,55 @@ func TestParsedFlags_MustHumanReadableBytesString(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustHumanReadableBytesString(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedHumanReadableBytesString(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue string }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=1MB"}, expectValue: "1MB", }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=2MB"}, expectValue: "2MB", }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=1MB", "--bar=2MB"}, expectValue: "1MB", }, } { - fs := flag.NewFlagSet("tests", flag.ContinueOnError) - fs.String("foo", "", "") - fs.String("bar", "", "") + t.Run(tc.scenario, func(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.String("foo", "", "") + fs.String("bar", "", "") - parsedFlags := ParsedFlags{FlagSet: fs} + parsedFlags := ParsedFlags{FlagSet: fs} - err := parsedFlags.Parse(tc.rawFlags) - if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) - } + err := parsedFlags.Parse(tc.rawFlags) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } - actual := parsedFlags.MustDeprecatedHumanReadableBytesString("foo", "bar") - if actual != tc.expectValue { - t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expectValue, actual) - } + actual := parsedFlags.MustDeprecatedHumanReadableBytesString("foo", "bar") + if actual != tc.expectValue { + t.Errorf("expected '%s' but got '%s'", tc.expectValue, actual) + } + }) } } @@ -674,27 +748,27 @@ func TestParsedFlags_MustRegexp(t *testing.T) { parsedFlags := ParsedFlags{FlagSet: fs} - for i, tc := range []struct { + for _, tc := range []struct { + scenario string name string expectPanic bool }{ { - name: "foo", + scenario: "success", + name: "foo", + expectPanic: false, }, { + scenario: "non-existing flag", name: "bar", expectPanic: true, }, - { - name: "baz", - expectPanic: true, - }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Fatal("expected panic but got none") } }() } @@ -702,48 +776,54 @@ func TestParsedFlags_MustRegexp(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Fatalf("expected no panic but got: %v", r) } }() } parsedFlags.MustRegexp(tc.name) - }() + }) } } func TestParsedFlags_MustDeprecatedRegexp(t *testing.T) { - for i, tc := range []struct { + for _, tc := range []struct { + scenario string rawFlags []string expectValue *regexp.Regexp }{ { + scenario: "deprecated flag value", rawFlags: []string{"--foo=foo"}, expectValue: regexp.MustCompile("foo"), }, { + scenario: "non-deprecated flag value", rawFlags: []string{"--bar=bar"}, expectValue: regexp.MustCompile("bar"), }, { + scenario: "deprecated flag value > non-deprecated flag value", rawFlags: []string{"--foo=foo", "--bar=bar"}, expectValue: regexp.MustCompile("foo"), }, } { - fs := flag.NewFlagSet("tests", flag.ContinueOnError) - fs.String("foo", "", "") - fs.String("bar", "", "") + t.Run(tc.scenario, func(t *testing.T) { + fs := flag.NewFlagSet("tests", flag.ContinueOnError) + fs.String("foo", "", "") + fs.String("bar", "", "") - parsedFlags := ParsedFlags{FlagSet: fs} + parsedFlags := ParsedFlags{FlagSet: fs} - err := parsedFlags.Parse(tc.rawFlags) - if err != nil { - t.Fatalf("test %d: expected no error but got: %v", i, err) - } + err := parsedFlags.Parse(tc.rawFlags) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } - actual := parsedFlags.MustDeprecatedRegexp("foo", "bar") - if actual.String() != tc.expectValue.String() { - t.Errorf("test %d: expected '%s' but got '%s'", i, tc.expectValue.String(), actual.String()) - } + actual := parsedFlags.MustDeprecatedRegexp("foo", "bar") + if actual.String() != tc.expectValue.String() { + t.Errorf("expected '%s' but got '%s'", tc.expectValue.String(), actual.String()) + } + }) } } diff --git a/pkg/gotenberg/gc_test.go b/pkg/gotenberg/gc_test.go index 0d897868..4dd58e4f 100644 --- a/pkg/gotenberg/gc_test.go +++ b/pkg/gotenberg/gc_test.go @@ -14,14 +14,14 @@ func TestGarbageCollect(t *testing.T) { scenario string rootPath string includeSubstr []string - expectErr bool + expectError bool expectNotExists []string expectExists []string }{ { - scenario: "root path does not exist", - rootPath: uuid.NewString(), - expectErr: true, + scenario: "root path does not exist", + rootPath: uuid.NewString(), + expectError: true, }, { scenario: "remove include substrings", @@ -51,29 +51,30 @@ func TestGarbageCollect(t *testing.T) { return path }(), includeSubstr: []string{"foo", fmt.Sprintf("%s/a_directory/a_bar_file", os.TempDir())}, + expectError: false, expectExists: []string{"a_baz_file"}, expectNotExists: []string{"a_foo_file", "a_bar_file"}, }, } { - func() { + t.Run(tc.scenario, func(t *testing.T) { defer func() { err := os.RemoveAll(tc.rootPath) if err != nil { - t.Fatalf("%s: expected no error while cleaning up but got: %v", tc.scenario, err) + t.Fatalf("expected no error while cleaning up but got: %v", err) } }() err := GarbageCollect(zap.NewNop(), tc.rootPath, tc.includeSubstr) - if !tc.expectErr && err != nil { - t.Fatalf("%s: expected no error but got: %v", tc.scenario, err) + if !tc.expectError && err != nil { + t.Fatalf("expected no error but got: %v", err) } - if tc.expectErr && err == nil { - t.Fatalf("%s: expected error but got: %v", tc.scenario, err) + if tc.expectError && err == nil { + t.Fatal("expected error but got none") } - if tc.expectErr && err != nil { + if tc.expectError && err != nil { return } @@ -81,7 +82,7 @@ func TestGarbageCollect(t *testing.T) { path := fmt.Sprintf("%s/%s", tc.rootPath, name) _, err = os.Stat(path) if !os.IsNotExist(err) { - t.Errorf("%s: expected '%s' not to exist but it does: %v", tc.scenario, path, err) + t.Errorf("expected '%s' not to exist but it does: %v", path, err) } } @@ -89,9 +90,9 @@ func TestGarbageCollect(t *testing.T) { path := fmt.Sprintf("%s/%s", tc.rootPath, name) _, err = os.Stat(path) if os.IsNotExist(err) { - t.Errorf("%s: expected '%s' to exist but it does not: %v", tc.scenario, path, err) + t.Errorf("expected '%s' to exist but it does not: %v", path, err) } } - }() + }) } } diff --git a/pkg/gotenberg/mocks.go b/pkg/gotenberg/mocks.go index da796f7c..4e8fad02 100644 --- a/pkg/gotenberg/mocks.go +++ b/pkg/gotenberg/mocks.go @@ -15,6 +15,15 @@ func (mod *ModuleMock) Descriptor() ModuleDescriptor { return mod.DescriptorMock() } +// ProvisionerMock is a mock for the [Provisioner] interface. +type ProvisionerMock struct { + ProvisionMock func(*Context) error +} + +func (mod *ProvisionerMock) Provision(ctx *Context) error { + return mod.ProvisionMock(ctx) +} + // ValidatorMock is a mock for the [Validator] interface. type ValidatorMock struct { ValidateMock func() error diff --git a/pkg/gotenberg/mocks_test.go b/pkg/gotenberg/mocks_test.go index 1a57784d..dba04318 100644 --- a/pkg/gotenberg/mocks_test.go +++ b/pkg/gotenberg/mocks_test.go @@ -21,6 +21,19 @@ func TestModuleMock(t *testing.T) { } } +func TestProvisionerMock(t *testing.T) { + mock := &ProvisionerMock{ + ProvisionMock: func(*Context) error { + return nil + }, + } + + err := mock.Provision(&Context{}) + if err != nil { + t.Errorf("expected no error from ProvisionerMock.Provision, but got: %v", err) + } +} + func TestValidatorMock(t *testing.T) { mock := &ValidatorMock{ ValidateMock: func() error { diff --git a/pkg/gotenberg/modules_test.go b/pkg/gotenberg/modules_test.go index 725e2045..f8d62931 100644 --- a/pkg/gotenberg/modules_test.go +++ b/pkg/gotenberg/modules_test.go @@ -5,32 +5,6 @@ import ( "testing" ) -type ProtoModule struct { - descriptor func() ModuleDescriptor -} - -func (mod ProtoModule) Descriptor() ModuleDescriptor { - return mod.descriptor() -} - -type ProtoProvisioner struct { - ProtoModule - provision func(ctx *Context) error -} - -func (mod ProtoProvisioner) Provision(ctx *Context) error { - return mod.provision(ctx) -} - -type ProtoValidator struct { - ProtoModule - validate func() error -} - -func (mod ProtoValidator) Validate() error { - return mod.validate() -} - func TestMustRegisterModule(t *testing.T) { descriptorsMu.RLock() descriptors = map[string]ModuleDescriptor{ @@ -38,44 +12,51 @@ func TestMustRegisterModule(t *testing.T) { } descriptorsMu.RUnlock() - for i, tc := range []struct { + for _, tc := range []struct { + scenario string ID string New func() Module expectPanic bool }{ { + scenario: "no ID", ID: "", - New: func() Module { return new(ProtoModule) }, + New: func() Module { return new(ModuleMock) }, expectPanic: true, }, { + scenario: "nil New method", ID: "b", New: nil, expectPanic: true, }, { + scenario: "nil module", ID: "b", New: func() Module { return nil }, expectPanic: true, }, { + scenario: "existing module", ID: "a", - New: func() Module { return new(ProtoModule) }, + New: func() Module { return new(ModuleMock) }, expectPanic: true, }, { - ID: "b", - New: func() Module { return new(ProtoModule) }, + scenario: "success", + ID: "b", + New: func() Module { return new(ModuleMock) }, + expectPanic: false, }, } { - func() { - mod := struct{ ProtoModule }{} - mod.descriptor = func() ModuleDescriptor { return ModuleDescriptor{ID: tc.ID, New: tc.New} } + t.Run(tc.scenario, func(t *testing.T) { + mod := &struct{ ModuleMock }{} + mod.DescriptorMock = func() ModuleDescriptor { return ModuleDescriptor{ID: tc.ID, New: tc.New} } if tc.expectPanic { defer func() { if r := recover(); r == nil { - t.Errorf("test %d: expected panic but got none", i) + t.Error("expected panic but got none") } }() } @@ -83,13 +64,13 @@ func TestMustRegisterModule(t *testing.T) { if !tc.expectPanic { defer func() { if r := recover(); r != nil { - t.Errorf("test %d: expected no panic but got: %v", i, r) + t.Errorf("expected no panic but got: %v", r) } }() } MustRegisterModule(mod) - }() + }) } descriptorsMu.RLock() @@ -124,12 +105,3 @@ func TestGetModuleDescriptors(t *testing.T) { descriptors = make(map[string]ModuleDescriptor) descriptorsMu.RUnlock() } - -// Interface guards. -var ( - _ Module = (*ProtoModule)(nil) - _ Provisioner = (*ProtoProvisioner)(nil) - _ Module = (*ProtoProvisioner)(nil) - _ Validator = (*ProtoValidator)(nil) - _ Module = (*ProtoValidator)(nil) -) diff --git a/pkg/gotenberg/pdfengine.go b/pkg/gotenberg/pdfengine.go index 2ef04083..9775ce35 100644 --- a/pkg/gotenberg/pdfengine.go +++ b/pkg/gotenberg/pdfengine.go @@ -76,6 +76,6 @@ type PdfEngine interface { // engine, _ := provider.(gotenberg.PdfEngineProvider).PdfEngine() // } type PdfEngineProvider interface { - // PdfEngine returns an instance of the PdfEngine interface for PDF operations. + // PdfEngine returns an instance of the [PdfEngine] interface for PDF operations. PdfEngine() (PdfEngine, error) } diff --git a/pkg/modules/libreoffice/api/libreoffice.go b/pkg/modules/libreoffice/api/libreoffice.go index 453421b1..d1c4267a 100644 --- a/pkg/modules/libreoffice/api/libreoffice.go +++ b/pkg/modules/libreoffice/api/libreoffice.go @@ -29,7 +29,7 @@ type libreOfficeArguments struct { type libreOfficeProcess struct { socketPort int userProfileDirPath string - cmd gotenberg.Cmd + cmd *gotenberg.Cmd cfgMu sync.RWMutex isStarted atomic.Bool @@ -213,7 +213,7 @@ func (p *libreOfficeProcess) Stop(logger *zap.Logger) error { p.socketPort = 0 p.userProfileDirPath = "" - p.cmd = gotenberg.Cmd{} // FIXME: pointer. + p.cmd = nil p.isStarted.Store(false) return nil