patch accumulator system.
commit c215a37d7c5af3f2ea10d7452b2f504108ed62aa · parent 699341b1a2
· browse this tree
Eric Myhre, 2021-09-19 16:18:43 UTC
diff --git a/patch.go b/patch.go index e1342c4..6465ece 100644 --- a/patch.go +++ b/patch.go @@ -98,3 +98,21 @@ func appendHunkLines(lines [][]byte, hunkName string, hunkBlockTag string, hunkB lines = append(lines, sigilCodeBlock) return lines } + +type PatchAccumulator struct { + Patches []Hunk +} + +func (pa *PatchAccumulator) AppendPatchIfBodyDiffers(hunk Hunk, newBody []byte) { + if !bytes.Equal(hunk.Body, newBody) { + hunk.Body = newBody + pa.AppendPatch(hunk) + } +} + +func (pa *PatchAccumulator) AppendPatch(hunk Hunk) { + if pa.Patches == nil { + pa.Patches = make([]Hunk, 0) + } + pa.Patches = append(pa.Patches, hunk) +} diff --git a/testexec/testexec.go b/testexec/testexec.go index 8d056ef..8d673fd 100644 --- a/testexec/testexec.go +++ b/testexec/testexec.go @@ -55,10 +55,8 @@ type AssertFn func(t *testing.T, actual, expect string) // a nil FilterFn means no filtering will occur; // a nil AssertFn means a very basic check using t.Errorf will be used.) // -// The 'Patches' a slice for patched hunks will be appended to if `testmark.Regen` is true. -// (If the pointer is nil, a new slice will be made; -// if the pointer is handed in before usage, it can be used to accumulate patches -// batched up with other patches destined for the same document.) +// The 'Patches' accumulator will be used to gather new fixture data if `testmark.Regen` is true. +// (If the pointer is nil, a warning will be logged.) // It is the user's responsibility to actually apply the patches and save the updated document. type Tester struct { ExecFn @@ -66,7 +64,7 @@ type Tester struct { FilterFn AssertFn - Patches *[]testmark.Hunk + Patches *testmark.PatchAccumulator } func (tcfg *Tester) init() { @@ -132,7 +130,7 @@ func (tcfg *Tester) init() { // Regen mode will only update hunks that already exist; it won't add them. // As an edge case, note that if that an exitcode hunk is absent, but a nonzero exitcode is encountered, // the test will still be failed, even though in patch regen mode most assertions are usually skipped. -func (tcfg *Tester) TestSequence(t *testing.T, data testmark.DirEnt) { +func (tcfg Tester) TestSequence(t *testing.T, data testmark.DirEnt) { t.Helper() tcfg.init() @@ -140,6 +138,10 @@ func (tcfg *Tester) TestSequence(t *testing.T, data testmark.DirEnt) { if !exists { return } + if *testmark.Regen && tcfg.Patches == nil { + t.Logf("warning: testmark.regen mode engaged, but there is no patch accumulator available here") + t.Skipf("nothing to do if requested to regenerate test fixtures but have nowhere to put data") + } // Prepare output buffers. var stdout, stderr io.Writer @@ -184,7 +186,7 @@ func (tcfg *Tester) TestSequence(t *testing.T, data testmark.DirEnt) { if ent, exists := data.Children["output"]; exists { bs := stdout.(*bytes.Buffer).Bytes() if *testmark.Regen { - tcfg.maybeAppendPatch(*ent.Hunk, bs) + tcfg.Patches.AppendPatchIfBodyDiffers(*ent.Hunk, bs) } else { t.Run("check-combined-output", func(t *testing.T) { tcfg.AssertFn(t, string(bs), string(ent.Hunk.Body)) @@ -194,7 +196,7 @@ func (tcfg *Tester) TestSequence(t *testing.T, data testmark.DirEnt) { if ent, exists := data.Children["stdout"]; exists { bs := stdout.(*bytes.Buffer).Bytes() if *testmark.Regen { - tcfg.maybeAppendPatch(*ent.Hunk, bs) + tcfg.Patches.AppendPatchIfBodyDiffers(*ent.Hunk, bs) } else { t.Run("check-stdout", func(t *testing.T) { tcfg.AssertFn(t, string(bs), string(ent.Hunk.Body)) @@ -204,7 +206,7 @@ func (tcfg *Tester) TestSequence(t *testing.T, data testmark.DirEnt) { if ent, exists := data.Children["stderr"]; exists { bs := stderr.(*bytes.Buffer).Bytes() if *testmark.Regen { - tcfg.maybeAppendPatch(*ent.Hunk, bs) + tcfg.Patches.AppendPatchIfBodyDiffers(*ent.Hunk, bs) } else { t.Run("check-stderr", func(t *testing.T) { tcfg.AssertFn(t, string(bs), string(ent.Hunk.Body)) @@ -214,7 +216,7 @@ func (tcfg *Tester) TestSequence(t *testing.T, data testmark.DirEnt) { t.Run("check-exitcode", func(t *testing.T) { if ent, exists := data.Children["exitcode"]; exists { if *testmark.Regen { - tcfg.maybeAppendPatch(*ent.Hunk, []byte(strconv.Itoa(exitcode))) + tcfg.Patches.AppendPatchIfBodyDiffers(*ent.Hunk, []byte(strconv.Itoa(exitcode))) } else { tcfg.AssertFn(t, strconv.Itoa(exitcode), strings.TrimSpace(string(ent.Hunk.Body))) } @@ -226,29 +228,14 @@ func (tcfg *Tester) TestSequence(t *testing.T, data testmark.DirEnt) { // TODO: look for "then-*" dirs. } -func (tcfg *Tester) TestScript(t *testing.T, data testmark.DirEnt) { +func (tcfg Tester) TestScript(t *testing.T, data testmark.DirEnt) { panic("not yet implemented") } -func (tcfg *Tester) Test(t *testing.T, data testmark.DirEnt) { +func (tcfg Tester) Test(t *testing.T, data testmark.DirEnt) { panic("not yet implemented") } // Not yet defined how these will nest. ISTM if you specify one or the other, it shouldn't become willing to switch when it goes deeper into then-trees. // Not yet defined if these should complain loudly if they _don't_ find something that matches. I think being able to shrug is useful; otherwise that check will often get offloaded to callers. - -func (tcfg *Tester) maybeAppendPatch(hunk testmark.Hunk, newBody []byte) { - if !bytes.Equal(hunk.Body, newBody) { - hunk.Body = newBody - tcfg.appendPatch(hunk) - } -} - -func (tcfg *Tester) appendPatch(hunk testmark.Hunk) { - if tcfg.Patches == nil { - patches := make([]testmark.Hunk, 0) - tcfg.Patches = &patches - } - *tcfg.Patches = append(*tcfg.Patches, hunk) -} diff --git a/write.go b/write.go index eb5179b..dc44ffc 100644 --- a/write.go +++ b/write.go @@ -54,3 +54,11 @@ func WriteFileWithPatches(doc *Document, filename string, patches ...Hunk) error doc = Patch(doc, patches...) return WriteFile(doc, filename) } + +func (pa PatchAccumulator) WriteWithPatches(doc *Document, wr io.Writer) (int, error) { + return WriteWithPatches(doc, wr, pa.Patches...) +} + +func (pa PatchAccumulator) WriteFileWithPatches(doc *Document, filename string) error { + return WriteFileWithPatches(doc, filename, pa.Patches...) +}