github.com/shogo82148/goa-v1@v1.6.2/goagen/codegen/types_test.go (about) 1 package codegen_test 2 3 import ( 4 "fmt" 5 "strings" 6 7 . "github.com/onsi/ginkgo" 8 . "github.com/onsi/gomega" 9 "github.com/shogo82148/goa-v1/design" 10 "github.com/shogo82148/goa-v1/design/apidsl" 11 "github.com/shogo82148/goa-v1/dslengine" 12 "github.com/shogo82148/goa-v1/goagen/codegen" 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 connectives 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 connectives 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 *design.AttributeDefinition 181 var object design.Object 182 var required *dslengine.ValidationDefinition 183 var st string 184 185 JustBeforeEach(func() { 186 att = new(design.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 = design.Object{ 197 "foo": &design.AttributeDefinition{Type: design.Integer}, 198 "bar": &design.AttributeDefinition{Type: design.String}, 199 "baz": &design.AttributeDefinition{Type: design.DateTime}, 200 "qux": &design.AttributeDefinition{Type: design.UUID}, 201 "quz": &design.AttributeDefinition{Type: design.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 := &design.AttributeDefinition{Type: design.Integer} 303 keyType := &design.AttributeDefinition{Type: design.Integer} 304 hash := &design.Hash{KeyType: keyType, ElemType: elemType} 305 object = design.Object{ 306 "foo": &design.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 := &design.AttributeDefinition{Type: design.Integer} 319 array := &design.Array{ElemType: elemType} 320 object = design.Object{ 321 "foo": &design.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 := design.Object{ 334 "elemAtt": &design.AttributeDefinition{Type: design.Integer}, 335 } 336 key := design.Object{ 337 "keyAtt": &design.AttributeDefinition{Type: design.String}, 338 } 339 elemType := &design.AttributeDefinition{Type: elem} 340 keyType := &design.AttributeDefinition{Type: key} 341 hash := &design.Hash{KeyType: keyType, ElemType: elemType} 342 object = design.Object{ 343 "foo": &design.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 := design.Object{ 363 "bar": &design.AttributeDefinition{Type: design.Integer}, 364 } 365 elemType := &design.AttributeDefinition{Type: obj} 366 array := &design.Array{ElemType: elemType} 367 object = design.Object{ 368 "foo": &design.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 = design.Object{ 403 "foo": &design.AttributeDefinition{Type: design.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 *design.AttributeDefinition 422 var source string 423 424 JustBeforeEach(func() { 425 array := &design.Array{ElemType: elemType} 426 att := &design.AttributeDefinition{Type: array} 427 source = codegen.GoTypeDef(att, 0, true, false) 428 }) 429 430 Context("of primitive type", func() { 431 BeforeEach(func() { 432 elemType = &design.AttributeDefinition{Type: design.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 := design.Object{ 444 "foo": &design.AttributeDefinition{Type: design.Integer}, 445 "bar": &design.AttributeDefinition{Type: design.String}, 446 } 447 elemType = &design.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 *design.AttributeDefinition 458 var object design.Object 459 var required *dslengine.ValidationDefinition 460 var st string 461 462 JustBeforeEach(func() { 463 att = new(design.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 = design.Object{ 474 "foo": &design.AttributeDefinition{Type: design.Integer}, 475 "bar": &design.AttributeDefinition{Type: design.String}, 476 "baz": &design.AttributeDefinition{Type: design.DateTime}, 477 "qux": &design.AttributeDefinition{Type: design.UUID}, 478 "quz": &design.AttributeDefinition{Type: design.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 := &design.AttributeDefinition{Type: design.Integer} 516 keyType := &design.AttributeDefinition{Type: design.Integer} 517 hash := &design.Hash{KeyType: keyType, ElemType: elemType} 518 object = design.Object{ 519 "foo": &design.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 := &design.AttributeDefinition{Type: design.Integer} 532 array := &design.Array{ElemType: elemType} 533 object = design.Object{ 534 "foo": &design.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 = design.Object{ 547 "foo": &design.AttributeDefinition{Type: design.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 *design.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 = apidsl.Type("Source", func() { 584 apidsl.Attribute(attName) 585 }) 586 target = apidsl.Type("Target", func() { 587 apidsl.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 = apidsl.Type("Source", func() { 606 apidsl.Attribute("foo", func() { 607 apidsl.Metadata(codegen.TransformMapKey, mapKey) 608 }) 609 }) 610 target = apidsl.Type("Target", func() { 611 apidsl.Attribute("bar", func() { 612 apidsl.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 = apidsl.Type("Source", func() { 632 apidsl.Attribute(attName, apidsl.ArrayOf(design.Integer)) 633 }) 634 target = apidsl.Type("Target", func() { 635 apidsl.Attribute(attName, apidsl.ArrayOf(design.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 := apidsl.Type("elem", func() { 657 apidsl.Attribute("foo", design.Integer) 658 apidsl.Attribute("bar") 659 }) 660 source = apidsl.Type("Source", func() { 661 apidsl.Attribute(attName, apidsl.HashOf(design.String, elem)) 662 }) 663 target = apidsl.Type("Target", func() { 664 apidsl.Attribute(attName, apidsl.HashOf(design.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 BeforeEach(func() { 690 inner := apidsl.Type("inner", func() { 691 apidsl.Attribute("foo", design.Integer) 692 }) 693 outer := apidsl.Type("outer", func() { 694 apidsl.Attribute("in", inner) 695 }) 696 array := apidsl.Type("array", func() { 697 apidsl.Attribute("elem", apidsl.ArrayOf(outer)) 698 }) 699 hash := apidsl.Type("hash", func() { 700 apidsl.Attribute("elem", apidsl.HashOf(design.Integer, outer)) 701 }) 702 source = apidsl.Type("Source", func() { 703 apidsl.Attribute("outer", outer) 704 apidsl.Attribute("array", array) 705 apidsl.Attribute("hash", hash) 706 }) 707 target = apidsl.Type("Target", func() { 708 apidsl.Attribute("outer", outer) 709 apidsl.Attribute("array", array) 710 apidsl.Attribute("hash", hash) 711 }) 712 funcName = "Transform" 713 }) 714 715 It("generates the proper assignments", func() { 716 Ω(transform).Should(Equal(`func Transform(source *Source) (target *Target) { 717 target = new(Target) 718 target.Array = new(Array) 719 target.Array.Elem = make([]*Outer, len(source.Array.Elem)) 720 for i, v := range source.Array.Elem { 721 target.Array.Elem[i] = new(Outer) 722 target.Array.Elem[i].In = new(Inner) 723 target.Array.Elem[i].In.Foo = source.Array.Elem[i].In.Foo 724 } 725 target.Hash = new(Hash) 726 target.Hash.Elem = make(map[int]*Outer, len(source.Hash.Elem)) 727 for k, v := range source.Hash.Elem { 728 var tk int 729 tk = k 730 var tv *Outer 731 tv = new(Outer) 732 tv.In = new(Inner) 733 tv.In.Foo = v.In.Foo 734 target.Hash.Elem[tk] = tv 735 } 736 target.Outer = new(Outer) 737 target.Outer.In = new(Inner) 738 target.Outer.In.Foo = source.Outer.In.Foo 739 return 740 } 741 `)) 742 }) 743 }) 744 }) 745 746 var _ = Describe("GoTypeDesc", func() { 747 Context("With a type with a description", func() { 748 var description string 749 var ut *design.UserTypeDefinition 750 751 var desc string 752 753 BeforeEach(func() { 754 description = "foo" 755 }) 756 757 JustBeforeEach(func() { 758 ut = &design.UserTypeDefinition{AttributeDefinition: &design.AttributeDefinition{Description: description}} 759 desc = codegen.GoTypeDesc(ut, false) 760 }) 761 762 It("uses the description", func() { 763 Ω(desc).Should(Equal(description)) 764 }) 765 766 Context("containing newlines", func() { 767 BeforeEach(func() { 768 description = "foo\nbar" 769 }) 770 771 It("escapes the new lines", func() { 772 Ω(desc).Should(Equal(strings.Replace(description, "\n", "\n// ", -1))) 773 }) 774 }) 775 }) 776 })