| // Copyright 2016 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // The following enables go generate to generate the doc.go file. |
| //go:generate go run $JIRI_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go . -help |
| |
| package main |
| |
| import ( |
| "fmt" |
| "io" |
| "os" |
| "strings" |
| |
| "v.io/v23/vdl" |
| "v.io/v23/vdl/vdltest" |
| "v.io/x/lib/cmdline" |
| "v.io/x/lib/textutil" |
| "v.io/x/ref/lib/vdl/codegen/vdlgen" |
| ) |
| |
| var cmdGen = &cmdline.Command{ |
| Runner: cmdline.RunnerFunc(runGen), |
| Name: "vdltestgen", |
| Short: "generates test data for the vdltest package", |
| Long: ` |
| Command vdltestgen generates types and values for the vdltest package. The |
| following files are generated: |
| |
| vtype_gen.vdl - Named "V" types, regular VDL types. |
| ventry_pass_gen.vdl - Entries that pass conversion from source to target. |
| ventry_fail_gen.vdl - Entries that fail conversion from source to target. |
| |
| xtype_gen.vdl - Named "X" types, no VDL{IsZero,Read,Write} methods. |
| xentry_pass_gen.vdl - Entries that pass conversion from source to target. |
| xentry_fail_gen.vdl - Entries that fail conversion from source to target. |
| |
| This tool does not run the vdl tool on the generated *.vdl files; you must do |
| that yourself, typically via "jiri go install". |
| |
| Instead of running this tool manually, it is typically invoked via: |
| |
| $ jiri run go generate v.io/v23/vdl/vdltest |
| `, |
| } |
| |
| func main() { |
| cmdGen.Flags.StringVar(&flagVType, "vtype", "vtype_gen.vdl", "Name of the generated vtype file.") |
| cmdGen.Flags.StringVar(&flagVEntryPass, "ventry-pass", "ventry_pass_gen.vdl", "Name of the generated ventry pass file, containing passing test entries.") |
| cmdGen.Flags.StringVar(&flagVEntryFail, "ventry-fail", "ventry_fail_gen.vdl", "Name of the generated ventry fail file, containing failing test entries.") |
| |
| cmdGen.Flags.StringVar(&flagXType, "xtype", "xtype_gen.vdl", "Name of the generated xtype file.") |
| cmdGen.Flags.StringVar(&flagXEntryPass, "xentry-pass", "xentry_pass_gen.vdl", "Name of the generated xentry pass file, containing passing test entries.") |
| cmdGen.Flags.StringVar(&flagXEntryFail, "xentry-fail", "xentry_fail_gen.vdl", "Name of the generated xentry fail file, containing failing test entries.") |
| |
| cmdline.Main(cmdGen) |
| } |
| |
| var ( |
| flagVType string |
| flagVEntryPass string |
| flagVEntryFail string |
| flagXType string |
| flagXEntryPass string |
| flagXEntryFail string |
| ) |
| |
| func runGen(_ *cmdline.Env, _ []string) error { |
| const maxTypeDepth, seed = 3, 1 |
| // Generate "V" types and entries. |
| vTypeGen := vdltest.NewTypeGenerator() |
| vTypeGen.RandSeed(seed) |
| vTypeGen.NamePrefix = "V" |
| vTypes := vTypeGen.Gen(maxTypeDepth) |
| vEntryGen := vdltest.NewEntryGenerator(vTypes) |
| vEntryGen.RandSeed(seed) |
| writeTypeFile(flagVType, vTypes) |
| writeEntryFile(flagVEntryPass, "vAllPass", vEntryGen.GenAllPass(vTypes)) |
| writeEntryFile(flagVEntryFail, "vAllFail", vEntryGen.GenAllFail(vTypes)) |
| // Generate "X" types and entries. |
| xTypeGen := vdltest.NewTypeGenerator() |
| xTypeGen.RandSeed(seed) |
| xTypeGen.NamePrefix = "X" |
| xTypes := xTypeGen.Gen(maxTypeDepth) |
| xEntryGen := vdltest.NewEntryGenerator(xTypes) |
| xEntryGen.RandSeed(seed) |
| // Don't generate "X" entries for types already covered by "V" entries. |
| xTargetTypes := subtractTypes(xTypes, vTypes) |
| writeTypeFile(flagXType, xTypes) |
| writeEntryFile(flagXEntryPass, "xAllPass", xEntryGen.GenAllPass(xTargetTypes)) |
| writeEntryFile(flagXEntryFail, "xAllFail", xEntryGen.GenAllFail(xTargetTypes)) |
| return nil |
| } |
| |
| // subtractTypes returns all types that don't appear in sub. |
| func subtractTypes(types, sub []*vdl.Type) []*vdl.Type { |
| subMap := make(map[*vdl.Type]bool) |
| for _, tt := range sub { |
| subMap[tt] = true |
| } |
| var result []*vdl.Type |
| for _, tt := range types { |
| if !subMap[tt] { |
| result = append(result, tt) |
| } |
| } |
| return result |
| } |
| |
| // This tool is only used to generate test cases for the vdltest package, so the |
| // strategy is to panic on any error, to make the code simpler. |
| func panicOnError(err error) { |
| if err != nil { |
| panic(err) |
| } |
| } |
| |
| func createFile(name string) (*os.File, func()) { |
| file, err := os.Create(name) |
| panicOnError(err) |
| return file, func() { panicOnError(file.Close()) } |
| } |
| |
| func writef(w io.Writer, format string, args ...interface{}) { |
| _, err := fmt.Fprintf(w, format, args...) |
| panicOnError(err) |
| } |
| |
| func writeHeader(w io.Writer) { |
| writef(w, `// Copyright 2016 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // This file was auto-generated by v.io/v23/vdl/vdltest/internal/vdltestgen |
| // Run the following to re-generate: |
| // $ jiri run go generate v.io/v23/vdl/vdltest |
| |
| package vdltest |
| |
| `) |
| } |
| |
| func writeTypeFile(fileName string, types []*vdl.Type) { |
| fmt.Printf("Writing %[1]s:\t%[2]d types\n", fileName, len(types)) |
| file, cleanup := createFile(fileName) |
| defer cleanup() |
| writeHeader(file) |
| comment := textutil.PrefixLineWriter(file, "// ") |
| panicOnError(vdltest.PrintTypeStats(comment, types...)) |
| writef(comment, "\nOnly named types appear below, by definition.\n") |
| panicOnError(comment.Flush()) |
| writef(file, "\ntype (\n") |
| for _, tt := range types { |
| if tt.Name() != "" { |
| base := vdlgen.BaseType(tt, "", nil) |
| base = strings.Replace(base, "\n", "\n\t", -1) |
| writef(file, "\t%[1]s %[2]s\n", tt.Name(), base) |
| } |
| } |
| writef(file, ")\n") |
| } |
| |
| func writeEntryFile(fileName, constName string, entries []vdltest.EntryValue) { |
| fmt.Printf("Writing %[1]s:\t%[2]d entries\n", fileName, len(entries)) |
| file, cleanup := createFile(fileName) |
| defer cleanup() |
| writeHeader(file) |
| comment := textutil.PrefixLineWriter(file, "// ") |
| panicOnError(vdltest.PrintEntryStats(comment, entries...)) |
| panicOnError(comment.Flush()) |
| writef(file, "\nconst %[1]s = []Entry{\n", constName) |
| for _, e := range entries { |
| if e.IsCanonical() { |
| writef(file, "\t// Canonical\n") |
| } |
| target := vdlgen.TypedConst(e.Target, "", nil) |
| source := vdlgen.TypedConst(e.Source, "", nil) |
| if len(target)*2+len(source)*2 < 100 { |
| // Write a pretty one-liner, if it's short enough. |
| writef(file, "\t{ %[1]v, %#[2]q, %#[3]q, %[3]s, %#[4]q, %[4]s },\n", e.IsCanonical(), e.Label, target, source) |
| } else { |
| writef(file, "\t{ %[1]v, %#[2]q,\n\t %#[3]q,\n\t %[3]s,\n\t %#[4]q,\n\t %[4]s,\n\t},\n", e.IsCanonical(), e.Label, target, source) |
| } |
| } |
| writef(file, "}\n") |
| } |