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  }