diff --git a/go/.gitignore b/go/.gitignore new file mode 100644 index 0000000..aaadf73 --- /dev/null +++ b/go/.gitignore @@ -0,0 +1,32 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Code coverage profiles and other test artifacts +*.out +coverage.* +*.coverprofile +profile.cov + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work +go.work.sum + +# env file +.env + +# Editor/IDE +# .idea/ +# .vscode/ diff --git a/go/examp.go b/go/exam/exam.go similarity index 95% rename from go/examp.go rename to go/exam/exam.go index b02a09f..4023d02 100644 --- a/go/examp.go +++ b/go/exam/exam.go @@ -68,9 +68,9 @@ func getAll(nums []int64, ops []byte) []Pair { return result } -func main() { - reader := bufio.NewReader(os.Stdin) - writer := bufio.NewWriter(os.Stdout) +func exam(in *os.File, out *os.File) { + reader := bufio.NewReader(in) + writer := bufio.NewWriter(out) defer writer.Flush() var n int @@ -136,3 +136,7 @@ func main() { fmt.Fprintln(writer, "NO SOLUTION") } } + +func main() { + exam(os.Stdin, os.Stdout) +} diff --git a/go/exam/exam_test.go b/go/exam/exam_test.go new file mode 100644 index 0000000..ad6e165 --- /dev/null +++ b/go/exam/exam_test.go @@ -0,0 +1,82 @@ +package main + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func runTest(testcase string) func(t *testing.T) { + return func(t *testing.T) { + inPath := filepath.Join("in", testcase+".txt") + outPath := filepath.Join("out", testcase+".txt") + expectPath := filepath.Join("expected", testcase+".txt") + + inFile, err := os.Open(inPath) + if err != nil { + t.Fatal(err) + } + outFile, err := os.Create(outPath) + if err != nil { + t.Fatal(err) + } + exam(inFile, outFile) + + actual, err := os.ReadFile(outPath) + if err != nil { + t.Fatalf("cannot read output file: %v", err) + } + + expected, err := os.ReadFile(expectPath) + if err != nil { + t.Fatalf("cannot read expected file: %v", err) + } + + actualLines := strings.Split(strings.ReplaceAll(string(actual), "\r\n", "\n"), "\n") + expectedLines := strings.Split(strings.ReplaceAll(string(expected), "\r\n", "\n"), "\n") + + maxLen := max(len(actualLines), len(expectedLines)) + + for i := 0; i < maxLen; i++ { + var a, e string + if i < len(actualLines) { + a = actualLines[i] + } + if i < len(expectedLines) { + e = expectedLines[i] + } + + if a != e { + t.Fatalf( + "difference at line %d\nexpected: %q\nactual: %q\n", + i+1, + e, + a, + ) + } + } + + } +} + +func TestRunFromFiles(t *testing.T) { + files, err := os.ReadDir("in") + if err != nil { + t.Fatalf("cannot read in dir %v", err) + } + + if err := os.MkdirAll("out", 0755); err != nil { + t.Fatalf("cannot create out dir: %v", err) + } + + for _, f := range files { + if f.IsDir() || !strings.HasSuffix(f.Name(), ".txt") { + continue + } + + testcase := strings.TrimSuffix(f.Name(), ".txt") + + t.Run(testcase, runTest(testcase)) + } +} diff --git a/go/exam/expected/.gitignore b/go/exam/expected/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/go/exam/expected/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/go/exam/go.mod b/go/exam/go.mod new file mode 100644 index 0000000..f0d6607 --- /dev/null +++ b/go/exam/go.mod @@ -0,0 +1,3 @@ +module exam + +go 1.23.4 diff --git a/go/exam/go.work b/go/exam/go.work new file mode 100644 index 0000000..f146cd6 --- /dev/null +++ b/go/exam/go.work @@ -0,0 +1,3 @@ +go 1.23.4 + +use . diff --git a/go/exam/in/.gitignore b/go/exam/in/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/go/exam/in/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/go/exam/out/.gitignore b/go/exam/out/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/go/exam/out/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore