rspec-networking 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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