common.amp.armor_test.go Maven / Gradle / Ivy
The newest version!
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 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 0aGVsbG8gd29
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 0aGVsbG8gd29
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
}
}
}