From d7acf72688e081a0793c3f083a17b26250923227 Mon Sep 17 00:00:00 2001 From: baude Date: Wed, 25 Apr 2018 11:50:28 -0500 Subject: Latest revendoring deleted the cmd dir in varlink Signed-off-by: baude Closes: #672 Approved by: baude --- .../generator_test.go | 90 ++++++ .../go/cmd/varlink-go-interface-generator/main.go | 354 +++++++++++++++++++++ .../go/cmd/varlink-go-type-generator/main.go | 172 ++++++++++ .../varlink/go/golang-github-varlink-go.spec | 44 +++ .../github.com/varlink/go/varlink/external_test.go | 181 +++++++++++ .../github.com/varlink/go/varlink/idl/idl_test.go | 150 +++++++++ .../github.com/varlink/go/varlink/varlink_test.go | 232 ++++++++++++++ 7 files changed, 1223 insertions(+) create mode 100644 vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/generator_test.go create mode 100644 vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go create mode 100644 vendor/github.com/varlink/go/cmd/varlink-go-type-generator/main.go create mode 100644 vendor/github.com/varlink/go/golang-github-varlink-go.spec create mode 100644 vendor/github.com/varlink/go/varlink/external_test.go create mode 100644 vendor/github.com/varlink/go/varlink/idl/idl_test.go create mode 100644 vendor/github.com/varlink/go/varlink/varlink_test.go (limited to 'vendor') diff --git a/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/generator_test.go b/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/generator_test.go new file mode 100644 index 000000000..8e749f411 --- /dev/null +++ b/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/generator_test.go @@ -0,0 +1,90 @@ +package main + +import ( + "strings" + "testing" +) + +func expect(t *testing.T, expected string, returned string) { + if strings.Compare(returned, expected) != 0 { + t.Fatalf("Expected(%d): `%s`\nGot(%d): `%s`\n", + len(expected), expected, + len(returned), returned) + } +} + +func TestIDLParser(t *testing.T) { + pkgname, b, err := generateTemplate(` +# Interface to jump a spacecraft to another point in space. The +# FTL Drive is the propulsion system to achieve faster-than-light +# travel through space. A ship making a properly calculated +# jump can arrive safely in planetary orbit, or alongside other +# ships or spaceborne objects. +interface org.example.ftl + +# The current state of the FTL drive and the amount of fuel +# available to jump. +type DriveCondition ( + state: (idle, spooling, busy), + booster: bool, + active_engines: [](id: int, state: bool), + tylium_level: int +) + +# Speed, trajectory and jump duration is calculated prior to +# activating the FTL drive. +type DriveConfiguration ( + speed: int, + trajectory: int, + duration: int +) + +# The galactic coordinates use the Sun as the origin. Galactic +# longitude is measured with primary direction from the Sun to +# the center of the galaxy in the galactic plane, while the +# galactic latitude measures the angle of the object above the +# galactic plane. +type Coordinate ( + longitude: float, + latitude: float, + distance: int +) + +# Monitor the drive. The method will reply with an update whenever +# the drive's state changes +method Monitor() -> (condition: DriveCondition) + +# Calculate the drive's jump parameters from the current +# position to the target position in the galaxy +method CalculateConfiguration( + current: Coordinate, + target: Coordinate +) -> (configuration: DriveConfiguration) + +# Jump to the calculated point in space +method Jump(configuration: DriveConfiguration) -> () + +# There is not enough tylium to jump with the given parameters +error NotEnoughEnergy () + +# The supplied parameters are outside the supported range +error ParameterOutOfRange (field: string) + +# some more coverage +method Foo(interface: string) -> (ret: (go: string, switch: bool, more: (t:bool, f:bool))) + +# some more coverage +method TestMap(map: [string]string) -> (map: [string](i: int, val: string)) +method TestSet(set: [string]()) -> (set: [string]()) +method TestObject(object: object) -> (object: object) + `) + + if err != nil { + t.Fatalf("Error parsing %v", err) + } + expect(t, "orgexampleftl", pkgname) + if len(b) <= 0 { + t.Fatal("No generated go source") + } + // FIXME: compare b.String() against expected output +} diff --git a/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go b/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go new file mode 100644 index 000000000..2db4e5cfd --- /dev/null +++ b/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go @@ -0,0 +1,354 @@ +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "os" + "path" + "strings" + + "github.com/varlink/go/varlink/idl" +) + +func writeType(b *bytes.Buffer, t *idl.Type, json bool, ident int) { + switch t.Kind { + case idl.TypeBool: + b.WriteString("bool") + + case idl.TypeInt: + b.WriteString("int64") + + case idl.TypeFloat: + b.WriteString("float64") + + case idl.TypeString, idl.TypeEnum: + b.WriteString("string") + + case idl.TypeObject: + b.WriteString("json.RawMessage") + + case idl.TypeArray: + b.WriteString("[]") + writeType(b, t.ElementType, json, ident) + + case idl.TypeMap: + b.WriteString("map[string]") + writeType(b, t.ElementType, json, ident) + + case idl.TypeMaybe: + b.WriteString("*") + writeType(b, t.ElementType, json, ident) + + case idl.TypeAlias: + b.WriteString(t.Alias) + + case idl.TypeStruct: + if len(t.Fields) == 0 { + b.WriteString("struct{}") + } else { + b.WriteString("struct {\n") + for _, field := range t.Fields { + for i := 0; i < ident+1; i++ { + b.WriteString("\t") + } + + b.WriteString(strings.Title(field.Name) + " ") + writeType(b, field.Type, json, ident+1) + if json { + b.WriteString(" `json:\"" + field.Name) + if field.Type.Kind == idl.TypeMaybe { + b.WriteString(",omitempty") + } + b.WriteString("\"`") + } + b.WriteString("\n") + } + for i := 0; i < ident; i++ { + b.WriteString("\t") + } + b.WriteString("}") + } + } +} + +func generateTemplate(description string) (string, []byte, error) { + description = strings.TrimRight(description, "\n") + + midl, err := idl.New(description) + if err != nil { + return "", nil, err + } + + pkgname := strings.Replace(midl.Name, ".", "", -1) + + var b bytes.Buffer + b.WriteString("// Generated with github.com/varlink/go/cmd/varlink-go-interface-generator\n") + b.WriteString("package " + pkgname + "\n\n") + b.WriteString("@IMPORTS@\n\n") + + b.WriteString("// Type declarations\n") + for _, a := range midl.Aliases { + b.WriteString("type " + a.Name + " ") + writeType(&b, a.Type, true, 0) + b.WriteString("\n\n") + } + + b.WriteString("// Client method calls and reply readers\n") + for _, m := range midl.Methods { + b.WriteString("func " + m.Name + "(c__ *varlink.Connection, more__ bool, oneway__ bool") + for _, field := range m.In.Fields { + b.WriteString(", " + field.Name + "_ ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error {\n") + if len(m.In.Fields) > 0 { + b.WriteString("\tvar in ") + writeType(&b, m.In, true, 1) + b.WriteString("\n") + for _, field := range m.In.Fields { + switch field.Type.Kind { + case idl.TypeStruct, idl.TypeArray, idl.TypeMap: + b.WriteString("\tin." + strings.Title(field.Name) + " = ") + writeType(&b, field.Type, true, 1) + b.WriteString("(" + field.Name + "_)\n") + + default: + b.WriteString("\tin." + strings.Title(field.Name) + " = " + field.Name + "_\n") + } + } + b.WriteString("\treturn c__.Send(\"" + midl.Name + "." + m.Name + "\", in, more__, oneway__)\n" + + "}\n\n") + } else { + b.WriteString("\treturn c__.Send(\"" + midl.Name + "." + m.Name + "\", nil, more__, oneway__)\n" + + "}\n\n") + } + + b.WriteString("func Read" + m.Name + "_(c__ *varlink.Connection") + for _, field := range m.Out.Fields { + b.WriteString(", " + field.Name + "_ *") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") (bool, error) {\n") + if len(m.Out.Fields) > 0 { + b.WriteString("\tvar out ") + writeType(&b, m.Out, true, 1) + b.WriteString("\n") + b.WriteString("\tcontinues_, err := c__.Receive(&out)\n") + } else { + b.WriteString("\tcontinues_, err := c__.Receive(nil)\n") + } + b.WriteString("\tif err != nil {\n" + + "\t\treturn false, err\n" + + "\t}\n") + for _, field := range m.Out.Fields { + b.WriteString("\tif " + field.Name + "_ != nil {\n") + switch field.Type.Kind { + case idl.TypeStruct, idl.TypeArray, idl.TypeMap: + b.WriteString("\t\t*" + field.Name + "_ = ") + writeType(&b, field.Type, false, 2) + b.WriteString(" (out." + strings.Title(field.Name) + ")\n") + + default: + b.WriteString("\t\t*" + field.Name + "_ = out." + strings.Title(field.Name) + "\n") + } + b.WriteString("\t}\n") + } + + b.WriteString("\treturn continues_, nil\n" + + "}\n\n") + } + + b.WriteString("// Service interface with all methods\n") + b.WriteString("type " + pkgname + "Interface interface {\n") + for _, m := range midl.Methods { + b.WriteString("\t" + m.Name + "(c__ VarlinkCall") + for _, field := range m.In.Fields { + b.WriteString(", " + field.Name + "_ ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error\n") + } + b.WriteString("}\n\n") + + b.WriteString("// Service object with all methods\n") + b.WriteString("type VarlinkCall struct{ varlink.Call }\n\n") + + b.WriteString("// Reply methods for all varlink errors\n") + for _, e := range midl.Errors { + b.WriteString("func (c__ *VarlinkCall) Reply" + e.Name + "(") + for i, field := range e.Type.Fields { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(field.Name + "_ ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error {\n") + if len(e.Type.Fields) > 0 { + b.WriteString("\tvar out ") + writeType(&b, e.Type, true, 1) + b.WriteString("\n") + for _, field := range e.Type.Fields { + switch field.Type.Kind { + case idl.TypeStruct, idl.TypeArray, idl.TypeMap: + b.WriteString("\tout." + strings.Title(field.Name) + " = ") + writeType(&b, field.Type, true, 1) + b.WriteString("(" + field.Name + "_)\n") + + default: + b.WriteString("\tout." + strings.Title(field.Name) + " = " + field.Name + "_\n") + } + } + b.WriteString("\treturn c__.ReplyError(\"" + midl.Name + "." + e.Name + "\", &out)\n") + } else { + b.WriteString("\treturn c__.ReplyError(\"" + midl.Name + "." + e.Name + "\", nil)\n") + } + b.WriteString("}\n\n") + } + + b.WriteString("// Reply methods for all varlink methods\n") + for _, m := range midl.Methods { + b.WriteString("func (c__ *VarlinkCall) Reply" + m.Name + "(") + for i, field := range m.Out.Fields { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(field.Name + "_ ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error {\n") + if len(m.Out.Fields) > 0 { + b.WriteString("\tvar out ") + writeType(&b, m.Out, true, 1) + b.WriteString("\n") + for _, field := range m.Out.Fields { + switch field.Type.Kind { + case idl.TypeStruct, idl.TypeArray, idl.TypeMap: + b.WriteString("\tout." + strings.Title(field.Name) + " = ") + writeType(&b, field.Type, true, 1) + b.WriteString("(" + field.Name + "_)\n") + + default: + b.WriteString("\tout." + strings.Title(field.Name) + " = " + field.Name + "_\n") + } + } + b.WriteString("\treturn c__.Reply(&out)\n") + } else { + b.WriteString("\treturn c__.Reply(nil)\n") + } + b.WriteString("}\n\n") + } + + b.WriteString("// Dummy methods for all varlink methods\n") + for _, m := range midl.Methods { + b.WriteString("func (s__ *VarlinkInterface) " + m.Name + "(c__ VarlinkCall") + for _, field := range m.In.Fields { + b.WriteString(", " + field.Name + "_ ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error {\n" + + "\treturn c__.ReplyMethodNotImplemented(\"" + m.Name + "\")\n" + + "}\n\n") + } + + b.WriteString("// Method call dispatcher\n") + b.WriteString("func (s__ *VarlinkInterface) VarlinkDispatch(call varlink.Call, methodname string) error {\n" + + "\tswitch methodname {\n") + for _, m := range midl.Methods { + b.WriteString("\tcase \"" + m.Name + "\":\n") + if len(m.In.Fields) > 0 { + b.WriteString("\t\tvar in ") + writeType(&b, m.In, true, 2) + b.WriteString("\n") + b.WriteString("\t\terr := call.GetParameters(&in)\n" + + "\t\tif err != nil {\n" + + "\t\t\treturn call.ReplyInvalidParameter(\"parameters\")\n" + + "\t\t}\n") + b.WriteString("\t\treturn s__." + pkgname + "Interface." + m.Name + "(VarlinkCall{call}") + if len(m.In.Fields) > 0 { + for _, field := range m.In.Fields { + switch field.Type.Kind { + case idl.TypeStruct, idl.TypeArray, idl.TypeMap: + b.WriteString(", ") + writeType(&b, field.Type, false, 2) + b.WriteString("(in." + strings.Title(field.Name) + ")") + + default: + b.WriteString(", in." + strings.Title(field.Name)) + } + } + } + b.WriteString(")\n") + } else { + b.WriteString("\t\treturn s__." + pkgname + "Interface." + m.Name + "(VarlinkCall{call})\n") + } + b.WriteString("\n") + } + b.WriteString("\tdefault:\n" + + "\t\treturn call.ReplyMethodNotFound(methodname)\n" + + "\t}\n" + + "}\n\n") + + b.WriteString("// Varlink interface name\n") + b.WriteString("func (s__ *VarlinkInterface) VarlinkGetName() string {\n" + + "\treturn `" + midl.Name + "`\n" + "}\n\n") + + b.WriteString("// Varlink interface description\n") + b.WriteString("func (s__ *VarlinkInterface) VarlinkGetDescription() string {\n" + + "\treturn `" + midl.Description + "\n`\n}\n\n") + + b.WriteString("// Service interface\n") + b.WriteString("type VarlinkInterface struct {\n" + + "\t" + pkgname + "Interface\n" + + "}\n\n") + + b.WriteString("func VarlinkNew(m " + pkgname + "Interface) *VarlinkInterface {\n" + + "\treturn &VarlinkInterface{m}\n" + + "}\n") + + ret_string := b.String() + + if strings.Contains(ret_string, "json.RawMessage") { + ret_string = strings.Replace(ret_string, "@IMPORTS@", "import (\n\t\"github.com/varlink/go/varlink\"\n\t\"encoding/json\"\n)", 1) + } else { + ret_string = strings.Replace(ret_string, "@IMPORTS@", `import "github.com/varlink/go/varlink"`, 1) + } + + pretty, err := format.Source([]byte(ret_string)) + if err != nil { + return "", nil, err + } + + return pkgname, pretty, nil +} + +func generateFile(varlinkFile string) { + file, err := ioutil.ReadFile(varlinkFile) + if err != nil { + fmt.Fprintf(os.Stderr, "Error reading file '%s': %s\n", varlinkFile, err) + os.Exit(1) + } + + pkgname, b, err := generateTemplate(string(file)) + if err != nil { + fmt.Fprintf(os.Stderr, "Error parsing file '%s': %s\n", varlinkFile, err) + os.Exit(1) + } + + filename := path.Dir(varlinkFile) + "/" + pkgname + ".go" + err = ioutil.WriteFile(filename, b, 0660) + if err != nil { + fmt.Fprintf(os.Stderr, "Error writing file '%s': %s\n", filename, err) + os.Exit(1) + } +} + +func main() { + if len(os.Args) != 2 { + fmt.Printf("Usage: %s \n", os.Args[0]) + os.Exit(1) + } + generateFile(os.Args[1]) +} diff --git a/vendor/github.com/varlink/go/cmd/varlink-go-type-generator/main.go b/vendor/github.com/varlink/go/cmd/varlink-go-type-generator/main.go new file mode 100644 index 000000000..46414b7bf --- /dev/null +++ b/vendor/github.com/varlink/go/cmd/varlink-go-type-generator/main.go @@ -0,0 +1,172 @@ +package main + +import ( + "fmt" + "go/ast" + "go/importer" + "go/parser" + "go/token" + "go/types" + "log" + "os" +) + +func IsBasicGoType(t types.Type, flag types.BasicInfo) bool { + switch u := t.(type) { + case *types.Basic: + if u.Info()&flag != 0 { + return true + } + return false + case *types.Named: + return IsBasicGoType(u.Underlying(), flag) + } + return false +} + +func GoToVarlinkType(t types.Type) string { + if IsBasicGoType(t, types.IsBoolean) { + return "bool" + } + + if IsBasicGoType(t, types.IsInteger) { + return "int" + } + + if IsBasicGoType(t, types.IsFloat) { + return "float" + } + + if IsBasicGoType(t, types.IsString) { + return "string" + } + + switch u := t.(type) { + case *types.Basic: + return fmt.Sprintf("<<<%s>>>", t.String()) + + case *types.Named: + return u.Obj().Name() + + case *types.Map: + if IsBasicGoType(u.Key(), types.IsString) { + return fmt.Sprintf("[string]%s", GoToVarlinkType(u.Elem())) + } else { + return fmt.Sprintf("<<<%s>>>", u.String()) + } + + case *types.Interface: + if u.Empty() { + return "()" + } + return fmt.Sprintf("<<<%s>>>", u.String()) + + case *types.Pointer: + return fmt.Sprintf("?%s", GoToVarlinkType(u.Elem())) + + case *types.Array: + return fmt.Sprintf("[]%s", GoToVarlinkType(u.Elem())) + + case *types.Slice: + return fmt.Sprintf("[]%s", GoToVarlinkType(u.Elem())) + + case *types.Struct: + if u.NumFields() > 0 { + s := "" + for i := 0; i < u.NumFields(); i++ { + if i > 0 { + s += ",\n" + } + s += fmt.Sprintf("\t%s: %s", + u.Field(i).Name(), GoToVarlinkType(u.Field(i).Type())) + } + + return fmt.Sprintf("(\n%s\n)", s) + } + return "()" + + default: + return fmt.Sprintf("<<<%T %s>>>", t, u) + } +} + +func PrintDefsUses(name string, fset *token.FileSet, files []*ast.File) error { + conf := types.Config{ + Importer: importer.Default(), + FakeImportC: true, + } + + info := &types.Info{ + Defs: make(map[*ast.Ident]types.Object), + } + + _, err := conf.Check(name, fset, files, info) + if err != nil { + return err // type error + } + + seen := map[string]interface{}{} + + for id, obj := range info.Defs { + if obj == nil { + continue + } + + if _, ok := seen[id.Name]; ok { + continue + } + + /* + if !obj.Exported() || obj.Pkg().Name() != name { + continue + } + */ + switch f := obj.Type().Underlying().(type) { + case *types.Struct: + if f.NumFields() > 0 { + fmt.Printf("type %s %s\n\n", id.Name, GoToVarlinkType(f)) + } + } + seen[id.Name] = nil + } + + return nil +} + +func main() { + + path := os.Args[1] + fs := token.NewFileSet() + + if stat, err := os.Stat(path); err == nil && stat.IsDir() { + pkgs, err := parser.ParseDir(fs, path, nil, 0) + if err != nil { + fmt.Printf("parsing dir '%s': %s", path, err) + } + for name, pkg := range pkgs { + log.Println("Found package:", name) + + fset := make([]*ast.File, len(pkg.Files), len(pkg.Files)) + idx := 0 + for _, value := range pkg.Files { + fset[idx] = value + idx++ + } + + if err := PrintDefsUses(name, fs, fset); err != nil { + log.Print(err) // type error + } + } + } else { + + fset, err := parser.ParseFile(fs, path, nil, 0) + + if err != nil { + fmt.Printf("parsing file '%s': %s", path, err) + } + name := fset.Name.String() + if err := PrintDefsUses(name, fs, []*ast.File{fset}); err != nil { + log.Print(err) // type error + } + } +} diff --git a/vendor/github.com/varlink/go/golang-github-varlink-go.spec b/vendor/github.com/varlink/go/golang-github-varlink-go.spec new file mode 100644 index 000000000..85f5d1788 --- /dev/null +++ b/vendor/github.com/varlink/go/golang-github-varlink-go.spec @@ -0,0 +1,44 @@ +%global goipath github.com/varlink/go +Version: 0 +%gometa + +Name: %{goname} +Release: 1%{?dist} +Summary: Go bindings for varlink +License: ASL 2.0 +URL: %{gourl} +Source0: %{gosource} + +%description +Native Go bindings for the varlink protocol. + +%package devel +Summary: %{summary} +BuildArch: noarch + +%description devel +%{summary} + +This package contains library source intended for +building other packages which use import path with +%{gobaseipath} prefix. + +%prep +%forgesetup + +%build +%gobuildroot + +%install +gofiles=$(find . %{gofindfilter} -print) +%goinstall $gofiles + +%check + +%files devel -f devel.file-list +%license LICENSE +%doc README.md + +%changelog +* Tue Mar 20 2018 0-1 +- Version 0 diff --git a/vendor/github.com/varlink/go/varlink/external_test.go b/vendor/github.com/varlink/go/varlink/external_test.go new file mode 100644 index 000000000..daed4ba2d --- /dev/null +++ b/vendor/github.com/varlink/go/varlink/external_test.go @@ -0,0 +1,181 @@ +package varlink_test + +// test with no internal access + +import ( + "github.com/varlink/go/varlink" + "os" + "runtime" + "testing" + "time" +) + +type VarlinkInterface struct{} + +func (s *VarlinkInterface) VarlinkDispatch(call varlink.Call, methodname string) error { + return call.ReplyMethodNotImplemented(methodname) +} +func (s *VarlinkInterface) VarlinkGetName() string { + return `org.example.test` +} + +func (s *VarlinkInterface) VarlinkGetDescription() string { + return "#" +} + +type VarlinkInterface2 struct{} + +func (s *VarlinkInterface2) VarlinkDispatch(call varlink.Call, methodname string) error { + return call.ReplyMethodNotImplemented(methodname) +} +func (s *VarlinkInterface2) VarlinkGetName() string { + return `org.example.test2` +} + +func (s *VarlinkInterface2) VarlinkGetDescription() string { + return "#" +} + +func TestRegisterService(t *testing.T) { + newTestInterface := new(VarlinkInterface) + service, err := varlink.NewService( + "Varlink", + "Varlink Test", + "1", + "https://github.com/varlink/go/varlink", + ) + if err != nil { + t.Fatalf("NewService(): %v", err) + } + + if err := service.RegisterInterface(newTestInterface); err != nil { + t.Fatalf("Couldn't register service: %v", err) + } + + if err := service.RegisterInterface(newTestInterface); err == nil { + t.Fatal("Could register service twice") + } + + defer func() { service.Shutdown() }() + + servererror := make(chan error) + + go func() { + servererror <- service.Listen("unix:varlinkexternal_TestRegisterService", 0) + }() + + time.Sleep(time.Second / 5) + + n := new(VarlinkInterface2) + + if err := service.RegisterInterface(n); err == nil { + t.Fatal("Could register service while running") + } + time.Sleep(time.Second / 5) + service.Shutdown() + + if err := <-servererror; err != nil { + t.Fatalf("service.Listen(): %v", err) + } +} + +func TestUnix(t *testing.T) { + newTestInterface := new(VarlinkInterface) + service, err := varlink.NewService( + "Varlink", + "Varlink Test", + "1", + "https://github.com/varlink/go/varlink", + ) + + if err != nil { + t.Fatalf("NewService(): %v", err) + } + + if err := service.RegisterInterface(newTestInterface); err != nil { + t.Fatalf("RegisterInterface(): %v", err) + } + + servererror := make(chan error) + + go func() { + servererror <- service.Listen("unix:varlinkexternal_TestUnix", 0) + }() + + time.Sleep(time.Second / 5) + service.Shutdown() + + if err := <-servererror; err != nil { + t.Fatalf("service.Listen(): %v", err) + } +} + +func TestAnonUnix(t *testing.T) { + if runtime.GOOS != "linux" { + return + } + + newTestInterface := new(VarlinkInterface) + service, err := varlink.NewService( + "Varlink", + "Varlink Test", + "1", + "https://github.com/varlink/go/varlink", + ) + + if err != nil { + t.Fatalf("NewService(): %v", err) + } + + if err := service.RegisterInterface(newTestInterface); err != nil { + t.Fatalf("RegisterInterface(): %v", err) + } + + servererror := make(chan error) + + go func() { + servererror <- service.Listen("unix:@varlinkexternal_TestAnonUnix", 0) + }() + + time.Sleep(time.Second / 5) + service.Shutdown() + + if err := <-servererror; err != nil { + t.Fatalf("service.Listen(): %v", err) + } +} + +func TestListenFDSNotInt(t *testing.T) { + newTestInterface := new(VarlinkInterface) + service, err := varlink.NewService( + "Varlink", + "Varlink Test", + "1", + "https://github.com/varlink/go/varlink", + ) + + if err != nil { + t.Fatalf("NewService(): %v", err) + } + + if err := service.RegisterInterface(newTestInterface); err != nil { + t.Fatalf("Couldn't register service: %v", err) + } + os.Setenv("LISTEN_FDS", "foo") + os.Setenv("LISTEN_PID", string(os.Getpid())) + + servererror := make(chan error) + + go func() { + servererror <- service.Listen("unix:varlinkexternal_TestListenFDSNotInt", 0) + }() + + time.Sleep(time.Second / 5) + service.Shutdown() + + err = <-servererror + + if err != nil { + t.Fatalf("service.Run(): %v", err) + } +} diff --git a/vendor/github.com/varlink/go/varlink/idl/idl_test.go b/vendor/github.com/varlink/go/varlink/idl/idl_test.go new file mode 100644 index 000000000..a3377bec0 --- /dev/null +++ b/vendor/github.com/varlink/go/varlink/idl/idl_test.go @@ -0,0 +1,150 @@ +package idl + +import ( + "fmt" + "runtime" + "testing" +) + +/* +func expect(t *testing.T, expected string, returned string) { + if strings.Compare(returned, expected) != 0 { + t.Fatalf("Expected(%d): `%s`\nGot(%d): `%s`\n", + len(expected), expected, + len(returned), returned) + } +} +*/ + +func testParse(t *testing.T, pass bool, description string) { + _, _, line, _ := runtime.Caller(1) + + t.Run(fmt.Sprintf("Line-%d", line), func(t *testing.T) { + midl, err := New(description) + if pass { + if err != nil { + t.Fatalf("generateTemplate(`%s`): %v", description, err) + } + if len(midl.Name) <= 0 { + t.Fatalf("generateTemplate(`%s`): returned no pkgname", description) + } + } + if !pass && (err == nil) { + t.Fatalf("generateTemplate(`%s`): did not fail", description) + } + }) +} + +func TestOneMethod(t *testing.T) { + testParse(t, true, "interface foo.bar\nmethod Foo()->()") +} + +func TestOneMethodNoType(t *testing.T) { + testParse(t, false, "interface foo.bar\nmethod Foo()->(b:)") +} + +func TestDomainNames(t *testing.T) { + testParse(t, true, "interface org.varlink.service\nmethod F()->()") + testParse(t, true, "interface com.example.0example\nmethod F()->()") + testParse(t, true, "interface com.example.example-dash\nmethod F()->()") + testParse(t, true, "interface xn--lgbbat1ad8j.example.algeria\nmethod F()->()") + testParse(t, false, "interface com.-example.leadinghyphen\nmethod F()->()") + testParse(t, false, "interface com.example-.danglinghyphen-\nmethod F()->()") + testParse(t, false, "interface Com.example.uppercase-toplevel\nmethod F()->()") + testParse(t, false, "interface Co9.example.number-toplevel\nmethod F()->()") + testParse(t, false, "interface 1om.example.number-toplevel\nmethod F()->()") + testParse(t, false, "interface com.Example\nmethod F()->()") + var name string + for i := 0; i < 255; i++ { + name += "a" + } + testParse(t, false, "interface com.example.toolong"+name+"\nmethod F()->()") + testParse(t, false, "interface xn--example.toolong"+name+"\nmethod F()->()") +} + +func TestNoMethod(t *testing.T) { + testParse(t, false, ` +interface org.varlink.service + type Interface (name: string, types: []Type, methods: []Method) + type Property (key: string, value: string) +`) +} + +func TestTypeNoArgs(t *testing.T) { + testParse(t, true, "interface foo.bar\n type I ()\nmethod F()->()") +} + +func TestTypeOneArg(t *testing.T) { + testParse(t, true, "interface foo.bar\n type I (b:bool)\nmethod F()->()") +} + +func TestBasicTypes(t *testing.T) { + testParse(t, true, "interface foo.bar\n type I (b:bool)\nmethod F()->()") + testParse(t, true, "interface foo.bar\n type I (b:string)\nmethod F()->()") + testParse(t, true, "interface foo.bar\n type I (b:float)\nmethod F()->()") + testParse(t, true, "interface foo.bar\n type I (b:int)\nmethod F()->()") + testParse(t, true, "interface foo.bar\n type I (b:object)\nmethod F()->()") +} + +func TestTypeOneArray(t *testing.T) { + testParse(t, true, "interface foo.bar\n type I (b:[]bool)\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (b:bool[ ])\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (b:bool[1])\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (b:bool[ 1 ])\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (b:bool[ 1 1 ])\nmethod F()->()") +} + +func TestFieldnames(t *testing.T) { + testParse(t, false, "interface foo.bar\n type I (Test:[]bool)\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (_test:[]bool)\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (Ă„est:[]bool)\nmethod F()->()") +} + +func TestNestedStructs(t *testing.T) { + testParse(t, true, "interface foo.bar\n type I ( b: [](foo: bool, bar: bool, baz: int) )\nmethod F()->()") +} + +func TestEnum(t *testing.T) { + testParse(t, true, "interface foo.bar\n type I (b:(foo, bar, baz))\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (foo, bar, baz : bool)\nmethod F()->()") +} + +func TestMap(t *testing.T) { + testParse(t, true, "interface foo.bar\n type I (m: [string]string)\nmethod F()->()") + testParse(t, true, "interface foo.bar\n type I (m: [string]int)\nmethod F()->()") + testParse(t, true, "interface foo.bar\n type I (m: [string]())\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (m: [int]string)\nmethod F()->()") +} + +func TestMaybe(t *testing.T) { + testParse(t, true, "interface foo.bar\n type I (m: ?string)\nmethod F()->()") + testParse(t, true, "interface foo.bar\n type I (m: ?[string]?int)\nmethod F()->()") + testParse(t, true, "interface foo.bar\n type I (m: ?[]?int)\nmethod F()->()") + testParse(t, false, "interface foo.bar\n type I (m: ??int)\nmethod F()->()") +} + +func TestIncomplete(t *testing.T) { + testParse(t, false, "interfacef foo.bar\nmethod F()->()") + testParse(t, false, "interface foo.bar\nmethod F()->()\ntype I (b: bool") + testParse(t, false, "interface foo.bar\nmethod F()->(") + testParse(t, false, "interface foo.bar\nmethod F(") + testParse(t, false, "interface foo.bar\nmethod ()->()") + testParse(t, false, "interface foo.bar\nmethod F->()\n") + testParse(t, false, "interface foo.bar\nmethod F()->\n") + testParse(t, false, "interface foo.bar\nmethod F()>()\n") + testParse(t, false, "interface foo.bar\nmethod F()->()\ntype (b: bool)") + testParse(t, false, "interface foo.bar\nmethod F()->()\nerror (b: bool)") + testParse(t, false, "interface foo.bar\nmethod F()->()\n dfghdrg") +} + +func TestDuplicate(t *testing.T) { + testParse(t, false, ` +interface foo.example + type Device() + type Device() + type T() + type T() + method F() -> () + method F() -> () +`) +} diff --git a/vendor/github.com/varlink/go/varlink/varlink_test.go b/vendor/github.com/varlink/go/varlink/varlink_test.go new file mode 100644 index 000000000..e19e768a2 --- /dev/null +++ b/vendor/github.com/varlink/go/varlink/varlink_test.go @@ -0,0 +1,232 @@ +package varlink + +// tests with access to internals + +import ( + "bufio" + "bytes" + "fmt" + "strings" + "testing" +) + +func expect(t *testing.T, expected string, returned string) { + if strings.Compare(returned, expected) != 0 { + t.Fatalf("Expected(%d): `%s`\nGot(%d): `%s`\n", + len(expected), expected, + len(returned), strings.Replace(returned, "\000", "`+\"\\000\"+`", -1)) + } +} + +func TestService(t *testing.T) { + service, _ := NewService( + "Varlink", + "Varlink Test", + "1", + "https://github.com/varlink/go/varlink", + ) + + t.Run("ZeroMessage", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + if err := service.handleMessage(w, []byte{0}); err == nil { + t.Fatal("HandleMessage returned non-error") + } + }) + + t.Run("InvalidJson", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"foo.GetInterfaceDescription" fdgdfg}`) + if err := service.handleMessage(w, msg); err == nil { + t.Fatal("HandleMessage returned no error on invalid json") + } + }) + + t.Run("WrongInterface", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"foo.GetInterfaceDescription"}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatal("HandleMessage returned error on wrong interface") + } + expect(t, `{"parameters":{"interface":"foo"},"error":"org.varlink.service.InterfaceNotFound"}`+"\000", + b.String()) + }) + + t.Run("InvalidMethod", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"InvalidMethod"}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatal("HandleMessage returned error on invalid method") + } + expect(t, `{"parameters":{"parameter":"method"},"error":"org.varlink.service.InvalidParameter"}`+"\000", + b.String()) + }) + + t.Run("WrongMethod", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.varlink.service.WrongMethod"}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatal("HandleMessage returned error on wrong method") + } + expect(t, `{"parameters":{"method":"WrongMethod"},"error":"org.varlink.service.MethodNotFound"}`+"\000", + b.String()) + }) + + t.Run("GetInterfaceDescriptionNullParameters", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.varlink.service.GetInterfaceDescription","parameters": null}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatalf("HandleMessage returned error: %v", err) + } + expect(t, `{"parameters":{"parameter":"parameters"},"error":"org.varlink.service.InvalidParameter"}`+"\000", + b.String()) + }) + + t.Run("GetInterfaceDescriptionNoInterface", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.varlink.service.GetInterfaceDescription","parameters":{}}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatalf("HandleMessage returned error: %v", err) + } + expect(t, `{"parameters":{"parameter":"interface"},"error":"org.varlink.service.InvalidParameter"}`+"\000", + b.String()) + }) + + t.Run("GetInterfaceDescriptionWrongInterface", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.varlink.service.GetInterfaceDescription","parameters":{"interface":"foo"}}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatalf("HandleMessage returned error: %v", err) + } + expect(t, `{"parameters":{"parameter":"interface"},"error":"org.varlink.service.InvalidParameter"}`+"\000", + b.String()) + }) + + t.Run("GetInterfaceDescription", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.varlink.service.GetInterfaceDescription","parameters":{"interface":"org.varlink.service"}}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatalf("HandleMessage returned error: %v", err) + } + expect(t, `{"parameters":{"description":"# The Varlink Service Interface is provided by every varlink service. It\n# describes the service and the interfaces it implements.\ninterface org.varlink.service\n\n# Get a list of all the interfaces a service provides and information\n# about the implementation.\nmethod GetInfo() -\u003e (\n vendor: string,\n product: string,\n version: string,\n url: string,\n interfaces: []string\n)\n\n# Get the description of an interface that is implemented by this service.\nmethod GetInterfaceDescription(interface: string) -\u003e (description: string)\n\n# The requested interface was not found.\nerror InterfaceNotFound (interface: string)\n\n# The requested method was not found\nerror MethodNotFound (method: string)\n\n# The interface defines the requested method, but the service does not\n# implement it.\nerror MethodNotImplemented (method: string)\n\n# One of the passed parameters is invalid.\nerror InvalidParameter (parameter: string)"}}`+"\000", + b.String()) + }) + + t.Run("GetInfo", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.varlink.service.GetInfo"}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatalf("HandleMessage returned error: %v", err) + } + expect(t, `{"parameters":{"vendor":"Varlink","product":"Varlink Test","version":"1","url":"https://github.com/varlink/go/varlink","interfaces":["org.varlink.service"]}}`+"\000", + b.String()) + }) +} + +type VarlinkInterface struct{} + +func (s *VarlinkInterface) VarlinkDispatch(call Call, methodname string) error { + switch methodname { + case "Ping": + if !call.WantsMore() { + return fmt.Errorf("More flag not passed") + } + if call.IsOneShot() { + return fmt.Errorf("OneShot flag set") + } + call.Continues = true + if err := call.Reply(nil); err != nil { + return err + } + if err := call.Reply(nil); err != nil { + return err + } + call.Continues = false + if err := call.Reply(nil); err != nil { + return err + } + return nil + + case "PingError": + return call.ReplyError("org.example.test.PingError", nil) + } + + call.Continues = true + if err := call.Reply(nil); err == nil { + return fmt.Errorf("call.Reply did not fail for Continues/More mismatch") + } + call.Continues = false + + if err := call.ReplyError("WrongName", nil); err == nil { + return fmt.Errorf("call.ReplyError accepted invalid error name") + } + + if err := call.ReplyError("org.varlink.service.MethodNotImplemented", nil); err == nil { + return fmt.Errorf("call.ReplyError accepted org.varlink.service error") + } + + return call.ReplyMethodNotImplemented(methodname) +} +func (s *VarlinkInterface) VarlinkGetName() string { + return `org.example.test` +} + +func (s *VarlinkInterface) VarlinkGetDescription() string { + return "#" +} + +func TestMoreService(t *testing.T) { + newTestInterface := new(VarlinkInterface) + + service, _ := NewService( + "Varlink", + "Varlink Test", + "1", + "https://github.com/varlink/go/varlink", + ) + + if err := service.RegisterInterface(newTestInterface); err != nil { + t.Fatalf("Couldn't register service: %v", err) + } + + t.Run("MethodNotImplemented", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.example.test.Pingf"}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatalf("HandleMessage returned error: %v", err) + } + expect(t, `{"parameters":{"method":"Pingf"},"error":"org.varlink.service.MethodNotImplemented"}`+"\000", + b.String()) + }) + + t.Run("PingError", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.example.test.PingError", "more" : true}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatalf("HandleMessage returned error: %v", err) + } + expect(t, `{"error":"org.example.test.PingError"}`+"\000", + b.String()) + }) + t.Run("MoreTest", func(t *testing.T) { + var b bytes.Buffer + w := bufio.NewWriter(&b) + msg := []byte(`{"method":"org.example.test.Ping", "more" : true}`) + if err := service.handleMessage(w, msg); err != nil { + t.Fatalf("HandleMessage returned error: %v", err) + } + expect(t, `{"continues":true}`+"\000"+`{"continues":true}`+"\000"+`{}`+"\000", + b.String()) + }) +} -- cgit v1.2.3-54-g00ecf