github.com/blp1526/goa@v1.4.0/goagen/codegen/types_test.go (about) 1 package codegen_test 2 3 import ( 4 "fmt" 5 "strings" 6 7 . "github.com/goadesign/goa/design" 8 . "github.com/goadesign/goa/design/apidsl" 9 "github.com/goadesign/goa/dslengine" 10 "github.com/goadesign/goa/goagen/codegen" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 ) 14 15 var _ = Describe("code generation", func() { 16 BeforeEach(func() { 17 codegen.TempCount = 0 18 }) 19 20 Describe("Goify", func() { 21 Context("given a string with an initialism", func() { 22 var str, goified, expected string 23 var firstUpper bool 24 JustBeforeEach(func() { 25 goified = codegen.Goify(str, firstUpper) 26 }) 27 28 Context("with first upper false", func() { 29 BeforeEach(func() { 30 firstUpper = false 31 str = "blue_id" 32 expected = "blueID" 33 }) 34 It("creates a lowercased camelcased string", func() { 35 Ω(goified).Should(Equal(expected)) 36 }) 37 }) 38 Context("with first upper false normal identifier", func() { 39 BeforeEach(func() { 40 firstUpper = false 41 str = "blue" 42 expected = "blue" 43 }) 44 It("creates an uppercased camelcased string", func() { 45 Ω(goified).Should(Equal(expected)) 46 }) 47 }) 48 Context("with first upper false and UUID", func() { 49 BeforeEach(func() { 50 firstUpper = false 51 str = "blue_uuid" 52 expected = "blueUUID" 53 }) 54 It("creates an uppercased camelcased string", func() { 55 Ω(goified).Should(Equal(expected)) 56 }) 57 }) 58 Context("with first upper true", func() { 59 BeforeEach(func() { 60 firstUpper = true 61 str = "blue_id" 62 expected = "BlueID" 63 }) 64 It("creates an uppercased camelcased string", func() { 65 Ω(goified).Should(Equal(expected)) 66 }) 67 }) 68 Context("with first upper true and UUID", func() { 69 BeforeEach(func() { 70 firstUpper = true 71 str = "blue_uuid" 72 expected = "BlueUUID" 73 }) 74 It("creates an uppercased camelcased string", func() { 75 Ω(goified).Should(Equal(expected)) 76 }) 77 }) 78 Context("with first upper true normal identifier", func() { 79 BeforeEach(func() { 80 firstUpper = true 81 str = "blue" 82 expected = "Blue" 83 }) 84 It("creates an uppercased camelcased string", func() { 85 Ω(goified).Should(Equal(expected)) 86 }) 87 }) 88 Context("with first upper false normal identifier", func() { 89 BeforeEach(func() { 90 firstUpper = false 91 str = "Blue" 92 expected = "blue" 93 }) 94 It("creates a lowercased string", func() { 95 Ω(goified).Should(Equal(expected)) 96 }) 97 }) 98 Context("with first upper true normal identifier", func() { 99 BeforeEach(func() { 100 firstUpper = true 101 str = "Blue" 102 expected = "Blue" 103 }) 104 It("creates an uppercased string", func() { 105 Ω(goified).Should(Equal(expected)) 106 }) 107 }) 108 Context("with invalid identifier", func() { 109 BeforeEach(func() { 110 firstUpper = true 111 str = "Blue%50" 112 expected = "Blue50" 113 }) 114 It("creates an uppercased string", func() { 115 Ω(goified).Should(Equal(expected)) 116 }) 117 }) 118 119 Context("with invalid identifier firstupper false", func() { 120 BeforeEach(func() { 121 firstUpper = false 122 str = "Blue%50" 123 expected = "blue50" 124 }) 125 It("creates an uppercased string", func() { 126 Ω(goified).Should(Equal(expected)) 127 }) 128 }) 129 130 Context("with only UUID and firstupper false", func() { 131 BeforeEach(func() { 132 firstUpper = false 133 str = "UUID" 134 expected = "uuid" 135 }) 136 It("creates a lowercased string", func() { 137 Ω(goified).Should(Equal(expected)) 138 }) 139 }) 140 141 Context("with consecutives invalid identifiers", func() { 142 BeforeEach(func() { 143 firstUpper = false 144 str = "[[fields___type]]" 145 expected = "fieldsType" 146 }) 147 It("creates a camelcased string", func() { 148 Ω(goified).Should(Equal(expected)) 149 }) 150 }) 151 152 Context("with consecutives invalid identifiers", func() { 153 BeforeEach(func() { 154 firstUpper = true 155 str = "[[fields___type]]" 156 expected = "FieldsType" 157 }) 158 It("creates a camelcased string", func() { 159 Ω(goified).Should(Equal(expected)) 160 }) 161 }) 162 163 Context("with all invalid identifiers", func() { 164 BeforeEach(func() { 165 firstUpper = false 166 str = "[[" 167 expected = "" 168 }) 169 It("creates an empty string", func() { 170 Ω(goified).Should(Equal(expected)) 171 }) 172 }) 173 174 }) 175 176 }) 177 178 Describe("GoTypeDef", func() { 179 Context("given an attribute definition with fields", func() { 180 var att *AttributeDefinition 181 var object Object 182 var required *dslengine.ValidationDefinition 183 var st string 184 185 JustBeforeEach(func() { 186 att = new(AttributeDefinition) 187 att.Type = object 188 if required != nil { 189 att.Validation = required 190 } 191 st = codegen.GoTypeDef(att, 0, true, false) 192 }) 193 194 Context("of primitive types", func() { 195 BeforeEach(func() { 196 object = Object{ 197 "foo": &AttributeDefinition{Type: Integer}, 198 "bar": &AttributeDefinition{Type: String}, 199 "baz": &AttributeDefinition{Type: DateTime}, 200 "qux": &AttributeDefinition{Type: UUID}, 201 "quz": &AttributeDefinition{Type: Any}, 202 } 203 required = nil 204 }) 205 206 It("produces the struct go code", func() { 207 expected := "struct {\n" + 208 " Bar *string `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n" + 209 " Baz *time.Time `form:\"baz,omitempty\" json:\"baz,omitempty\" yaml:\"baz,omitempty\" xml:\"baz,omitempty\"`\n" + 210 " Foo *int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n" + 211 " Qux *uuid.UUID `form:\"qux,omitempty\" json:\"qux,omitempty\" yaml:\"qux,omitempty\" xml:\"qux,omitempty\"`\n" + 212 " Quz interface{} `form:\"quz,omitempty\" json:\"quz,omitempty\" yaml:\"quz,omitempty\" xml:\"quz,omitempty\"`\n" + 213 "}" 214 Ω(st).Should(Equal(expected)) 215 }) 216 217 Context("using struct tags metadata", func() { 218 tn1 := "struct:tag:foo" 219 tv11 := "bar" 220 tv12 := "baz" 221 tn2 := "struct:tag:foo2" 222 tv21 := "bar2" 223 224 BeforeEach(func() { 225 object["foo"].Metadata = dslengine.MetadataDefinition{ 226 tn1: []string{tv11, tv12}, 227 tn2: []string{tv21}, 228 } 229 }) 230 231 It("produces the struct tags", func() { 232 expected := fmt.Sprintf("struct {\n"+ 233 " Bar *string `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n"+ 234 " Baz *time.Time `form:\"baz,omitempty\" json:\"baz,omitempty\" yaml:\"baz,omitempty\" xml:\"baz,omitempty\"`\n"+ 235 " Foo *int `%s:\"%s,%s\" %s:\"%s\"`\n"+ 236 " Qux *uuid.UUID `form:\"qux,omitempty\" json:\"qux,omitempty\" yaml:\"qux,omitempty\" xml:\"qux,omitempty\"`\n"+ 237 " Quz interface{} `form:\"quz,omitempty\" json:\"quz,omitempty\" yaml:\"quz,omitempty\" xml:\"quz,omitempty\"`\n"+ 238 "}", tn1[11:], tv11, tv12, tn2[11:], tv21) 239 Ω(st).Should(Equal(expected)) 240 }) 241 }) 242 243 Context("using struct field name metadata", func() { 244 BeforeEach(func() { 245 object["foo"].Metadata = dslengine.MetadataDefinition{ 246 "struct:field:name": []string{"serviceName", "unused"}, 247 } 248 }) 249 250 It("produces the struct tags", func() { 251 expected := "struct {\n" + 252 " Bar *string `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n" + 253 " Baz *time.Time `form:\"baz,omitempty\" json:\"baz,omitempty\" yaml:\"baz,omitempty\" xml:\"baz,omitempty\"`\n" + 254 " ServiceName *int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n" + 255 " Qux *uuid.UUID `form:\"qux,omitempty\" json:\"qux,omitempty\" yaml:\"qux,omitempty\" xml:\"qux,omitempty\"`\n" + 256 " Quz interface{} `form:\"quz,omitempty\" json:\"quz,omitempty\" yaml:\"quz,omitempty\" xml:\"quz,omitempty\"`\n" + 257 "}" 258 Ω(st).Should(Equal(expected)) 259 }) 260 }) 261 262 Context("using struct field type metadata", func() { 263 BeforeEach(func() { 264 object["foo"].Metadata = dslengine.MetadataDefinition{ 265 "struct:field:type": []string{"[]byte"}, 266 } 267 }) 268 269 It("produces the struct tags", func() { 270 expected := "struct {\n" + 271 " Bar *string `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n" + 272 " Baz *time.Time `form:\"baz,omitempty\" json:\"baz,omitempty\" yaml:\"baz,omitempty\" xml:\"baz,omitempty\"`\n" + 273 " Foo *[]byte `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n" + 274 " Qux *uuid.UUID `form:\"qux,omitempty\" json:\"qux,omitempty\" yaml:\"qux,omitempty\" xml:\"qux,omitempty\"`\n" + 275 " Quz interface{} `form:\"quz,omitempty\" json:\"quz,omitempty\" yaml:\"quz,omitempty\" xml:\"quz,omitempty\"`\n" + 276 "}" 277 Ω(st).Should(Equal(expected)) 278 }) 279 }) 280 281 Context("that are required", func() { 282 BeforeEach(func() { 283 required = &dslengine.ValidationDefinition{ 284 Required: []string{"foo", "bar", "baz", "qux", "quz"}, 285 } 286 }) 287 It("produces the struct go code", func() { 288 expected := "struct {\n" + 289 " Bar string `form:\"bar\" json:\"bar\" yaml:\"bar\" xml:\"bar\"`\n" + 290 " Baz time.Time `form:\"baz\" json:\"baz\" yaml:\"baz\" xml:\"baz\"`\n" + 291 " Foo int `form:\"foo\" json:\"foo\" yaml:\"foo\" xml:\"foo\"`\n" + 292 " Qux uuid.UUID `form:\"qux\" json:\"qux\" yaml:\"qux\" xml:\"qux\"`\n" + 293 " Quz interface{} `form:\"quz\" json:\"quz\" yaml:\"quz\" xml:\"quz\"`\n" + 294 "}" 295 Ω(st).Should(Equal(expected)) 296 }) 297 }) 298 }) 299 300 Context("of hash of primitive types", func() { 301 BeforeEach(func() { 302 elemType := &AttributeDefinition{Type: Integer} 303 keyType := &AttributeDefinition{Type: Integer} 304 hash := &Hash{KeyType: keyType, ElemType: elemType} 305 object = Object{ 306 "foo": &AttributeDefinition{Type: hash}, 307 } 308 required = nil 309 }) 310 311 It("produces the struct go code", func() { 312 Ω(st).Should(Equal("struct {\n\tFoo map[int]int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n}")) 313 }) 314 }) 315 316 Context("of array of primitive types", func() { 317 BeforeEach(func() { 318 elemType := &AttributeDefinition{Type: Integer} 319 array := &Array{ElemType: elemType} 320 object = Object{ 321 "foo": &AttributeDefinition{Type: array}, 322 } 323 required = nil 324 }) 325 326 It("produces the struct go code", func() { 327 Ω(st).Should(Equal("struct {\n\tFoo []int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n}")) 328 }) 329 }) 330 331 Context("of hash of objects", func() { 332 BeforeEach(func() { 333 elem := Object{ 334 "elemAtt": &AttributeDefinition{Type: Integer}, 335 } 336 key := Object{ 337 "keyAtt": &AttributeDefinition{Type: String}, 338 } 339 elemType := &AttributeDefinition{Type: elem} 340 keyType := &AttributeDefinition{Type: key} 341 hash := &Hash{KeyType: keyType, ElemType: elemType} 342 object = Object{ 343 "foo": &AttributeDefinition{Type: hash}, 344 } 345 required = nil 346 }) 347 348 It("produces the struct go code", func() { 349 expected := "struct {\n" + 350 " Foo map[*struct {\n" + 351 " KeyAtt *string `form:\"keyAtt,omitempty\" json:\"keyAtt,omitempty\" yaml:\"keyAtt,omitempty\" xml:\"keyAtt,omitempty\"`\n" + 352 " }]*struct {\n" + 353 " ElemAtt *int `form:\"elemAtt,omitempty\" json:\"elemAtt,omitempty\" yaml:\"elemAtt,omitempty\" xml:\"elemAtt,omitempty\"`\n" + 354 " } `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n" + 355 "}" 356 Ω(st).Should(Equal(expected)) 357 }) 358 }) 359 360 Context("of array of objects", func() { 361 BeforeEach(func() { 362 obj := Object{ 363 "bar": &AttributeDefinition{Type: Integer}, 364 } 365 elemType := &AttributeDefinition{Type: obj} 366 array := &Array{ElemType: elemType} 367 object = Object{ 368 "foo": &AttributeDefinition{Type: array}, 369 } 370 required = nil 371 }) 372 373 It("produces the struct go code", func() { 374 expected := "struct {\n" + 375 " Foo []*struct {\n" + 376 " Bar *int `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n" + 377 " } `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n" + 378 "}" 379 Ω(st).Should(Equal(expected)) 380 }) 381 382 Context("that are required", func() { 383 BeforeEach(func() { 384 required = &dslengine.ValidationDefinition{ 385 Required: []string{"foo"}, 386 } 387 }) 388 389 It("produces the struct go code", func() { 390 expected := "struct {\n" + 391 " Foo []*struct {\n" + 392 " Bar *int `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n" + 393 " } `form:\"foo\" json:\"foo\" yaml:\"foo\" xml:\"foo\"`\n" + 394 "}" 395 Ω(st).Should(Equal(expected)) 396 }) 397 }) 398 }) 399 400 Context("that are required", func() { 401 BeforeEach(func() { 402 object = Object{ 403 "foo": &AttributeDefinition{Type: Integer}, 404 } 405 required = &dslengine.ValidationDefinition{ 406 Required: []string{"foo"}, 407 } 408 }) 409 410 It("produces the struct go code", func() { 411 expected := "struct {\n" + 412 " Foo int `form:\"foo\" json:\"foo\" yaml:\"foo\" xml:\"foo\"`\n" + 413 "}" 414 Ω(st).Should(Equal(expected)) 415 }) 416 }) 417 418 }) 419 420 Context("given an array", func() { 421 var elemType *AttributeDefinition 422 var source string 423 424 JustBeforeEach(func() { 425 array := &Array{ElemType: elemType} 426 att := &AttributeDefinition{Type: array} 427 source = codegen.GoTypeDef(att, 0, true, false) 428 }) 429 430 Context("of primitive type", func() { 431 BeforeEach(func() { 432 elemType = &AttributeDefinition{Type: Integer} 433 }) 434 435 It("produces the array go code", func() { 436 Ω(source).Should(Equal("[]int")) 437 }) 438 439 }) 440 441 Context("of object type", func() { 442 BeforeEach(func() { 443 object := Object{ 444 "foo": &AttributeDefinition{Type: Integer}, 445 "bar": &AttributeDefinition{Type: String}, 446 } 447 elemType = &AttributeDefinition{Type: object} 448 }) 449 450 It("produces the array go code", func() { 451 Ω(source).Should(Equal("[]*struct {\n\tBar *string `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n\tFoo *int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n}")) 452 }) 453 }) 454 }) 455 456 Context("when generating an all-optional private struct, given an attribute definition with fields", func() { 457 var att *AttributeDefinition 458 var object Object 459 var required *dslengine.ValidationDefinition 460 var st string 461 462 JustBeforeEach(func() { 463 att = new(AttributeDefinition) 464 att.Type = object 465 if required != nil { 466 att.Validation = required 467 } 468 st = codegen.GoTypeDef(att, 0, true, true) 469 }) 470 471 Context("of primitive types", func() { 472 BeforeEach(func() { 473 object = Object{ 474 "foo": &AttributeDefinition{Type: Integer}, 475 "bar": &AttributeDefinition{Type: String}, 476 "baz": &AttributeDefinition{Type: DateTime}, 477 "qux": &AttributeDefinition{Type: UUID}, 478 "quz": &AttributeDefinition{Type: Any}, 479 } 480 required = nil 481 }) 482 483 It("produces the struct go code", func() { 484 expected := "struct {\n" + 485 " Bar *string `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n" + 486 " Baz *time.Time `form:\"baz,omitempty\" json:\"baz,omitempty\" yaml:\"baz,omitempty\" xml:\"baz,omitempty\"`\n" + 487 " Foo *int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n" + 488 " Qux *uuid.UUID `form:\"qux,omitempty\" json:\"qux,omitempty\" yaml:\"qux,omitempty\" xml:\"qux,omitempty\"`\n" + 489 " Quz interface{} `form:\"quz,omitempty\" json:\"quz,omitempty\" yaml:\"quz,omitempty\" xml:\"quz,omitempty\"`\n" + 490 "}" 491 Ω(st).Should(Equal(expected)) 492 }) 493 494 Context("that are required", func() { 495 BeforeEach(func() { 496 required = &dslengine.ValidationDefinition{ 497 Required: []string{"foo", "bar", "baz", "qux", "quz"}, 498 } 499 }) 500 It("produces the struct go code", func() { 501 expected := "struct {\n" + 502 " Bar *string `form:\"bar,omitempty\" json:\"bar,omitempty\" yaml:\"bar,omitempty\" xml:\"bar,omitempty\"`\n" + 503 " Baz *time.Time `form:\"baz,omitempty\" json:\"baz,omitempty\" yaml:\"baz,omitempty\" xml:\"baz,omitempty\"`\n" + 504 " Foo *int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n" + 505 " Qux *uuid.UUID `form:\"qux,omitempty\" json:\"qux,omitempty\" yaml:\"qux,omitempty\" xml:\"qux,omitempty\"`\n" + 506 " Quz interface{} `form:\"quz,omitempty\" json:\"quz,omitempty\" yaml:\"quz,omitempty\" xml:\"quz,omitempty\"`\n" + 507 "}" 508 Ω(st).Should(Equal(expected)) 509 }) 510 }) 511 }) 512 513 Context("of hash of primitive types", func() { 514 BeforeEach(func() { 515 elemType := &AttributeDefinition{Type: Integer} 516 keyType := &AttributeDefinition{Type: Integer} 517 hash := &Hash{KeyType: keyType, ElemType: elemType} 518 object = Object{ 519 "foo": &AttributeDefinition{Type: hash}, 520 } 521 required = nil 522 }) 523 524 It("produces the struct go code", func() { 525 Ω(st).Should(Equal("struct {\n\tFoo map[int]int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n}")) 526 }) 527 }) 528 529 Context("of array of primitive types", func() { 530 BeforeEach(func() { 531 elemType := &AttributeDefinition{Type: Integer} 532 array := &Array{ElemType: elemType} 533 object = Object{ 534 "foo": &AttributeDefinition{Type: array}, 535 } 536 required = nil 537 }) 538 539 It("produces the struct go code", func() { 540 Ω(st).Should(Equal("struct {\n\tFoo []int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n}")) 541 }) 542 }) 543 544 Context("that are required", func() { 545 BeforeEach(func() { 546 object = Object{ 547 "foo": &AttributeDefinition{Type: Integer}, 548 } 549 required = &dslengine.ValidationDefinition{ 550 Required: []string{"foo"}, 551 } 552 }) 553 554 It("produces the struct go code", func() { 555 expected := "struct {\n" + 556 " Foo *int `form:\"foo,omitempty\" json:\"foo,omitempty\" yaml:\"foo,omitempty\" xml:\"foo,omitempty\"`\n" + 557 "}" 558 Ω(st).Should(Equal(expected)) 559 }) 560 }) 561 }) 562 }) 563 }) 564 565 var _ = Describe("GoTypeTransform", func() { 566 var source, target *UserTypeDefinition 567 var targetPkg, funcName string 568 569 var transform string 570 571 BeforeEach(func() { 572 dslengine.Reset() 573 }) 574 JustBeforeEach(func() { 575 err := dslengine.Run() 576 Ω(err).ShouldNot(HaveOccurred()) 577 transform, _ = codegen.GoTypeTransform(source, target, targetPkg, funcName) 578 }) 579 580 Context("transforming simple objects", func() { 581 const attName = "att" 582 BeforeEach(func() { 583 source = Type("Source", func() { 584 Attribute(attName) 585 }) 586 target = Type("Target", func() { 587 Attribute(attName) 588 }) 589 funcName = "Transform" 590 }) 591 592 It("generates a simple assignment", func() { 593 Ω(transform).Should(Equal(`func Transform(source *Source) (target *Target) { 594 target = new(Target) 595 target.Att = source.Att 596 return 597 } 598 `)) 599 }) 600 }) 601 602 Context("transforming objects with attributes with map key metadata", func() { 603 const mapKey = "key" 604 BeforeEach(func() { 605 source = Type("Source", func() { 606 Attribute("foo", func() { 607 Metadata(codegen.TransformMapKey, mapKey) 608 }) 609 }) 610 target = Type("Target", func() { 611 Attribute("bar", func() { 612 Metadata(codegen.TransformMapKey, mapKey) 613 }) 614 }) 615 funcName = "Transform" 616 }) 617 618 It("generates a simple assignment", func() { 619 Ω(transform).Should(Equal(`func Transform(source *Source) (target *Target) { 620 target = new(Target) 621 target.Bar = source.Foo 622 return 623 } 624 `)) 625 }) 626 }) 627 628 Context("transforming objects with array attributes", func() { 629 const attName = "att" 630 BeforeEach(func() { 631 source = Type("Source", func() { 632 Attribute(attName, ArrayOf(Integer)) 633 }) 634 target = Type("Target", func() { 635 Attribute(attName, ArrayOf(Integer)) 636 }) 637 funcName = "Transform" 638 }) 639 640 It("generates a simple assignment", func() { 641 Ω(transform).Should(Equal(`func Transform(source *Source) (target *Target) { 642 target = new(Target) 643 target.Att = make([]int, len(source.Att)) 644 for i, v := range source.Att { 645 target.Att[i] = source.Att[i] 646 } 647 return 648 } 649 `)) 650 }) 651 }) 652 653 Context("transforming objects with hash attributes", func() { 654 const attName = "att" 655 BeforeEach(func() { 656 elem := Type("elem", func() { 657 Attribute("foo", Integer) 658 Attribute("bar") 659 }) 660 source = Type("Source", func() { 661 Attribute(attName, HashOf(String, elem)) 662 }) 663 target = Type("Target", func() { 664 Attribute(attName, HashOf(String, elem)) 665 }) 666 funcName = "Transform" 667 }) 668 669 It("generates a simple assignment", func() { 670 Ω(transform).Should(Equal(`func Transform(source *Source) (target *Target) { 671 target = new(Target) 672 target.Att = make(map[string]*Elem, len(source.Att)) 673 for k, v := range source.Att { 674 var tk string 675 tk = k 676 var tv *Elem 677 tv = new(Elem) 678 tv.Bar = v.Bar 679 tv.Foo = v.Foo 680 target.Att[tk] = tv 681 } 682 return 683 } 684 `)) 685 }) 686 }) 687 688 Context("transforming objects with recursive attributes", func() { 689 const attName = "att" 690 BeforeEach(func() { 691 inner := Type("inner", func() { 692 Attribute("foo", Integer) 693 }) 694 outer := Type("outer", func() { 695 Attribute("in", inner) 696 }) 697 array := Type("array", func() { 698 Attribute("elem", ArrayOf(outer)) 699 }) 700 hash := Type("hash", func() { 701 Attribute("elem", HashOf(Integer, outer)) 702 }) 703 source = Type("Source", func() { 704 Attribute("outer", outer) 705 Attribute("array", array) 706 Attribute("hash", hash) 707 }) 708 target = Type("Target", func() { 709 Attribute("outer", outer) 710 Attribute("array", array) 711 Attribute("hash", hash) 712 }) 713 funcName = "Transform" 714 }) 715 716 It("generates the proper assignments", func() { 717 Ω(transform).Should(Equal(`func Transform(source *Source) (target *Target) { 718 target = new(Target) 719 target.Array = new(Array) 720 target.Array.Elem = make([]*Outer, len(source.Array.Elem)) 721 for i, v := range source.Array.Elem { 722 target.Array.Elem[i] = new(Outer) 723 target.Array.Elem[i].In = new(Inner) 724 target.Array.Elem[i].In.Foo = source.Array.Elem[i].In.Foo 725 } 726 target.Hash = new(Hash) 727 target.Hash.Elem = make(map[int]*Outer, len(source.Hash.Elem)) 728 for k, v := range source.Hash.Elem { 729 var tk int 730 tk = k 731 var tv *Outer 732 tv = new(Outer) 733 tv.In = new(Inner) 734 tv.In.Foo = v.In.Foo 735 target.Hash.Elem[tk] = tv 736 } 737 target.Outer = new(Outer) 738 target.Outer.In = new(Inner) 739 target.Outer.In.Foo = source.Outer.In.Foo 740 return 741 } 742 `)) 743 }) 744 }) 745 }) 746 747 var _ = Describe("GoTypeDesc", func() { 748 Context("With a type with a description", func() { 749 var description string 750 var ut *UserTypeDefinition 751 752 var desc string 753 754 BeforeEach(func() { 755 description = "foo" 756 }) 757 758 JustBeforeEach(func() { 759 ut = &UserTypeDefinition{AttributeDefinition: &AttributeDefinition{Description: description}} 760 desc = codegen.GoTypeDesc(ut, false) 761 }) 762 763 It("uses the description", func() { 764 Ω(desc).Should(Equal(description)) 765 }) 766 767 Context("containing newlines", func() { 768 BeforeEach(func() { 769 description = "foo\nbar" 770 }) 771 772 It("escapes the new lines", func() { 773 Ω(desc).Should(Equal(strings.Replace(description, "\n", "\n// ", -1))) 774 }) 775 }) 776 }) 777 })