jeckyl 0.2.1

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