observed 0.1.1

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.
Files changed (119) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +204 -0
  7. data/Rakefile +4 -0
  8. data/examples/00readme/Gemfile +5 -0
  9. data/examples/00readme/clockwork.rb +16 -0
  10. data/examples/00readme/observed.rb +17 -0
  11. data/examples/observed.rb +10 -0
  12. data/exe/observed-oneshot +11 -0
  13. data/features/oneshot.feature +24 -0
  14. data/features/support/env.rb +8 -0
  15. data/features/test_in_single_ruby_source.feature +32 -0
  16. data/integrations/observed-clockwork/.gitignore +17 -0
  17. data/integrations/observed-clockwork/Gemfile +4 -0
  18. data/integrations/observed-clockwork/LICENSE.txt +22 -0
  19. data/integrations/observed-clockwork/README.md +53 -0
  20. data/integrations/observed-clockwork/Rakefile +1 -0
  21. data/integrations/observed-clockwork/bin/clockwork +16 -0
  22. data/integrations/observed-clockwork/bin/clockworkd +16 -0
  23. data/integrations/observed-clockwork/bin/observed-clockwork +16 -0
  24. data/integrations/observed-clockwork/bin/rake +16 -0
  25. data/integrations/observed-clockwork/examples/clockwork/clockwork.rb +9 -0
  26. data/integrations/observed-clockwork/examples/clockwork/foo_plugin.rb +19 -0
  27. data/integrations/observed-clockwork/examples/clockwork/observed.conf +6 -0
  28. data/integrations/observed-clockwork/features/run_observed_inside_clockwork.feature +59 -0
  29. data/integrations/observed-clockwork/features/support/env.rb +8 -0
  30. data/integrations/observed-clockwork/lib/observed/clockwork/version.rb +5 -0
  31. data/integrations/observed-clockwork/lib/observed/clockwork.rb +20 -0
  32. data/integrations/observed-clockwork/observed-clockwork.gemspec +29 -0
  33. data/lib/observed/application/oneshot.rb +114 -0
  34. data/lib/observed/application.rb +1 -0
  35. data/lib/observed/builtin_plugins/file.rb +49 -0
  36. data/lib/observed/builtin_plugins/stdout.rb +35 -0
  37. data/lib/observed/builtin_plugins.rb +2 -0
  38. data/lib/observed/config.rb +27 -0
  39. data/lib/observed/config_builder.rb +167 -0
  40. data/lib/observed/config_dsl.rb +77 -0
  41. data/lib/observed/configurable.rb +56 -0
  42. data/lib/observed/default/observer.rb +16 -0
  43. data/lib/observed/default/reporter.rb +17 -0
  44. data/lib/observed/default.rb +2 -0
  45. data/lib/observed/hash/builder.rb +24 -0
  46. data/lib/observed/hash/fetcher.rb +19 -0
  47. data/lib/observed/hash/key_path_encoding.rb +62 -0
  48. data/lib/observed/hash.rb +3 -0
  49. data/lib/observed/observer.rb +18 -0
  50. data/lib/observed/observer_helpers/timer.rb +37 -0
  51. data/lib/observed/pluggable.rb +34 -0
  52. data/lib/observed/reader.rb +14 -0
  53. data/lib/observed/reporter/regexp_matching.rb +11 -0
  54. data/lib/observed/reporter.rb +25 -0
  55. data/lib/observed/system.rb +109 -0
  56. data/lib/observed/version.rb +3 -0
  57. data/lib/observed/writer.rb +14 -0
  58. data/lib/observed.rb +77 -0
  59. data/observed.gemspec +30 -0
  60. data/plugins/observed-fluentd/.gitignore +20 -0
  61. data/plugins/observed-fluentd/Gemfile +12 -0
  62. data/plugins/observed-fluentd/LICENSE.txt +22 -0
  63. data/plugins/observed-fluentd/README.md +99 -0
  64. data/plugins/observed-fluentd/Rakefile +1 -0
  65. data/plugins/observed-fluentd/features/plugin.feature +61 -0
  66. data/plugins/observed-fluentd/features/support/env.rb +32 -0
  67. data/plugins/observed-fluentd/fluent.d/fluent.conf +93 -0
  68. data/plugins/observed-fluentd/fluentd.pid +1 -0
  69. data/plugins/observed-fluentd/lib/observed/fluentd/version.rb +5 -0
  70. data/plugins/observed-fluentd/lib/observed/fluentd.rb +30 -0
  71. data/plugins/observed-fluentd/observe.d/clockwork.rb +9 -0
  72. data/plugins/observed-fluentd/observe.d/observed.conf +17 -0
  73. data/plugins/observed-fluentd/observed-fluentd.gemspec +26 -0
  74. data/plugins/observed-gauge/.gitignore +18 -0
  75. data/plugins/observed-gauge/Gemfile +4 -0
  76. data/plugins/observed-gauge/LICENSE.txt +22 -0
  77. data/plugins/observed-gauge/README.md +29 -0
  78. data/plugins/observed-gauge/Rakefile +1 -0
  79. data/plugins/observed-gauge/lib/observed/gauge/version.rb +5 -0
  80. data/plugins/observed-gauge/lib/observed/gauge.rb +117 -0
  81. data/plugins/observed-gauge/observed-gauge.gemspec +30 -0
  82. data/plugins/observed-gauge/spec/gauge_spec.rb +195 -0
  83. data/plugins/observed-gauge/spec/spec_helper.rb +25 -0
  84. data/plugins/observed-http/.gitignore +17 -0
  85. data/plugins/observed-http/Gemfile +4 -0
  86. data/plugins/observed-http/LICENSE.txt +22 -0
  87. data/plugins/observed-http/README.md +37 -0
  88. data/plugins/observed-http/Rakefile +1 -0
  89. data/plugins/observed-http/features/observe_web_services_via_http.feature +32 -0
  90. data/plugins/observed-http/features/support/env.rb +8 -0
  91. data/plugins/observed-http/lib/observed/http/version.rb +5 -0
  92. data/plugins/observed-http/lib/observed/http.rb +60 -0
  93. data/plugins/observed-http/observed-http.gemspec +31 -0
  94. data/plugins/observed-http/spec/fixtures/observed.conf +10 -0
  95. data/plugins/observed-http/spec/http_spec.rb +14 -0
  96. data/plugins/observed-http/spec/spec_helper.rb +25 -0
  97. data/spec/builtin_plugins/file_spec.rb +145 -0
  98. data/spec/builtin_plugins/stdout_spec.rb +56 -0
  99. data/spec/config_builder_spec.rb +146 -0
  100. data/spec/config_dsl_spec.rb +50 -0
  101. data/spec/configurable_spec.rb +65 -0
  102. data/spec/fixtures/configure_by_conf/foo_plugin.rb +12 -0
  103. data/spec/fixtures/configure_by_conf/observed.conf +6 -0
  104. data/spec/fixtures/configure_by_conf_dot_d/foo_plugin.rb +18 -0
  105. data/spec/fixtures/configure_by_conf_dot_d/observed.conf.d/check_foo_1.rb +1 -0
  106. data/spec/fixtures/configure_by_conf_dot_d/observed.conf.d/plugins.rb +1 -0
  107. data/spec/fixtures/configure_by_require/observed_conf.rb +6 -0
  108. data/spec/hash/builder_spec.rb +36 -0
  109. data/spec/hash/fetcher_spec.rb +29 -0
  110. data/spec/input_helpers/timer_spec.rb +54 -0
  111. data/spec/observed_spec.rb +79 -0
  112. data/spec/observer_spec.rb +123 -0
  113. data/spec/oneshot_spec.rb +58 -0
  114. data/spec/reader_spec.rb +15 -0
  115. data/spec/reporter_spec.rb +19 -0
  116. data/spec/spec_helper.rb +65 -0
  117. data/spec/system_spec.rb +75 -0
  118. data/spec/writer_spec.rb +16 -0
  119. metadata +299 -0
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ require 'observed/builtin_plugins/stdout'
4
+
5
+ describe Observed::BuiltinPlugins::Stdout do
6
+
7
+ subject {
8
+ reporter = Observed::BuiltinPlugins::Stdout.new
9
+ reporter.configure config
10
+ reporter
11
+ }
12
+
13
+ let(:config) {
14
+ { tag_pattern: /foo\..+/, format: formatter }
15
+ }
16
+
17
+ context 'with a specific formatter' do
18
+
19
+ let(:formatter) {
20
+ -> tag, time, data, fetcher { "foo #{time.to_i} #{data[:foo]} #{fetcher['bar.baz']}" }
21
+ }
22
+
23
+ it 'reports the formatted data to the stdout' do
24
+ time = Time.now
25
+ STDOUT.expects(:puts).with("foo #{time.to_i} 1 2")
26
+ expect { subject.report('foo', time, {foo: 1, bar: {baz: 2}}) }.to_not raise_error
27
+ end
28
+
29
+ end
30
+
31
+ context 'without a specific formatter' do
32
+
33
+ let(:formatter) {
34
+ nil
35
+ }
36
+
37
+ it 'reports the data formatted by the default formatter to the stdout' do
38
+ time = Time.now
39
+ STDOUT.expects(:puts).with("#{time.to_s} foo {:foo=>1}")
40
+ expect { subject.report('foo', time, {foo: 1}) }.to_not raise_error
41
+ end
42
+
43
+ end
44
+
45
+ context 'with the formatter whose number of parameters is not 3 nor 4' do
46
+
47
+ let(:formatter) {
48
+ -> a, b {}
49
+ }
50
+
51
+ it 'fails while reporting' do
52
+ pattern = /Number of parameters for the function for the key :format must be 3 or 4, but was 2/
53
+ expect { subject.report('foo', Time.now, {}) }.to raise_error(pattern)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+ require 'observed/config_builder'
3
+
4
+ describe Observed::ConfigBuilder do
5
+
6
+ include FakeFS::SpecHelpers
7
+
8
+ subject {
9
+ Observed::ConfigBuilder.new(
10
+ writer_plugins: writer_plugins,
11
+ reader_plugins: reader_plugins,
12
+ observer_plugins: observer_plugins,
13
+ reporter_plugins: reporter_plugins,
14
+ system: system
15
+ )
16
+ }
17
+
18
+ let(:system) {
19
+ mock('system')
20
+ }
21
+
22
+ let(:observer_plugins) {
23
+ my_file = Class.new(Observed::Observer) do
24
+ attribute :path
25
+ attribute :key
26
+ def observe
27
+ content = File.open(path, 'r') do |f|
28
+ f.read
29
+ end
30
+ system.report(tag, { key => content })
31
+ end
32
+ end
33
+ { 'my_file' => my_file }
34
+ }
35
+
36
+ let(:reporter_plugins) {
37
+ my_stdout = Class.new(Observed::Reporter) do
38
+ attribute :format
39
+ def match(tag)
40
+ true
41
+ end
42
+ def report(tag, time, data)
43
+ text = format.call tag, time, data, Observed::Hash::Fetcher.new(data)
44
+ STDOUT.puts text
45
+ end
46
+ end
47
+ { 'my_stdout' => my_stdout }
48
+ }
49
+
50
+ let(:writer_plugins) {
51
+ stdout = Class.new(Observed::Writer) do
52
+ attribute :format
53
+ def write(tag, time, data)
54
+ text = format.call tag, time, data, Observed::Hash::Fetcher.new(data)
55
+ STDOUT.puts text
56
+ end
57
+ end
58
+ { 'stdout' => stdout }
59
+ }
60
+
61
+ let(:reader_plugins) {
62
+ file = Class.new(Observed::Reader) do
63
+ attribute :path
64
+ attribute :key
65
+ def read
66
+ content = File.open(path, 'r') do |f|
67
+ f.read
68
+ end
69
+ { key => content }
70
+ end
71
+ end
72
+ {
73
+ 'file' => file
74
+ }
75
+ }
76
+
77
+ it 'creates writers' do
78
+ time = Time.now
79
+ subject.write to: 'stdout', with: {
80
+ format: -> tag, time, data, d { "value:#{d['foo.bar']}" }
81
+ }
82
+ STDOUT.expects(:puts).with('value:123')
83
+ expect { subject.build.writers.first.write('foo.bar', time, {foo:{bar:123}}) }.to_not raise_error
84
+ end
85
+
86
+ it 'creates readers' do
87
+ subject.read from: 'file', with: {
88
+ path: 'foo.txt',
89
+ key: 'content'
90
+ }
91
+ File.open('foo.txt', 'w') do |f|
92
+ f.write('file content')
93
+ end
94
+ expect(subject.build.readers.first.read).to eq({ 'content' => 'file content' })
95
+ end
96
+
97
+ it 'creates observers from reader plugins' do
98
+ subject.observe 'foo.bar', from: 'file', with: {
99
+ path: 'foo.txt',
100
+ key: 'content'
101
+ }
102
+ File.open('foo.txt', 'w') do |f|
103
+ f.write('file content')
104
+ end
105
+ system.expects(:report).with('foo.bar', { 'content' => 'file content' })
106
+ expect { subject.build.observers.first.observe }.to_not raise_error
107
+ end
108
+
109
+ it 'creates observers from observer plugins' do
110
+ subject.observe 'foo.bar', via: 'my_file', which: {
111
+ path: 'foo.txt',
112
+ key: 'content'
113
+ }
114
+ File.open('foo.txt', 'w') do |f|
115
+ f.write('file content')
116
+ end
117
+ system.expects(:report).with('foo.bar', { 'content' => 'file content' })
118
+ expect { subject.build.observers.first.observe }.to_not raise_error
119
+ end
120
+
121
+ it 'creates reporters from writer plugins' do
122
+ tag = 'foo.bar'
123
+ time = Time.now
124
+
125
+ subject.report /foo\.bar/, to: 'stdout', with: {
126
+ format: -> tag, time, data, d { "foo.bar #{time} #{d[tag]}" }
127
+ }
128
+ reporter = subject.reporters.first
129
+ STDOUT.expects(:puts).with("foo.bar #{time} 123").once
130
+ expect(reporter.match(tag)).to be_true
131
+ expect { reporter.report(tag, time, { foo: { bar: 123 }}) }.to_not raise_error
132
+ end
133
+
134
+ it 'creates reporters from reporter plugins' do
135
+ tag = 'foo.bar'
136
+ time = Time.now
137
+
138
+ subject.report /foo\.bar/, via: 'my_stdout', with: {
139
+ format: -> tag, time, data, d { "foo.bar #{time} #{d[tag]}" }
140
+ }
141
+ reporter = subject.reporters.first
142
+ STDOUT.expects(:puts).with("foo.bar #{time} 123").once
143
+ expect(reporter.match(tag)).to be_true
144
+ expect { reporter.report(tag, time, { foo: { bar: 123 }}) }.to_not raise_error
145
+ end
146
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'observed/config_dsl'
3
+ require 'observed/observer'
4
+ require 'observed/reporter'
5
+ require 'observed/reporter/regexp_matching'
6
+ require 'observed/config_builder'
7
+
8
+ describe Observed::ConfigDSL do
9
+ subject {
10
+ Observed::ConfigDSL.new(builder: Observed::ConfigBuilder.new(
11
+ observer_plugins: observer_plugins,
12
+ reporter_plugins: reporter_plugins,
13
+ system: sys
14
+ ))
15
+ }
16
+ let(:foo) {
17
+ Class.new(Observed::Observer) do
18
+ def observe
19
+
20
+ end
21
+ plugin_name 'foo'
22
+ end
23
+ }
24
+ let(:stdout) {
25
+ Class.new(Observed::Reporter) do
26
+ include Observed::Reporter::RegexpMatching
27
+ def report(tag, time, data)
28
+
29
+ end
30
+ plugin_name 'stdout'
31
+ end
32
+ }
33
+ let(:sys) {
34
+ mock('sys')
35
+ }
36
+ let(:observer_plugins) {
37
+ { 'foo' => foo }
38
+ }
39
+ let(:reporter_plugins) {
40
+ { 'stdout' => stdout }
41
+ }
42
+ it 'creates a config' do
43
+ subject.instance_eval do
44
+ observe 'foo', via: 'foo', with: { name: 'name' }
45
+ report /foo/, via: 'stdout'
46
+ end
47
+
48
+ #expect(subject.config).to eq({ observers: {'foo' => {plugin: 'foo', name: 'name'}}, reporters: {'foo' => {plugin: 'stdout'}}})
49
+ end
50
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+ require 'observed/configurable'
3
+
4
+ module ConfigurableSpec
5
+ class Foo
6
+ include Observed::Configurable
7
+
8
+ attribute :foo, default: 123
9
+ attribute :bar, default: 234
10
+ attribute :baz
11
+
12
+ default :bar => 345
13
+ end
14
+ end
15
+
16
+ describe Observed::Configurable do
17
+
18
+ context 'without parameters for the constructor' do
19
+ subject {
20
+ ConfigurableSpec::Foo.new
21
+ }
22
+ it 'uses default values for attributes' do
23
+ expect(subject.foo).to eq(123)
24
+ end
25
+ it 'overrides default values on `attribute name, :default => default_value`' do
26
+ expect(subject.bar).to eq(345)
27
+ end
28
+ it 'raises errors when attributes without values are read' do
29
+ expect { subject.baz }.to raise_error
30
+ end
31
+ end
32
+
33
+ context 'with parameters for the constructor' do
34
+ subject {
35
+ ConfigurableSpec::Foo.new({foo: 1, bar: 2, baz: 3})
36
+ }
37
+ it 'prefers values from constructor parameters over defaults' do
38
+ expect(subject.foo).to eq(1)
39
+ expect(subject.bar).to eq(2)
40
+ expect(subject.baz).to eq(3)
41
+ end
42
+ end
43
+
44
+ context 'configured through `configure(args)` method' do
45
+ subject {
46
+ foo = ConfigurableSpec::Foo.new
47
+ foo.configure(args)
48
+ foo
49
+ }
50
+ shared_examples_for 'values are set' do
51
+ it 'prefers values from `configure(args)` over defaults' do
52
+ expect(subject.foo).to eq(1)
53
+ expect(subject.bar).to eq(2)
54
+ expect(subject.baz).to eq(3)
55
+ end
56
+ end
57
+ context 'when args has symbol keys' do
58
+ let(:args) {
59
+ {foo: 1, bar: 2, baz: 3}
60
+ }
61
+ it_behaves_like 'values are set'
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,12 @@
1
+ module OneshotSpec
2
+ class FooPlugin < Observed::Observer
3
+
4
+ def observe
5
+ sleep_duration = rand / 20
6
+ sleep sleep_duration
7
+ system.report(tag, system.now, "Foo #{sleep_duration}")
8
+ end
9
+
10
+ plugin_name 'foo'
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ require 'observed/builtin_plugins'
2
+ require_relative 'foo_plugin'
3
+
4
+ observe 'foo_1', via: 'foo'
5
+
6
+ report 'foo_1', via: 'stdout'
@@ -0,0 +1,18 @@
1
+ module OneshotSpec
2
+ class FooPlugin < Observed::Observer
3
+ default :timeout_in_milliseconds => 5000
4
+ default :number_of_trials => 10
5
+
6
+ def sample
7
+ sleep_duration = rand / 20
8
+ sleep sleep_duration
9
+ "Foo #{sleep_duration}"
10
+ end
11
+
12
+ def logger
13
+ Logger.new(STDOUT)
14
+ end
15
+
16
+ plugin_name 'foo'
17
+ end
18
+ end
@@ -0,0 +1 @@
1
+ observe 'foo_1', via: 'foo'
@@ -0,0 +1 @@
1
+ require_relative '../foo_plugin'
@@ -0,0 +1,6 @@
1
+ require 'observed'
2
+ include Observed
3
+
4
+ require_relative '../configure_by_conf/foo_plugin'
5
+
6
+ observe 'foo', via: 'foo'
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'observed/hash/builder'
3
+
4
+ describe Observed::Hash::Builder do
5
+
6
+ subject {
7
+ described_class.new(hash)
8
+ }
9
+
10
+ context 'with a source hash' do
11
+
12
+ let(:hash) { {} }
13
+
14
+ context 'with a key path' do
15
+ it 'decodes the key path and recursively creates missing Hash object for each part in the key path' do
16
+ subject['foo.bar'] = 1
17
+
18
+ expect(subject.build).to eq({foo:{bar:1}})
19
+ end
20
+ end
21
+
22
+ context 'with a regular string key' do
23
+ it 'updates the value for the key' do
24
+ subject['foo'] = 1
25
+ expect(subject.build).to eq({foo:1})
26
+ end
27
+ end
28
+
29
+ context 'with a regular symbol key' do
30
+ it 'updates the value for the key' do
31
+ subject[:foo] = 1
32
+ expect(subject.build).to eq({foo:1})
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ require 'observed/hash/fetcher'
4
+
5
+ describe Observed::Hash::Fetcher do
6
+
7
+ subject {
8
+ described_class.new(hash)
9
+ }
10
+
11
+ context 'when the source hash is nil' do
12
+
13
+ let(:hash) { nil }
14
+
15
+ it 'fails' do
16
+ expect { subject }.to raise_error
17
+ end
18
+ end
19
+
20
+ context 'when the source hash is nested' do
21
+
22
+ let(:hash) { {foo:{bar:1},baz:2} }
23
+
24
+ it 'decodes the key path to recursively find the value' do
25
+ expect(subject['foo.bar']).to eq(1)
26
+ expect(subject['baz']).to eq(2)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'observed/observer_helpers/timer'
3
+ require 'observed/observer'
4
+
5
+ describe Observed::ObserverHelpers::Timer do
6
+
7
+ include Observed::SpecHelpers
8
+
9
+ before {
10
+ class ExampleTimerPlugin < Observed::Observer
11
+ include Observed::ObserverHelpers::Timer
12
+
13
+ attribute :timeout_in_milliseconds
14
+ attribute :time_to_sleep
15
+
16
+ def observe
17
+ time_and_report(timeout_in_seconds: self.timeout_in_milliseconds / 1000.0) do
18
+ sleep(time_to_sleep)
19
+ time_to_sleep
20
+ end
21
+ end
22
+
23
+ def self.plugin_name
24
+ 'timer'
25
+ end
26
+ end
27
+ }
28
+
29
+ subject {
30
+ input = ExampleTimerPlugin.new
31
+ input.configure system: system, tag: 'foo.timed', time_to_sleep: 0.001, timeout_in_milliseconds: 1000
32
+ input
33
+ }
34
+
35
+ let(:system) {
36
+ m = mock('system')
37
+ m.stubs(:now).returns(1.0)
38
+ .then.returns(2.0)
39
+ .then.returns(3.0)
40
+ .then.returns(5.0)
41
+ .then.returns(6.0)
42
+ .then.returns(9.0)
43
+ m
44
+ }
45
+
46
+ it 'should report results with elapsed times' do
47
+ system.expects(:report).with('foo.timed.success', status: :success, elapsed_time: 1.0, result: 0.001)
48
+ system.expects(:report).with('foo.timed.success', status: :success, elapsed_time: 2.0, result: 0.001)
49
+ system.expects(:report).with('foo.timed.success', status: :success, elapsed_time: 3.0, result: 0.001)
50
+ subject.observe
51
+ subject.observe
52
+ subject.observe
53
+ end
54
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+ require 'observed'
3
+ require 'observed/builtin_plugins'
4
+
5
+ describe Observed do
6
+ include FakeFS::SpecHelpers
7
+
8
+ describe '#load!`' do
9
+
10
+ context 'with a relative file path under the current working directory' do
11
+
12
+ subject do
13
+ mod = Module.new do
14
+ extend Observed
15
+ end
16
+ mod.load! './observed.rb'
17
+ mod.config
18
+ end
19
+
20
+ context 'with invalid file path' do
21
+ it 'should raise an error while loading' do
22
+ expect { subject }.to raise_error(%r|No such file or directory.+observed\.rb|)
23
+ end
24
+ end
25
+
26
+ context 'with a valid relative file path' do
27
+ before do
28
+ File.open('./observed.rb', 'w') do |file|
29
+ file.write(
30
+ <<-EOS
31
+ report /foo/, via: 'stdout'
32
+ EOS
33
+ )
34
+ end
35
+ end
36
+
37
+ it 'should load observed.rb' do
38
+ expect { subject }.to_not raise_error
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'with an absolute file path' do
44
+
45
+ subject {
46
+ mod = Module.new do
47
+ extend Observed
48
+ end
49
+ mod.load! '/tmp/foo/observed_conf.rb'
50
+ mod.config
51
+ }
52
+
53
+ context 'when the file does not exist' do
54
+
55
+ it 'fails to load it' do
56
+ expect { subject }.to raise_error(%r|No such file or directory - /tmp/foo/observed_conf.rb|)
57
+ end
58
+ end
59
+
60
+ context 'when the file exists' do
61
+
62
+ before {
63
+ FileUtils.mkdir_p('/tmp/foo')
64
+ File.open('/tmp/foo/observed_conf.rb', 'w') do |f|
65
+ f.write(
66
+ <<-EOS
67
+ report /foo/, via: 'stdout'
68
+ EOS
69
+ )
70
+ end
71
+ }
72
+
73
+ it 'succeeds to load it' do
74
+ expect { subject }.to_not raise_error
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+ require 'observed/observer'
3
+
4
+ describe Observed::Observer do
5
+
6
+ subject {
7
+ described_class.new(tag: 'the_tag', system: sys)
8
+ }
9
+
10
+ let(:sys) { mock('system') }
11
+
12
+ it 'fails when the method `observe` is not overrode' do
13
+ expect { subject.observe }.to raise_error
14
+ end
15
+
16
+ describe 'attribute' do
17
+
18
+ it 'can be given by constructor parameters' do
19
+ klass = Class.new(Observed::Observer) do
20
+ attribute :timeout_in_milliseconds
21
+ attribute :number_of_trials
22
+ end
23
+
24
+ subject = klass.new(
25
+ timeout_in_milliseconds: 5000,
26
+ number_of_trials: 5000,
27
+ tag: 'tag'
28
+ )
29
+
30
+ expect(subject.timeout_in_milliseconds).to eq(5000)
31
+ expect(subject.number_of_trials).to eq(5000)
32
+ expect(subject.tag).to eq('tag')
33
+ end
34
+
35
+ it 'can have a default value' do
36
+ klass = Class.new(Observed::Observer) do
37
+ attribute :timeout_in_milliseconds
38
+ attribute :number_of_trials
39
+ default :timeout_in_milliseconds => 5000
40
+ default :number_of_trials => 5000
41
+ default :tag => 'tag'
42
+ end
43
+
44
+ subject = klass.new
45
+
46
+ expect(subject.timeout_in_milliseconds).to eq(5000)
47
+ expect(subject.number_of_trials).to eq(5000)
48
+ expect(subject.tag).to eq('tag')
49
+ end
50
+
51
+ context 'without a default value or a given value' do
52
+ it 'raises errors when accessed' do
53
+ klass = Class.new(Observed::Observer) do
54
+ attribute :timeout_in_milliseconds
55
+ attribute :number_of_trials
56
+ end
57
+
58
+ subject = klass.new
59
+
60
+ expect { subject.timeout_in_milliseconds }.to raise_error
61
+ expect { subject.number_of_trials }.to raise_error
62
+ expect { subject.tag }.to raise_error
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ describe '.find_plugin_named' do
69
+
70
+ it 'returns nil when no plugin with the specific name found' do
71
+ expect(Observed::Observer.find_plugin_named('an_invalid_name')).to be_nil
72
+ end
73
+
74
+ context 'with one named plugin' do
75
+ let(:klass) {
76
+ Class.new(Observed::Observer) do
77
+ attribute :timeout_in_milliseconds
78
+ attribute :number_of_trials
79
+
80
+ default :timeout_in_milliseconds => 5000
81
+ default :number_of_trials => 2
82
+
83
+ def sample
84
+ time_to_sleep = rand / 100
85
+ sleep rand
86
+ "Foo #{time_to_sleep}"
87
+ end
88
+
89
+ plugin_name 'observer_spec_foo'
90
+ end
91
+ }
92
+ before {
93
+ klass
94
+ }
95
+ it 'returns the plugin' do
96
+ expect(Observed::Observer.find_plugin_named('observer_spec_foo')).to eq(klass)
97
+ end
98
+ end
99
+
100
+ context 'with two named plugins' do
101
+ let(:bar) {
102
+ Class.new(Observed::Observer) do
103
+ plugin_name 'observer_spec_bar'
104
+ end
105
+ }
106
+ let(:baz) {
107
+ Class.new(Observed::Observer) do
108
+ plugin_name 'observer_spec_baz'
109
+ end
110
+ }
111
+ before {
112
+ bar
113
+ baz
114
+ }
115
+ it 'returns each plugin' do
116
+ expect(Observed::Observer.find_plugin_named('observer_spec_bar')).to eq(bar)
117
+ expect(Observed::Observer.find_plugin_named('observer_spec_baz')).to eq(baz)
118
+ end
119
+ end
120
+
121
+ end
122
+
123
+ end