From d02f298ad457f115fddac9a8fa51d16b5f83b986 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Sat, 20 Sep 2025 06:08:34 +1000 Subject: [PATCH] govis: switch to testify tests testify makes most bog-standard test checks much easier to read and maintain, and is quite widely used. It wasn't really well known back when govis was first written, but the migration is fairly straight-forward for most tests. Signed-off-by: Aleksa Sarai --- pkg/govis/govis.go | 42 ++++++++ pkg/govis/govis_test.go | 234 ++++++++++++++++++++++------------------ pkg/govis/unvis_test.go | 80 ++++++-------- pkg/govis/vis_test.go | 57 +++++----- 4 files changed, 233 insertions(+), 180 deletions(-) diff --git a/pkg/govis/govis.go b/pkg/govis/govis.go index 9888c27..e8dfb3a 100644 --- a/pkg/govis/govis.go +++ b/pkg/govis/govis.go @@ -17,6 +17,11 @@ package govis +import ( + "strconv" + "strings" +) + // VisFlag manipulates how the characters are encoded/decoded type VisFlag uint @@ -37,3 +42,40 @@ const ( VisWhite VisFlag = (VisSpace | VisTab | VisNewline) ) + +// String pretty-prints VisFlag. +func (vflags VisFlag) String() string { + flagNames := []struct { + name string + bits VisFlag + }{ + {"VisOctal", VisOctal}, + {"VisCStyle", VisCStyle}, + {"VisSpace", VisSpace}, + {"VisTab", VisTab}, + {"VisNewline", VisNewline}, + {"VisSafe", VisSafe}, + {"VisNoSlash", VisNoSlash}, + {"VisHTTPStyle", VisHTTPStyle}, + {"VisGlob", VisGlob}, + } + var ( + flagSet = make([]string, 0, len(flagNames)) + seenBits VisFlag + ) + for _, flag := range flagNames { + if vflags&flag.bits == flag.bits { + seenBits |= flag.bits + flagSet = append(flagSet, flag.name) + } + } + // If there were any remaining flags specified we don't know the name of, + // just add them in an 0x... format. + if remaining := vflags &^ seenBits; remaining != 0 { + flagSet = append(flagSet, "0x"+strconv.FormatUint(uint64(remaining), 16)) + } + if len(flagSet) == 0 { + return "0" + } + return strings.Join(flagSet, "|") +} diff --git a/pkg/govis/govis_test.go b/pkg/govis/govis_test.go index 312cec3..eaab701 100644 --- a/pkg/govis/govis_test.go +++ b/pkg/govis/govis_test.go @@ -18,9 +18,11 @@ package govis import ( - "bytes" "crypto/rand" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const DefaultVisFlags = VisWhite | VisOctal | VisGlob @@ -31,31 +33,29 @@ func TestRandomVisUnvis(t *testing.T) { for i := 0; i < N; i++ { testBytes := make([]byte, 256) - if n, err := rand.Read(testBytes); n != cap(testBytes) || err != nil { - t.Fatalf("could not read enough bytes: err=%v n=%d", err, n) - } + + n, err := rand.Read(testBytes) + require.NoErrorf(t, err, "read %d random bytes", len(testBytes)) + require.Equal(t, len(testBytes), n, "read unexpected number of bytes") + test := string(testBytes) for flag := VisFlag(0); flag <= visMask; flag++ { - // VisNoSlash is frankly just a dumb flag, and it is impossible for us - // to actually preserve things in a round-trip. + // VisNoSlash is frankly just a dumb flag, and it is impossible + // for us to actually preserve things in a round-trip. if flag&VisNoSlash == VisNoSlash { continue } enc, err := Vis(test, flag) - if err != nil { - t.Errorf("unexpected error doing vis(%q, %b): %s", test, flag, err) - continue - } + require.NoErrorf(t, err, "vis(%q, %s)", test, flag) + dec, err := Unvis(enc, flag) - if err != nil { - t.Errorf("unexpected error doing unvis(%q, %b): %s", enc, flag, err) + require.NoErrorf(t, err, "unvis(%q, %s)", enc, flag) + + if !assert.Equalf(t, test, dec, "unvis(vis(%q, %b) = %q, %b) round-trip", test, flag, enc, flag) { continue } - if dec != test { - t.Errorf("roundtrip failed: unvis(vis(%q, %b) = %q, %b) = %q", test, flag, enc, flag, dec) - } } } } @@ -66,93 +66,88 @@ func TestRandomVisVisUnvisUnvis(t *testing.T) { for i := 0; i < N; i++ { testBytes := make([]byte, 256) - if n, err := rand.Read(testBytes); n != cap(testBytes) || err != nil { - t.Fatalf("could not read enough bytes: err=%v n=%d", err, n) - } + + n, err := rand.Read(testBytes) + require.NoErrorf(t, err, "read %d random bytes", len(testBytes)) + require.Equal(t, len(testBytes), n, "read unexpected number of bytes") + test := string(testBytes) for flag := VisFlag(0); flag <= visMask; flag++ { - // VisNoSlash is frankly just a dumb flag, and it is impossible for us - // to actually preserve things in a round-trip. + // VisNoSlash is frankly just a dumb flag, and it is impossible + // for us to actually preserve things in a round-trip. if flag&VisNoSlash == VisNoSlash { continue } enc, err := Vis(test, flag) - if err != nil { - t.Errorf("unexpected error doing vis(%q, %b): %s", test, flag, err) - continue - } + require.NoErrorf(t, err, "vis(%q, %s)", test, flag) + enc2, err := Vis(enc, flag) - if err != nil { - t.Errorf("unexpected error doing vis(%q, %b): %s", enc, flag, err) + require.NoErrorf(t, err, "vis(%q, %s)", enc, flag) + + dec2, err := Unvis(enc2, flag) + require.NoErrorf(t, err, "unvis(%q, %s)", enc2, flag) + + dec, err := Unvis(dec2, flag) + require.NoErrorf(t, err, "unvis(%q, %s)", dec2, flag) + + if !assert.Equalf(t, test, dec, "unvis(unvis(vis(vis(%q) = %q) = %q) = %q, %b) round-trip", test, enc, enc2, dec2, flag) { continue } - dec, err := Unvis(enc2, flag) - if err != nil { - t.Errorf("unexpected error doing unvis(%q, %b): %s", enc2, flag, err) - continue - } - dec2, err := Unvis(dec, flag) - if err != nil { - t.Errorf("unexpected error doing unvis(%q, %b): %s", dec, flag, err) - continue - } - if dec2 != test { - t.Errorf("roundtrip failed: unvis(unvis(vis(vis(%q) = %q) = %q) = %q, %b) = %q", test, enc, enc2, dec, flag, dec2) - } } } } func TestVisUnvis(t *testing.T) { - for flag := VisFlag(0); flag <= visMask; flag++ { - // VisNoSlash is frankly just a dumb flag, and it is impossible for us - // to actually preserve things in a round-trip. - if flag&VisNoSlash == VisNoSlash { - continue - } + // Round-trip testing. + for _, test := range []struct { + name string + input string + }{ + {"Empty", ""}, + {"Plain", "hello world"}, + {"Backslash", "THIS\\IS_A_TEST1234"}, + {"Punctuation", "this.is.a.normal_string"}, + {"Unicode1", "AC_Ra\u00edz_Certic\u00e1mara_S.A..pem"}, + {"Unicode2", "NetLock_Arany_=Class_Gold=_F\u0151tan\u00fas\u00edtv\u00e1ny.pem"}, + {"Unicode3", "T\u00dcB\u0130TAK_UEKAE_K\u00f6k_Sertifika_Hizmet_Sa\u011flay\u0131c\u0131s\u0131_-_S\u00fcr\u00fcm_3.pem"}, + {"ExtraPunctuation", "hello world [ this string needs=enco ding! ]"}, + {"Whitespace", "even \n more encoding necessary\a\a "}, + {"WeirdChars", "\024 <-- some more weird characters --> \u4f60\u597d\uff0c\u4e16\u754c"}, + {"DoubleEncoding", "\\xff\\n double encoding is also great fun \\x"}, + {"Unicode1-Encoded", "AC_Ra\\M-C\\M--z_Certic\\M-C\\M-!mara_S.A..pem"}, + {"Rand1", "z^i3i$\u00d3\u008anqgh5/t\u00e5<86>\u00b2kzla\\e^lv\u00df\u0093nv\u00df\u00aea|3}\u00d8\u0088\u00d6\u0084"}, + {"Rand2", `z^i3i$\M-C\M^S\M-B\M^Jnqgh5/t\M-C\M-%<86>\M-B\M-2kzla\\e^lv\M-C\M^_\M-B\M^Snv\M-C\M^_\M-B\M-.a|3}\M-C\M^X\M-B\M^H\M-C\M^V\M-B\M^D`}, + {"Rand3", "@?e1xs+.R_Kjo]7s8pgRP:*nXCE4{!c"}, + {"Rand4", "62_\u00c6\u00c62\u00ae\u00b7m\u00db\u00c3r^\u00bfp\u00c6u'q\u00fbc2\u00f0u\u00b8\u00dd\u00e8v\u00ff\u00b0\u00dc\u00c2\u00f53\u00db-k\u00f2sd4\\p\u00da\u00a6\u00d3\u00eea<\u00e6s{\u00a0p\u00f0\u00ffj\u00e0\u00e8\u00b8\u00b8\u00bc\u00fcb"}, + {"Rand4-Encoded", `62_\M-C\M^F\M-C\M^F2\M-B\M-.\M-B\M-7m\M-C\M^[\M-C\M^Cr^\M-B\M-?p\M-C\M^Fu'q\M-C\M-;c2\M-C\M-0u\M-B\M-8\M-C\M^]\M-C\M-(v\M-C\M-?\M-B\M-0\M-C\M^\\M-C\M^B\M-C\M-53\M-C\M^[-k\M-C\M-2sd4\\p\M-C\M^Z\M-B\M-&\M-C\M^S\M-C\M-.a<\M-C\M-&s{\M-B\240p\M-C\M-0\M-C\M-?j\M-C\240\M-C\M-(\M-B\M-8\M-B\M-8\M-B\M-<\M-C\M- \u4f60\u597d\uff0c\u4e16\u754c", - "\\xff\\n double encoding is also great fun \\x", - "AC_Ra\\M-C\\M--z_Certic\\M-C\\M-!mara_S.A..pem", - "z^i3i$\u00d3\u008anqgh5/t\u00e5<86>\u00b2kzla\\e^lv\u00df\u0093nv\u00df\u00aea|3}\u00d8\u0088\u00d6\u0084", - `z^i3i$\M-C\M^S\M-B\M^Jnqgh5/t\M-C\M-%<86>\M-B\M-2kzla\\e^lv\M-C\M^_\M-B\M^Snv\M-C\M^_\M-B\M-.a|3}\M-C\M^X\M-B\M^H\M-C\M^V\M-B\M^D`, - "@?e1xs+.R_Kjo]7s8pgRP:*nXCE4{!c", - "62_\u00c6\u00c62\u00ae\u00b7m\u00db\u00c3r^\u00bfp\u00c6u'q\u00fbc2\u00f0u\u00b8\u00dd\u00e8v\u00ff\u00b0\u00dc\u00c2\u00f53\u00db-k\u00f2sd4\\p\u00da\u00a6\u00d3\u00eea<\u00e6s{\u00a0p\u00f0\u00ffj\u00e0\u00e8\u00b8\u00b8\u00bc\u00fcb", - `62_\M-C\M^F\M-C\M^F2\M-B\M-.\M-B\M-7m\M-C\M^[\M-C\M^Cr^\M-B\M-?p\M-C\M^Fu'q\M-C\M-;c2\M-C\M-0u\M-B\M-8\M-C\M^]\M-C\M-(v\M-C\M-?\M-B\M-0\M-C\M^\\M-C\M^B\M-C\M-53\M-C\M^[-k\M-C\M-2sd4\\p\M-C\M^Z\M-B\M-&\M-C\M^S\M-C\M-.a<\M-C\M-&s{\M-B\240p\M-C\M-0\M-C\M-?j\M-C\240\M-C\M-(\M-B\M-8\M-B\M-8\M-B\M-<\M-C\M-