diff --git a/cmd/sum.go b/cmd/sum.go new file mode 100644 index 0000000..ea548e1 --- /dev/null +++ b/cmd/sum.go @@ -0,0 +1,20 @@ +package cmd + +import ( + "fmt" + "github.com/mpppk/cli-template/lib" + "github.com/spf13/cobra" +) + +var sumCmd = &cobra.Command{ + Use: "sum", + Short: "print sum of arguments", + Long: ``, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(lib.SumFromString(args)) + }, +} + +func init() { + rootCmd.AddCommand(sumCmd) +} diff --git a/lib/sum.go b/lib/sum.go new file mode 100644 index 0000000..9cb6954 --- /dev/null +++ b/lib/sum.go @@ -0,0 +1,17 @@ +package lib + +func Sum(numbers []int) (sum int) { + for _, number := range numbers { + sum += number + } + return +} + +func SumFromString(stringNumbers []string) (sum int, err error) { + numbers, err := ConvertStringSliceToIntSlice(stringNumbers) + if err != nil { + return 0, err + } + return Sum(numbers), nil +} + diff --git a/lib/sum_test.go b/lib/sum_test.go new file mode 100644 index 0000000..f72b76a --- /dev/null +++ b/lib/sum_test.go @@ -0,0 +1,70 @@ +package lib + +import "testing" + +func TestSum(t *testing.T) { + type args struct { + numbers []int + } + tests := []struct { + name string + args args + wantSum int + }{ + { + name: "return sum of numbers", + args: args{ + numbers: []int{1,2,3}, + }, + wantSum: 6, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if gotSum := Sum(tt.args.numbers); gotSum != tt.wantSum { + t.Errorf("Sum() = %v, want %v", gotSum, tt.wantSum) + } + }) + } +} + +func TestSumFromString(t *testing.T) { + type args struct { + stringNumbers []string + } + tests := []struct { + name string + args args + wantSum int + wantErr bool + }{ + { + name: "return sum of numbers", + args: args{ + stringNumbers: []string{"1", "2", "3"}, + }, + wantSum: 6, + wantErr: false, + }, + { + name: "will be error if args includes not number string", + args: args{ + stringNumbers: []string{"1", "2", "a"}, + }, + wantSum: 0, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotSum, err := SumFromString(tt.args.stringNumbers) + if (err != nil) != tt.wantErr { + t.Errorf("SumFromString() error = %v, wantErr %v", err, tt.wantErr) + return + } + if gotSum != tt.wantSum { + t.Errorf("SumFromString() = %v, want %v", gotSum, tt.wantSum) + } + }) + } +} diff --git a/lib/util.go b/lib/util.go new file mode 100644 index 0000000..a37ffdd --- /dev/null +++ b/lib/util.go @@ -0,0 +1,29 @@ +package lib + +import ( + "fmt" + "github.com/pkg/errors" + "os" + "strconv" +) + +func ConvertStringSliceToIntSlice(stringSlice []string) (intSlice []int, err error) { + for _, s := range stringSlice { + num, err := strconv.Atoi(s) + if err != nil { + return nil, errors.Wrap(err, "failed to convert string slice to int slice") + } + intSlice = append(intSlice, num) + } + return +} + +func EPrintlnIFErrExist(err error, msg string) (bool, error) { + if err != nil { + if _, err := fmt.Fprintln(os.Stderr, msg); err != nil { + return true, err + } + return true, nil + } + return false, nil +} diff --git a/lib/util_test.go b/lib/util_test.go new file mode 100644 index 0000000..2c0bb1a --- /dev/null +++ b/lib/util_test.go @@ -0,0 +1,47 @@ +package lib + +import ( + "reflect" + "testing" +) + +func TestConvertStringSliceToIntSlice(t *testing.T) { + type args struct { + stringSlice []string + } + tests := []struct { + name string + args args + wantIntSlice []int + wantErr bool + }{ + { + name: "can convert string slice to int slice", + args: args{ + stringSlice: []string{"1", "2", "3"}, + }, + wantIntSlice: []int{1, 2, 3}, + wantErr: false, + }, + { + name: "will be error if string can not be convert to number", + args: args{ + stringSlice: []string{"1", "2", "a"}, + }, + wantIntSlice: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotIntSlice, err := ConvertStringSliceToIntSlice(tt.args.stringSlice) + if (err != nil) != tt.wantErr { + t.Errorf("ConvertStringSliceToIntSlice() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotIntSlice, tt.wantIntSlice) { + t.Errorf("ConvertStringSliceToIntSlice() = %v, want %v", gotIntSlice, tt.wantIntSlice) + } + }) + } +}