github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/apiserver/params/params_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package params_test
     5  
     6  import (
     7  	"encoding/json"
     8  	stdtesting "testing"
     9  
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/juju/charm.v5"
    13  
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/constraints"
    16  	"github.com/juju/juju/instance"
    17  	"github.com/juju/juju/network"
    18  	"github.com/juju/juju/state"
    19  	"github.com/juju/juju/state/multiwatcher"
    20  	"github.com/juju/juju/testing"
    21  )
    22  
    23  // TestPackage integrates the tests into gotest.
    24  func TestPackage(t *stdtesting.T) {
    25  	gc.TestingT(t)
    26  }
    27  
    28  type MarshalSuite struct{}
    29  
    30  var _ = gc.Suite(&MarshalSuite{})
    31  
    32  var marshalTestCases = []struct {
    33  	about string
    34  	// Value holds a real Go struct.
    35  	value multiwatcher.Delta
    36  	// JSON document.
    37  	json string
    38  }{{
    39  	about: "MachineInfo Delta",
    40  	value: multiwatcher.Delta{
    41  		Entity: &multiwatcher.MachineInfo{
    42  			Id:                      "Benji",
    43  			InstanceId:              "Shazam",
    44  			Status:                  "error",
    45  			StatusInfo:              "foo",
    46  			Life:                    multiwatcher.Life("alive"),
    47  			Series:                  "trusty",
    48  			SupportedContainers:     []instance.ContainerType{instance.LXC},
    49  			Jobs:                    []multiwatcher.MachineJob{state.JobManageEnviron.ToParams()},
    50  			Addresses:               []network.Address{},
    51  			HardwareCharacteristics: &instance.HardwareCharacteristics{},
    52  		},
    53  	},
    54  	json: `["machine","change",{"Id":"Benji","InstanceId":"Shazam","HasVote":false,"WantsVote":false,"Status":"error","StatusInfo":"foo","StatusData":null,"Life":"alive","Series":"trusty","SupportedContainers":["lxc"],"SupportedContainersKnown":false,"Jobs":["JobManageEnviron"],"Addresses":[],"HardwareCharacteristics":{}}]`,
    55  }, {
    56  	about: "ServiceInfo Delta",
    57  	value: multiwatcher.Delta{
    58  		Entity: &multiwatcher.ServiceInfo{
    59  			Name:        "Benji",
    60  			Exposed:     true,
    61  			CharmURL:    "cs:quantal/name",
    62  			Life:        multiwatcher.Life("dying"),
    63  			OwnerTag:    "test-owner",
    64  			MinUnits:    42,
    65  			Constraints: constraints.MustParse("arch=armhf mem=1024M"),
    66  			Config: charm.Settings{
    67  				"hello": "goodbye",
    68  				"foo":   false,
    69  			},
    70  			Status: multiwatcher.StatusInfo{
    71  				Current: multiwatcher.Status("active"),
    72  				Message: "all good",
    73  			},
    74  		},
    75  	},
    76  	json: `["service","change",{"CharmURL": "cs:quantal/name","Name":"Benji","Exposed":true,"Life":"dying","OwnerTag":"test-owner","MinUnits":42,"Constraints":{"arch":"armhf", "mem": 1024},"Config": {"hello":"goodbye","foo":false},"Subordinate":false,"Status":{"Current":"active", "Message":"all good", "Version": "", "Err": null, "Data": null, "Since": null}}]`,
    77  }, {
    78  	about: "UnitInfo Delta",
    79  	value: multiwatcher.Delta{
    80  		Entity: &multiwatcher.UnitInfo{
    81  			Name:     "Benji",
    82  			Service:  "Shazam",
    83  			Series:   "precise",
    84  			CharmURL: "cs:~user/precise/wordpress-42",
    85  			Ports: []network.Port{{
    86  				Protocol: "http",
    87  				Number:   80,
    88  			}},
    89  			PortRanges: []network.PortRange{{
    90  				FromPort: 80,
    91  				ToPort:   80,
    92  				Protocol: "http",
    93  			}},
    94  			PublicAddress:  "testing.invalid",
    95  			PrivateAddress: "10.0.0.1",
    96  			MachineId:      "1",
    97  			Status:         "error",
    98  			StatusInfo:     "foo",
    99  			WorkloadStatus: multiwatcher.StatusInfo{
   100  				Current: multiwatcher.Status("active"),
   101  				Message: "all good",
   102  			},
   103  			AgentStatus: multiwatcher.StatusInfo{
   104  				Current: multiwatcher.Status("idle"),
   105  			},
   106  		},
   107  	},
   108  	json: `["unit", "change", {"CharmURL": "cs:~user/precise/wordpress-42", "MachineId": "1", "Series": "precise", "Name": "Benji", "PublicAddress": "testing.invalid", "Service": "Shazam", "PrivateAddress": "10.0.0.1", "Ports": [{"Protocol": "http", "Number": 80}], "PortRanges": [{"FromPort": 80, "ToPort": 80, "Protocol": "http"}], "Status": "error", "StatusInfo": "foo", "StatusData": null, "WorkloadStatus":{"Current":"active", "Message":"all good", "Version": "", "Err": null, "Data": null, "Since": null}, "AgentStatus":{"Current":"idle", "Message":"", "Version": "", "Err": null, "Data": null, "Since": null}, "Subordinate": false}]`,
   109  }, {
   110  	about: "RelationInfo Delta",
   111  	value: multiwatcher.Delta{
   112  		Entity: &multiwatcher.RelationInfo{
   113  			Key: "Benji",
   114  			Id:  4711,
   115  			Endpoints: []multiwatcher.Endpoint{
   116  				{ServiceName: "logging", Relation: charm.Relation{Name: "logging-directory", Role: "requirer", Interface: "logging", Optional: false, Limit: 1, Scope: "container"}},
   117  				{ServiceName: "wordpress", Relation: charm.Relation{Name: "logging-dir", Role: "provider", Interface: "logging", Optional: false, Limit: 0, Scope: "container"}}},
   118  		},
   119  	},
   120  	json: `["relation","change",{"Key":"Benji", "Id": 4711, "Endpoints": [{"ServiceName":"logging", "Relation":{"Name":"logging-directory", "Role":"requirer", "Interface":"logging", "Optional":false, "Limit":1, "Scope":"container"}}, {"ServiceName":"wordpress", "Relation":{"Name":"logging-dir", "Role":"provider", "Interface":"logging", "Optional":false, "Limit":0, "Scope":"container"}}]}]`,
   121  }, {
   122  	about: "AnnotationInfo Delta",
   123  	value: multiwatcher.Delta{
   124  		Entity: &multiwatcher.AnnotationInfo{
   125  			Tag: "machine-0",
   126  			Annotations: map[string]string{
   127  				"foo":   "bar",
   128  				"arble": "2 4",
   129  			},
   130  		},
   131  	},
   132  	json: `["annotation","change",{"Tag":"machine-0","Annotations":{"foo":"bar","arble":"2 4"}}]`,
   133  }, {
   134  	about: "Delta Removed True",
   135  	value: multiwatcher.Delta{
   136  		Removed: true,
   137  		Entity: &multiwatcher.RelationInfo{
   138  			Key: "Benji",
   139  		},
   140  	},
   141  	json: `["relation","remove",{"Key":"Benji", "Id": 0, "Endpoints": null}]`,
   142  }}
   143  
   144  func (s *MarshalSuite) TestDeltaMarshalJSON(c *gc.C) {
   145  	for _, t := range marshalTestCases {
   146  		c.Log(t.about)
   147  		output, err := t.value.MarshalJSON()
   148  		c.Check(err, jc.ErrorIsNil)
   149  		// We check unmarshalled output both to reduce the fragility of the
   150  		// tests (because ordering in the maps can change) and to verify that
   151  		// the output is well-formed.
   152  		var unmarshalledOutput interface{}
   153  		err = json.Unmarshal(output, &unmarshalledOutput)
   154  		c.Check(err, jc.ErrorIsNil)
   155  		var expected interface{}
   156  		err = json.Unmarshal([]byte(t.json), &expected)
   157  		c.Check(err, jc.ErrorIsNil)
   158  		c.Check(unmarshalledOutput, jc.DeepEquals, expected)
   159  	}
   160  }
   161  
   162  func (s *MarshalSuite) TestDeltaUnmarshalJSON(c *gc.C) {
   163  	for i, t := range marshalTestCases {
   164  		c.Logf("test %d. %s", i, t.about)
   165  		var unmarshalled multiwatcher.Delta
   166  		err := json.Unmarshal([]byte(t.json), &unmarshalled)
   167  		c.Check(err, jc.ErrorIsNil)
   168  		c.Check(unmarshalled, gc.DeepEquals, t.value)
   169  	}
   170  }
   171  
   172  func (s *MarshalSuite) TestDeltaMarshalJSONCardinality(c *gc.C) {
   173  	err := json.Unmarshal([]byte(`[1,2]`), new(multiwatcher.Delta))
   174  	c.Check(err, gc.ErrorMatches, "Expected 3 elements in top-level of JSON but got 2")
   175  }
   176  
   177  func (s *MarshalSuite) TestDeltaMarshalJSONUnknownOperation(c *gc.C) {
   178  	err := json.Unmarshal([]byte(`["relation","masticate",{}]`), new(multiwatcher.Delta))
   179  	c.Check(err, gc.ErrorMatches, `Unexpected operation "masticate"`)
   180  }
   181  
   182  func (s *MarshalSuite) TestDeltaMarshalJSONUnknownEntity(c *gc.C) {
   183  	err := json.Unmarshal([]byte(`["qwan","change",{}]`), new(multiwatcher.Delta))
   184  	c.Check(err, gc.ErrorMatches, `Unexpected entity name "qwan"`)
   185  }
   186  
   187  type ErrorResultsSuite struct{}
   188  
   189  var _ = gc.Suite(&ErrorResultsSuite{})
   190  
   191  func (s *ErrorResultsSuite) TestOneError(c *gc.C) {
   192  	for i, test := range []struct {
   193  		results  params.ErrorResults
   194  		errMatch string
   195  	}{
   196  		{
   197  			errMatch: "expected 1 result, got 0",
   198  		}, {
   199  			results: params.ErrorResults{
   200  				[]params.ErrorResult{{nil}},
   201  			},
   202  		}, {
   203  			results: params.ErrorResults{
   204  				[]params.ErrorResult{{nil}, {nil}},
   205  			},
   206  			errMatch: "expected 1 result, got 2",
   207  		}, {
   208  			results: params.ErrorResults{
   209  				[]params.ErrorResult{
   210  					{&params.Error{Message: "test error"}},
   211  				},
   212  			},
   213  			errMatch: "test error",
   214  		},
   215  	} {
   216  		c.Logf("test %d", i)
   217  		err := test.results.OneError()
   218  		if test.errMatch == "" {
   219  			c.Check(err, jc.ErrorIsNil)
   220  		} else {
   221  			c.Check(err, gc.ErrorMatches, test.errMatch)
   222  		}
   223  	}
   224  }
   225  
   226  func (s *ErrorResultsSuite) TestCombine(c *gc.C) {
   227  	for i, test := range []struct {
   228  		msg      string
   229  		results  params.ErrorResults
   230  		errMatch string
   231  	}{
   232  		{
   233  			msg: "no results, no error",
   234  		}, {
   235  			msg: "single nil result",
   236  			results: params.ErrorResults{
   237  				[]params.ErrorResult{{nil}},
   238  			},
   239  		}, {
   240  			msg: "multiple nil results",
   241  			results: params.ErrorResults{
   242  				[]params.ErrorResult{{nil}, {nil}},
   243  			},
   244  		}, {
   245  			msg: "one error result",
   246  			results: params.ErrorResults{
   247  				[]params.ErrorResult{
   248  					{&params.Error{Message: "test error"}},
   249  				},
   250  			},
   251  			errMatch: "test error",
   252  		}, {
   253  			msg: "mixed error results",
   254  			results: params.ErrorResults{
   255  				[]params.ErrorResult{
   256  					{&params.Error{Message: "test error"}},
   257  					{nil},
   258  					{&params.Error{Message: "second error"}},
   259  				},
   260  			},
   261  			errMatch: "test error\nsecond error",
   262  		},
   263  	} {
   264  		c.Logf("test %d: %s", i, test.msg)
   265  		err := test.results.Combine()
   266  		if test.errMatch == "" {
   267  			c.Check(err, jc.ErrorIsNil)
   268  		} else {
   269  			c.Check(err, gc.ErrorMatches, test.errMatch)
   270  		}
   271  	}
   272  }
   273  
   274  type importSuite struct{}
   275  
   276  var _ = gc.Suite(&importSuite{})
   277  
   278  func (*importSuite) TestParamsDoesNotDependOnState(c *gc.C) {
   279  	imports := testing.FindJujuCoreImports(c, "github.com/juju/juju/apiserver/params")
   280  	for _, i := range imports {
   281  		c.Assert(i, gc.Not(gc.Equals), "state")
   282  	}
   283  }