github.com/ndau/noms@v1.0.5/go/types/encode_human_readable_test.go (about) 1 // Copyright 2016 Attic Labs, Inc. All rights reserved. 2 // Licensed under the Apache License, version 2.0: 3 // http://www.apache.org/licenses/LICENSE-2.0 4 5 package types 6 7 import ( 8 "bytes" 9 "errors" 10 "strings" 11 "testing" 12 13 "github.com/ndau/noms/go/util/test" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 func assertWriteHRSEqual(t *testing.T, expected string, v Value) { 18 assert := assert.New(t) 19 var buf bytes.Buffer 20 w := &hrsWriter{w: &buf, floatFormat: 'g'} 21 w.Write(v) 22 assert.Equal(test.RemoveHashes(expected), test.RemoveHashes(buf.String())) 23 } 24 25 func TestWriteHumanReadablePrimitiveValues(t *testing.T) { 26 assertWriteHRSEqual(t, "true", Bool(true)) 27 assertWriteHRSEqual(t, "false", Bool(false)) 28 29 assertWriteHRSEqual(t, "0", Number(0)) 30 assertWriteHRSEqual(t, "42", Number(42)) 31 32 assertWriteHRSEqual(t, "-42", Number(-42)) 33 34 assertWriteHRSEqual(t, "3.1415926535", Number(3.1415926535)) 35 assertWriteHRSEqual(t, "314159.26535", Number(3.1415926535e5)) 36 assertWriteHRSEqual(t, "3.1415926535e+20", Number(3.1415926535e20)) 37 38 assertWriteHRSEqual(t, `"abc"`, String("abc")) 39 assertWriteHRSEqual(t, `" "`, String(" ")) 40 assertWriteHRSEqual(t, `"\t"`, String("\t")) 41 assertWriteHRSEqual(t, `"\t"`, String(" ")) 42 assertWriteHRSEqual(t, `"\n"`, String("\n")) 43 assertWriteHRSEqual(t, `"\n"`, String(` 44 `)) 45 assertWriteHRSEqual(t, `"\r"`, String("\r")) 46 assertWriteHRSEqual(t, `"\r\n"`, String("\r\n")) 47 assertWriteHRSEqual(t, `"\xff"`, String("\xff")) 48 assertWriteHRSEqual(t, `"💩"`, String("\xf0\x9f\x92\xa9")) 49 assertWriteHRSEqual(t, `"💩"`, String("💩")) 50 assertWriteHRSEqual(t, `"\a"`, String("\007")) 51 assertWriteHRSEqual(t, `"☺"`, String("\u263a")) 52 } 53 54 func TestWriteHumanReadableRef(t *testing.T) { 55 vs := newTestValueStore() 56 57 x := Number(42) 58 rv := vs.WriteValue(x) 59 assertWriteHRSEqual(t, "#0123456789abcdefghijklmnopqrstuv", rv) 60 } 61 62 func TestWriteHumanReadableCollections(t *testing.T) { 63 vrw := newTestValueStore() 64 65 l := NewList(vrw, Number(0), Number(1), Number(2), Number(3)) 66 assertWriteHRSEqual(t, "[ // 4 items\n 0,\n 1,\n 2,\n 3,\n]", l) 67 68 s := NewSet(vrw, Number(0), Number(1), Number(2), Number(3)) 69 assertWriteHRSEqual(t, "set { // 4 items\n 0,\n 1,\n 2,\n 3,\n}", s) 70 71 m := NewMap(vrw, Number(0), Bool(false), Number(1), Bool(true)) 72 assertWriteHRSEqual(t, "map {\n 0: false,\n 1: true,\n}", m) 73 74 l2 := NewList(vrw) 75 assertWriteHRSEqual(t, "[]", l2) 76 77 l3 := NewList(vrw, Number(0)) 78 assertWriteHRSEqual(t, "[\n 0,\n]", l3) 79 80 nums := make([]Value, 2000) 81 for i := range nums { 82 nums[i] = Number(0) 83 } 84 l4 := NewList(vrw, nums...) 85 assertWriteHRSEqual(t, "[ // 2,000 items\n"+strings.Repeat(" 0,\n", 2000)+"]", l4) 86 } 87 88 func TestWriteHumanReadableNested(t *testing.T) { 89 vrw := newTestValueStore() 90 91 l := NewList(vrw, Number(0), Number(1)) 92 l2 := NewList(vrw, Number(2), Number(3)) 93 94 s := NewSet(vrw, String("a"), String("b")) 95 s2 := NewSet(vrw, String("c"), String("d")) 96 97 m := NewMap(vrw, s, l, s2, l2) 98 assertWriteHRSEqual(t, `map { 99 set { 100 "c", 101 "d", 102 }: [ 103 2, 104 3, 105 ], 106 set { 107 "a", 108 "b", 109 }: [ 110 0, 111 1, 112 ], 113 }`, m) 114 } 115 116 func TestWriteHumanReadableStruct(t *testing.T) { 117 str := NewStruct("S1", StructData{ 118 "x": Number(1), 119 "y": Number(2), 120 }) 121 assertWriteHRSEqual(t, "struct S1 {\n x: 1,\n y: 2,\n}", str) 122 } 123 124 func TestWriteHumanReadableListOfStruct(t *testing.T) { 125 vrw := newTestValueStore() 126 127 str1 := NewStruct("S3", StructData{ 128 "x": Number(1), 129 }) 130 str2 := NewStruct("S3", StructData{ 131 "x": Number(2), 132 }) 133 str3 := NewStruct("S3", StructData{ 134 "x": Number(3), 135 }) 136 l := NewList(vrw, str1, str2, str3) 137 assertWriteHRSEqual(t, `[ 138 struct S3 { 139 x: 1, 140 }, 141 struct S3 { 142 x: 2, 143 }, 144 struct S3 { 145 x: 3, 146 }, 147 ]`, l) 148 } 149 150 func TestWriteHumanReadableBlob(t *testing.T) { 151 vrw := newTestValueStore() 152 assertWriteHRSEqual(t, "blob {}", NewEmptyBlob(vrw)) 153 154 b1 := NewBlob(vrw, bytes.NewBuffer([]byte{0x01})) 155 assertWriteHRSEqual(t, "blob {01}", b1) 156 157 b2 := NewBlob(vrw, bytes.NewBuffer([]byte{0x01, 0x02})) 158 assertWriteHRSEqual(t, "blob {01 02}", b2) 159 160 b3 := NewBlob(vrw, bytes.NewBuffer([]byte{ 161 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 162 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 163 })) 164 assertWriteHRSEqual(t, "blob {00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f}", b3) 165 166 b4 := NewBlob(vrw, bytes.NewBuffer([]byte{ 167 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 168 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 169 0x10, 170 })) 171 assertWriteHRSEqual(t, "blob { // 17 B\n 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n 10\n}", b4) 172 173 bs := make([]byte, 256) 174 for i := range bs { 175 bs[i] = byte(i) 176 } 177 178 b5 := NewBlob(vrw, bytes.NewBuffer(bs)) 179 assertWriteHRSEqual(t, "blob { // 256 B\n 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f\n 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f\n 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f\n 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f\n 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f\n 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f\n 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f\n 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f\n 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f\n a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af\n b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf\n c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf\n d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df\n e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef\n f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff\n}", b5) 180 181 b6 := NewBlob(vrw, bytes.NewBuffer(make([]byte, 16*100))) 182 row := " " + strings.Repeat("00 ", 15) + "00\n" 183 s := strings.Repeat(row, 100) 184 assertWriteHRSEqual(t, "blob { // 1.6 kB\n"+s+"}", b6) 185 } 186 187 func TestWriteHumanReadableListOfBlob(t *testing.T) { 188 vrw := newTestValueStore() 189 190 b1 := NewBlob(vrw, bytes.NewBuffer([]byte{0x01})) 191 b2 := NewBlob(vrw, bytes.NewBuffer([]byte{0x02})) 192 b3 := NewBlob(vrw, bytes.NewBuffer([]byte{ 193 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 194 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 195 0x10, 196 })) 197 l := NewList(vrw, b1, NewEmptyBlob(vrw), b2, b3) 198 assertWriteHRSEqual(t, "[ // 4 items\n blob {01},\n blob {},\n blob {02},\n blob { // 17 B\n 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n 10\n },\n]", l) 199 } 200 201 func TestWriteHumanReadableType(t *testing.T) { 202 assertWriteHRSEqual(t, "Bool", BoolType) 203 assertWriteHRSEqual(t, "Blob", BlobType) 204 assertWriteHRSEqual(t, "String", StringType) 205 assertWriteHRSEqual(t, "Number", NumberType) 206 207 assertWriteHRSEqual(t, "List<Number>", MakeListType(NumberType)) 208 assertWriteHRSEqual(t, "Set<Number>", MakeSetType(NumberType)) 209 assertWriteHRSEqual(t, "Ref<Number>", MakeRefType(NumberType)) 210 assertWriteHRSEqual(t, "Map<Number, String>", MakeMapType(NumberType, StringType)) 211 assertWriteHRSEqual(t, "Number | String", MakeUnionType(NumberType, StringType)) 212 assertWriteHRSEqual(t, "Bool", MakeUnionType(BoolType)) 213 assertWriteHRSEqual(t, "", MakeUnionType()) 214 assertWriteHRSEqual(t, "List<Number | String>", MakeListType(MakeUnionType(NumberType, StringType))) 215 assertWriteHRSEqual(t, "List<>", MakeListType(MakeUnionType())) 216 } 217 218 func TestRecursiveStruct(t *testing.T) { 219 // struct A { 220 // b: A 221 // c: List<A> 222 // d: struct D { 223 // e: D 224 // f: A 225 // } 226 // } 227 228 a := MakeStructType("A", 229 StructField{"b", MakeCycleType("A"), false}, 230 StructField{"c", MakeListType(MakeCycleType("A")), false}, 231 StructField{"d", MakeStructType("D", 232 StructField{"e", MakeCycleType("D"), false}, 233 StructField{"f", MakeCycleType("A"), false}, 234 ), false}, 235 ) 236 237 assertWriteHRSEqual(t, `Struct A { 238 b: Cycle<A>, 239 c: List<Cycle<A>>, 240 d: Struct D { 241 e: Cycle<D>, 242 f: Cycle<A>, 243 }, 244 }`, a) 245 246 d, _ := a.Desc.(StructDesc).Field("d") 247 248 assertWriteHRSEqual(t, `Struct D { 249 e: Cycle<D>, 250 f: Struct A { 251 b: Cycle<A>, 252 c: List<Cycle<A>>, 253 d: Cycle<D>, 254 }, 255 }`, d) 256 } 257 258 func TestUnresolvedRecursiveStruct(t *testing.T) { 259 // struct A { 260 // a: A 261 // b: Cycle<1> (unresolved) 262 // } 263 a := MakeStructType("A", 264 StructField{"a", MakeCycleType("A"), false}, 265 StructField{"b", MakeCycleType("X"), false}, 266 ) 267 268 assertWriteHRSEqual(t, `Struct A { 269 a: Cycle<A>, 270 b: UnresolvedCycle<X>, 271 }`, a) 272 } 273 274 type errorWriter struct { 275 err error 276 } 277 278 func (w *errorWriter) Write(p []byte) (int, error) { 279 return 0, w.err 280 } 281 282 func TestWriteHumanReadableWriterError(t *testing.T) { 283 assert := assert.New(t) 284 err := errors.New("test") 285 w := &errorWriter{err} 286 assert.Equal(err, WriteEncodedValue(w, Number(42))) 287 } 288 289 func TestEmptyCollections(t *testing.T) { 290 vrw := newTestValueStore() 291 292 a := MakeStructType("Nothing") 293 assertWriteHRSEqual(t, "Struct Nothing {}", a) 294 b := NewStruct("Rien", StructData{}) 295 assertWriteHRSEqual(t, "struct Rien {}", b) 296 c := MakeMapType(BlobType, NumberType) 297 assertWriteHRSEqual(t, "Map<Blob, Number>", c) 298 d := NewMap(vrw) 299 assertWriteHRSEqual(t, "map {}", d) 300 e := MakeSetType(StringType) 301 assertWriteHRSEqual(t, "Set<String>", e) 302 f := NewSet(vrw) 303 assertWriteHRSEqual(t, "set {}", f) 304 } 305 306 func TestEncodedValueMaxLines(t *testing.T) { 307 assert := assert.New(t) 308 vrw := newTestValueStore() 309 310 l1 := NewList(vrw, generateNumbersAsValues(11)...) 311 expected := strings.Join(strings.SplitAfterN(EncodedValue(l1), "\n", 6)[:5], "") 312 assert.Equal(expected, EncodedValueMaxLines(l1, 5)) 313 314 buf := bytes.Buffer{} 315 WriteEncodedValueMaxLines(&buf, l1, 5) 316 assert.Equal(expected, buf.String()) 317 } 318 319 func TestWriteHumanReadableStructOptionalFields(t *testing.T) { 320 typ := MakeStructType("S1", 321 StructField{"a", BoolType, false}, 322 StructField{"b", BoolType, true}) 323 assertWriteHRSEqual(t, "Struct S1 {\n a: Bool,\n b?: Bool,\n}", typ) 324 } 325 326 type TestCommenter struct { 327 prefix string 328 testType *Type 329 } 330 331 func (c TestCommenter) Comment(v Value) string { 332 if !(v.typeOf().Equals(c.testType)) { 333 return "" 334 } 335 return c.prefix + string(v.(Struct).Get("Name").(String)) 336 } 337 338 func TestRegisterCommenter(t *testing.T) { 339 a := assert.New(t) 340 341 tt := NewStruct("TestType1", StructData{"Name": String("abc-123")}) 342 nt := NewStruct("TestType2", StructData{"Name": String("abc-123")}) 343 344 RegisterHRSCommenter("TestType1", "mylib1", TestCommenter{prefix: "MyTest: ", testType: tt.typeOf()}) 345 346 s1 := EncodedValue(tt) 347 a.True(strings.Contains(s1, "// MyTest: abc-123")) 348 s1 = EncodedValue(nt) 349 a.False(strings.Contains(s1, "// MyTest: abc-123")) 350 351 RegisterHRSCommenter("TestType1", "mylib1", TestCommenter{prefix: "MyTest2: ", testType: tt.typeOf()}) 352 s1 = EncodedValue(tt) 353 a.True(strings.Contains(s1, "// MyTest2: abc-123")) 354 355 UnregisterHRSCommenter("TestType1", "mylib1") 356 s1 = EncodedValue(tt) 357 a.False(strings.Contains(s1, "// MyTest2: abc-123")) 358 }