~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/state/linklayerdevices_internal_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2016 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package state
 
5
 
 
6
import (
 
7
        "strings"
 
8
 
 
9
        "github.com/juju/errors"
 
10
        "github.com/juju/testing"
 
11
        jc "github.com/juju/testing/checkers"
 
12
        gc "gopkg.in/check.v1"
 
13
 
 
14
        "github.com/juju/juju/network"
 
15
        coretesting "github.com/juju/juju/testing"
 
16
)
 
17
 
 
18
// linkLayerDevicesInternalSuite contains black-box tests for link-layer network
 
19
// devices' internals, which do not actually access mongo. The rest of the logic
 
20
// is tested in linkLayerDevicesStateSuite.
 
21
type linkLayerDevicesInternalSuite struct {
 
22
        testing.IsolationSuite
 
23
}
 
24
 
 
25
var _ = gc.Suite(&linkLayerDevicesInternalSuite{})
 
26
 
 
27
func (s *linkLayerDevicesInternalSuite) TestNewLinkLayerDeviceCreatesLinkLayerDevice(c *gc.C) {
 
28
        result := newLinkLayerDevice(nil, linkLayerDeviceDoc{})
 
29
        c.Assert(result, gc.NotNil)
 
30
        c.Assert(result.st, gc.IsNil)
 
31
        c.Assert(result.doc, jc.DeepEquals, linkLayerDeviceDoc{})
 
32
}
 
33
 
 
34
func (s *linkLayerDevicesInternalSuite) TestDocIDIncludesModelUUID(c *gc.C) {
 
35
        const localDocID = "foo"
 
36
        globalDocID := coretesting.ModelTag.Id() + ":" + localDocID
 
37
 
 
38
        result := s.newLinkLayerDeviceWithDummyState(linkLayerDeviceDoc{DocID: localDocID})
 
39
        c.Assert(result.DocID(), gc.Equals, globalDocID)
 
40
 
 
41
        result = s.newLinkLayerDeviceWithDummyState(linkLayerDeviceDoc{DocID: globalDocID})
 
42
        c.Assert(result.DocID(), gc.Equals, globalDocID)
 
43
}
 
44
 
 
45
func (s *linkLayerDevicesInternalSuite) newLinkLayerDeviceWithDummyState(doc linkLayerDeviceDoc) *LinkLayerDevice {
 
46
        // We only need the model UUID set for localID() and docID() to work.
 
47
        // The rest is tested in linkLayerDevicesStateSuite.
 
48
        dummyState := &State{modelTag: coretesting.ModelTag}
 
49
        return newLinkLayerDevice(dummyState, doc)
 
50
}
 
51
 
 
52
func (s *linkLayerDevicesInternalSuite) TestProviderIDIsEmptyWhenNotSet(c *gc.C) {
 
53
        result := s.newLinkLayerDeviceWithDummyState(linkLayerDeviceDoc{})
 
54
        c.Assert(result.ProviderID(), gc.Equals, network.Id(""))
 
55
}
 
56
 
 
57
func (s *linkLayerDevicesInternalSuite) TestProviderIDDoesNotIncludeModelUUIDWhenSet(c *gc.C) {
 
58
        const localProviderID = "foo"
 
59
        result := s.newLinkLayerDeviceWithDummyState(linkLayerDeviceDoc{ProviderID: localProviderID})
 
60
        c.Assert(result.ProviderID(), gc.Equals, network.Id(localProviderID))
 
61
 
 
62
}
 
63
 
 
64
func (s *linkLayerDevicesInternalSuite) TestParentDeviceReturnsNoErrorWhenParentNameNotSet(c *gc.C) {
 
65
        result := s.newLinkLayerDeviceWithDummyState(linkLayerDeviceDoc{})
 
66
        parent, err := result.ParentDevice()
 
67
        c.Check(parent, gc.IsNil)
 
68
        c.Check(err, jc.ErrorIsNil)
 
69
}
 
70
 
 
71
func (s *linkLayerDevicesInternalSuite) TestLinkLayerDeviceGlobalKeyHelper(c *gc.C) {
 
72
        result := linkLayerDeviceGlobalKey("42", "eno1")
 
73
        c.Assert(result, gc.Equals, "m#42#d#eno1")
 
74
 
 
75
        result = linkLayerDeviceGlobalKey("", "")
 
76
        c.Assert(result, gc.Equals, "")
 
77
}
 
