package amp import ( "crypto/rand" "io" "io/ioutil" "strings" "testing" ) func armorDecodeToString(src string) (string, error) { dec, err := NewArmorDecoder(strings.NewReader(src)) if err != nil { return "", err } p, err := ioutil.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 blah
0aGVsbG8gd29ybGQK
0aGVsbG8gd29ybGQK blah blah blah `, "hello world\n", false, }, {`
0QUJDREV
GR0hJSkt
MTU5PUFF
SU1RVVld
junk
YWVowMTI
zNDU2Nzg
5Cg
=
=
`, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n", false, }, // no
 elements, hence no version indicator
		{`
aGVsbG8gd29ybGQK
blah blah blah
aGVsbG8gd29ybGQK
aGVsbG8gd29ybGQK
blah blah blah
`,
			"",
			true,
		},
		// empty 
 elements, hence no version indicator
		{`
aGVsbG8gd29ybGQK
blah blah blah
   
aGVsbG8gd29ybGQK aGVsbG8gd29ybGQK

blah blah blah
`,
			"",
			true,
		},
		// other elements inside 
		{
			"blah 
0aGVsb

G8gd29

ybGQK
", "hello world\n", false, }, // HTML comment { "blah ", "", true, }, // all kinds of ASCII whitespace { "blah
\x200\x09aG\x0aV\x0csb\x0dG8\x20gd29ybGQK
", "hello world\n", false, }, // bad padding {`
0QUJDREV
GR0hJSkt
MTU5PUFF
SU1RVVld
junk
YWVowMTI
zNDU2Nzg
5Cg
=
`, "", true, }, /* // per-chunk base64 // test disabled because Go stdlib handles this incorrectly: // https://github.com/golang/go/issues/31626 { "
QQ==
Qg==
", "", true, }, */ // missing
{ "blah
0aGVsbG8gd29ybGQK",
			"",
			true,
		},
		// nested 
		{
			"blah 
0aGVsb
G8gd29
ybGQK
", "", 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 } } }