github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/network/debinterfaces/parser_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package debinterfaces_test 5 6 import ( 7 "fmt" 8 "io/ioutil" 9 "path/filepath" 10 "runtime" 11 12 "github.com/juju/testing" 13 "github.com/pkg/errors" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/network/debinterfaces" 17 ) 18 19 type ParserSuite struct { 20 testing.IsolationSuite 21 22 expander debinterfaces.WordExpander 23 } 24 25 var _ = gc.Suite(&ParserSuite{}) 26 27 // Ensure wordExpanderWithError is a WordExpander 28 var _ debinterfaces.WordExpander = (*wordExpanderErrors)(nil) 29 30 type wordExpanderErrors struct { 31 errmsg string 32 } 33 34 func wordExpanderWithError(errmsg string) debinterfaces.WordExpander { 35 return &wordExpanderErrors{errmsg: errmsg} 36 } 37 38 func (w *wordExpanderErrors) Expand(s string) ([]string, error) { 39 return nil, errors.Errorf("word expansion failed: %s", w.errmsg) 40 } 41 42 func (s *ParserSuite) SetUpTest(c *gc.C) { 43 s.expander = debinterfaces.NewWordExpander() 44 } 45 46 func (s *ParserSuite) TestNilInput(c *gc.C) { 47 interfaces, err := debinterfaces.ParseSource("", nil, s.expander) 48 c.Assert(interfaces, gc.IsNil) 49 c.Check(err, gc.ErrorMatches, "filename and input is nil") 50 } 51 52 func (s *ParserSuite) TestNilInputAndNoFilename(c *gc.C) { 53 stanzas, err := debinterfaces.ParseSource("", "", s.expander) 54 c.Assert(err, gc.IsNil) 55 c.Check(stanzas, gc.HasLen, 0) 56 } 57 58 func (s *ParserSuite) TestUnsupportedInputType(c *gc.C) { 59 stanzas, err := debinterfaces.ParseSource("", []float64{3.141}, s.expander) 60 c.Assert(err, gc.ErrorMatches, "invalid source type") 61 c.Check(stanzas, gc.IsNil) 62 } 63 64 func (s *ParserSuite) TestFilenameEmpty(c *gc.C) { 65 emptyFile := filepath.Join(c.MkDir(), "TestFilenameEmpty") 66 err := ioutil.WriteFile(emptyFile, []byte(""), 0644) 67 c.Assert(err, gc.IsNil) 68 stanzas, err := debinterfaces.ParseSource(emptyFile, nil, s.expander) 69 c.Assert(err, gc.IsNil) 70 c.Check(stanzas, gc.HasLen, 0) 71 } 72 73 func (s *ParserSuite) TestParseErrorObject(c *gc.C) { 74 content := `hunky dory` 75 _, err := debinterfaces.ParseSource("", content, s.expander) 76 c.Assert(err, gc.NotNil) 77 _, parseError := err.(*debinterfaces.ParseError) 78 c.Assert(parseError, gc.NotNil) 79 c.Assert(err, gc.ErrorMatches, "misplaced option") 80 } 81 82 func (s *ParserSuite) TestCommentsAndBlankLinesOnly(c *gc.C) { 83 content := ` 84 85 # Comment 1. 86 87 # Comment 2, after empty line. 88 89 # An indented comment, followed by a line with leading whitespace 90 91 ` 92 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 93 c.Assert(err, gc.IsNil) 94 c.Assert(stanzas, gc.HasLen, 0) 95 } 96 97 func (s *ParserSuite) TestAllowStanzaMissingArg(c *gc.C) { 98 _, err := debinterfaces.ParseSource("", "allow-hotplug", s.expander) 99 c.Assert(err, gc.NotNil) 100 c.Check(err, gc.ErrorMatches, "missing device name") 101 } 102 103 func (s *ParserSuite) TestAutoStanzaMissingArg(c *gc.C) { 104 _, err := debinterfaces.ParseSource("", "auto", s.expander) 105 c.Assert(err, gc.NotNil) 106 c.Check(err, gc.ErrorMatches, "missing device name") 107 } 108 109 func (s *ParserSuite) TestIfaceStanzaMissingArg(c *gc.C) { 110 _, err := debinterfaces.ParseSource("", "iface", s.expander) 111 c.Assert(err, gc.NotNil) 112 c.Check(err, gc.ErrorMatches, "missing device name") 113 } 114 115 func (s *ParserSuite) TestMappingStanzaMissingArg(c *gc.C) { 116 _, err := debinterfaces.ParseSource("", "mapping", s.expander) 117 c.Assert(err, gc.NotNil) 118 c.Check(err, gc.ErrorMatches, "missing device name") 119 } 120 121 func (s *ParserSuite) TestNoAutoDownStanzaMissingArg(c *gc.C) { 122 _, err := debinterfaces.ParseSource("", "no-auto-down", s.expander) 123 c.Assert(err, gc.NotNil) 124 c.Check(err, gc.ErrorMatches, "missing device name") 125 } 126 127 func (s *ParserSuite) TestNoScriptsStanzaMissingArg(c *gc.C) { 128 _, err := debinterfaces.ParseSource("", "no-scripts", s.expander) 129 c.Assert(err, gc.NotNil) 130 c.Check(err, gc.ErrorMatches, "missing device name") 131 } 132 133 func (s *ParserSuite) TestSourceStanzaMissingArg(c *gc.C) { 134 _, err := debinterfaces.ParseSource("", "source", s.expander) 135 c.Assert(err, gc.NotNil) 136 c.Check(err, gc.ErrorMatches, "missing filename") 137 } 138 139 func (s *ParserSuite) TestSourceDirectoryStanzaMissingArg(c *gc.C) { 140 _, err := debinterfaces.ParseSource("", "source-directory", s.expander) 141 c.Assert(err, gc.NotNil) 142 c.Check(err, gc.ErrorMatches, "missing directory") 143 } 144 145 func (s *ParserSuite) TestAllowStanza(c *gc.C) { 146 definition := "allow-hotplug eth0 eth1 eth2" 147 stanzas, err := debinterfaces.ParseSource("", definition, s.expander) 148 c.Assert(err, gc.IsNil) 149 c.Assert(stanzas, gc.HasLen, 1) 150 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.AllowStanza{}) 151 allow := stanzas[0].(debinterfaces.AllowStanza) 152 c.Check(allow.Location().Filename, gc.Equals, "") 153 c.Check(allow.Location().LineNum, gc.Equals, 1) 154 c.Assert(allow.Definition(), gc.HasLen, 1) 155 c.Check(allow.Definition()[0], gc.Equals, definition) 156 c.Check(allow.DeviceNames, gc.DeepEquals, []string{"eth0", "eth1", "eth2"}) 157 } 158 159 func (s *ParserSuite) TestAutoStanza(c *gc.C) { 160 definition := "auto eth0 eth1 eth2" 161 stanzas, err := debinterfaces.ParseSource("", definition, s.expander) 162 c.Assert(err, gc.IsNil) 163 c.Assert(stanzas, gc.HasLen, 1) 164 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 165 auto := stanzas[0].(debinterfaces.AutoStanza) 166 c.Check(auto.Location().Filename, gc.Equals, "") 167 c.Check(auto.Location().LineNum, gc.Equals, 1) 168 c.Assert(auto.Definition(), gc.HasLen, 1) 169 c.Check(auto.Definition()[0], gc.Equals, definition) 170 c.Check(auto.DeviceNames, gc.DeepEquals, []string{"eth0", "eth1", "eth2"}) 171 } 172 173 func (s *ParserSuite) TestWithIfaceStanzaAndOneOption(c *gc.C) { 174 content := ` 175 iface eth0 inet manual 176 # A comment. 177 address 192.168.1.254/24 ` 178 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 179 c.Assert(err, gc.IsNil) 180 c.Assert(stanzas, gc.HasLen, 1) 181 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 182 iface := stanzas[0].(debinterfaces.IfaceStanza) 183 c.Assert(iface.Definition(), gc.HasLen, 2) 184 c.Check(iface.Definition()[0], gc.Equals, "iface eth0 inet manual") 185 c.Check(iface.Definition()[1], gc.Equals, "address 192.168.1.254/24") 186 c.Check(iface.Location().Filename, gc.Equals, "") 187 c.Check(iface.Location().LineNum, gc.Equals, 2) 188 c.Check(iface.Options, gc.HasLen, 1) 189 c.Check(iface.Options[0], gc.Equals, "address 192.168.1.254/24") 190 c.Check(iface.HasBondMasterOption, gc.Equals, false) 191 c.Check(iface.HasBondOptions, gc.Equals, false) 192 c.Check(iface.IsAlias, gc.Equals, false) 193 c.Check(iface.IsBridged, gc.Equals, false) 194 c.Check(iface.IsVLAN, gc.Equals, false) 195 } 196 197 func (s *ParserSuite) TestWithIfaceStanzaAndMultipleOptions(c *gc.C) { 198 content := ` 199 iface eth0 inet manual 200 # A comment. 201 address 192.168.1.254/24 202 dns-nameservers 8.8.8.8 203 # Another comment. 204 dns-search ubuntu.com 205 # An ending comment` 206 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 207 c.Assert(err, gc.IsNil) 208 c.Assert(stanzas, gc.HasLen, 1) 209 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 210 iface := stanzas[0].(debinterfaces.IfaceStanza) 211 c.Assert(iface.Definition(), gc.HasLen, 4) 212 c.Check(iface.Definition()[0], gc.Equals, "iface eth0 inet manual") 213 c.Check(iface.Definition()[1], gc.Equals, "address 192.168.1.254/24") 214 c.Check(iface.Definition()[2], gc.Equals, "dns-nameservers 8.8.8.8") 215 c.Check(iface.Definition()[3], gc.Equals, "dns-search ubuntu.com") 216 c.Check(iface.Location().Filename, gc.Equals, "") 217 c.Check(iface.Location().LineNum, gc.Equals, 2) 218 c.Assert(iface.Options, gc.HasLen, 3) 219 c.Check(iface.Options[0], gc.Equals, "address 192.168.1.254/24") 220 c.Check(iface.Options[1], gc.Equals, "dns-nameservers 8.8.8.8") 221 c.Check(iface.Options[2], gc.Equals, "dns-search ubuntu.com") 222 c.Check(iface.HasBondMasterOption, gc.Equals, false) 223 c.Check(iface.HasBondOptions, gc.Equals, false) 224 c.Check(iface.IsAlias, gc.Equals, false) 225 c.Check(iface.IsBridged, gc.Equals, false) 226 c.Check(iface.IsVLAN, gc.Equals, false) 227 } 228 229 func (s *ParserSuite) TestWithIfaceStanzaAndNoOptions(c *gc.C) { 230 content := ` 231 iface eth0 inet manual 232 # A comment.` 233 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 234 c.Assert(err, gc.IsNil) 235 c.Assert(stanzas, gc.HasLen, 1) 236 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 237 iface := stanzas[0].(debinterfaces.IfaceStanza) 238 c.Assert(iface.Definition(), gc.HasLen, 1) 239 c.Check(iface.Definition()[0], gc.Equals, "iface eth0 inet manual") 240 c.Check(iface.Location().Filename, gc.Equals, "") 241 c.Check(iface.Location().LineNum, gc.Equals, 2) 242 c.Check(iface.Options, gc.HasLen, 0) 243 c.Check(iface.HasBondMasterOption, gc.Equals, false) 244 c.Check(iface.HasBondOptions, gc.Equals, false) 245 c.Check(iface.IsAlias, gc.Equals, false) 246 c.Check(iface.IsBridged, gc.Equals, false) 247 c.Check(iface.IsVLAN, gc.Equals, false) 248 } 249 250 func (s *ParserSuite) TestAutoStanzaFollowedByIfaceStanza(c *gc.C) { 251 content := ` 252 auto eth0 253 254 iface eth0 inet static 255 address 192.168.1.254/24 256 gateway 192.168.1.1` 257 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 258 c.Assert(err, gc.IsNil) 259 c.Assert(stanzas, gc.HasLen, 2) 260 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 261 c.Assert(stanzas[1], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 262 263 auto := stanzas[0].(debinterfaces.AutoStanza) 264 c.Assert(auto.Definition(), gc.HasLen, 1) 265 c.Check(auto.Definition()[0], gc.Equals, "auto eth0") 266 c.Check(auto.Location().Filename, gc.Equals, "") 267 c.Check(auto.Location().LineNum, gc.Equals, 2) 268 269 iface := stanzas[1].(debinterfaces.IfaceStanza) 270 c.Assert(iface.Definition(), gc.HasLen, 3) 271 c.Check(iface.Definition()[0], gc.Equals, "iface eth0 inet static") 272 c.Check(iface.Definition()[1], gc.Equals, "address 192.168.1.254/24") 273 c.Check(iface.Definition()[2], gc.Equals, "gateway 192.168.1.1") 274 c.Check(iface.Location().Filename, gc.Equals, "") 275 c.Check(iface.Location().LineNum, gc.Equals, 4) 276 c.Assert(iface.Options, gc.HasLen, 2) 277 c.Check(iface.Options[0], gc.Equals, "address 192.168.1.254/24") 278 c.Check(iface.Options[1], gc.Equals, "gateway 192.168.1.1") 279 c.Check(iface.HasBondMasterOption, gc.Equals, false) 280 c.Check(iface.HasBondOptions, gc.Equals, false) 281 c.Check(iface.IsAlias, gc.Equals, false) 282 c.Check(iface.IsBridged, gc.Equals, false) 283 c.Check(iface.IsVLAN, gc.Equals, false) 284 } 285 286 func (s *ParserSuite) TestVLANIfaceStanza(c *gc.C) { 287 content := ` 288 iface eth0.100 inet static 289 address 192.168.1.254/24 290 vlan-raw-device eth1` 291 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 292 c.Assert(err, gc.IsNil) 293 c.Assert(stanzas, gc.HasLen, 1) 294 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 295 296 iface := stanzas[0].(debinterfaces.IfaceStanza) 297 c.Assert(iface.Definition(), gc.HasLen, 3) 298 c.Check(iface.Definition()[0], gc.Equals, "iface eth0.100 inet static") 299 c.Check(iface.Definition()[1], gc.Equals, "address 192.168.1.254/24") 300 c.Check(iface.Definition()[2], gc.Equals, "vlan-raw-device eth1") 301 c.Check(iface.Location().Filename, gc.Equals, "") 302 c.Check(iface.Location().LineNum, gc.Equals, 2) 303 c.Assert(iface.Options, gc.HasLen, 2) 304 c.Check(iface.Options[0], gc.Equals, "address 192.168.1.254/24") 305 c.Check(iface.Options[1], gc.Equals, "vlan-raw-device eth1") 306 c.Check(iface.HasBondMasterOption, gc.Equals, false) 307 c.Check(iface.HasBondOptions, gc.Equals, false) 308 c.Check(iface.IsAlias, gc.Equals, false) 309 c.Check(iface.IsBridged, gc.Equals, false) 310 c.Check(iface.IsVLAN, gc.Equals, true) 311 } 312 313 func (s *ParserSuite) TestBondedIfaceStanza(c *gc.C) { 314 content := ` 315 auto eth0 316 iface eth0 inet manual 317 bond-lacp_rate slow 318 bond-xmit_hash_policy layer2 319 bond-miimon 100 320 bond-master bond0 321 bond-mode active-backup 322 323 auto eth1 324 iface eth1 inet manual 325 bond-lacp_rate slow 326 bond-xmit_hash_policy layer2 327 bond-miimon 100 328 bond-master bond0 329 mtu 1500 330 bond-mode active-backup 331 332 auto bond0 333 iface bond0 inet dhcp 334 bond-lacp_rate slow 335 bond-xmit_hash_policy layer2 336 bond-miimon 100 337 mtu 1500 338 bond-mode active-backup 339 hwaddress 52:54:00:1c:f1:5b 340 bond-slaves none` 341 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 342 c.Assert(err, gc.IsNil) 343 c.Assert(stanzas, gc.HasLen, 6) 344 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 345 c.Assert(stanzas[1], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 346 c.Assert(stanzas[2], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 347 c.Assert(stanzas[3], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 348 c.Assert(stanzas[4], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 349 c.Assert(stanzas[5], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 350 351 iface0 := stanzas[1].(debinterfaces.IfaceStanza) 352 c.Assert(iface0.Definition(), gc.HasLen, 6) 353 c.Check(iface0.Definition()[0], gc.Equals, "iface eth0 inet manual") 354 c.Check(iface0.Location().Filename, gc.Equals, "") 355 c.Check(iface0.Location().LineNum, gc.Equals, 3) 356 c.Check(iface0.Options, gc.HasLen, 5) 357 c.Check(iface0.HasBondMasterOption, gc.Equals, true) 358 c.Check(iface0.HasBondOptions, gc.Equals, true) 359 c.Check(iface0.IsAlias, gc.Equals, false) 360 c.Check(iface0.IsBridged, gc.Equals, false) 361 c.Check(iface0.IsVLAN, gc.Equals, false) 362 363 iface1 := stanzas[3].(debinterfaces.IfaceStanza) 364 c.Assert(iface1.Definition(), gc.HasLen, 7) 365 c.Check(iface1.Definition()[0], gc.Equals, "iface eth1 inet manual") 366 c.Check(iface1.Location().Filename, gc.Equals, "") 367 c.Check(iface1.Location().LineNum, gc.Equals, 11) 368 c.Check(iface1.Options, gc.HasLen, 6) 369 c.Check(iface1.HasBondMasterOption, gc.Equals, true) 370 c.Check(iface1.HasBondOptions, gc.Equals, true) 371 c.Check(iface1.IsAlias, gc.Equals, false) 372 c.Check(iface1.IsBridged, gc.Equals, false) 373 c.Check(iface1.IsVLAN, gc.Equals, false) 374 375 iface2 := stanzas[5].(debinterfaces.IfaceStanza) 376 c.Assert(iface2.Definition(), gc.HasLen, 8) 377 c.Check(iface2.Definition()[0], gc.Equals, "iface bond0 inet dhcp") 378 c.Check(iface2.Location().Filename, gc.Equals, "") 379 c.Check(iface2.Location().LineNum, gc.Equals, 20) 380 c.Check(iface2.Options, gc.HasLen, 7) 381 c.Check(iface2.HasBondOptions, gc.Equals, true) 382 c.Check(iface2.HasBondMasterOption, gc.Equals, false) 383 c.Check(iface2.IsAlias, gc.Equals, false) 384 c.Check(iface2.IsBridged, gc.Equals, false) 385 c.Check(iface2.IsVLAN, gc.Equals, false) 386 } 387 388 func (s *ParserSuite) TestMappingStanza(c *gc.C) { 389 content := ` 390 mapping eth0 eth1 391 script /path/to/get-mac-address.sh 392 map 11:22:33:44:55:66 lan 393 map AA:BB:CC:DD:EE:FF internet` 394 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 395 c.Assert(err, gc.IsNil) 396 c.Assert(stanzas, gc.HasLen, 1) 397 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.MappingStanza{}) 398 399 mapping := stanzas[0].(debinterfaces.MappingStanza) 400 c.Assert(mapping.Definition(), gc.HasLen, 4) 401 c.Check(mapping.Definition()[0], gc.Equals, "mapping eth0 eth1") 402 c.Check(mapping.Location().Filename, gc.Equals, "") 403 c.Check(mapping.Location().LineNum, gc.Equals, 2) 404 c.Check(mapping.DeviceNames, gc.DeepEquals, []string{"eth0", "eth1"}) 405 c.Assert(mapping.Options, gc.HasLen, 3) 406 c.Check(mapping.Options[0], gc.Equals, "script /path/to/get-mac-address.sh") 407 c.Check(mapping.Options[1], gc.Equals, "map 11:22:33:44:55:66 lan") 408 c.Check(mapping.Options[2], gc.Equals, "map AA:BB:CC:DD:EE:FF internet") 409 } 410 411 func (s *ParserSuite) TestNoAutoDownStanza(c *gc.C) { 412 content := `no-auto-down eth0 eth1` 413 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 414 c.Assert(err, gc.IsNil) 415 c.Assert(stanzas, gc.HasLen, 1) 416 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.NoAutoDownStanza{}) 417 418 noautodown := stanzas[0].(debinterfaces.NoAutoDownStanza) 419 c.Assert(noautodown.Definition(), gc.HasLen, 1) 420 c.Check(noautodown.Definition()[0], gc.Equals, "no-auto-down eth0 eth1") 421 c.Check(noautodown.Location().Filename, gc.Equals, "") 422 c.Check(noautodown.Location().LineNum, gc.Equals, 1) 423 c.Check(noautodown.DeviceNames, gc.DeepEquals, []string{"eth0", "eth1"}) 424 } 425 426 func (s *ParserSuite) TestNoScriptsStanza(c *gc.C) { 427 content := `no-scripts eth0 eth1` 428 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 429 c.Assert(err, gc.IsNil) 430 c.Assert(stanzas, gc.HasLen, 1) 431 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.NoScriptsStanza{}) 432 433 noscripts := stanzas[0].(debinterfaces.NoScriptsStanza) 434 c.Assert(noscripts.Definition(), gc.HasLen, 1) 435 c.Check(noscripts.Definition()[0], gc.Equals, "no-scripts eth0 eth1") 436 c.Check(noscripts.Location().Filename, gc.Equals, "") 437 c.Check(noscripts.Location().LineNum, gc.Equals, 1) 438 c.Check(noscripts.DeviceNames, gc.DeepEquals, []string{"eth0", "eth1"}) 439 } 440 441 func (s *ParserSuite) TestFailParseDirectoryAsInput(c *gc.C) { 442 stanzas, err := debinterfaces.Parse("testdata/TestInputSourceStanza") 443 c.Assert(err, gc.NotNil) 444 c.Check(err, gc.ErrorMatches, ".* testdata/TestInputSourceStanza: .*") 445 c.Assert(stanzas, gc.IsNil) 446 } 447 448 func (s *ParserSuite) TestSourceStanzaNonExistentFile(c *gc.C) { 449 _, err := debinterfaces.Parse("testdata/TestInputSourceStanza/non-existent-file") 450 c.Assert(err, gc.NotNil) 451 c.Check(err, gc.ErrorMatches, ".* testdata/TestInputSourceStanza/non-existent-file: .*") 452 } 453 454 func (s *ParserSuite) TestSourceStanzaWhereGlobHasZeroMatches(c *gc.C) { 455 stanzas, err := debinterfaces.ParseSource("testdata/TestSourceStanzaWhereGlobHasZeroMatches/interfaces", nil, s.expander) 456 c.Assert(err, gc.IsNil) 457 c.Assert(stanzas, gc.HasLen, 1) 458 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.SourceStanza{}) 459 src := stanzas[0].(debinterfaces.SourceStanza) 460 c.Assert(src.Sources, gc.HasLen, 0) 461 c.Assert(src.Stanzas, gc.HasLen, 0) 462 } 463 464 func (s *ParserSuite) TestSourceStanzaWithRelativeFilenames(c *gc.C) { 465 stanzas, err := debinterfaces.Parse("testdata/TestInputSourceStanza/interfaces") 466 c.Assert(err, gc.IsNil) 467 c.Assert(stanzas, gc.HasLen, 3) 468 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 469 c.Assert(stanzas[1], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 470 c.Assert(stanzas[2], gc.FitsTypeOf, debinterfaces.SourceStanza{}) 471 472 c.Assert(stanzas[0].Location().Filename, gc.Equals, "testdata/TestInputSourceStanza/interfaces") 473 c.Assert(stanzas[0].Location().LineNum, gc.Equals, 5) 474 475 c.Assert(stanzas[1].Location().Filename, gc.Equals, "testdata/TestInputSourceStanza/interfaces") 476 c.Assert(stanzas[1].Location().LineNum, gc.Equals, 6) 477 478 c.Assert(stanzas[2].Location().Filename, gc.Equals, "testdata/TestInputSourceStanza/interfaces") 479 c.Assert(stanzas[2].Location().LineNum, gc.Equals, 12) 480 481 source := stanzas[2].(debinterfaces.SourceStanza) 482 c.Check(source.Path, gc.Equals, "interfaces.d/*.cfg") 483 484 c.Assert(source.Stanzas, gc.HasLen, 6) 485 486 c.Assert(source.Stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 487 c.Assert(source.Stanzas[1], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 488 c.Assert(source.Stanzas[2], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 489 c.Assert(source.Stanzas[3], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 490 c.Assert(source.Stanzas[4], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 491 c.Assert(source.Stanzas[5], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 492 493 basePath := filepath.Join("testdata", "TestInputSourceStanza", "interfaces.d") 494 c.Check(source.Sources, gc.DeepEquals, []string{ 495 filepath.Join(basePath, "eth0.cfg"), 496 filepath.Join(basePath, "eth1.cfg"), 497 filepath.Join(basePath, "eth2.cfg"), 498 }) 499 500 // Note: we don't have tests for stanzas nested > 1 deep. 501 502 eth0 := source.Stanzas[1].(debinterfaces.IfaceStanza) 503 eth1 := source.Stanzas[3].(debinterfaces.IfaceStanza) 504 eth2 := source.Stanzas[5].(debinterfaces.IfaceStanza) 505 506 c.Assert(eth0.Definition(), gc.HasLen, 1) 507 c.Check(eth0.Definition()[0], gc.Equals, "iface eth0 inet dhcp") 508 c.Check(eth0.Location().Filename, gc.Equals, filepath.Join(basePath, "eth0.cfg")) 509 c.Check(eth0.Location().LineNum, gc.Equals, 2) 510 511 c.Assert(eth1.Definition(), gc.HasLen, 3) 512 c.Check(eth1.Definition()[0], gc.Equals, "iface eth1 inet static") 513 c.Check(eth1.Definition()[1], gc.Equals, "address 192.168.1.64") 514 c.Check(eth1.Definition()[2], gc.Equals, "dns-nameservers 192.168.1.254") 515 c.Check(eth1.Location().Filename, gc.Equals, filepath.Join(basePath, "eth1.cfg")) 516 c.Check(eth1.Location().LineNum, gc.Equals, 2) 517 518 c.Assert(eth2.Definition(), gc.HasLen, 1) 519 c.Check(eth2.Definition()[0], gc.Equals, "iface eth2 inet manual") 520 c.Check(eth2.Location().Filename, gc.Equals, filepath.Join(basePath, "eth2.cfg")) 521 c.Check(eth2.Location().LineNum, gc.Equals, 2) 522 } 523 524 func (s *ParserSuite) TestSourceStanzaFromFileWithStanzaErrors(c *gc.C) { 525 _, err := debinterfaces.Parse("testdata/TestInputSourceStanzaWithErrors/interfaces") 526 c.Assert(err, gc.NotNil) 527 c.Assert(err, gc.FitsTypeOf, &debinterfaces.ParseError{}) 528 parseError := err.(*debinterfaces.ParseError) 529 c.Assert(parseError, gc.DeepEquals, &debinterfaces.ParseError{ 530 Filename: filepath.Join("testdata", "TestInputSourceStanzaWithErrors", "interfaces.d", "eth1.cfg"), 531 Line: "iface", 532 LineNum: 2, 533 Message: "missing device name", 534 }) 535 } 536 537 func (s *ParserSuite) TestSourceDirectoryStanzaWithRelativeFilenames(c *gc.C) { 538 stanzas, err := debinterfaces.Parse("testdata/TestInputSourceDirectoryStanza/interfaces") 539 c.Assert(err, gc.IsNil) 540 c.Assert(stanzas, gc.HasLen, 3) 541 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 542 c.Assert(stanzas[1], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 543 c.Assert(stanzas[2], gc.FitsTypeOf, debinterfaces.SourceDirectoryStanza{}) 544 545 c.Assert(stanzas[0].Location().Filename, gc.Equals, "testdata/TestInputSourceDirectoryStanza/interfaces") 546 c.Assert(stanzas[0].Location().LineNum, gc.Equals, 1) 547 548 c.Assert(stanzas[1].Location().Filename, gc.Equals, "testdata/TestInputSourceDirectoryStanza/interfaces") 549 c.Assert(stanzas[1].Location().LineNum, gc.Equals, 2) 550 551 c.Assert(stanzas[2].Location().Filename, gc.Equals, "testdata/TestInputSourceDirectoryStanza/interfaces") 552 c.Assert(stanzas[2].Location().LineNum, gc.Equals, 4) 553 554 source := stanzas[2].(debinterfaces.SourceDirectoryStanza) 555 c.Check(source.Path, gc.Equals, "interfaces.d") 556 557 c.Assert(source.Stanzas, gc.HasLen, 2) 558 559 c.Assert(source.Stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 560 c.Assert(source.Stanzas[1], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 561 562 c.Check(source.Sources, gc.DeepEquals, []string{ 563 filepath.Join("testdata", "TestInputSourceDirectoryStanza", "interfaces.d", "eth3"), 564 }) 565 566 // Note: we don't have tests for stanzas nested > 1 deep. 567 568 eth3 := source.Stanzas[1].(debinterfaces.IfaceStanza) 569 c.Assert(eth3.Definition(), gc.HasLen, 3) 570 c.Check(eth3.Definition()[0], gc.Equals, "iface eth3 inet static") 571 c.Check(eth3.Definition()[1], gc.Equals, "address 192.168.1.128") 572 c.Check(eth3.Definition()[2], gc.Equals, "dns-nameservers 192.168.1.254") 573 c.Check(eth3.Location().Filename, gc.Equals, filepath.Join("testdata", "TestInputSourceDirectoryStanza", "interfaces.d", "eth3")) 574 c.Check(eth3.Location().LineNum, gc.Equals, 2) 575 } 576 577 func (s *ParserSuite) TestSourceDirectoryStanzaFromDirectoryWithStanzaErrors(c *gc.C) { 578 _, err := debinterfaces.Parse("testdata/TestInputSourceDirectoryStanzaWithErrors/interfaces") 579 c.Assert(err, gc.NotNil) 580 c.Assert(err, gc.FitsTypeOf, &debinterfaces.ParseError{}) 581 parseError := err.(*debinterfaces.ParseError) 582 c.Assert(parseError, gc.DeepEquals, &debinterfaces.ParseError{ 583 Filename: filepath.Join("testdata", "TestInputSourceDirectoryStanzaWithErrors", "interfaces.d", "eth3"), 584 Line: "iface", 585 LineNum: 2, 586 Message: "missing device name", 587 }) 588 } 589 590 func (s *ParserSuite) TestSourceStanzaWithWordExpanderError(c *gc.C) { 591 _, err := debinterfaces.ParseSource("testdata/TestInputSourceStanza/interfaces", nil, wordExpanderWithError("boom")) 592 c.Assert(err, gc.NotNil) 593 c.Assert(err, gc.FitsTypeOf, &debinterfaces.ParseError{}) 594 parseError := err.(*debinterfaces.ParseError) 595 c.Assert(parseError, gc.DeepEquals, &debinterfaces.ParseError{ 596 Filename: "testdata/TestInputSourceStanza/interfaces", 597 Line: "source interfaces.d/*.cfg", 598 LineNum: 12, 599 Message: "word expansion failed: boom", 600 }) 601 } 602 603 func (s *ParserSuite) TestSourceDirectoryStanzaWithWordExpanderError(c *gc.C) { 604 _, err := debinterfaces.ParseSource("testdata/TestInputSourceDirectoryStanza/interfaces", nil, wordExpanderWithError("boom")) 605 c.Assert(err, gc.NotNil) 606 c.Assert(err, gc.FitsTypeOf, &debinterfaces.ParseError{}) 607 parseError := err.(*debinterfaces.ParseError) 608 c.Assert(parseError, gc.DeepEquals, &debinterfaces.ParseError{ 609 Filename: "testdata/TestInputSourceDirectoryStanza/interfaces", 610 Line: "source-directory interfaces.d", 611 LineNum: 4, 612 Message: "word expansion failed: boom", 613 }) 614 } 615 616 func (s *ParserSuite) TestSourceStanzaWithAbsoluteFilenames(c *gc.C) { 617 _, testfile, _, _ := runtime.Caller(0) 618 dir := filepath.Dir(testfile) 619 fullpath := fmt.Sprintf("%s/testdata/TestInputSourceStanza/interfaces.d/*.cfg", dir) 620 content := fmt.Sprintf("source %s", fullpath) 621 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 622 c.Assert(err, gc.IsNil) 623 c.Assert(stanzas, gc.HasLen, 1) 624 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.SourceStanza{}) 625 626 c.Assert(stanzas[0].Location().Filename, gc.Equals, "") 627 c.Assert(stanzas[0].Location().LineNum, gc.Equals, 1) 628 629 source := stanzas[0].(debinterfaces.SourceStanza) 630 c.Check(source.Path, gc.Equals, fullpath) 631 632 c.Assert(source.Stanzas, gc.HasLen, 6) 633 634 c.Assert(source.Stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 635 c.Assert(source.Stanzas[1], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 636 c.Assert(source.Stanzas[2], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 637 c.Assert(source.Stanzas[3], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 638 c.Assert(source.Stanzas[4], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 639 c.Assert(source.Stanzas[5], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 640 641 c.Check(source.Sources, gc.DeepEquals, []string{ 642 filepath.Join(dir, "testdata/TestInputSourceStanza/interfaces.d/eth0.cfg"), 643 filepath.Join(dir, "testdata/TestInputSourceStanza/interfaces.d/eth1.cfg"), 644 filepath.Join(dir, "testdata/TestInputSourceStanza/interfaces.d/eth2.cfg"), 645 }) 646 647 // Note: we don't have tests for stanzas nested > 1 deep. 648 649 eth0 := source.Stanzas[1].(debinterfaces.IfaceStanza) 650 eth1 := source.Stanzas[3].(debinterfaces.IfaceStanza) 651 eth2 := source.Stanzas[5].(debinterfaces.IfaceStanza) 652 653 c.Assert(eth0.Definition(), gc.HasLen, 1) 654 c.Check(eth0.Definition()[0], gc.Equals, "iface eth0 inet dhcp") 655 c.Check(eth0.Location().Filename, gc.Equals, filepath.Join(dir, "testdata/TestInputSourceStanza/interfaces.d/eth0.cfg")) 656 c.Check(eth0.Location().LineNum, gc.Equals, 2) 657 658 c.Assert(eth1.Definition(), gc.HasLen, 3) 659 c.Check(eth1.Definition()[0], gc.Equals, "iface eth1 inet static") 660 c.Check(eth1.Definition()[1], gc.Equals, "address 192.168.1.64") 661 c.Check(eth1.Definition()[2], gc.Equals, "dns-nameservers 192.168.1.254") 662 c.Check(eth1.Location().Filename, gc.Equals, filepath.Join(dir, "testdata/TestInputSourceStanza/interfaces.d/eth1.cfg")) 663 c.Check(eth1.Location().LineNum, gc.Equals, 2) 664 665 c.Assert(eth2.Definition(), gc.HasLen, 1) 666 c.Check(eth2.Definition()[0], gc.Equals, "iface eth2 inet manual") 667 c.Check(eth2.Location().Filename, gc.Equals, filepath.Join(dir, "testdata/TestInputSourceStanza/interfaces.d/eth2.cfg")) 668 c.Check(eth2.Location().LineNum, gc.Equals, 2) 669 } 670 671 func (s *ParserSuite) TestSourceDirectoryStanzaWithAbsoluteFilenames(c *gc.C) { 672 _, testfile, _, _ := runtime.Caller(0) 673 dir := filepath.Dir(testfile) 674 fullpath := fmt.Sprintf("%s/testdata/TestInputSourceDirectoryStanza/interfaces.d", dir) 675 content := fmt.Sprintf("source-directory %s", fullpath) 676 stanzas, err := debinterfaces.ParseSource("", content, s.expander) 677 c.Assert(err, gc.IsNil) 678 c.Assert(stanzas, gc.HasLen, 1) 679 c.Assert(stanzas[0], gc.FitsTypeOf, debinterfaces.SourceDirectoryStanza{}) 680 681 c.Assert(stanzas[0].Location().Filename, gc.Equals, "") 682 c.Assert(stanzas[0].Location().LineNum, gc.Equals, 1) 683 684 source := stanzas[0].(debinterfaces.SourceDirectoryStanza) 685 c.Check(source.Path, gc.Equals, fullpath) 686 687 c.Assert(source.Stanzas, gc.HasLen, 2) 688 689 c.Assert(source.Stanzas[0], gc.FitsTypeOf, debinterfaces.AutoStanza{}) 690 c.Assert(source.Stanzas[1], gc.FitsTypeOf, debinterfaces.IfaceStanza{}) 691 692 c.Check(source.Sources, gc.DeepEquals, []string{ 693 filepath.Join(fullpath, "eth3"), 694 }) 695 696 // Note: we don't have tests for source directory stanzas nested > 1 deep. 697 698 eth3 := source.Stanzas[1].(debinterfaces.IfaceStanza) 699 c.Assert(eth3.Definition(), gc.HasLen, 3) 700 c.Check(eth3.Definition()[0], gc.Equals, "iface eth3 inet static") 701 c.Check(eth3.Definition()[1], gc.Equals, "address 192.168.1.128") 702 c.Check(eth3.Definition()[2], gc.Equals, "dns-nameservers 192.168.1.254") 703 c.Check(eth3.Location().Filename, gc.Equals, filepath.Join(fullpath, "eth3")) 704 c.Check(eth3.Location().LineNum, gc.Equals, 2) 705 } 706 707 func (s *ParserSuite) TestSourceStanzaWithAbsoluteNonExistentFilenames(c *gc.C) { 708 _, testfile, _, _ := runtime.Caller(0) 709 dir := filepath.Dir(testfile) 710 fullpath := fmt.Sprintf("%s/testdata/non-existent.d/*", dir) 711 content := fmt.Sprintf("source %s", fullpath) 712 _, err := debinterfaces.ParseSource("", content, s.expander) 713 c.Assert(err, gc.IsNil) 714 } 715 716 func (s *ParserSuite) TestSourceDirectoryStanzaWithAbsoluteNonExistentFilenames(c *gc.C) { 717 _, testfile, _, _ := runtime.Caller(0) 718 dir := filepath.Dir(testfile) 719 fullpath := fmt.Sprintf("%s/testdata/non-existent", dir) 720 content := fmt.Sprintf("source-directory %s", fullpath) 721 _, err := debinterfaces.ParseSource("", content, s.expander) 722 c.Assert(err, gc.NotNil) 723 } 724 725 func (s *ParserSuite) TestIfupdownPackageExample(c *gc.C) { 726 _, err := debinterfaces.ParseSource("testdata/ifupdown-examples", nil, s.expander) 727 c.Assert(err, gc.IsNil) 728 }