netsnmp 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +42 -0
- data/AUTHORS +1 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +201 -0
- data/README.md +162 -0
- data/Rakefile +26 -0
- data/lib/netsnmp.rb +16 -0
- data/lib/netsnmp/client.rb +131 -0
- data/lib/netsnmp/core.rb +12 -0
- data/lib/netsnmp/core/client.rb +15 -0
- data/lib/netsnmp/core/constants.rb +153 -0
- data/lib/netsnmp/core/inline.rb +20 -0
- data/lib/netsnmp/core/libc.rb +48 -0
- data/lib/netsnmp/core/libsnmp.rb +44 -0
- data/lib/netsnmp/core/structures.rb +167 -0
- data/lib/netsnmp/core/utilities.rb +13 -0
- data/lib/netsnmp/errors.rb +8 -0
- data/lib/netsnmp/handlers/celluloid.rb +27 -0
- data/lib/netsnmp/handlers/em.rb +56 -0
- data/lib/netsnmp/oid.rb +94 -0
- data/lib/netsnmp/pdu.rb +105 -0
- data/lib/netsnmp/session.rb +306 -0
- data/lib/netsnmp/varbind.rb +181 -0
- data/lib/netsnmp/version.rb +3 -0
- data/netsnmp.gemspec +36 -0
- data/spec/client_spec.rb +90 -0
- data/spec/core/libc_spec.rb +2 -0
- data/spec/core/libsnmp_spec.rb +32 -0
- data/spec/core/structures_spec.rb +54 -0
- data/spec/handlers/celluloid_spec.rb +29 -0
- data/spec/handlers/em_client_spec.rb +34 -0
- data/spec/oid_spec.rb +9 -0
- data/spec/pdu_spec.rb +29 -0
- data/spec/session_spec.rb +34 -0
- data/spec/spec_helper.rb +114 -0
- data/spec/support/Dockerfile +14 -0
- data/spec/support/celluloid.rb +22 -0
- data/spec/support/start_docker.sh +4 -0
- data/spec/support/stop_docker.sh +5 -0
- data/spec/varbind_spec.rb +54 -0
- metadata +187 -0
data/netsnmp.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path('../lib/netsnmp/version',__FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = "netsnmp"
|
5
|
+
gem.summary = "SNMP Client library"
|
6
|
+
gem.description = <<DESC
|
7
|
+
Wraps the net-snmp core usage into idiomatic ruby.
|
8
|
+
It is designed to support as many environments and concurrency frameworks as possible.
|
9
|
+
DESC
|
10
|
+
gem.requirements = ['net-snmp']
|
11
|
+
gem.version = NETSNMP::VERSION
|
12
|
+
gem.license = "Apache-2.0"
|
13
|
+
gem.authors = ["Tiago Cardoso"]
|
14
|
+
gem.email = "cardoso_tiago@hotmail.com"
|
15
|
+
gem.homepage = ""
|
16
|
+
gem.platform = Gem::Platform::RUBY
|
17
|
+
gem.required_ruby_version = '>=2.0.0'
|
18
|
+
|
19
|
+
# Manifest
|
20
|
+
gem.files = `git ls-files`.split("\n") - Dir['tmp/**/*']
|
21
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
gem.require_paths = ["lib"]
|
24
|
+
|
25
|
+
gem.executables = Dir["bin/*"].map { |e| File.basename e }
|
26
|
+
gem.add_runtime_dependency "ffi", ["~> 1.9"]
|
27
|
+
unless RUBY_PLATFORM == "java"
|
28
|
+
gem.add_runtime_dependency "RubyInline", ["~> 3.12"]
|
29
|
+
end
|
30
|
+
|
31
|
+
gem.add_development_dependency "rake", ["~> 10.4.2"]
|
32
|
+
gem.add_development_dependency "rspec", ["~> 3.3.0"]
|
33
|
+
|
34
|
+
gem.add_development_dependency "em-synchrony", ["~> 1.0.4"]
|
35
|
+
gem.add_development_dependency "celluloid-io", ["~> 0.17.2"]
|
36
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
RSpec.describe NETSNMP::Client do
|
2
|
+
let(:host) { "localhost" }
|
3
|
+
let(:host_options) { {
|
4
|
+
peername: "localhost",
|
5
|
+
port: SNMPPORT,
|
6
|
+
username: "simulator",
|
7
|
+
auth_password: "auctoritas",
|
8
|
+
auth_protocol: :md5,
|
9
|
+
priv_password: "privatus",
|
10
|
+
priv_protocol: :des
|
11
|
+
} }
|
12
|
+
|
13
|
+
subject { described_class.new(host, options) }
|
14
|
+
|
15
|
+
describe "#get" do
|
16
|
+
let(:oid) { "1.3.6.1.2.1.1.5.0" } # sysName.0
|
17
|
+
let(:value) { subject.get(oid) }
|
18
|
+
let(:options) { host_options.merge(context: "a172334d7d97871b72241397f713fa12") }
|
19
|
+
it "fetches the varbinds for a given oid" do
|
20
|
+
expect(value).to eq("tt")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#get_next" do
|
25
|
+
let(:oid) { "1.3.6.1.2.1.1.5.0" } # sysName.0
|
26
|
+
let(:value) { subject.get_next(oid) }
|
27
|
+
let(:options) { host_options.merge(context: "a172334d7d97871b72241397f713fa12") }
|
28
|
+
it "fetches the varbinds for the next oid" do
|
29
|
+
expect(value).to start_with("KK12")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#walk" do
|
34
|
+
let(:oid) { "1.3.6.1.2.1.1.9.1.3" } # sysORDescr
|
35
|
+
let(:value) { subject.walk(oid) }
|
36
|
+
let(:options) { host_options.merge(context: "a172334d7d97871b72241397f713fa12") }
|
37
|
+
it "fetches the varbinds for the next oid" do
|
38
|
+
expect(value.next).to eq(["#{oid}.1","The SNMP Management Architecture MIB."])
|
39
|
+
expect(value.next).to eq(["#{oid}.2","The MIB for Message Processing and Dispatching."])
|
40
|
+
expect(value.next).to eq(["#{oid}.3","The management information definitions for the SNMP User-based Security Model."])
|
41
|
+
expect(value.next).to eq(["#{oid}.4","The MIB module for SNMPv2 entities"])
|
42
|
+
expect(value.next).to eq(["#{oid}.5","The MIB module for managing TCP implementations"])
|
43
|
+
expect(value.next).to eq(["#{oid}.6","The MIB module for managing IP and ICMP implementations"])
|
44
|
+
expect(value.next).to eq(["#{oid}.7","The MIB module for managing UDP implementations"])
|
45
|
+
expect(value.next).to eq(["#{oid}.8","View-based Access Control Model for SNMP."])
|
46
|
+
expect{ value.next }.to raise_error(StopIteration)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#get_bulk" do
|
51
|
+
let(:oid) { "1.3.6.1.2.1.1.9.1.3" }
|
52
|
+
let(:value) { subject.get_bulk(oid) }
|
53
|
+
let(:options) { host_options.merge(context: "a172334d7d97871b72241397f713fa12") }
|
54
|
+
it "fetches the varbinds for the next oid" do
|
55
|
+
expect(value.next).to eq(["#{oid}.1","The SNMP Management Architecture MIB."])
|
56
|
+
expect(value.next).to eq(["#{oid}.2","The MIB for Message Processing and Dispatching."])
|
57
|
+
expect(value.next).to eq(["#{oid}.3","The management information definitions for the SNMP User-based Security Model."])
|
58
|
+
expect(value.next).to eq(["#{oid}.4","The MIB module for SNMPv2 entities"])
|
59
|
+
expect(value.next).to eq(["#{oid}.5","The MIB module for managing TCP implementations"])
|
60
|
+
expect(value.next).to eq(["#{oid}.6","The MIB module for managing IP and ICMP implementations"])
|
61
|
+
expect(value.next).to eq(["#{oid}.7","The MIB module for managing UDP implementations"])
|
62
|
+
expect(value.next).to eq(["#{oid}.8","View-based Access Control Model for SNMP."])
|
63
|
+
expect(value.next).to eq(["1.3.6.1.2.1.1.9.1.4.1",2])
|
64
|
+
expect(value.next).to eq(["1.3.6.1.2.1.1.9.1.4.2",2])
|
65
|
+
expect{ value.next }.to raise_error(StopIteration)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# TODO: use this oid to test error calls
|
71
|
+
# let(:oid) { "SNMPv2-MIB::sysORDescr.1" }
|
72
|
+
|
73
|
+
describe "#set" do
|
74
|
+
let(:options) { host_options.merge(context: "0886e1397d572377c17c15036a1e6c66") } # write cache
|
75
|
+
let(:oid) { "1.3.6.1.2.1.1.3.0" } # sysUpTimeInstance
|
76
|
+
let(:new_value) { 43 }
|
77
|
+
after { subject.set(oid, value: 42) }
|
78
|
+
it "updates the value of the oid" do
|
79
|
+
expect(subject.get(oid)).to be(42)
|
80
|
+
|
81
|
+
# without type
|
82
|
+
subject.set(oid, value: 43)
|
83
|
+
expect(subject.get(oid)).to be(43)
|
84
|
+
|
85
|
+
subject.set(oid, value: 44, type: :integer)
|
86
|
+
expect(subject.get(oid)).to be(44)
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
RSpec.describe NETSNMP::Core::LibSNMP do
|
2
|
+
subject { described_class }
|
3
|
+
it "exposes initialization and shutdown methods" do
|
4
|
+
[:init_snmp, :snmp_perror].each do |meth|
|
5
|
+
is_expected.to respond_to(meth)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
it "exposes netsnmp session handling methods" do
|
10
|
+
[:snmp_sess_init, :snmp_sess_open, :snmp_sess_close, :generate_Ku].each do |meth|
|
11
|
+
is_expected.to respond_to(meth)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "exposes netsnmp read API" do
|
16
|
+
[:snmp_sess_synch_response, :snmp_sess_send].each do |meth|
|
17
|
+
is_expected.to respond_to(meth)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "exposes netsnmp session async send/read" do
|
22
|
+
[:snmp_sess_async_send, :snmp_sess_select_info, :snmp_sess_read].each do |meth|
|
23
|
+
is_expected.to respond_to(meth)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "exposes the pdu API" do
|
28
|
+
[:snmp_pdu_create, :snmp_free_pdu, :snmp_pdu_add_variable].each do |meth|
|
29
|
+
is_expected.to respond_to(meth)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
RSpec.describe NETSNMP::Core::Structures do
|
2
|
+
describe NETSNMP::Core::Structures::Session do
|
3
|
+
[:version, :retries, :timeout, :flags, :subsession, :next, :peername, :remote_port, :localname, :local_port, :authenticator,
|
4
|
+
:callback, :callback_magic, :community, :community_len, :rcvMsgMaxSize, :sndMsgMaxSize, :isAuthoritative, :contextEngineID,
|
5
|
+
:contextEngineIDLen, :engineBoots, :engineTime, :contextName, :contextNameLen, :securityEngineID, :securityEngineIDLen,
|
6
|
+
:securityName, :securityNameLen, :securityAuthProto, :securityAuthProtoLen, :securityAuthKey, :securityAuthKeyLen,
|
7
|
+
:securityAuthLocalKey, :securityAuthLocalKeyLen, :securityPrivProto, :securityPrivProtoLen, :securityPrivKey, :securityPrivKeyLen,
|
8
|
+
:securityPrivLocalKey, :securityPrivLocalKeyLen, :securityModel, :securityLevel, :paramName, :securityInfo, :myvoid].each do |attr|
|
9
|
+
it { expect(subject[attr]).not_to be_nil }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe NETSNMP::Core::Structures::Vardata do
|
14
|
+
[:integer, :string, :objid, :bitstring, :counter64, :float, :double].each do |attr|
|
15
|
+
it { expect(subject[attr]).not_to be_nil }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe NETSNMP::Core::Structures::VariableList do
|
20
|
+
[:next_variable, :name, :name_length, :type, :val, :val_len, :name_loc, :buf, :data, :dataFreeHook, :index].each do |attr|
|
21
|
+
it { expect(subject[attr]).not_to be_nil }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe NETSNMP::Core::Structures::PDU do
|
26
|
+
[:version, :command, :reqid, :msgid, :transid, :sessid, :errstat, :errindex, :time, :flags, :securityModel,
|
27
|
+
:securityLevel, :msgParseModel, :transport_data, :transport_data_length, :tDomain, :tDomainLen, :variables,
|
28
|
+
:community, :community_len, :enterprise, :enterprise_length, :trap_type, :specific_type, :agent_addr,
|
29
|
+
:contextEngineID, :contextEngineIDLen, :contextName, :contextNameLen, :securityEngineID, :securityEngineIDLen,
|
30
|
+
:securityName, :securityNameLen, :priority, :range_subid, :securityStateRef].each do |attr|
|
31
|
+
it { expect(subject[attr]).not_to be_nil }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe NETSNMP::Core::Structures::SessionList do
|
36
|
+
[:next, :session, :transport, :internal].each do |attr|
|
37
|
+
it { expect(subject[attr]).not_to be_nil }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe NETSNMP::Core::Structures::Transport do
|
42
|
+
[:domain, :domain_length, :local, :local_length, :remote, :remote_length,
|
43
|
+
:sock, :flags, :data, :data_length, :msgMaxSize, :base_transport].each do |attr|
|
44
|
+
it { expect(subject[attr]).not_to be_nil }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe NETSNMP::Core::Structures::Counter64 do
|
49
|
+
[:high, :low].each do |attr|
|
50
|
+
it { expect(subject[attr]).not_to be_nil }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'celluloid/io'
|
2
|
+
require 'netsnmp/handlers/celluloid'
|
3
|
+
require_relative '../support/celluloid'
|
4
|
+
|
5
|
+
RSpec.describe NETSNMP::Celluloid::Client, type: :celluloid do
|
6
|
+
include CelluloidHelpers
|
7
|
+
let(:host) { "localhost" }
|
8
|
+
let(:host_options) { {
|
9
|
+
peername: "localhost",
|
10
|
+
port: SNMPPORT,
|
11
|
+
username: "simulator",
|
12
|
+
auth_password: "auctoritas",
|
13
|
+
auth_protocol: :md5,
|
14
|
+
priv_password: "privatus",
|
15
|
+
priv_protocol: :des
|
16
|
+
} }
|
17
|
+
|
18
|
+
subject { described_class.new(host, options) }
|
19
|
+
|
20
|
+
describe "#get" do
|
21
|
+
let(:oid) { "1.3.6.1.2.1.1.5.0" } # sysName.0
|
22
|
+
let(:options) { host_options.merge(context: "a172334d7d97871b72241397f713fa12") }
|
23
|
+
it "fetches the varbinds for a given oid" do
|
24
|
+
value = within_io_actor { value = subject.get(oid) }
|
25
|
+
expect(value).to eq("tt")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'em-synchrony'
|
2
|
+
require 'netsnmp/handlers/em'
|
3
|
+
|
4
|
+
RSpec.describe NETSNMP::EM::Client do
|
5
|
+
let(:host) { "localhost" }
|
6
|
+
let(:host_options) { {
|
7
|
+
peername: "localhost",
|
8
|
+
port: SNMPPORT,
|
9
|
+
username: "simulator",
|
10
|
+
auth_password: "auctoritas",
|
11
|
+
auth_protocol: :md5,
|
12
|
+
priv_password: "privatus",
|
13
|
+
priv_protocol: :des
|
14
|
+
} }
|
15
|
+
|
16
|
+
subject { described_class.new(host, options) }
|
17
|
+
|
18
|
+
describe "#get" do
|
19
|
+
let(:oid) { "1.3.6.1.2.1.1.5.0" } # sysName.0
|
20
|
+
let(:options) { host_options.merge(context: "a172334d7d97871b72241397f713fa12") }
|
21
|
+
it "fetches the varbinds for a given oid" do
|
22
|
+
value = nil
|
23
|
+
EM.synchrony do
|
24
|
+
begin
|
25
|
+
value = subject.get(oid)
|
26
|
+
ensure
|
27
|
+
EM.stop_event_loop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
expect(value).to eq("tt")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/spec/oid_spec.rb
ADDED
data/spec/pdu_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
RSpec.describe NETSNMP::PDU do
|
2
|
+
let(:struct) { double(:structure) }
|
3
|
+
let(:pointer) { double(:pointer) }
|
4
|
+
subject { NETSNMP::PDU.new(pointer) }
|
5
|
+
before do
|
6
|
+
allow(NETSNMP::Core::Structures::PDU).to receive(:new).with(pointer).and_return(struct)
|
7
|
+
end
|
8
|
+
|
9
|
+
it { is_expected.to respond_to(:struct) }
|
10
|
+
it { expect(subject.varbinds).to be_empty }
|
11
|
+
|
12
|
+
describe NETSNMP::RequestPDU do
|
13
|
+
before { allow(NETSNMP::Core::LibSNMP).to receive(:snmp_pdu_create).and_return(pointer) }
|
14
|
+
subject { NETSNMP::PDU.build(:get) }
|
15
|
+
|
16
|
+
describe "#add_varbind" do
|
17
|
+
let(:oid) { double(:oid) }
|
18
|
+
let(:value) { double(:value) }
|
19
|
+
let(:varbind) { double(:varbind) }
|
20
|
+
before { allow(NETSNMP::RequestVarbind).to receive(:new).with(subject, oid, value, instance_of(Hash)).and_return(varbind) }
|
21
|
+
it "creates a new varbind and adds it to the structure" do
|
22
|
+
subject.add_varbind(oid, { value: value })
|
23
|
+
expect(subject.varbinds).not_to be_empty
|
24
|
+
expect(subject.varbinds).to include(varbind)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
RSpec.describe NETSNMP::Session do
|
2
|
+
let(:host) { "localhost" }
|
3
|
+
let(:options) { {
|
4
|
+
version: '2c',
|
5
|
+
context: "public",
|
6
|
+
port: SNMPPORT
|
7
|
+
} }
|
8
|
+
subject { described_class.new(host, options) }
|
9
|
+
after { subject.close }
|
10
|
+
|
11
|
+
|
12
|
+
describe "#send" do
|
13
|
+
let(:pointer) { double(:pointer) }
|
14
|
+
let(:pdu) { double(:pdu, pointer: pointer) }
|
15
|
+
let(:response) { double(:response) }
|
16
|
+
let(:reqid) { double(:requestid) }
|
17
|
+
let(:requests) { {} }
|
18
|
+
|
19
|
+
before do
|
20
|
+
allow(pdu).to receive(:[]).with(:reqid).and_return(reqid)
|
21
|
+
allow(requests).to receive(:[]).with(reqid).and_return([:success, response])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "sends and receives a pdu" do
|
25
|
+
expect(IO).to receive(:select).twice.and_return([[], []])
|
26
|
+
expect(NETSNMP::Core::LibSNMP).to receive(:snmp_sess_async_send).with(subject.signature, pointer, instance_of(FFI::Function), nil)
|
27
|
+
expect(subject).to receive(:handle_response).and_return(response)
|
28
|
+
expect(subject.send(pdu)).to be(response)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'simplecov' if ENV["COVERAGE"]
|
2
|
+
require 'coveralls'
|
3
|
+
Coveralls.wear!
|
4
|
+
|
5
|
+
SimpleCov.start do
|
6
|
+
minimum_coverage 85
|
7
|
+
add_filter ".bundle"
|
8
|
+
add_filter "/spec/"
|
9
|
+
end if defined?(SimpleCov)
|
10
|
+
|
11
|
+
require 'bundler/setup'
|
12
|
+
Bundler.require(:default, :test)
|
13
|
+
|
14
|
+
require 'netsnmp'
|
15
|
+
|
16
|
+
|
17
|
+
SNMPPORT = `sudo docker port test-snmp-emulator 1161/udp`[/.*:(\d+)/, 1].to_i
|
18
|
+
|
19
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
20
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
21
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
22
|
+
# this file to always be loaded, without a need to explicitly require it in any
|
23
|
+
# files.
|
24
|
+
#
|
25
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
26
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
27
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
28
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
29
|
+
# a separate helper file that requires the additional dependencies and performs
|
30
|
+
# the additional setup, and require it from the spec files that actually need
|
31
|
+
# it.
|
32
|
+
#
|
33
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
34
|
+
# users commonly want.
|
35
|
+
#
|
36
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
37
|
+
RSpec.configure do |config|
|
38
|
+
# rspec-expectations config goes here. You can use an alternate
|
39
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
40
|
+
# assertions if you prefer.
|
41
|
+
config.expect_with :rspec do |expectations|
|
42
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
43
|
+
# and `failure_message` of custom matchers include text for helper methods
|
44
|
+
# defined using `chain`, e.g.:
|
45
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
46
|
+
# # => "be bigger than 2 and smaller than 4"
|
47
|
+
# ...rather than:
|
48
|
+
# # => "be bigger than 2"
|
49
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
50
|
+
end
|
51
|
+
|
52
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
53
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
54
|
+
config.mock_with :rspec do |mocks|
|
55
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
56
|
+
# a real object. This is generally recommended, and will default to
|
57
|
+
# `true` in RSpec 4.
|
58
|
+
mocks.verify_partial_doubles = true
|
59
|
+
end
|
60
|
+
|
61
|
+
# The settings below are suggested to provide a good initial experience
|
62
|
+
# with RSpec, but feel free to customize to your heart's content.
|
63
|
+
=begin
|
64
|
+
# These two settings work together to allow you to limit a spec run
|
65
|
+
# to individual examples or groups you care about by tagging them with
|
66
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
67
|
+
# get run.
|
68
|
+
config.filter_run :focus
|
69
|
+
config.run_all_when_everything_filtered = true
|
70
|
+
|
71
|
+
# Allows RSpec to persist some state between runs in order to support
|
72
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
73
|
+
# you configure your source control system to ignore this file.
|
74
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
75
|
+
|
76
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
77
|
+
# recommended. For more details, see:
|
78
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
79
|
+
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
80
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
81
|
+
config.disable_monkey_patching!
|
82
|
+
|
83
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
84
|
+
# be too noisy due to issues in dependencies.
|
85
|
+
config.warnings = true
|
86
|
+
|
87
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
88
|
+
# file, and it's useful to allow more verbose output when running an
|
89
|
+
# individual spec file.
|
90
|
+
if config.files_to_run.one?
|
91
|
+
# Use the documentation formatter for detailed output,
|
92
|
+
# unless a formatter has already been configured
|
93
|
+
# (e.g. via a command-line flag).
|
94
|
+
config.default_formatter = 'doc'
|
95
|
+
end
|
96
|
+
|
97
|
+
# Print the 10 slowest examples and example groups at the
|
98
|
+
# end of the spec run, to help surface which specs are running
|
99
|
+
# particularly slow.
|
100
|
+
config.profile_examples = 10
|
101
|
+
|
102
|
+
# Run specs in random order to surface order dependencies. If you find an
|
103
|
+
# order dependency and want to debug it, you can fix the order by providing
|
104
|
+
# the seed, which is printed after each run.
|
105
|
+
# --seed 1234
|
106
|
+
config.order = :random
|
107
|
+
|
108
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
109
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
110
|
+
# test failures related to randomization by passing the same `--seed` value
|
111
|
+
# as the one that triggered the failure.
|
112
|
+
Kernel.srand config.seed
|
113
|
+
=end
|
114
|
+
end
|