78
 
 
79
func (s *linkLayerDevicesInternalSuite) TestGlobalKeyMethod(c *gc.C) {
 
80
        doc := linkLayerDeviceDoc{
 
81
                MachineID: "42",
 
82
                Name:      "foo",
 
83
        }
 
84
        config := s.newLinkLayerDeviceWithDummyState(doc)
 
85
        c.Check(config.globalKey(), gc.Equals, "m#42#d#foo")
 
86
 
 
87
        config = s.newLinkLayerDeviceWithDummyState(linkLayerDeviceDoc{})
 
88
        c.Check(config.globalKey(), gc.Equals, "")
 
89
}
 
90
 
 
91
func (s *linkLayerDevicesInternalSuite) TestParseLinkLayerParentNameAsGlobalKey(c *gc.C) {
 
92
        for i, test := range []struct {
 
93
                about              string
 
94
                input              string
 
95
                expectedError      string
 
96
                expectedMachineID  string
 
97
                expectedParentName string
 
98
        }{{
 
99
                about: "empty input - empty outputs and no error",
 
100
                input: "",
 
101
        }, {
 
102
                about: "name only as input - empty outputs and no error",
 
103
                input: "some-parent",
 
104
        }, {
 
105
                about:              "global key as input - parsed outputs and no error",
 
106
                input:              "m#42#d#br-eth1",
 
107
                expectedMachineID:  "42",
 
108
                expectedParentName: "br-eth1",
 
109
        }, {
 
110
                about:         "invalid name as input - empty outputs and NotValidError",
 
111
                input:         "some name with not enough # in it",
 
112
                expectedError: `ParentName "some name with not enough # in it" format not valid`,
 
113
        }, {
 
114
                about:         "almost a global key as input - empty outputs and NotValidError",
 
115
                input:         "x#foo#y#bar",
 
116
                expectedError: `ParentName "x#foo#y#bar" format not valid`,
 
117
        }} {
 
118
                c.Logf("test #%d: %q", i, test.about)
 
119
                gotMachineID, gotParentName, gotError := parseLinkLayerDeviceParentNameAsGlobalKey(test.input)
 
120
                if test.expectedError != "" {
 
121
                        c.Check(gotError, gc.ErrorMatches, test.expectedError)
 
122
                        c.Check(gotError, jc.Satisfies, errors.IsNotValid)
 
123
                } else {
 
124
                        c.Check(gotError, jc.ErrorIsNil)
 
125
                }
 
126
                c.Check(gotMachineID, gc.Equals, test.expectedMachineID)
 
127
                c.Check(gotParentName, gc.Equals, test.expectedParentName)
 
128
        }
 
129
}
 
130
 
 
131
func (s *linkLayerDevicesInternalSuite) TestStringIncludesTypeNameAndMachineID(c *gc.C) {
 
132
        doc := linkLayerDeviceDoc{
 
133
                MachineID: "42",
 
134
                Name:      "foo",
 
135
                Type:      BondDevice,
 
136
        }
 
137
        result := s.newLinkLayerDeviceWithDummyState(doc)
 
138
        expectedString := `bond device "foo" on machine "42"`
 
139
 
 
140
        c.Assert(result.String(), gc.Equals, expectedString)
 
141
}
 
142
 
 
143
func (s *linkLayerDevicesInternalSuite) TestRemainingSimpleGetterMethods(c *gc.C) {
 
144
        doc := linkLayerDeviceDoc{
 
145
                Name:        "bond0",
 
146
                MachineID:   "99",
 
147
                MTU:         uint(9000),
 
148
                Type:        BondDevice,
 
149
                MACAddress:  "aa:bb:cc:dd:ee:f0",
 
150
                IsAutoStart: true,
 
151
                IsUp:        true,
 
152
                ParentName:  "br-bond0",
 
153
        }
 
154
        result := s.newLinkLayerDeviceWithDummyState(doc)
 
155
 
 
156
        c.Check(result.Name(), gc.Equals, "bond0")
 
157
        c.Check(result.MachineID(), gc.Equals, "99")
 
158
        c.Check(result.MTU(), gc.Equals, uint(9000))
 
159
        c.Check(result.Type(), gc.Equals, BondDevice)
 
160
        c.Check(result.MACAddress(), gc.Equals, "aa:bb:cc:dd:ee:f0")
 
161
        c.Check(result.IsAutoStart(), jc.IsTrue)
 
162
        c.Check(result.IsUp(), jc.IsTrue)
 
163
        c.Check(result.ParentName(), gc.Equals, "br-bond0")
 
164
}
 
