github.com/mirantis/virtlet@v1.5.2-0.20191204181327-1659b8a48e9b/pkg/diag/diag_test.go (about) 1 /* 2 Copyright 2018 Mirantis 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package diag 18 19 import ( 20 "errors" 21 "io/ioutil" 22 "os" 23 "path/filepath" 24 "reflect" 25 "strings" 26 "testing" 27 28 "github.com/davecgh/go-spew/spew" 29 30 testutils "github.com/Mirantis/virtlet/pkg/utils/testing" 31 ) 32 33 type diagTester struct { 34 t *testing.T 35 tmpDir string 36 ds *Set 37 s *Server 38 socketPath string 39 logDir string 40 } 41 42 func setupLogDir(t *testing.T, baseDir string) string { 43 logDir := filepath.Join(baseDir, "logs") 44 // "dummy" dir is to be ignored. This also creates the log dir 45 if err := os.MkdirAll(filepath.Join(logDir, "dummy"), 0777); err != nil { 46 t.Fatalf("MkdirAll(): %v", err) 47 } 48 for name, contents := range map[string]string{ 49 "log1.txt": "log1 contents", 50 "log2.txt": "log2 contents", 51 ".placeholder": "ignored file", 52 ".place.holder": "another ignored file", 53 } { 54 if err := ioutil.WriteFile(filepath.Join(logDir, name), []byte(contents), 0777); err != nil { 55 t.Fatalf("WriteFile(): %v", err) 56 } 57 } 58 return logDir 59 } 60 61 func newDiagTester(t *testing.T) *diagTester { 62 tmpDir, err := ioutil.TempDir("", "diag-out") 63 if err != nil { 64 t.Fatalf("TempDir(): %v", err) 65 } 66 logDir := setupLogDir(t, tmpDir) 67 ds := NewDiagSet() 68 ds.RegisterDiagSource("foo", NewCommandSource("txt", []string{"echo", "-n", "this is foo"})) 69 ds.RegisterDiagSource("bar", NewCommandSource("log", []string{"echo", "-n", "this is bar"})) 70 ds.RegisterDiagSource("simple_text", NewSimpleTextSource("txt", func() (string, error) { return "baz", nil })) 71 ds.RegisterDiagSource("fail", NewSimpleTextSource("txt", func() (string, error) { return "", errors.New("oops") })) 72 ds.RegisterDiagSource("logdir", NewLogDirSource(logDir)) 73 ds.RegisterDiagSource("stack", StackDumpSource) 74 s := NewServer(ds) 75 socketPath := filepath.Join(tmpDir, "diag.sock") 76 readyCh := make(chan struct{}) 77 go func() { 78 s.Serve(socketPath, readyCh) 79 }() 80 <-readyCh 81 return &diagTester{ 82 t: t, 83 tmpDir: tmpDir, 84 ds: ds, 85 s: s, 86 socketPath: socketPath, 87 logDir: logDir, 88 } 89 } 90 91 func (dt *diagTester) teardown() { 92 dt.s.Stop() 93 os.RemoveAll(dt.tmpDir) 94 } 95 96 func TestDiagServer(t *testing.T) { 97 dt := newDiagTester(t) 98 defer dt.teardown() 99 expectedResult := Result{ 100 Name: "diagnostics", 101 IsDir: true, 102 Children: map[string]Result{ 103 "foo": { 104 Name: "foo", 105 Ext: "txt", 106 Data: "this is foo", 107 }, 108 "bar": { 109 Name: "bar", 110 Ext: "log", 111 Data: "this is bar", 112 }, 113 "simple_text": { 114 Name: "simple_text", 115 Ext: "txt", 116 Data: "baz", 117 }, 118 "logdir": { 119 Name: "logdir", 120 IsDir: true, 121 Children: map[string]Result{ 122 "log1": { 123 Name: "log1", 124 Ext: "txt", 125 Data: "log1 contents", 126 }, 127 "log2": { 128 Name: "log2", 129 Ext: "txt", 130 Data: "log2 contents", 131 }, 132 }, 133 }, 134 "fail": { 135 Name: "fail", 136 Error: "oops", 137 }, 138 // stack is not compared because it's volatile 139 }, 140 } 141 dr, err := RetrieveDiagnostics(dt.socketPath) 142 if err != nil { 143 t.Fatalf("RetrieveDiagnostics(): %v", err) 144 } 145 if dr.Children != nil { 146 expectedSubstr := "TestDiagServer" 147 if !strings.Contains(dr.Children["stack"].Data, expectedSubstr) { 148 t.Errorf("Bad go stack: expected substring %q not found:\n%s", expectedSubstr, dr.Children["stack"].Data) 149 } 150 // dr.Children["stack"] is volatile and can't be 151 // compared reliably, so we remove it after checking it 152 // for the substring above. 153 delete(dr.Children, "stack") 154 } 155 if !reflect.DeepEqual(expectedResult, dr) { 156 t.Errorf("Bad diag result. Expected:\n%s--- got ---\n%s", spew.Sdump(expectedResult), spew.Sdump(dr)) 157 } 158 if err := dr.Unpack(dt.tmpDir); err != nil { 159 t.Fatalf("Unpack(): %v", err) 160 } 161 diagDir := filepath.Join(dt.tmpDir, "diagnostics") 162 expectedFiles := map[string]interface{}{ 163 "foo.txt": "this is foo", 164 "bar.log": "this is bar", 165 "simple_text.txt": "baz", 166 "logdir": map[string]interface{}{ 167 "log1.txt": "log1 contents", 168 "log2.txt": "log2 contents", 169 }, 170 } 171 files, err := testutils.DirToMap(diagDir) 172 if err != nil { 173 t.Fatalf("DirToMap(): %v", err) 174 } 175 if !reflect.DeepEqual(expectedFiles, files) { 176 t.Errorf("Bad dir structure after Unpack(). Expected:\n%s--- got ---\n%s", spew.Sdump(expectedFiles), spew.Sdump(files)) 177 } 178 }