package amp import ( "io" "math/rand" "strings" "testing" ) func armorDecodeToString(src string) (string, error) { dec, err := NewArmorDecoder(strings.NewReader(src)) if err != nil { return "", err } p, err := io.ReadAll(dec) return string(p), err } func TestArmorDecoder(t *testing.T) { for _, test := range []struct { input string expectedOutput string expectedErr bool }{ {`
0`, "", false, }, {`
0aGVsbG8gd29ybGQK`, "hello world\n", false, }, // bad version indicator {`
1aGVsbG8gd29ybGQK`, "", true, }, // text outside
elements {` 0aGVsbG8gd29ybGQK blah blah blah0aGVsbG8gd29ybGQK0aGVsbG8gd29ybGQK blah blah blah `, "hello world\n", false, }, {`0QUJDREV GR0hJSkt MTU5PUFF SU1RVVldjunkYWVowMTI zNDU2Nzg 5Cg ==`, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n", false, }, // noelements, hence no version indicator {` aGVsbG8gd29ybGQK blah blah blah aGVsbG8gd29ybGQK aGVsbG8gd29ybGQK blah blah blah `, "", true, }, // emptyelements, hence no version indicator {` aGVsbG8gd29ybGQK blah blah blahaGVsbG8gd29ybGQK aGVsbG8gd29ybGQK blah blah blah `, "", true, }, // other elements inside{ "blah{ "blah0aGVsb", "hello world\n", false, }, // HTML comment { "blah ", "", true, }, // all kinds of ASCII whitespace { "blahG8gd29
ybGQK\x200\x09aG\x0aV\x0csb\x0dG8\x20gd29ybGQK", "hello world\n", false, }, // bad padding {`0QUJDREV GR0hJSkt MTU5PUFF SU1RVVldjunkYWVowMTI zNDU2Nzg 5Cg =`, "", true, }, /* // per-chunk base64 // test disabled because Go stdlib handles this incorrectly: // https://github.com/golang/go/issues/31626 { "QQ==Qg==", "", true, }, */ // missing0aGVsbG8gd29ybGQK", "", true, }, // nested{ "blah0aGVsb", "", true, }, } { output, err := armorDecodeToString(test.input) if test.expectedErr && err == nil { t.Errorf("%+q → (%+q, %v), expected error", test.input, output, err) continue } if !test.expectedErr && err != nil { t.Errorf("%+q → (%+q, %v), expected no error", test.input, output, err) continue } if !test.expectedErr && output != test.expectedOutput { t.Errorf("%+q → (%+q, %v), expected (%+q, %v)", test.input, output, err, test.expectedOutput, nil) continue } } } func armorRoundTrip(s string) (string, error) { var encoded strings.Builder enc, err := NewArmorEncoder(&encoded) if err != nil { return "", err } _, err = io.Copy(enc, strings.NewReader(s)) if err != nil { return "", err } err = enc.Close() if err != nil { return "", err } return armorDecodeToString(encoded.String()) } func TestArmorRoundTrip(t *testing.T) { lengths := make([]int, 0) // Test short strings and lengths around elementSizeLimit thresholds. for i := 0; i < bytesPerChunk*2; i++ { lengths = append(lengths, i) } for i := -10; i < +10; i++ { lengths = append(lengths, elementSizeLimit+i) lengths = append(lengths, 2*elementSizeLimit+i) } for _, n := range lengths { buf := make([]byte, n) rand.Read(buf) input := string(buf) output, err := armorRoundTrip(input) if err != nil { t.Errorf("length %d → error %v", n, err) continue } if output != input { t.Errorf("length %d → %+q", n, output) continue } } }G8gd29ybGQK