165
 
 
166
func (s *linkLayerDevicesInternalSuite) TestIsValidLinkLayerDeviceTypeWithValidValue(c *gc.C) {
 
167
        validTypes := []LinkLayerDeviceType{
 
168
                LoopbackDevice,
 
169
                EthernetDevice,
 
170
                VLAN_8021QDevice,
 
171
                BondDevice,
 
172
                BridgeDevice,
 
173
        }
 
174
 
 
175
        for _, value := range validTypes {
 
176
                result := IsValidLinkLayerDeviceType(string(value))
 
177
                c.Check(result, jc.IsTrue)
 
178
        }
 
179
}
 
180
 
 
181
func (s *linkLayerDevicesInternalSuite) TestIsValidLinkLayerDeviceTypeWithInvalidValue(c *gc.C) {
 
182
        result := IsValidLinkLayerDeviceType("")
 
183
        c.Check(result, jc.IsFalse)
 
184
 
 
185
        result = IsValidLinkLayerDeviceType("anything")
 
186
        c.Check(result, jc.IsFalse)
 
187
 
 
188
        result = IsValidLinkLayerDeviceType(" ")
 
189
        c.Check(result, jc.IsFalse)
 
190
 
 
191
        result = IsValidLinkLayerDeviceType("unknown")
 
192
        c.Check(result, jc.IsFalse)
 
193
}
 
194
 
 
195
func (s *linkLayerDevicesInternalSuite) TestIsValidLinkLayerDeviceNameWithUnpatchedGOOS(c *gc.C) {
 
196
        result := IsValidLinkLayerDeviceName("valid")
 
197
        c.Check(result, jc.IsTrue)
 
198
}
 
199
 
 
200
func (s *linkLayerDevicesInternalSuite) TestIsValidLinkLayerDeviceNameWithValidNamesWhenGOOSIsinux(c *gc.C) {
 
201
        s.PatchValue(&runtimeGOOS, "linux") // isolate the test from the host machine OS.
 
202
 
 
203
        for i, name := range validUnixDeviceNames {
 
204
                c.Logf("test #%d: %q -> valid", i, name)
 
205
                result := IsValidLinkLayerDeviceName(name)
 
206
                c.Check(result, jc.IsTrue)
 
207
        }
 
208
}
 
209
 
 
210
var validUnixDeviceNames = []string{
 
211
        "eth0", "eno1", "br-eth0.123", "tun:1", "bond0.42",
 
212
}
 
213
 
 
214
func (s *linkLayerDevicesInternalSuite) TestIsValidLinkLayerDeviceNameWithInvalidNamesWhenGOOIsLinux(c *gc.C) {
 
215
        s.PatchValue(&runtimeGOOS, "linux") // isolate the test from the host machine OS.
 
216
 
 
217
        result := IsValidLinkLayerDeviceName("")
 
218
        c.Check(result, jc.IsFalse)
 
219
 
 
220
        const tooLongLength = 16
 
221
        result = IsValidLinkLayerDeviceName(strings.Repeat("x", tooLongLength))
 
222
        c.Check(result, jc.IsFalse)
 
223
 
 
224
        result = IsValidLinkLayerDeviceName("with-hash#")
 
225
        c.Check(result, jc.IsFalse)
 
226
 
 
227
        result = IsValidLinkLayerDeviceName("has spaces")
 
228
        c.Check(result, jc.IsFalse)
 
229
 
 
230
        result = IsValidLinkLayerDeviceName("has\tabs")
 
231
        c.Check(result, jc.IsFalse)
 
232
 
 
233
        result = IsValidLinkLayerDeviceName("has\newline")
 
234
        c.Check(result, jc.IsFalse)
 
235
 
 
236
        result = IsValidLinkLayerDeviceName("has\r")
 
237
        c.Check(result, jc.IsFalse)
 
238
 
 
239
        result = IsValidLinkLayerDeviceName("has\vtab")
 
240
        c.Check(result, jc.IsFalse)
 
241
 
 
242
        result = IsValidLinkLayerDeviceName(".")
 
243
        c.Check(result, jc.IsFalse)
 
244
 
 
245
        result = IsValidLinkLayerDeviceName("..")
 
246
        c.Check(result, jc.IsFalse)
 
247
}
 
