rspec-networking 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,121 @@
1
- # https://en.wikipedia.org/wiki/MAC_address
1
+ require 'rspec/networking/mac_address_manufacturers'
2
2
 
3
3
  RSpec::Matchers.define :be_a_mac_address do
4
+ chain :from do |manufacturer|
5
+ @manufacturer_str = manufacturer
6
+
7
+ if manufacturer.match?(/^\h{2}([:-])\h{2}\1\h{2}$/) || manufacturer.match?(/^\h{3}\.\h{3}$/)
8
+ # exact match
9
+ @manufacturer = manufacturer.delete('.:-').upcase
10
+ else
11
+ # manufacturer lookup
12
+ @manufacturer = manufacturer.to_s.downcase.tr(' ', '_')
13
+
14
+ unless RSpec::Networking::MANUFACTURERS.key?(@manufacturer)
15
+ raise ArgumentError, "unknown manufacturer: #{manufacturer}"
16
+ end
17
+ end
18
+ end
19
+
20
+ chain :for do |device|
21
+ unless device.match?(/^\h{2}([:-])\h{2}\1\h{2}$/) || device.match?(/^\h{3}\.\h{3}$/)
22
+ raise ArgumentError, "invalid device: #{device}"
23
+ end
24
+
25
+ @device = device
26
+ end
27
+
28
+ chain :bits do |bits|
29
+ unless [ 48, 64 ].include?(bits)
30
+ raise ArgumentError, "invalid bit length: #{bits}"
31
+ end
32
+
33
+ @bits = bits
34
+ end
35
+
36
+ chain :broadcast do
37
+ @broadcast = true
38
+ end
39
+
40
+ chain :unicast do
41
+ @cast = :unicast
42
+ end
43
+
44
+ chain :multicast do
45
+ @cast = :multicast
46
+ end
47
+
4
48
  match do |actual|
5
49
  @actual = actual
6
50
 
7
51
  return false unless actual.is_a?(String)
8
52
 
9
- hex = ['\h{2}'] * 5
10
- actual.match?(/^\h{2}([:-])#{hex.join('\1')}$/)
53
+ hex = nil
54
+
55
+ if actual.match?(/^\h{2}(:\h{2}){7}$/) || actual.match?(/^\h{4}(:\h{4}){3}$/)
56
+ # 64 bits
57
+ # 00:00:00:FF:FE:00:00:00
58
+ # 0000:00FF:FE00:0000
59
+
60
+ hex = actual.delete(':').upcase
61
+ return false unless hex.slice(6, 4) == 'FFFE'
62
+ return false if @bits == 48
63
+
64
+ # normalize to 48 bits
65
+ hex.slice!(6, 4)
66
+ elsif actual.match?(/^\h{2}([:-])(\h{2}\1){4}\h{2}$/) || actual.match?(/^\h{3}(\.\h{3}){3}$/)
67
+ # 48 bits
68
+ # MM:MM:MM:SS:SS:SS
69
+ # MM-MM-MM-SS-SS-SS
70
+ # MMM.MMM.SSS.SSS
71
+
72
+ return false if @bits == 64
73
+
74
+ hex = actual.delete('.:-').upcase
75
+ else
76
+ return false
77
+ end
78
+
79
+ if @broadcast
80
+ return false unless hex == 'FF' * 6
81
+ end
82
+
83
+ if @cast
84
+ bit = @cast == :multicast ? 1 : 0
85
+
86
+ return false unless hex[1].to_i(16) & 1 == bit
87
+ end
88
+
89
+ matches = true
90
+
91
+ if @manufacturer
92
+ prefix = hex.slice(0, 6)
93
+
94
+ matches &&= if @manufacturer_str.match?(/[.:-]/)
95
+ # exact match
96
+ prefix == @manufacturer
97
+ else
98
+ # manufacturer lookup
99
+ RSpec::Networking::MANUFACTURERS[@manufacturer].include?(prefix)
100
+ end
101
+ end
102
+
103
+ if @device
104
+ suffix = hex.slice(-6, 6)
105
+ matches &&= suffix == @device.delete('.:-').upcase
106
+ end
107
+
108
+ matches
11
109
  end
12
110
 
13
111
  description do
14
- "a MAC address"
112
+ from_s = @manufacturer ? " from #{@manufacturer_str}" : ""
113
+ for_s = @device ? " for #{@device}" : ""
114
+ bits_s = @bits ? " with #{@bits} bits" : ""
115
+ broadcast_s = @broadcast ? " broadcast" : ""
116
+ cast_s = @cast ? " #{@cast}" : ""
117
+
118
+ "a MAC address#{bits_s}#{from_s}#{for_s}#{broadcast_s}#{cast_s}"
15
119
  end
16
120
 
17
121
  failure_message do
@@ -0,0 +1,19 @@
1
+ require 'set'
2
+
3
+ module RSpec
4
+ module Networking
5
+ MANUFACTURERS = {
6
+ "xerox" => Set.new(['00:00:00'.delete(':')]),
7
+ }
8
+
9
+ # load manufacturers
10
+ Dir.glob("#{__dir__}/mac_address/*.txt").each do |file|
11
+ manufacturer = File.basename(file, '.txt').downcase
12
+
13
+ File.readlines(file).map(&:chomp).each do |entry|
14
+ MANUFACTURERS[manufacturer] ||= Set.new
15
+ MANUFACTURERS[manufacturer] << entry.upcase
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module Networking
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-networking
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Pepper
@@ -95,6 +95,19 @@ files:
95
95
  - lib/rspec/networking.rb
96
96
  - lib/rspec/networking/ip_address.rb
97
97
  - lib/rspec/networking/mac_address.rb
98
+ - lib/rspec/networking/mac_address/apple.txt
99
+ - lib/rspec/networking/mac_address/eero.txt
100
+ - lib/rspec/networking/mac_address/google.txt
101
+ - lib/rspec/networking/mac_address/microsoft.txt
102
+ - lib/rspec/networking/mac_address/nokia.txt
103
+ - lib/rspec/networking/mac_address/oracle.txt
104
+ - lib/rspec/networking/mac_address/sony.txt
105
+ - lib/rspec/networking/mac_address/texas_instruments.txt
106
+ - lib/rspec/networking/mac_address/toshiba.txt
107
+ - lib/rspec/networking/mac_address/xerox.txt
108
+ - lib/rspec/networking/mac_address/xiaomi.txt
109
+ - lib/rspec/networking/mac_address/zyxel.txt
110
+ - lib/rspec/networking/mac_address_manufacturers.rb
98
111
  - lib/rspec/networking/version.rb
99
112
  - rspec-networking.gemspec
100
113
  homepage: https://github.com/dpep/rspec-networking
@@ -116,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
129
  - !ruby/object:Gem::Version
117
130
  version: '0'
118
131
  requirements: []
119
- rubygems_version: 3.5.17
132
+ rubygems_version: 3.5.18
120
133
  signing_key:
121
134
  specification_version: 4
122
135
  summary: RSpec::Networking