github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/romulus/agree/agree_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package agree_test
     5  
     6  import (
     7  	"runtime"
     8  	"sync"
     9  	"testing"
    10  
    11  	"github.com/juju/cmd"
    12  	"github.com/juju/cmd/cmdtesting"
    13  	"github.com/juju/terms-client/api"
    14  	"github.com/juju/terms-client/api/wireformat"
    15  	jujutesting "github.com/juju/testing"
    16  	jc "github.com/juju/testing/checkers"
    17  	gc "gopkg.in/check.v1"
    18  
    19  	"github.com/juju/juju/cmd/juju/romulus/agree"
    20  	"github.com/juju/juju/jujuclient"
    21  	coretesting "github.com/juju/juju/testing"
    22  )
    23  
    24  func TestPackage(t *testing.T) {
    25  	gc.TestingT(t)
    26  }
    27  
    28  var _ = gc.Suite(&agreeSuite{})
    29  
    30  var testTerms = "Test Terms"
    31  
    32  type agreeSuite struct {
    33  	client *mockClient
    34  	coretesting.FakeJujuXDGDataHomeSuite
    35  }
    36  
    37  func (s *agreeSuite) SetUpTest(c *gc.C) {
    38  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    39  	s.client = &mockClient{}
    40  
    41  	jujutesting.PatchValue(agree.ClientNew, func(...api.ClientOption) (api.Client, error) {
    42  		return s.client, nil
    43  	})
    44  }
    45  
    46  func (s *agreeSuite) TestAgreementNothingToSign(c *gc.C) {
    47  	jujutesting.PatchValue(agree.UserAnswer, func() (string, error) {
    48  		return "y", nil
    49  	})
    50  
    51  	s.client.user = "test-user"
    52  	s.client.setUnsignedTerms([]wireformat.GetTermsResponse{})
    53  
    54  	ctx, err := s.runCommand(c, "test-term/1")
    55  	c.Assert(err, jc.ErrorIsNil)
    56  	c.Assert(cmdtesting.Stdout(ctx), gc.Equals, `Already agreed
    57  `)
    58  }
    59  
    60  func (s *agreeSuite) TestAgreement(c *gc.C) {
    61  	if runtime.GOOS == "windows" {
    62  		c.Skip("less not on windows, bug 1614330")
    63  	}
    64  	var answer string
    65  	jujutesting.PatchValue(agree.UserAnswer, func() (string, error) {
    66  		return answer, nil
    67  	})
    68  
    69  	s.client.user = "test-user"
    70  	s.client.setUnsignedTerms([]wireformat.GetTermsResponse{{
    71  		Name:     "test-term",
    72  		Revision: 1,
    73  		Content:  testTerms,
    74  	}})
    75  	tests := []struct {
    76  		about       string
    77  		args        []string
    78  		err         string
    79  		stdout      string
    80  		answer      string
    81  		apiCalls    []jujutesting.StubCall
    82  		clientTerms []wireformat.GetTermsResponse
    83  	}{{
    84  		about:    "everything works",
    85  		args:     []string{"test-term/1", "--yes"},
    86  		stdout:   "Agreed to revision 1 of test-term for Juju users\n",
    87  		apiCalls: []jujutesting.StubCall{{FuncName: "SaveAgreement", Args: []interface{}{&wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{{TermName: "test-term", TermRevision: 1}}}}}},
    88  	}, {
    89  		about:    "everything works with owner term",
    90  		args:     []string{"owner/test-term/1", "--yes"},
    91  		stdout:   "Agreed to revision 1 of owner/test-term for Juju users\n",
    92  		apiCalls: []jujutesting.StubCall{{FuncName: "SaveAgreement", Args: []interface{}{&wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{{TermOwner: "owner", TermName: "test-term", TermRevision: 1}}}}}},
    93  	}, {
    94  		about: "cannot parse revision number",
    95  		args:  []string{"test-term/abc"},
    96  		err:   `must specify a valid term revision "test-term/abc"`,
    97  	}, {
    98  		about: "missing arguments",
    99  		args:  []string{},
   100  		err:   "missing arguments",
   101  	}, {
   102  		about:  "everything works - user accepts",
   103  		args:   []string{"test-term/1"},
   104  		answer: "y",
   105  		stdout: `
   106  === test-term/1: 0001-01-01 00:00:00 +0000 UTC ===
   107  Test Terms
   108  ========
   109  Do you agree to the displayed terms? (Y/n): Agreed to revision 1 of test-term for Juju users
   110  `,
   111  		apiCalls: []jujutesting.StubCall{{
   112  			FuncName: "GetUnunsignedTerms", Args: []interface{}{
   113  				&wireformat.CheckAgreementsRequest{Terms: []string{"test-term/1"}},
   114  			},
   115  		}, {
   116  			FuncName: "SaveAgreement", Args: []interface{}{
   117  				&wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{{TermName: "test-term", TermRevision: 1}}},
   118  			},
   119  		}},
   120  	}, {
   121  		about:  "everything works - user refuses",
   122  		args:   []string{"test-term/1"},
   123  		answer: "n",
   124  		stdout: `
   125  === test-term/1: 0001-01-01 00:00:00 +0000 UTC ===
   126  Test Terms
   127  ========
   128  Do you agree to the displayed terms? (Y/n): You didn't agree to the presented terms.
   129  `,
   130  		apiCalls: []jujutesting.StubCall{{
   131  			FuncName: "GetUnunsignedTerms", Args: []interface{}{
   132  				&wireformat.CheckAgreementsRequest{Terms: []string{"test-term/1"}},
   133  			},
   134  		}},
   135  	}, {
   136  		about: "must not accept 0 revision",
   137  		args:  []string{"test-term/0", "--yes"},
   138  		err:   `must specify a valid term revision "test-term/0"`,
   139  	}, {
   140  		about:  "user accepts, multiple terms",
   141  		args:   []string{"test-term/1", "test-term/2"},
   142  		answer: "y",
   143  		stdout: `
   144  === test-term/1: 0001-01-01 00:00:00 +0000 UTC ===
   145  Test Terms
   146  ========
   147  Do you agree to the displayed terms? (Y/n): Agreed to revision 1 of test-term for Juju users
   148  `,
   149  		apiCalls: []jujutesting.StubCall{
   150  			{
   151  				FuncName: "GetUnunsignedTerms", Args: []interface{}{
   152  					&wireformat.CheckAgreementsRequest{Terms: []string{"test-term/1", "test-term/2"}},
   153  				},
   154  			}, {
   155  				FuncName: "SaveAgreement", Args: []interface{}{
   156  					&wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{
   157  						{TermName: "test-term", TermRevision: 1},
   158  					}},
   159  				},
   160  			}},
   161  	}, {
   162  		about: "valid then unknown arguments",
   163  		args:  []string{"test-term/1", "unknown", "arguments"},
   164  		err:   `must specify a valid term revision "unknown"`,
   165  	}, {
   166  		about: "user accepts all the terms",
   167  		args:  []string{"test-term/1", "test-term/2", "--yes"},
   168  		stdout: `Agreed to revision 1 of test-term for Juju users
   169  Agreed to revision 2 of test-term for Juju users
   170  `,
   171  		apiCalls: []jujutesting.StubCall{
   172  			{FuncName: "SaveAgreement", Args: []interface{}{&wireformat.SaveAgreements{
   173  				Agreements: []wireformat.SaveAgreement{
   174  					{TermName: "test-term", TermRevision: 1},
   175  					{TermName: "test-term", TermRevision: 2},
   176  				}}}}},
   177  	}, {
   178  		about: "everything works with term owner - user accepts",
   179  		clientTerms: []wireformat.GetTermsResponse{{
   180  			Name:     "test-term",
   181  			Owner:    "test-owner",
   182  			Revision: 1,
   183  			Content:  testTerms,
   184  		}},
   185  		args:   []string{"test-owner/test-term/1"},
   186  		answer: "y",
   187  		stdout: `
   188  === test-owner/test-term/1: 0001-01-01 00:00:00 +0000 UTC ===
   189  Test Terms
   190  ========
   191  Do you agree to the displayed terms? (Y/n): Agreed to revision 1 of test-owner/test-term for Juju users
   192  `,
   193  		apiCalls: []jujutesting.StubCall{{
   194  			FuncName: "GetUnunsignedTerms", Args: []interface{}{
   195  				&wireformat.CheckAgreementsRequest{Terms: []string{"test-owner/test-term/1"}},
   196  			},
   197  		}, {
   198  			FuncName: "SaveAgreement", Args: []interface{}{
   199  				&wireformat.SaveAgreements{Agreements: []wireformat.SaveAgreement{{TermOwner: "test-owner", TermName: "test-term", TermRevision: 1}}},
   200  			},
   201  		}},
   202  	}}
   203  	for i, test := range tests {
   204  		s.client.ResetCalls()
   205  		if len(test.clientTerms) > 0 {
   206  			s.client.setUnsignedTerms(test.clientTerms)
   207  		}
   208  		c.Logf("running test %d: %s", i, test.about)
   209  		if test.answer != "" {
   210  			answer = test.answer
   211  		}
   212  		ctx, err := s.runCommand(c, test.args...)
   213  		if test.err != "" {
   214  			c.Assert(err, gc.ErrorMatches, test.err)
   215  		} else {
   216  			c.Assert(err, jc.ErrorIsNil)
   217  		}
   218  		if ctx != nil {
   219  			c.Assert(cmdtesting.Stdout(ctx), gc.Equals, test.stdout)
   220  		}
   221  		if len(test.apiCalls) > 0 {
   222  			s.client.CheckCalls(c, test.apiCalls)
   223  		}
   224  	}
   225  }
   226  
   227  func (s *agreeSuite) runCommand(c *gc.C, args ...string) (*cmd.Context, error) {
   228  	cmd := agree.NewAgreeCommand()
   229  	cmd.SetClientStore(newMockStore())
   230  	return cmdtesting.RunCommand(c, cmd, args...)
   231  }
   232  
   233  type mockClient struct {
   234  	api.Client
   235  	jujutesting.Stub
   236  
   237  	lock          sync.Mutex
   238  	user          string
   239  	terms         []wireformat.GetTermsResponse
   240  	unsignedTerms []wireformat.GetTermsResponse
   241  }
   242  
   243  func (c *mockClient) setUnsignedTerms(t []wireformat.GetTermsResponse) {
   244  	c.lock.Lock()
   245  	defer c.lock.Unlock()
   246  	c.unsignedTerms = t
   247  }
   248  
   249  // SaveAgreement saves user's agreement to the specified
   250  // revision of the terms documents
   251  func (c *mockClient) SaveAgreement(p *wireformat.SaveAgreements) (*wireformat.SaveAgreementResponses, error) {
   252  	c.AddCall("SaveAgreement", p)
   253  	responses := make([]wireformat.AgreementResponse, len(p.Agreements))
   254  	for i, agreement := range p.Agreements {
   255  		responses[i] = wireformat.AgreementResponse{
   256  			User:     c.user,
   257  			Owner:    agreement.TermOwner,
   258  			Term:     agreement.TermName,
   259  			Revision: agreement.TermRevision,
   260  		}
   261  	}
   262  	return &wireformat.SaveAgreementResponses{responses}, nil
   263  }
   264  
   265  func (c *mockClient) GetUnsignedTerms(p *wireformat.CheckAgreementsRequest) ([]wireformat.GetTermsResponse, error) {
   266  	c.MethodCall(c, "GetUnunsignedTerms", p)
   267  	r := make([]wireformat.GetTermsResponse, len(c.unsignedTerms))
   268  	copy(r, c.unsignedTerms)
   269  	return r, nil
   270  }
   271  
   272  func (c *mockClient) GetUsersAgreements() ([]wireformat.AgreementResponse, error) {
   273  	c.MethodCall(c, "GetUsersAgreements")
   274  	return []wireformat.AgreementResponse{}, nil
   275  }
   276  
   277  func newMockStore() *jujuclient.MemStore {
   278  	store := jujuclient.NewMemStore()
   279  	store.CurrentControllerName = "foo"
   280  	store.Controllers["foo"] = jujuclient.ControllerDetails{
   281  		APIEndpoints: []string{"0.1.2.3:1234"},
   282  	}
   283  	return store
   284  }