github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/jsonutil/safejson/safejson_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2018 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package safejson_test
    21  
    22  import (
    23  	"encoding/json"
    24  	"testing"
    25  
    26  	"gopkg.in/check.v1"
    27  
    28  	"github.com/snapcore/snapd/jsonutil/safejson"
    29  )
    30  
    31  func Test(t *testing.T) { check.TestingT(t) }
    32  
    33  type escapeSuite struct{}
    34  
    35  var _ = check.Suite(escapeSuite{})
    36  
    37  var table = map[string]string{
    38  	"null":           "",
    39  	`"hello"`:        "hello",
    40  	`"árbol"`:        "árbol",
    41  	`"\u0020"`:       " ",
    42  	`"\uD83D\uDE00"`: "😀",
    43  	`"a\b\r\tb"`:     "ab",
    44  	`"\\\""`:         `\"`,
    45  	// escape sequences (NOTE just the control char is stripped)
    46  	`"\u001b[3mhello\u001b[m"`: "[3mhello[m",
    47  	`"a\u0080z"`:               "az",
    48  	"\"a\u0080z\"":             "az",
    49  	"\"a\u007fz\"":             "az",
    50  	"\"a\u009fz\"":             "az",
    51  	// replacement char
    52  	`"a\uFFFDb"`: "ab",
    53  	// private unicode chars
    54  	`"a\uE000b"`:       "ab",
    55  	`"a\uDB80\uDC00b"`: "ab",
    56  }
    57  
    58  func (escapeSuite) TestStrings(c *check.C) {
    59  	var u safejson.String
    60  	for j, s := range table {
    61  		comm := check.Commentf(j)
    62  		c.Assert(json.Unmarshal([]byte(j), &u), check.IsNil, comm)
    63  		c.Check(u.Clean(), check.Equals, s, comm)
    64  
    65  		c.Assert(u.UnmarshalJSON([]byte(j)), check.IsNil, comm)
    66  		c.Check(u.Clean(), check.Equals, s, comm)
    67  	}
    68  }
    69  
    70  func (escapeSuite) TestBadStrings(c *check.C) {
    71  	var u1 safejson.String
    72  
    73  	cc0 := make([][]byte, 0x20)
    74  	for i := range cc0 {
    75  		cc0[i] = []byte{'"', byte(i), '"'}
    76  	}
    77  	badesc := make([][]byte, 0, 0x7f-0x21-9)
    78  	for c := byte('!'); c <= '~'; c++ {
    79  		switch c {
    80  		case '"', '\\', '/', 'b', 'f', 'n', 'r', 't', 'u':
    81  			continue
    82  		default:
    83  			badesc = append(badesc, []byte{'"', '\\', c, '"'})
    84  		}
    85  	}
    86  
    87  	table := map[string][][]byte{
    88  		// these are from json itself (so we're not checking them):
    89  		"invalid character '.+' in string literal":     cc0,
    90  		"invalid character '.+' in string escape code": badesc,
    91  		`invalid character '.+' in \\u .*`:             {[]byte(`"\u02"`), []byte(`"\u02zz"`)},
    92  		"invalid character '\"' after top-level value": {[]byte(`"""`)},
    93  		"unexpected end of JSON input":                 {[]byte(`"\"`)},
    94  	}
    95  
    96  	for e, js := range table {
    97  		for _, j := range js {
    98  			comm := check.Commentf("%q", j)
    99  			c.Check(json.Unmarshal(j, &u1), check.ErrorMatches, e, comm)
   100  		}
   101  	}
   102  
   103  	table = map[string][][]byte{
   104  		// these are from our lib
   105  		`missing string delimiters.*`:                 {{}, {'"'}},
   106  		`unexpected control character at 0 in "\\.+"`: cc0,
   107  		`unknown escape '.' at 1 of "\\."`:            badesc,
   108  		`badly formed \\u escape.*`: {
   109  			[]byte(`"\u02"`), []byte(`"\u02zz"`), []byte(`"a\u02xxz"`),
   110  			[]byte(`"\uD83Da"`), []byte(`"\uD83Da\u20"`), []byte(`"\uD83Da\u20zzz"`),
   111  		},
   112  		`unexpected unescaped quote at 0 in """`:            {[]byte(`"""`)},
   113  		`unexpected end of string \(trailing backslash\).*`: {[]byte(`"\"`)},
   114  	}
   115  
   116  	for e, js := range table {
   117  		for _, j := range js {
   118  			comm := check.Commentf("%q", j)
   119  			c.Check(u1.UnmarshalJSON(j), check.ErrorMatches, e, comm)
   120  		}
   121  	}
   122  }
   123  
   124  func (escapeSuite) TestParagraph(c *check.C) {
   125  	var u safejson.Paragraph
   126  	for j1, v1 := range table {
   127  		for j2, v2 := range table {
   128  			if j2 == "null" && j1 != "null" {
   129  				continue
   130  			}
   131  
   132  			var j, s string
   133  
   134  			if j1 == "null" {
   135  				j = j2
   136  				s = v2
   137  			} else {
   138  				j = j1[:len(j1)-1] + "\\n" + j2[1:]
   139  				s = v1 + "\n" + v2
   140  			}
   141  
   142  			comm := check.Commentf(j)
   143  			c.Assert(json.Unmarshal([]byte(j), &u), check.IsNil, comm)
   144  			c.Check(u.Clean(), check.Equals, s, comm)
   145  		}
   146  	}
   147  
   148  }