jeckyl 0.2.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.
@@ -0,0 +1,202 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'jeckyl/errors'
3
+ require File.expand_path(File.dirname(__FILE__) + '/../test/test_configurator')
4
+ require File.expand_path(File.dirname(__FILE__) + '/../test/test_configurator_errors')
5
+ require File.expand_path(File.dirname(__FILE__) + '/../test/test_class')
6
+ require File.expand_path(File.dirname(__FILE__) + '/../test/test_subclass')
7
+
8
+ conf_path = File.expand_path(File.dirname(__FILE__) + '/../test/conf.d')
9
+
10
+ describe "Jeckyl" do
11
+
12
+ # general tests
13
+
14
+ it "should return the defaults" do
15
+ conf = TestJeckyl.new(File.join(conf_path, 'defaults.rb'))
16
+ conf[:log_dir].should == '/tmp'
17
+ #conf[:key_file].should be_nil
18
+ conf[:log_level].should == :verbose
19
+ conf[:log_rotation].should == 5
20
+ conf[:threshold].should == 5.0
21
+ end
22
+
23
+ it "should create a simple config" do
24
+ #TestJeckyl.debug(true)
25
+ conf_file = conf_path + '/jeckyl'
26
+ conf = TestJeckyl.new(conf_file)
27
+ conf[:log_dir].should match(/test$/)
28
+ conf[:log_level].should == :verbose
29
+ conf[:log_rotation].should == 5
30
+ conf[:email].should == "robert@osburn-sharp.ath.cx"
31
+ conf.has_key?(:sieve).should be_true
32
+ conf[:config_files].length.should == 1
33
+ end
34
+
35
+
36
+
37
+ # general exceptions
38
+
39
+ it "should fail if the config file does not exist" do
40
+ conf_file = conf_path + "/never/likely/to/be/there"
41
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigFileMissing, conf_file)
42
+ end
43
+
44
+ it "should raise an exception if a file parameter does not exist" do
45
+ conf_file = conf_path + '/bad_filename'
46
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[log_dir\]:/)
47
+ end
48
+
49
+ it "should raise an exception if there is a syntax error" do
50
+ conf_file = conf_path + '/syntax_error'
51
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigSyntaxError)
52
+ end
53
+
54
+ it "should raise an exception if there is an unknown parameter used" do
55
+ conf_file = conf_path + '/unknown_param'
56
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::UnknownParameter)
57
+ end
58
+
59
+ # test parameters
60
+
61
+ describe "File Parameters" do
62
+
63
+ it "should raise an exception if a dir is not writable" do
64
+ conf_file = conf_path + '/unwritable_dir'
65
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[log_dir\]:/)
66
+ end
67
+
68
+ it "should raise an exception if file is not readable" do
69
+ conf_file = conf_path + '/no_such_file'
70
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[key_file\]:/)
71
+ end
72
+
73
+ end
74
+
75
+ describe "Numeric Parameters" do
76
+
77
+ it "should raise an exception if it gets a float when expecting an integer" do
78
+ conf_file = conf_path + '/wrong_type'
79
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[log_rotation\]:.*value is not of required type: Integer$/)
80
+ end
81
+
82
+ it "should raise an exception if it gets a number out of range" do
83
+ conf_file = conf_path + '/out_of_range'
84
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[log_rotation\]:.*value is not within required range: 0..20$/)
85
+ end
86
+
87
+ it "should raise an exception if it gets an integer instead of a float" do
88
+ conf_file = conf_path + '/not_a_float'
89
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[pi\]:.*value is not of required type: Float$/)
90
+ end
91
+
92
+ end
93
+
94
+ describe "Boolean Parameters" do
95
+
96
+ it "should raise an exception if it gets a string instead of a boolean" do
97
+ conf_file = conf_path + '/not_a_bool'
98
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[debug\]:.*Value is not a Boolean$/)
99
+ end
100
+
101
+ it "should raise an exception if it gets an invalid flag value" do
102
+ conf_file = conf_path + '/not_a_flag'
103
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[flag\]:.*Cannot convert to Boolean$/)
104
+ end
105
+
106
+ end
107
+
108
+ describe "Compound Parameters" do
109
+
110
+ it "should raise an exception if it gets a string instead of an array" do
111
+ conf_file = conf_path + '/not_an_array'
112
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[collection\]:.*value is not an Array$/)
113
+ end
114
+
115
+ it "should raise an exception if it gets a string instead of a hash" do
116
+ conf_file = conf_path + '/not_a_hash'
117
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[options\]:.*value is not a Hash$/)
118
+ end
119
+
120
+ it "should raise an exception if it gets an array of strings instead of a integers" do
121
+ conf_file = conf_path + '/not_an_integer_array'
122
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[sieve\]:.*element of array is not of type: Integer$/)
123
+ end
124
+
125
+ end
126
+
127
+ describe "String Parameters" do
128
+
129
+ it "should raise an exception if it gets a number instead of a string" do
130
+ conf_file = conf_path + '/not_a_string'
131
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[email\]:.*is not a String$/)
132
+ end
133
+
134
+ it "should raise an exception if a string does not match the required pattern" do
135
+ conf_file = conf_path + '/not_an_email'
136
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[email\]:.*does not match required pattern:/)
137
+ end
138
+
139
+ it "should raise an exception if it gets a pattern that is not a pattern" do
140
+ conf_file = conf_path + '/not_a_pattern'
141
+ lambda{conf = TestJeckylErrors.new(conf_file)}.should raise_error(Jeckyl::ConfigSyntaxError, "Attempt to pattern match without a Regexp")
142
+ end
143
+
144
+ end
145
+
146
+ describe "Set Parameters" do
147
+
148
+ it "should raise an exception if it gets a set that is not an array" do
149
+ conf_file = conf_path + '/not_a_set'
150
+ lambda{conf = TestJeckylErrors.new(conf_file)}.should raise_error(Jeckyl::ConfigSyntaxError, "Sets to test membership must be arrays")
151
+ end
152
+
153
+ it "should raise an exception if a value is not in the given set" do
154
+ conf_file = conf_path + '/not_a_member'
155
+ lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[log_level\]:.*is not a member of:/)
156
+ end
157
+
158
+
159
+ end
160
+
161
+ describe "Operating in a more relaxed mode" do
162
+
163
+ # leave at the end or you need to re-strict Jeckyl.
164
+ it "should load any parameter if its not being strict" do
165
+ conf_file = conf_path + '/sloppy_params'
166
+ conf = TestJeckyl.new(conf_file, :relax=>true)
167
+ conf[:my_age].should == 50
168
+ end
169
+
170
+ end
171
+
172
+ describe "find the parameters for a specific class" do
173
+ it "should sift out the parameters" do
174
+ bconf = File.join(conf_path, 'bclass.rb')
175
+ opts = Bclass.new(bconf)
176
+ opts.length.should == 4
177
+ subopts = Aclass.intersection(opts)
178
+ subopts.length.should ==2
179
+ subopts.has_key?(:a_bool).should be_true
180
+ subopts.has_key?(:no_def).should be_true
181
+ opts.complement(subopts)
182
+ opts.length.should == 2
183
+ opts.has_key?(:config_files).should be_true
184
+ opts.has_key?(:another).should be_true
185
+ end
186
+ end
187
+
188
+ describe "Merging config files" do
189
+ it "should merge another config file" do
190
+ conf_file = conf_path + '/jeckyl'
191
+ conf = TestJeckyl.new(conf_file)
192
+ conf.merge File.join(conf_path, 'merger.rb')
193
+ conf[:log_dir].should match(/reports$/)
194
+ conf[:log_level].should == :debug
195
+ conf[:log_rotation].should == 6
196
+ conf[:email].should == "robert@osburn-associates.ath.cx"
197
+ conf[:config_files].length.should == 2
198
+ conf[:pi].should == 3.14592
199
+ end
200
+ end
201
+
202
+ end
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'jeckyl'
4
+ require 'rspec'
5
+ require 'rspec/autorun'
6
+
7
+ RSpec.configure do |config|
8
+ config.color_enabled = true
9
+ config.formatter = :doc
10
+
11
+ end
@@ -0,0 +1,2 @@
1
+
2
+ log_level :debug
@@ -0,0 +1,2 @@
1
+
2
+ log_dir '/never/going/to/exist'
@@ -0,0 +1,2 @@
1
+ a_bool false
2
+ no_def "Its a problem"
File without changes
@@ -0,0 +1,46 @@
1
+ #
2
+ # Jeckyl test file
3
+ #
4
+
5
+ # should be a writable directory
6
+ log_dir "./test"
7
+
8
+ #should be a valid symbol
9
+ log_level :verbose
10
+
11
+ # should be an integer
12
+ log_rotation 5
13
+
14
+ # can be a float or any numeric
15
+ threshold 5.6
16
+ threshold 10
17
+
18
+ # must be a float
19
+ pi 3.14592
20
+
21
+ # array of anything
22
+ collection ["names", 1, true ]
23
+ # array of integers
24
+ sieve [2, 5, 7, 10, 15]
25
+
26
+ # hash of anything
27
+ my_opts = {:peter=>37, :paul=>40, :birds=>true}
28
+ options my_opts
29
+
30
+ # string formatted as email address
31
+ email "robert@osburn-sharp.ath.cx"
32
+
33
+ # real booleans
34
+ debug false
35
+ debug true
36
+
37
+ # generous booleans
38
+ flag "true"
39
+ flag "false"
40
+ flag "off"
41
+ flag "on"
42
+ flag "yes"
43
+ flag "no"
44
+ flag 1
45
+ flag 0
46
+
@@ -0,0 +1,46 @@
1
+ #
2
+ # Jeckyl test file
3
+ #
4
+
5
+ # should be a writable directory
6
+ log_dir "jeckyl/test"
7
+
8
+ #should be a valid symbol
9
+ log_level :verbose
10
+
11
+ # should be an integer
12
+ log_rotation 5
13
+
14
+ # can be a float or any numeric
15
+ threshold 5.6
16
+ threshold 10
17
+
18
+ # must be a float
19
+ pi 3.14592
20
+
21
+ # array of anything
22
+ collection ["names", 1, true ]
23
+ # array of integers
24
+ sieve [2, 5, 7, 10, 15]
25
+
26
+ # hash of anything
27
+ my_opts = {:peter=>37, :paul=>40, :birds=>true}
28
+ options my_opts
29
+
30
+ # string formatted as email address
31
+ email "robert@osburn-sharp.ath.cx"
32
+
33
+ # real booleans
34
+ debug false
35
+ debug true
36
+
37
+ # generous booleans
38
+ flag "true"
39
+ flag "false"
40
+ flag "off"
41
+ flag "on"
42
+ flag "yes"
43
+ flag "no"
44
+ flag 1
45
+ flag 0
46
+
@@ -0,0 +1,31 @@
1
+ #
2
+ # Jeckyl test file
3
+ #
4
+
5
+ # should be a writable directory
6
+ log_dir "./test/reports"
7
+
8
+ #should be a valid symbol
9
+ log_level :debug
10
+
11
+ # should be an integer
12
+ log_rotation 6
13
+
14
+ # can be a float or any numeric
15
+ threshold 5.6
16
+ threshold 10
17
+
18
+ # must be a float
19
+ pi 3.14592
20
+
21
+ # array of anything
22
+ collection ["names", 1, true ]
23
+ # array of integers
24
+ sieve [2, 5, 7, 10, 15]
25
+
26
+ # hash of anything
27
+ my_opts = {:peter=>37, :paul=>40, :birds=>true}
28
+ options my_opts
29
+
30
+ # string formatted as email address
31
+ email "robert@osburn-associates.ath.cx"
@@ -0,0 +1,2 @@
1
+
2
+ key_file "../test/key_file.asc"
@@ -0,0 +1 @@
1
+ debug "true"
@@ -0,0 +1 @@
1
+ flag "maybe"
@@ -0,0 +1 @@
1
+ pi 3
@@ -0,0 +1 @@
1
+ options "string"
@@ -0,0 +1 @@
1
+ log_level :turgid
@@ -0,0 +1 @@
1
+ invalid_pattern "robert@osburn-sharp.ath.cx"
@@ -0,0 +1 @@
1
+ invalid_set :verbose
@@ -0,0 +1 @@
1
+ email 12.0
@@ -0,0 +1 @@
1
+ collection "String"
@@ -0,0 +1 @@
1
+ email "robert-osburn-sharp"
@@ -0,0 +1 @@
1
+ sieve [1, 2, 3, "4", 5]
@@ -0,0 +1 @@
1
+ log_rotation 100
@@ -0,0 +1,5 @@
1
+ anything_goes true
2
+
3
+ my_age 50
4
+
5
+ great_things_to_do "Naturism"
@@ -0,0 +1,3 @@
1
+
2
+ log_dir "unfinished string
3
+
@@ -0,0 +1,2 @@
1
+
2
+ unusual_value "Not likely to be recognised"
@@ -0,0 +1 @@
1
+ log_dir "/home/robert/dev/projects/jeckyl/test/unwritable"
@@ -0,0 +1,2 @@
1
+
2
+ log_rotation 5.6
@@ -0,0 +1 @@
1
+ [debug]: true - Value is not a Boolean
@@ -0,0 +1 @@
1
+ No errors found in: /home/robert/dev/projects/jeckyl/test/conf.d/jeckyl
@@ -0,0 +1,32 @@
1
+ #
2
+ #
3
+ # = Title
4
+ #
5
+ # == SubTitle
6
+ #
7
+ # Author:: Robert Sharp
8
+ # Copyright:: Copyright (c) 2011 Robert Sharp
9
+ # License:: Open Software Licence v3.0
10
+ #
11
+ # This software is licensed for use under the Open Software Licence v. 3.0
12
+ # The terms of this licence can be found at http://www.opensource.org/licenses/osl-3.0.php
13
+ # and in the file copyright.txt. Under the terms of this licence, all derivative works
14
+ # must themselves be licensed under the Open Software Licence v. 3.0
15
+ #
16
+ #
17
+ #
18
+
19
+ #require 'jeckyl'
20
+
21
+ class Aclass < Jeckyl::Options
22
+
23
+ def configure_a_bool(bool)
24
+ default true
25
+ a_boolean(bool)
26
+ end
27
+
28
+ def configure_no_def(text)
29
+ a_string(text)
30
+ end
31
+
32
+ end
@@ -0,0 +1,105 @@
1
+ #
2
+ # Description
3
+ #
4
+ # Author:: Robert Sharp
5
+ # Copyright:: Copyright (c) 2010 Robert Sharp
6
+ # License:: Open Software Licence v3.0
7
+ #
8
+ # This software is licensed for use under the Open Software Licence v. 3.0
9
+ # The terms of this licence can be found at http://www.opensource.org/licenses/osl-3.0.php
10
+ # and in the file copyright.txt. Under the terms of this licence, all derivative works
11
+ # must themselves be licensed under the Open Software Licence v. 3.0
12
+ #
13
+ #
14
+ #require 'jeckyl'
15
+
16
+ class TestJeckyl < Jeckyl::Options
17
+
18
+ def prefix
19
+ 'set'
20
+ end
21
+
22
+ def set_log_dir(path)
23
+ default '/tmp'
24
+ comment "Location to write log files to"
25
+ a_writable_dir(path)
26
+ end
27
+
28
+ def set_key_file(path)
29
+ comment "key file to be used to check secure commands"
30
+ a_readable_file(path)
31
+ end
32
+
33
+ def set_log_level(symb)
34
+ default :verbose
35
+ comment "Log level can one of the following:",
36
+ "",
37
+ " * :system - log all important messages and use syslog",
38
+ " * :verbose - be more generous with logging to help resolve problems"
39
+ symbol_set = [:system, :verbose, :debug]
40
+ a_member_of(symb, symbol_set)
41
+ end
42
+
43
+ def set_log_rotation(val)
44
+ default 5
45
+ a_type_of(val, Integer)
46
+ in_range(val, 0, 20)
47
+ end
48
+
49
+ def set_threshold(val)
50
+ default 5.0
51
+ # make sure it is a number
52
+ a_type_of(val, Numeric)
53
+ # now make sure it is a float
54
+ in_range(val.to_f, 0.0, 10.0)
55
+
56
+ end
57
+
58
+ def set_pi(val)
59
+ default 3.14
60
+ a_type_of(val, Float)
61
+ end
62
+
63
+ def set_debug(bool)
64
+ default false
65
+ a_boolean(bool)
66
+ end
67
+
68
+ def set_flag(flag)
69
+ default "on"
70
+ a_flag(flag)
71
+ end
72
+
73
+ def set_collection(ary)
74
+ default Array.new
75
+ an_array(ary)
76
+ end
77
+
78
+ def set_sieve(ary)
79
+ default [1,2,3]
80
+ an_array_of(ary, Integer)
81
+ end
82
+
83
+ def set_options(opts)
84
+ default Hash.new
85
+ a_hash(opts)
86
+ end
87
+
88
+ def set_email(email)
89
+ default "me@home.org.uk"
90
+ a_matching_string(email, /^[a-z]+\@[a-z][a-z\-\.]+[a-z]$/)
91
+ end
92
+
93
+ # def set_invalid_set(member)
94
+ # default 1
95
+ # invalid_set = {:one=>1, :two=>2, :three=>3}
96
+ # a_member_of(member, invalid_set)
97
+ # end
98
+ #
99
+ # def set_invalid_pattern(email)
100
+ # default "me@work.org.uk"
101
+ # pattern = "email"
102
+ # a_matching_string(email, pattern)
103
+ # end
104
+
105
+ end
@@ -0,0 +1,105 @@
1
+ #
2
+ # Description
3
+ #
4
+ # Author:: Robert Sharp
5
+ # Copyright:: Copyright (c) 2010 Robert Sharp
6
+ # License:: Open Software Licence v3.0
7
+ #
8
+ # This software is licensed for use under the Open Software Licence v. 3.0
9
+ # The terms of this licence can be found at http://www.opensource.org/licenses/osl-3.0.php
10
+ # and in the file copyright.txt. Under the terms of this licence, all derivative works
11
+ # must themselves be licensed under the Open Software Licence v. 3.0
12
+ #
13
+ #
14
+ #require 'jeckyl'
15
+
16
+ class TestJeckylErrors < Jeckyl::Options
17
+
18
+ def prefix
19
+ 'set'
20
+ end
21
+
22
+ def set_log_dir(path)
23
+ default '/tmp'
24
+ comment "Location to write log files to"
25
+ a_writable_dir(path)
26
+ end
27
+
28
+ def set_key_file(path)
29
+ comment "key file to be used to check secure commands"
30
+ a_readable_file(path)
31
+ end
32
+
33
+ def set_log_level(symb)
34
+ default :verbose
35
+ comment "Log level can one of the following:",
36
+ "",
37
+ " * :system - log all important messages and use syslog",
38
+ " * :verbose - be more generous with logging to help resolve problems"
39
+ symbol_set = [:system, :verbose, :debug]
40
+ a_member_of(symb, symbol_set)
41
+ end
42
+
43
+ def set_log_rotation(val)
44
+ default 5
45
+ a_type_of(val, Integer)
46
+ in_range(val, 0, 20)
47
+ end
48
+
49
+ def set_threshold(val)
50
+ default 5.0
51
+ # make sure it is a number
52
+ a_type_of(val, Numeric)
53
+ # now make sure it is a float
54
+ in_range(val.to_f, 0.0, 10.0)
55
+
56
+ end
57
+
58
+ def set_pi(val)
59
+ default 3.14
60
+ a_type_of(val, Float)
61
+ end
62
+
63
+ def set_debug(bool)
64
+ default false
65
+ a_boolean(bool)
66
+ end
67
+
68
+ def set_flag(flag)
69
+ default "on"
70
+ a_flag(flag)
71
+ end
72
+
73
+ def set_collection(ary)
74
+ default Array.new
75
+ an_array(ary)
76
+ end
77
+
78
+ def set_sieve(ary)
79
+ default [1,2,3]
80
+ an_array_of(ary, Integer)
81
+ end
82
+
83
+ def set_options(opts)
84
+ default Hash.new
85
+ a_hash(opts)
86
+ end
87
+
88
+ def set_email(email)
89
+ default "me@home.org.uk"
90
+ a_matching_string(email, /^[a-z]+\@[a-z][a-z\-\.]+[a-z]$/)
91
+ end
92
+
93
+ def set_invalid_set(member)
94
+ default 1
95
+ invalid_set = {:one=>1, :two=>2, :three=>3}
96
+ a_member_of(member, invalid_set)
97
+ end
98
+
99
+ def set_invalid_pattern(email)
100
+ default "me@work.org.uk"
101
+ pattern = "email"
102
+ a_matching_string(email, pattern)
103
+ end
104
+
105
+ end
@@ -0,0 +1,11 @@
1
+ require File.join(File.dirname(__FILE__), 'test_class')
2
+
3
+ class Bclass < Aclass
4
+
5
+ def configure_another(text)
6
+ default "Hey"
7
+ a_string(text)
8
+
9
+ end
10
+
11
+ end