blob: d36761f33d6d977ea48469e02304f237d730fd08 [file] [log] [blame]
// Copyright 2020 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package literal
import (
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
)
func TestQuote(t *testing.T) {
testCases := []struct {
form Form
in string
out string
lossy bool
}{
{form: String, in: "\x00", out: `"\u0000"`},
{form: String, in: "abc\xffdef", out: `"abc�def"`, lossy: true},
{form: Bytes, in: "abc\xffdef", out: `'abc\xffdef'`},
{form: String.WithASCIIOnly(),
in: "abc\xffdef", out: `"abc\ufffddef"`, lossy: true},
{form: String, in: "\a\b\f\r\n\t\v", out: `"\a\b\f\r\n\t\v"`},
{form: String, in: "\"", out: `"\""`},
{form: String, in: "\\", out: `"\\"`},
{form: String, in: "\u263a", out: `"☺"`},
{form: String, in: "\U0010ffff", out: `"\U0010ffff"`},
{form: String, in: "\x04", out: `"\u0004"`},
{form: Bytes, in: "\x04", out: `'\x04'`},
{form: String.WithASCIIOnly(), in: "\u263a", out: `"\u263a"`},
{form: String.WithGraphicOnly(), in: "\u263a", out: `"☺"`},
{
form: String.WithASCIIOnly(),
in: "!\u00a0!\u2000!\u3000!",
out: `"!\u00a0!\u2000!\u3000!"`,
},
{form: String, in: "a\nb", out: `"a\nb"`},
{form: String.WithTabIndent(3), in: "a\nb", out: `"""
a
b
"""`},
{form: String.WithTabIndent(3), in: "a", out: `"""
a
"""`},
{form: String.WithTabIndent(3), in: "a\n", out: `"""
a
"""`},
{form: String.WithTabIndent(3), in: "", out: `"""
"""`},
{form: String.WithTabIndent(3), in: "\n", out: `"""
"""`},
{form: String.WithTabIndent(3), in: "\n\n", out: `"""
"""`},
{form: String.WithOptionalTabIndent(3), in: "a", out: `"a"`},
{form: String.WithOptionalTabIndent(3), in: "a\n", out: `"""
a
"""`},
// Issue #541
{form: String.WithTabIndent(3), in: "foo\n\"bar\"", out: `"""
foo
"bar"
"""`},
{form: String.WithTabIndent(3), in: "foo\n\"\"\"bar\"", out: `#"""
foo
"""bar"
"""#`},
{form: String.WithTabIndent(3), in: "foo\n\"\"\"\"\"###bar\"", out: `####"""
foo
"""""###bar"
"""####`},
{form: String.WithTabIndent(3), in: "foo\n\"\"\"\r\f\\", out: `#"""
foo
"""\#r\#f\#\
"""#`},
{form: Bytes.WithTabIndent(3), in: "foo'''\nhello", out: `#'''
foo'''
hello
'''#`},
{form: Bytes.WithTabIndent(3), in: "foo\n'''\r\f\\", out: `#'''
foo
'''\#r\#f\#\
'''#`},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf("%q", tc.in), func(t *testing.T) {
got := tc.form.Quote(tc.in)
if got != tc.out {
t.Errorf("Quote: %s", cmp.Diff(tc.out, got))
}
got = string(tc.form.Append(nil, tc.in))
if got != tc.out {
t.Errorf("Append: %s", cmp.Diff(tc.out, got))
}
str, err := Unquote(got)
if err != nil {
t.Errorf("Roundtrip error: %v", err)
}
if !tc.lossy && str != tc.in {
t.Errorf("Quote: %s", cmp.Diff(tc.in, str))
}
})
}
}
func TestAppendEscaped(t *testing.T) {
testCases := []struct {
form Form
in string
out string
}{
{String, "a", "a"},
{String, "", ""},
{String.WithTabIndent(2), "", ""},
{String.WithTabIndent(2), "\n", "\n"},
{String.WithTabIndent(2), "a\n", "a\n"},
{String.WithTabIndent(2), "a\nb", "a\n\t\tb"},
}
for _, tc := range testCases {
t.Run(tc.in, func(t *testing.T) {
buf := tc.form.AppendEscaped(nil, tc.in)
if got := string(buf); got != tc.out {
t.Error(cmp.Diff(tc.out, got))
}
})
}
}
func BenchmarkQuote(b *testing.B) {
inputs := []string{
"aaaa",
"aaaaaaa\n\naaaaaa",
strings.Repeat("aaaaaaaaaaa\n", 1000),
}
for _, f := range []Form{
String,
Bytes,
String.WithTabIndent(3),
String.WithOptionalTabIndent(3),
} {
b.Run("", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, s := range inputs {
f.Quote(s)
}
}
})
}
}