func TestImports(t *testing.T) { g := NewGenWriter() pkg := typewriter.NewPackage("dummy", "SomePackage") typ := typewriter.Type{ Package: pkg, Name: "SomeType", Tags: typewriter.Tags{ { Name: "projections", Items: []string{"int"}, }, }, } g.Validate(typ) imports := g.Imports(typ) if !importSliceContains(imports, "errors") { t.Errorf("imports should include 'errors'") } if len(imports) > 1 { t.Errorf("imports should only include 'errors'") } // not easy to devise a test for Sort, since it requires the unexported typewriter.Type.ordered }
func TestWriteHeader(t *testing.T) { var b bytes.Buffer g := NewGenWriter() pkg := typewriter.NewPackage("dummy", "SomePackage") typ := typewriter.Type{ Package: pkg, Name: "SomeType", Tags: typewriter.Tags{ { Name: "methods", Items: []string{"All"}, }, // subset to ensure no Sort }, } g.Validate(typ) g.WriteHeader(&b, typ) if strings.Contains(b.String(), "Copyright") { t.Errorf("should not contain license info if no sort; got:\n%s", b.String()) } var b2 bytes.Buffer typ2 := typewriter.Type{ Package: pkg, Name: "SomeType", Tags: typewriter.Tags{}, // default includes sort } g.Validate(typ2) g.WriteHeader(&b2, typ2) if !strings.Contains(b2.String(), "Copyright") { t.Errorf("should contain license info if sort; got:\n%s", b2.String()) } }
func TestWrite(t *testing.T) { pkg := typewriter.NewPackage("dummy", "SomePackage") typs := []typewriter.Type{ { Package: pkg, Name: "FirstType", Tags: typewriter.Tags{}, // simple default }, { Package: pkg, Name: "SecondType", Tags: typewriter.Tags{ { Name: "projections", Items: []string{"int", "string"}, // with projections }, }, }, { Package: pkg, Name: "ThirdType", Tags: typewriter.Tags{ { Name: "methods", Items: []string{"All", "Any"}, // subsetted }, }, }, { Package: pkg, Name: "FourthType", Tags: typewriter.Tags{ { Name: "methods", Items: []string{"All", "Any"}, // subsetted }, { Name: "projections", Items: []string{"int", "string"}, // and projections }, }, }, { Package: pkg, Name: "FifthType", Tags: typewriter.Tags{ { Name: "methods", Items: []string{"Count", "Where"}, Negated: true, }, }, }, } for _, typ := range typs { var b bytes.Buffer g := NewGenWriter() g.Validate(typ) b.WriteString(fmt.Sprintf("package %s\n", pkg.Name())) g.WriteBody(&b, typ) src := b.String() fset := token.NewFileSet() _, err := parser.ParseFile(fset, "testwrite.go", src, 0) if err != nil { t.Errorf(err.Error()) } } }
func TestValidate(t *testing.T) { g := NewGenWriter() pkg := typewriter.NewPackage("dummy", "SomePackage") typ := typewriter.Type{ Package: pkg, Name: "SomeType", Tags: typewriter.Tags{}, } if g.validated[typ.String()] { t.Errorf("type should not show having been validated yet") } if err := g.ensureValidation(typ); err == nil { t.Errorf("ensure validation should return err prior to validation") } valid, err := g.Validate(typ) if !valid || err != nil { t.Errorf("type should be valid") } if !g.validated[typ.String()] { t.Errorf("type should show having been validated") } if err := g.ensureValidation(typ); err != nil { t.Errorf("ensure validation should not return err after validation") } if _, ok := g.models[typ.String()]; !ok { t.Errorf("type should appear in g.models") } if m := g.models[typ.String()]; len(m.methods) == 0 { t.Errorf("model without tags should have methods") } if m := g.models[typ.String()]; len(m.projections) != 0 { t.Errorf("model without tags should have no projections") } typ2 := typewriter.Type{ Package: pkg, Name: "SomeType2", Tags: typewriter.Tags{ typewriter.Tag{ Name: "projections", Items: []string{"int", "string"}, }, }, } valid2, err2 := g.Validate(typ2) if !valid2 || err2 != nil { t.Errorf("type should be valid") } if m := g.models[typ2.String()]; len(m.projections) == 0 { t.Errorf("model with projections tag should have projections") } typ3 := typewriter.Type{ Package: pkg, Name: "SomeType3", Tags: typewriter.Tags{ typewriter.Tag{ Name: "projections", Items: []string{"int", "Foo"}, }, }, } valid3, err3 := g.Validate(typ3) if valid3 { t.Errorf("type with unknown projection type should be invalid") } if err3 == nil { t.Errorf("type with unknown projection should return error") } if !strings.Contains(err3.Error(), "Foo") { t.Errorf("type with unknown projection type should mention the unknown projection type; got %v", err3) } if !strings.Contains(err3.Error(), typ3.Name) { t.Errorf("type with unknown projection type should mention the type on which it was declared; got %v", err3) } if m := g.models[typ2.String()]; len(m.projections) == 0 { t.Errorf("model with projections tag should have projections") } typ4 := typewriter.Type{ Package: pkg, Name: "SomeType4", Tags: typewriter.Tags{ typewriter.Tag{ Name: "methods", Items: []string{"All", "Foo"}, }, }, } valid4, err4 := g.Validate(typ4) if valid4 { t.Errorf("type with unknown method should be invalid") } if err4 == nil { t.Errorf("type with unknown method should return error") } if !strings.Contains(err4.Error(), "Foo") { t.Errorf("type with unknown method should mention the unknown projection type; got %v", err4) } if !strings.Contains(err4.Error(), typ4.Name) { t.Errorf("type with unknown method should mention the type on which it was declared; got %v", err4) } }
func TestValidate(t *testing.T) { g := NewContainerWriter() pkg := typewriter.NewPackage("dummy", "SomePackage") typ := typewriter.Type{ Package: pkg, Name: "SomeType", Tags: typewriter.Tags{}, } write, err := g.Validate(typ) if write { t.Errorf("no 'containers' tag should not write") } if err != nil { t.Error(err) } typ2 := typewriter.Type{ Package: pkg, Name: "SomeType2", Tags: typewriter.Tags{ typewriter.Tag{ Name: "containers", Items: []string{}, }, }, } write2, err2 := g.Validate(typ2) if write2 { t.Errorf("empty 'containers' tag should not write") } if err2 != nil { t.Error(err) } typ3 := typewriter.Type{ Package: pkg, Name: "SomeType3", Tags: typewriter.Tags{ typewriter.Tag{ Name: "containers", Items: []string{"List", "Foo"}, }, }, } write3, err3 := g.Validate(typ3) if !write3 { t.Errorf("'containers' tag with List should write (and ignore others)") } if err3 != nil { t.Error(err) } }
func TestEvaluateTags(t *testing.T) { typ := typewriter.Type{ Name: "TestType", Package: typewriter.NewPackage("dummy", "TestPackage"), } typ.Tags = typewriter.Tags{} standardMethods1, projectionMethods1, err1 := evaluateTags(typ) if err1 != nil { t.Errorf("empty methods should be ok, instead got '%v'", err1) } if len(standardMethods1) != len(standardTemplates.GetAllKeys()) { t.Errorf("standard methods should default to all") } if len(projectionMethods1) != 0 { t.Errorf("projection methods without projected type should be none, instead got %v", projectionMethods1) } typ.Tags = typewriter.Tags{ { Name: "methods", Items: []string{"Count", "Where"}, }, } standardMethods2, projectionMethods2, err2 := evaluateTags(typ) if err2 != nil { t.Errorf("empty methods should be ok, instead got %v", err2) } if len(standardMethods2) != 2 { t.Errorf("standard methods should be parsed") } if len(projectionMethods2) != 0 { t.Errorf("projection methods without projected typs should be none") } typ.Tags = typewriter.Tags{ { Name: "methods", Items: []string{"Count", "Unknown"}, }, } standardMethods3, projectionMethods3, err3 := evaluateTags(typ) if err3 == nil { t.Errorf("unknown method should be error") } if len(standardMethods3) != 1 { t.Errorf("standard methods (except unknown) should be 1, got %v", len(standardMethods3)) } if len(projectionMethods3) != 0 { t.Errorf("projection methods without projected types should be none") } typ.Tags = typewriter.Tags{ { Name: "projections", Items: []string{"SomeType"}, }, } standardMethods4, projectionMethods4, err4 := evaluateTags(typ) if err4 != nil { t.Errorf("projected types without subsetted methods should be ok, instead got: '%v'", err4) } if len(standardMethods4) != len(standardTemplates.GetAllKeys()) { t.Errorf("standard methods should default to all") } if len(projectionMethods4) != len(projectionTemplates.GetAllKeys()) { t.Errorf("projection methods should default to all in presence of projected types") } typ.Tags = typewriter.Tags{ { Name: "methods", Items: []string{"GroupBy"}, }, { Name: "projections", Items: []string{"SomeType"}, }, } standardMethods5, projectionMethods5, err5 := evaluateTags(typ) if err5 != nil { t.Errorf("projected types with subsetted methods should be ok, instead got: '%v'", err5) } if len(standardMethods5) != 0 { t.Errorf("standard methods should be none") } if len(projectionMethods5) != 1 { t.Errorf("projection methods should be subsetted") } typ.Tags = typewriter.Tags{ { Name: "methods", }, } standardMethods6, projectionMethods6, err6 := evaluateTags(typ) if err6 != nil { t.Errorf("empty subsetted methods should be ok, instead got: '%v'", err6) } if len(standardMethods6) != 0 { t.Errorf("standard methods should be empty when the tag is empty") } if len(projectionMethods6) != 0 { t.Errorf("projection methods should be none") } typ.Tags = typewriter.Tags{ { Name: "methods", Items: []string{"Sort", "Any"}, Negated: true, }, } standardMethods7, projectionMethods7, err7 := evaluateTags(typ) if err7 != nil { t.Errorf("subsetted methods should be ok, instead got: '%v'", err7) } expected7 := []string{"All", "Count", "Distinct", "DistinctBy", "Each", "First", "IsSorted", "IsSortedBy", "IsSortedByDesc", "IsSortedDesc", "Max", "MaxBy", "Min", "MinBy", "Single", "SortBy", "SortByDesc", "SortDesc", "Where"} if !sliceEqual(standardMethods7, expected7) { t.Errorf("standard methods should be negatively subsetted, expected %v, got %v", expected7, standardMethods7) } if len(projectionMethods7) != 0 { t.Errorf("projection methods should be none") } typ.Tags = typewriter.Tags{ { Name: "methods", Items: []string{"Sort", "Where", "GroupBy"}, Negated: true, }, { Name: "projections", Items: []string{"int"}, }, } standardMethods8, projectionMethods8, err8 := evaluateTags(typ) if err8 != nil { t.Errorf("subsetted methods should be ok, instead got: '%v'", err8) } expectedStd8 := []string{"All", "Any", "Count", "Distinct", "DistinctBy", "Each", "First", "IsSorted", "IsSortedBy", "IsSortedByDesc", "IsSortedDesc", "Max", "MaxBy", "Min", "MinBy", "Single", "SortBy", "SortByDesc", "SortDesc"} if !sliceEqual(standardMethods8, expectedStd8) { t.Errorf("standard methods should be negatively subsetted, expected %v, got %v", expectedStd8, standardMethods8) } expectedPrj8 := []string{"Aggregate", "Average", "Max", "Min", "Select", "Sum"} if !sliceEqual(projectionMethods8, expectedPrj8) { t.Errorf("projection methods should be negatively subsetted, expected %v, got %v", expectedPrj8, projectionMethods8) } }