github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/client/statushistory_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package client_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/names" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/apiserver/client" 15 "github.com/juju/juju/apiserver/params" 16 apiservertesting "github.com/juju/juju/apiserver/testing" 17 "github.com/juju/juju/status" 18 "github.com/juju/juju/testing" 19 ) 20 21 var _ = gc.Suite(&statusHistoryTestSuite{}) 22 23 type statusHistoryTestSuite struct { 24 testing.BaseSuite 25 st *mockState 26 api *client.Client 27 } 28 29 func (s *statusHistoryTestSuite) SetUpTest(c *gc.C) { 30 s.st = &mockState{} 31 client.PatchState(s, s.st) 32 tag := names.NewUserTag("user") 33 authorizer := &apiservertesting.FakeAuthorizer{Tag: tag} 34 var err error 35 s.api, err = client.NewClient(nil, nil, authorizer) 36 c.Assert(err, jc.ErrorIsNil) 37 } 38 39 func statusInfoWithDates(si []status.StatusInfo) []status.StatusInfo { 40 // Add timestamps to input status info records. 41 // Timestamps will be in descending order so that we can 42 // check that sorting has occurred and the output should 43 // be in ascending order. 44 result := make([]status.StatusInfo, len(si)) 45 for i, s := range si { 46 t := time.Unix(int64(1000-i), 0) 47 s.Since = &t 48 result[i] = s 49 } 50 return result 51 } 52 53 func reverseStatusInfo(si []status.StatusInfo) []status.StatusInfo { 54 result := make([]status.StatusInfo, len(si)) 55 for i, s := range si { 56 result[len(si)-i-1] = s 57 } 58 return result 59 } 60 61 func checkStatusInfo(c *gc.C, obtained []params.DetailedStatus, expected []status.StatusInfo) { 62 c.Assert(len(obtained), gc.Equals, len(expected)) 63 lastTimestamp := int64(0) 64 for i, obtainedInfo := range obtained { 65 c.Logf("Checking status %q with info %q", obtainedInfo.Status, obtainedInfo.Info) 66 thisTimeStamp := obtainedInfo.Since.Unix() 67 c.Assert(thisTimeStamp >= lastTimestamp, jc.IsTrue) 68 lastTimestamp = thisTimeStamp 69 obtainedInfo.Since = nil 70 c.Assert(obtainedInfo.Status, gc.Equals, status.Status(expected[i].Status)) 71 c.Assert(obtainedInfo.Info, gc.Equals, expected[i].Message) 72 } 73 } 74 75 func (s *statusHistoryTestSuite) TestSizeRequired(c *gc.C) { 76 _, err := s.api.StatusHistory(params.StatusHistoryArgs{ 77 Name: "unit", 78 Kind: params.KindUnit, 79 Size: 0, 80 }) 81 c.Assert(err, gc.ErrorMatches, "invalid history size: 0") 82 } 83 84 func (s *statusHistoryTestSuite) TestStatusHistoryUnitOnly(c *gc.C) { 85 s.st.unitHistory = statusInfoWithDates([]status.StatusInfo{ 86 { 87 Status: status.StatusMaintenance, 88 Message: "working", 89 }, 90 { 91 Status: status.StatusActive, 92 Message: "running", 93 }, 94 }) 95 s.st.agentHistory = statusInfoWithDates([]status.StatusInfo{ 96 { 97 Status: status.StatusIdle, 98 }, 99 }) 100 h, err := s.api.StatusHistory(params.StatusHistoryArgs{ 101 Name: "unit/0", 102 Kind: params.KindWorkload, 103 Size: 10, 104 }) 105 c.Assert(err, jc.ErrorIsNil) 106 checkStatusInfo(c, h.Statuses, reverseStatusInfo(s.st.unitHistory)) 107 } 108 109 func (s *statusHistoryTestSuite) TestStatusHistoryAgentOnly(c *gc.C) { 110 s.st.unitHistory = statusInfoWithDates([]status.StatusInfo{ 111 { 112 Status: status.StatusMaintenance, 113 Message: "working", 114 }, 115 { 116 Status: status.StatusActive, 117 Message: "running", 118 }, 119 }) 120 s.st.agentHistory = statusInfoWithDates([]status.StatusInfo{ 121 { 122 Status: status.StatusExecuting, 123 }, 124 { 125 Status: status.StatusIdle, 126 }, 127 }) 128 h, err := s.api.StatusHistory(params.StatusHistoryArgs{ 129 Name: "unit/0", 130 Kind: params.KindUnitAgent, 131 Size: 10, 132 }) 133 c.Assert(err, jc.ErrorIsNil) 134 checkStatusInfo(c, h.Statuses, reverseStatusInfo(s.st.agentHistory)) 135 } 136 137 func (s *statusHistoryTestSuite) TestStatusHistoryCombined(c *gc.C) { 138 s.st.unitHistory = statusInfoWithDates([]status.StatusInfo{ 139 { 140 Status: status.StatusMaintenance, 141 Message: "working", 142 }, 143 { 144 Status: status.StatusActive, 145 Message: "running", 146 }, 147 { 148 Status: status.StatusBlocked, 149 Message: "waiting", 150 }, 151 }) 152 s.st.agentHistory = statusInfoWithDates([]status.StatusInfo{ 153 { 154 Status: status.StatusExecuting, 155 }, 156 { 157 Status: status.StatusIdle, 158 }, 159 }) 160 h, err := s.api.StatusHistory(params.StatusHistoryArgs{ 161 Name: "unit/0", 162 Kind: params.KindUnit, 163 Size: 3, 164 }) 165 c.Assert(err, jc.ErrorIsNil) 166 expected := []status.StatusInfo{ 167 s.st.agentHistory[1], 168 s.st.unitHistory[0], 169 s.st.agentHistory[0], 170 } 171 checkStatusInfo(c, h.Statuses, expected) 172 } 173 174 type mockState struct { 175 client.StateInterface 176 unitHistory []status.StatusInfo 177 agentHistory []status.StatusInfo 178 } 179 180 func (m *mockState) ModelUUID() string { 181 return "uuid" 182 } 183 184 func (m *mockState) Unit(name string) (client.Unit, error) { 185 if name != "unit/0" { 186 return nil, errors.NotFoundf("%v", name) 187 } 188 return &mockUnit{ 189 status: m.unitHistory, 190 agent: &mockUnitAgent{m.agentHistory}, 191 }, nil 192 } 193 194 type mockUnit struct { 195 status statuses 196 agent *mockUnitAgent 197 client.Unit 198 } 199 200 func (m *mockUnit) StatusHistory(size int) ([]status.StatusInfo, error) { 201 return m.status.StatusHistory(size) 202 } 203 204 func (m *mockUnit) AgentHistory() status.StatusHistoryGetter { 205 return m.agent 206 } 207 208 type mockUnitAgent struct { 209 statuses 210 } 211 212 type statuses []status.StatusInfo 213 214 func (s statuses) StatusHistory(size int) ([]status.StatusInfo, error) { 215 if size > len(s) { 216 size = len(s) 217 } 218 return s[:size], nil 219 }