github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/cmd/juju/debuglog_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"strings"
    11  
    12  	"github.com/juju/errors"
    13  	"github.com/juju/loggo"
    14  	jc "github.com/juju/testing/checkers"
    15  	gc "launchpad.net/gocheck"
    16  
    17  	"github.com/juju/juju/cmd"
    18  	"github.com/juju/juju/cmd/envcmd"
    19  	"github.com/juju/juju/state/api"
    20  	"github.com/juju/juju/testing"
    21  )
    22  
    23  type DebugLogSuite struct {
    24  	testing.FakeJujuHomeSuite
    25  }
    26  
    27  var _ = gc.Suite(&DebugLogSuite{})
    28  
    29  func (s *DebugLogSuite) TestArgParsing(c *gc.C) {
    30  	for i, test := range []struct {
    31  		args     []string
    32  		expected api.DebugLogParams
    33  		errMatch string
    34  	}{
    35  		{
    36  			expected: api.DebugLogParams{
    37  				Backlog: 10,
    38  			},
    39  		}, {
    40  			args: []string{"-n0"},
    41  		}, {
    42  			args: []string{"--lines=50"},
    43  			expected: api.DebugLogParams{
    44  				Backlog: 50,
    45  			},
    46  		}, {
    47  			args:     []string{"-l", "foo"},
    48  			errMatch: `level value "foo" is not one of "TRACE", "DEBUG", "INFO", "WARNING", "ERROR"`,
    49  		}, {
    50  			args: []string{"--level=INFO"},
    51  			expected: api.DebugLogParams{
    52  				Backlog: 10,
    53  				Level:   loggo.INFO,
    54  			},
    55  		}, {
    56  			args: []string{"--include", "machine-1", "-i", "machine-2"},
    57  			expected: api.DebugLogParams{
    58  				IncludeEntity: []string{"machine-1", "machine-2"},
    59  				Backlog:       10,
    60  			},
    61  		}, {
    62  			args: []string{"--exclude", "machine-1", "-x", "machine-2"},
    63  			expected: api.DebugLogParams{
    64  				ExcludeEntity: []string{"machine-1", "machine-2"},
    65  				Backlog:       10,
    66  			},
    67  		}, {
    68  			args: []string{"--include-module", "juju.foo", "--include-module", "unit"},
    69  			expected: api.DebugLogParams{
    70  				IncludeModule: []string{"juju.foo", "unit"},
    71  				Backlog:       10,
    72  			},
    73  		}, {
    74  			args: []string{"--exclude-module", "juju.foo", "--exclude-module", "unit"},
    75  			expected: api.DebugLogParams{
    76  				ExcludeModule: []string{"juju.foo", "unit"},
    77  				Backlog:       10,
    78  			},
    79  		}, {
    80  			args: []string{"--replay"},
    81  			expected: api.DebugLogParams{
    82  				Backlog: 10,
    83  				Replay:  true,
    84  			},
    85  		}, {
    86  			args: []string{"--limit", "100"},
    87  			expected: api.DebugLogParams{
    88  				Backlog: 10,
    89  				Limit:   100,
    90  			},
    91  		},
    92  	} {
    93  		c.Logf("test %v", i)
    94  		command := &DebugLogCommand{}
    95  		err := testing.InitCommand(envcmd.Wrap(command), test.args)
    96  		if test.errMatch == "" {
    97  			c.Check(err, gc.IsNil)
    98  			c.Check(command.params, jc.DeepEquals, test.expected)
    99  		} else {
   100  			c.Check(err, gc.ErrorMatches, test.errMatch)
   101  		}
   102  	}
   103  }
   104  
   105  func (s *DebugLogSuite) TestParamsPassed(c *gc.C) {
   106  	fake := &fakeDebugLogAPI{}
   107  	s.PatchValue(&getDebugLogAPI, func(envName string) (DebugLogAPI, error) {
   108  		return fake, nil
   109  	})
   110  	_, err := testing.RunCommand(c, envcmd.Wrap(&DebugLogCommand{}),
   111  		"-i", "machine-1*", "-x", "machine-1-lxc-1",
   112  		"--include-module=juju.provisioner",
   113  		"--lines=500",
   114  		"--level=WARNING",
   115  	)
   116  	c.Assert(err, gc.IsNil)
   117  	c.Assert(fake.params, gc.DeepEquals, api.DebugLogParams{
   118  		IncludeEntity: []string{"machine-1*"},
   119  		IncludeModule: []string{"juju.provisioner"},
   120  		ExcludeEntity: []string{"machine-1-lxc-1"},
   121  		Backlog:       500,
   122  		Level:         loggo.WARNING,
   123  	})
   124  }
   125  
   126  func (s *DebugLogSuite) TestLogOutput(c *gc.C) {
   127  	s.PatchValue(&getDebugLogAPI, func(envName string) (DebugLogAPI, error) {
   128  		return &fakeDebugLogAPI{log: "this is the log output"}, nil
   129  	})
   130  	ctx, err := testing.RunCommand(c, envcmd.Wrap(&DebugLogCommand{}))
   131  	c.Assert(err, gc.IsNil)
   132  	c.Assert(testing.Stdout(ctx), gc.Equals, "this is the log output")
   133  }
   134  
   135  func (s *DebugLogSuite) TestTailFallback(c *gc.C) {
   136  	s.PatchValue(&runSSHCommand, func(sshCmd *SSHCommand, ctx *cmd.Context) error {
   137  		fmt.Fprintf(ctx.Stdout, "%s", sshCmd.Args)
   138  		return nil
   139  	})
   140  	s.PatchValue(&getDebugLogAPI, func(envName string) (DebugLogAPI, error) {
   141  		return &fakeDebugLogAPI{err: errors.NotSupportedf("testing")}, nil
   142  	})
   143  	ctx, err := testing.RunCommand(c, envcmd.Wrap(&DebugLogCommand{}), "-n", "100")
   144  	c.Assert(err, gc.IsNil)
   145  	c.Check(testing.Stderr(ctx), gc.Equals, "Server does not support new stream log, falling back to tail\n")
   146  	c.Check(testing.Stdout(ctx), gc.Equals, "[tail -n -100 -f /var/log/juju/all-machines.log]")
   147  }
   148  
   149  func newFakeDebugLogAPI(log string) DebugLogAPI {
   150  	return &fakeDebugLogAPI{log: log}
   151  }
   152  
   153  type fakeDebugLogAPI struct {
   154  	log    string
   155  	params api.DebugLogParams
   156  	err    error
   157  }
   158  
   159  func (fake *fakeDebugLogAPI) WatchDebugLog(params api.DebugLogParams) (io.ReadCloser, error) {
   160  	if fake.err != nil {
   161  		return nil, fake.err
   162  	}
   163  	fake.params = params
   164  	return ioutil.NopCloser(strings.NewReader(fake.log)), nil
   165  }
   166  
   167  func (fake *fakeDebugLogAPI) Close() error {
   168  	return nil
   169  }