github.com/mdlayher/yamlnetlink@v0.0.0-20221112165554-61a6fe600cd8/generate_test.go (about) 1 package yamlnetlink_test 2 3 import ( 4 "encoding/json" 5 "os" 6 "os/exec" 7 "path/filepath" 8 "testing" 9 10 "github.com/google/go-cmp/cmp" 11 "github.com/mdlayher/yamlnetlink" 12 "golang.org/x/exp/slices" 13 ) 14 15 func TestGenerateNlctrl(t *testing.T) { 16 out := generate(t, "nlctrl") 17 18 type mcastGroup struct { 19 ID uint32 `json:"Id"` 20 Name string `json:"Name"` 21 } 22 23 type family struct { 24 ID uint16 `json:"FamilyId"` 25 Name string `json:"FamilyName"` 26 McastGroups []mcastGroup `json:"McastGroups"` 27 } 28 29 type stdout struct { 30 Family family `json:"family"` 31 Families []string `json:"families"` 32 } 33 34 var got stdout 35 if err := json.Unmarshal(out, &got); err != nil { 36 t.Logf("stdout: %s", string(out)) 37 t.Fatalf("failed to unmarshal family: %v", err) 38 } 39 40 // nlctrl always occupies the same IDs. 41 want := family{ 42 ID: 16, 43 Name: "nlctrl", 44 McastGroups: []mcastGroup{{ 45 ID: 16, 46 Name: "notify", 47 }}, 48 } 49 50 if diff := cmp.Diff(want, got.Family); diff != "" { 51 t.Fatalf("unexpected generic netlink family (-want +got):\n%s", diff) 52 } 53 54 // Expect to find nlctrl in the dump list. 55 if !slices.Contains(got.Families, "nlctrl") { 56 t.Fatalf("did not find nlctrl: %v", got.Families) 57 } 58 } 59 60 func TestGenerateEthtool(t *testing.T) { 61 _ = generate(t, "ethtool") 62 // TODO! 63 } 64 65 // generate generates and executes Go code for the specified family using the 66 // family's directory under testdata. 67 func generate(t *testing.T, family string) []byte { 68 t.Helper() 69 70 // Example: ./testdata/nlctrl/nlctrl 71 path := filepath.Join("testdata", family, family) 72 f, err := os.Open(path + ".yaml") 73 if err != nil { 74 t.Fatalf("failed to open file: %v", err) 75 } 76 defer f.Close() 77 78 spec, err := yamlnetlink.Parse(f) 79 if err != nil { 80 t.Fatalf("failed to parse spec: %v", err) 81 } 82 _ = f.Close() 83 84 // Generate a client in another package which we can compile, run, and 85 // verify it works. 86 code, err := yamlnetlink.Generate(spec, &yamlnetlink.Config{Package: "main"}) 87 if err != nil { 88 t.Fatalf("failed to generate code: %v", err) 89 } 90 91 _ = os.Remove(path + ".go") 92 if err := os.WriteFile(path+".go", code, 0o644); err != nil { 93 t.Fatalf("failed to write generated code: %v", err) 94 } 95 96 pwd, err := os.Getwd() 97 if err != nil { 98 t.Fatalf("failed to get working directory: %v", err) 99 } 100 101 if err := os.Chdir(filepath.Dir(path)); err != nil { 102 t.Fatalf("failed to change working directory: %v", err) 103 } 104 105 defer func() { 106 if err := os.Chdir(pwd); err != nil { 107 t.Fatalf("failed to restore working directory: %v", err) 108 } 109 }() 110 111 // Execute the code and pass stdout back to the caller. 112 out, err := exec.Command("go", "run", ".").CombinedOutput() 113 if err != nil { 114 t.Fatalf("failed to execute code: %v\noutput: %q", err, out) 115 } 116 117 return out 118 }