diff --git a/fake_coverage_test.go b/fake_coverage_test.go index fe0568b..b201b2d 100644 --- a/fake_coverage_test.go +++ b/fake_coverage_test.go @@ -37,7 +37,7 @@ func TestTBCoverage(t *testing.T) { mn := m.Name // TODO(prashant): Implement new methods added in 1.24 before release. - if mn == "Chdir" || mn == "Context" { + if mn == "Context" { continue } if _, ok := ftSet[mn]; !ok { diff --git a/fake_tb.go b/fake_tb.go index 4f330f3..d1903fb 100644 --- a/fake_tb.go +++ b/fake_tb.go @@ -3,6 +3,7 @@ package faket import ( "fmt" "os" + "path/filepath" "runtime" "strings" "sync" @@ -415,3 +416,37 @@ func (tb *fakeTB) TempDir() string { return d } + +func (tb *fakeTB) Chdir(dir string) { + oldWd, err := os.Open(".") + if err != nil { + // Match stdlib error. + tb.Fatal(err) + } + if err := os.Chdir(dir); err != nil { + // Match stdlib error. + tb.Fatal(err) + } + + // Similar to stdlib, on POSIX, set PWD. + switch runtime.GOOS { + case "windows", "plan9": + // Windows and Plan 9 do not use the PWD variable. + default: + if !filepath.IsAbs(dir) { + dir, err = os.Getwd() + if err != nil { + tb.Fatal(err) + } + } + tb.Setenv("PWD", dir) + } + + tb.Cleanup(func() { + defer oldWd.Close() //nolint:errcheck // best-effort close to avoid leaks. + if err := oldWd.Chdir(); err != nil { + // Note: The stdlib implementation panics here, but we avoid panics. + tb.Errorf("ChDir failed to ChDir to original directory: %v", err) + } + }) +} diff --git a/integration_1_24_test.go b/integration_1_24_test.go new file mode 100644 index 0000000..d5c9b06 --- /dev/null +++ b/integration_1_24_test.go @@ -0,0 +1,60 @@ +//go:build go1.24 + +package faket_test + +import ( + "os" + "regexp" + "strings" + "testing" + + "github.com/prashantv/faket/internal/cmptest" + "github.com/prashantv/faket/internal/want" +) + +func TestCmp_Chdir(t *testing.T) { + t.Run("to non-existent", func(t *testing.T) { + // ChDir failures are reported by testing.go in stdlib + // and similarly fake_tb.go with faket. + opts := cmptest.Opts{ + LogReplace: func(s string) string { + s = regexp.MustCompile("testing.go:[0-9]+").ReplaceAllString(s, "testing.go:Chdir") + s = strings.ReplaceAll(s, "fake_tb.go:428", "testing.go:Chdir") + return s + }, + } + cmptest.CompareOpts(t, opts, func(t testing.TB) { + t.Chdir("./does/not/exist") + t.Log("skipped (due to fatal in ChDir)") + }) + }) + + mustGetWd := func() string { + wd, err := os.Getwd() + want.NoErr(t, err) + return wd + } + + initialWD := mustGetWd() + initialPWD := os.Getenv("PWD") + + stripWD := func(s string) string { + return strings.ReplaceAll(s, initialWD, "/path/to/faket") + } + + t.Run("success", func(t *testing.T) { + cmptest.Compare(t, func(t testing.TB) { + t.Chdir("./testdata") + + wd, err := os.Getwd() + want.NoErr(t, err) + t.Log("wd is", stripWD(wd)) + t.Log("PWD is", stripWD(os.Getenv("PWD"))) + }) + }) + + postWD := mustGetWd() + postPWD := os.Getenv("PWD") + want.Equal(t, "Getwd", postWD, initialWD) + want.Equal(t, "PWD", postPWD, initialPWD) +} diff --git a/internal/cmptest/cmptest.go b/internal/cmptest/cmptest.go index 8d0f806..8b5f64c 100644 --- a/internal/cmptest/cmptest.go +++ b/internal/cmptest/cmptest.go @@ -63,7 +63,8 @@ func Compare(t *testing.T, f func(testing.TB)) { // Opts are options for comparing faket to a real test run. type Opts struct { - WantPanic bool + WantPanic bool + LogReplace func(string) string } // CompareOpts is the same as Compare, but supports options for customizing comparisons. @@ -127,7 +128,14 @@ func CompareOpts(t *testing.T, opts Opts, f func(t testing.TB)) { } } + wantLogs := wantOutput.String() + gotLogs := logs.String() + if opts.LogReplace != nil { + wantLogs = opts.LogReplace(wantLogs) + gotLogs = opts.LogReplace(gotLogs) + } + want.Equal(t, "result event", resultEvent, true) - want.Equal(t, "log output", logs.String(), wantOutput.String()) + want.Equal(t, "log output", gotLogs, wantLogs) want.Equal(t, "panicked", res.Panicked(), opts.WantPanic) } diff --git a/internal/panictests/p1/testdata/cmp_test_results.json b/internal/panictests/p1/testdata/cmp_test_results.json index 3ba6bf5..ba525b6 100644 --- a/internal/panictests/p1/testdata/cmp_test_results.json +++ b/internal/panictests/p1/testdata/cmp_test_results.json @@ -16,8 +16,8 @@ {"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"\truntime/panic.go:1 +0x0000\n"} {"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"github.com/prashantv/faket/internal/panictests/p1.TestCmp_Panic.func1({0x0000, 0x0000})\n"} {"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"\tgithub.com/prashantv/faket/internal/panictests/p1/panic_1_test.go:15 +0x0000\n"} -{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"github.com/prashantv/faket/internal/cmptest.CompareOpts(0x0000, {0x0000?}, 0x0000?)\n"} -{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"\tgithub.com/prashantv/faket/internal/cmptest/cmptest.go:77 +0x0000\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"github.com/prashantv/faket/internal/cmptest.CompareOpts(0x0000, {0x0000?, 0x0000?}, 0x0000?)\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"\tgithub.com/prashantv/faket/internal/cmptest/cmptest.go:78 +0x0000\n"} {"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"github.com/prashantv/faket/internal/panictests/p1.TestCmp_Panic(0x0000?)\n"} {"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"\tgithub.com/prashantv/faket/internal/panictests/p1/panic_1_test.go:11 +0x0000\n"} {"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket/internal/panictests/p1","Test":"TestCmp_Panic","Output":"testing.tRunner(0x0000, 0x0000)\n"} diff --git a/testdata/cmp_test_results.json b/testdata/cmp_test_results.json index 285a166..a9f0295 100644 --- a/testdata/cmp_test_results.json +++ b/testdata/cmp_test_results.json @@ -1,4 +1,19 @@ {"Time":"2022-06-11T00:00:00.0Z","Action":"start","Package":"github.com/prashantv/faket"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"run","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir","Output":"=== RUN TestCmp_Chdir\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"run","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/to_non-existent"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/to_non-existent","Output":"=== RUN TestCmp_Chdir/to_non-existent\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/to_non-existent","Output":" testing.go:1358: chdir ./does/not/exist: no such file or directory\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"run","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/success"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/success","Output":"=== RUN TestCmp_Chdir/success\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/success","Output":" integration_1_24_test.go:51: wd is /path/to/faket/testdata\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/success","Output":" integration_1_24_test.go:52: PWD is /path/to/faket/testdata\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir","Output":"--- FAIL: TestCmp_Chdir (0.01s)\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/to_non-existent","Output":" --- FAIL: TestCmp_Chdir/to_non-existent (0.01s)\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"fail","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/to_non-existent","Elapsed":0} +{"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/success","Output":" --- PASS: TestCmp_Chdir/success (0.01s)\n"} +{"Time":"2022-06-11T00:00:00.0Z","Action":"pass","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir/success","Elapsed":0} +{"Time":"2022-06-11T00:00:00.0Z","Action":"fail","Package":"github.com/prashantv/faket","Test":"TestCmp_Chdir","Elapsed":0} {"Time":"2022-06-11T00:00:00.0Z","Action":"run","Package":"github.com/prashantv/faket","Test":"TestCmp_Success"} {"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Success","Output":"=== RUN TestCmp_Success\n"} {"Time":"2022-06-11T00:00:00.0Z","Action":"output","Package":"github.com/prashantv/faket","Test":"TestCmp_Success","Output":" integration_test.go:20: log1\n"}