248
 
 
249
func (s *linkLayerDevicesInternalSuite) TestIsValidLinkLayerDeviceNameWithValidNamesWhenGOOSNonLinux(c *gc.C) {
 
250
        s.PatchValue(&runtimeGOOS, "non-linux") // isolate the test from the host machine OS.
 
251
        validDeviceNames := append(validUnixDeviceNames,
 
252
                // Windows network device as friendly name and as underlying UUID.
 
253
                "Local Area Connection", "{4a62b748-43d0-4136-92e4-22ce7ee31938}",
 
254
        )
 
255
 
 
256
        for i, name := range validDeviceNames {
 
257
                c.Logf("test #%d: %q -> valid", i, name)
 
258
                result := IsValidLinkLayerDeviceName(name)
 
259
                c.Check(result, jc.IsTrue)
 
260
        }
 
261
}
 
262
 
 
263
func (s *linkLayerDevicesInternalSuite) TestIsValidLinkLayerDeviceNameWhenGOOSNonLinux(c *gc.C) {
 
264
        s.PatchValue(&runtimeGOOS, "non-linux") // isolate the test from the host machine OS.
 
265
 
 
266
        result := IsValidLinkLayerDeviceName("")
 
267
        c.Check(result, jc.IsFalse)
 
268
 
 
269
        const wayTooLongLength = 1024
 
270
        result = IsValidLinkLayerDeviceName(strings.Repeat("x", wayTooLongLength))
 
271
        c.Check(result, jc.IsFalse)
 
272
 
 
273
        result = IsValidLinkLayerDeviceName("hash# not allowed")
 
274
        c.Check(result, jc.IsFalse)
 
275
}
 
276
 
 
277
func (s *linkLayerDevicesInternalSuite) TestStringLengthBetweenWhenTooShort(c *gc.C) {
 
278
        result := stringLengthBetween("", 1, 2)
 
279
        c.Check(result, jc.IsFalse)
 
280
 
 
281
        result = stringLengthBetween("", 1, 1)
 
282
        c.Check(result, jc.IsFalse)
 
283
 
 
284
        result = stringLengthBetween("1", 2, 3)
 
285
        c.Check(result, jc.IsFalse)
 
286
 
 
287
        result = stringLengthBetween("12", 3, 3)
 
288
        c.Check(result, jc.IsFalse)
 
289
}
 
290
 
 
291
func (s *linkLayerDevicesInternalSuite) TestStringLengthBetweenWhenTooLong(c *gc.C) {
 
292
        result := stringLengthBetween("1", 0, 0)
 
293
        c.Check(result, jc.IsFalse)
 
294
 
 
295
        result = stringLengthBetween("12", 1, 1)
 
296
        c.Check(result, jc.IsFalse)
 
297
 
 
298
        result = stringLengthBetween("123", 1, 2)
 
299
        c.Check(result, jc.IsFalse)
 
300
 
 
301
        result = stringLengthBetween("123", 0, 1)
 
302
        c.Check(result, jc.IsFalse)
 
303
}
 
304
 
 
305
func (s *linkLayerDevicesInternalSuite) TestStringLengthBetweenWhenWithinLimit(c *gc.C) {
 
306
        const (
 
307
                minLength = 1
 
308
                maxLength = 255
 
309
        )
 
310
        for i := minLength; i <= maxLength; i++ {
 
311
                input := strings.Repeat("x", i)
 
312
                result := stringLengthBetween(input, minLength, maxLength)
 
313
                c.Check(result, jc.IsTrue)
 
314
        }
 
315
}