junkfood 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +11 -0
- data/.gitignore +6 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +76 -0
- data/LICENSE +202 -0
- data/NOTICE +4 -0
- data/README.md +375 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/junkfood.gemspec +147 -0
- data/lib/junkfood/adler32.rb +102 -0
- data/lib/junkfood/adler32_pure.rb +112 -0
- data/lib/junkfood/assert.rb +75 -0
- data/lib/junkfood/base32.rb +198 -0
- data/lib/junkfood/ceb/base_command.rb +62 -0
- data/lib/junkfood/ceb/base_event.rb +42 -0
- data/lib/junkfood/ceb/bus.rb +152 -0
- data/lib/junkfood/ceb/executors/command_executor.rb +44 -0
- data/lib/junkfood/ceb/executors/delayed_job_command_executor.rb +61 -0
- data/lib/junkfood/ceb/executors/event_executor.rb +35 -0
- data/lib/junkfood/ceb/executors.rb +25 -0
- data/lib/junkfood/ceb.rb +27 -0
- data/lib/junkfood/one_time.rb +247 -0
- data/lib/junkfood/paperclip_string_io.rb +66 -0
- data/lib/junkfood/settings.rb +67 -0
- data/lib/junkfood.rb +29 -0
- data/spec/.rspec +1 -0
- data/spec/junkfood/adler32_pure_spec.rb +16 -0
- data/spec/junkfood/adler32_spec.rb +16 -0
- data/spec/junkfood/assert_spec.rb +84 -0
- data/spec/junkfood/base32_spec.rb +39 -0
- data/spec/junkfood/ceb/base_command_spec.rb +73 -0
- data/spec/junkfood/ceb/base_event_spec.rb +67 -0
- data/spec/junkfood/ceb/bus_spec.rb +153 -0
- data/spec/junkfood/ceb/executors/command_executor_spec.rb +24 -0
- data/spec/junkfood/ceb/executors/delayed_job_command_executor_spec.rb +5 -0
- data/spec/junkfood/ceb/executors/event_executor_spec.rb +18 -0
- data/spec/junkfood/one_time_spec.rb +167 -0
- data/spec/junkfood/paperclip_string_io_spec.rb +40 -0
- data/spec/junkfood/settings_spec.rb +7 -0
- data/spec/junkfood_spec.rb +4 -0
- data/spec/spec_helper.rb +20 -0
- metadata +372 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe 'Junkfood::Base32' do
|
4
|
+
it 'should encode into an ASCII string' do
|
5
|
+
str = Junkfood::Base32.encode '1234567890abcdefghijklmnopqrstuvwxyz'
|
6
|
+
str.string.should eql(
|
7
|
+
'GEZDGNBVGY3TQOJQMFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI')
|
8
|
+
str.string.encoding.should eql(Encoding::ASCII)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should decode into a BINARY string' do
|
12
|
+
str = Junkfood::Base32.decode(
|
13
|
+
'GEZDGNBVGY3TQOJQMFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI')
|
14
|
+
str.string.should eql('1234567890abcdefghijklmnopqrstuvwxyz')
|
15
|
+
str.string.encoding.should eql(Encoding::BINARY)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should treat 0 and O the same' do
|
19
|
+
str1 = Junkfood::Base32.decode('000000000')
|
20
|
+
str2 = Junkfood::Base32.decode('oooOoooOo')
|
21
|
+
str1.string.should eql(str2.string)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should treat 1 and i the same' do
|
25
|
+
str1 = Junkfood::Base32.decode('111111111')
|
26
|
+
str2 = Junkfood::Base32.decode('iiiiIIIII')
|
27
|
+
str1.string.should eql(str2.string)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should ignore case' do
|
31
|
+
str1 = Junkfood::Base32.decode('12345670abcdefghijklmnopqrstuvwxyz')
|
32
|
+
str2 = Junkfood::Base32.decode('12345670ABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
33
|
+
str1.string.should eql(str2.string)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should have optional splitlines'
|
37
|
+
|
38
|
+
it 'should have splitlines at specified lengths'
|
39
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe 'Ceb::BaseCommand' do
|
4
|
+
before :all do
|
5
|
+
@test_class = Class.new(::Junkfood::Ceb::BaseCommand)
|
6
|
+
@test_instance = @test_class.new
|
7
|
+
@test_instance.origin = 'urn:user_id:1234'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should respond to new_record?' do
|
11
|
+
@test_instance.respond_to?(:new_record?).should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should respond to save!' do
|
15
|
+
@test_instance.respond_to?(:save!).should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should respond to valid?' do
|
19
|
+
@test_instance.respond_to?(:valid?).should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should have id attribute' do
|
23
|
+
@test_instance.respond_to?(:id).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should have created_at attribute' do
|
27
|
+
@test_instance.respond_to?(:created_at).should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should have origin attribute' do
|
31
|
+
@test_instance.respond_to?(:origin).should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'may have events' do
|
35
|
+
# NOTE: This is not a hard requirement. We mainly want the coupling
|
36
|
+
# to be looser. It's sufficient for Events to link to Commands,
|
37
|
+
# and not necesarily need Commands to map to all of its Events.
|
38
|
+
# This test is here because we have a Mongoid MongoDb implementation.
|
39
|
+
@test_instance.respond_to?(:events).should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should respond to to_json' do
|
43
|
+
@test_instance.respond_to?(:to_json).should be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'json should have _id attribute' do
|
47
|
+
json_data = @test_instance.to_json
|
48
|
+
json_hash = JSON.parse json_data
|
49
|
+
json_hash.key?('_id').should be_true
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'json should have _type attribute' do
|
53
|
+
json_data = @test_instance.to_json
|
54
|
+
json_hash = JSON.parse json_data
|
55
|
+
json_hash.key?('_type').should be_true
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'json should have created_at attribute' do
|
59
|
+
json_data = @test_instance.to_json
|
60
|
+
json_hash = JSON.parse json_data
|
61
|
+
json_hash.key?('created_at').should be_true
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'json should have origin attribute' do
|
65
|
+
json_data = @test_instance.to_json
|
66
|
+
json_hash = JSON.parse json_data
|
67
|
+
json_hash.key?('origin').should be_true
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should respond to perform' do
|
71
|
+
@test_instance.respond_to?(:perform).should be_true
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe 'Ceb::BaseEvent' do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
@command_class = Class.new(::Junkfood::Ceb::BaseCommand)
|
7
|
+
@command_instance = @command_class.new
|
8
|
+
@test_class = Class.new(::Junkfood::Ceb::BaseEvent)
|
9
|
+
@test_instance = @test_class.new
|
10
|
+
@test_instance.command = @command_instance
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should respond to new_record?' do
|
14
|
+
@test_instance.respond_to?(:new_record?).should be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should respond to save!' do
|
18
|
+
@test_instance.respond_to?(:save!).should be_true
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should respond to valid?' do
|
22
|
+
@test_instance.respond_to?(:valid?).should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should have id attribute' do
|
26
|
+
@test_instance.respond_to?(:id).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should have created_at attribute' do
|
30
|
+
@test_instance.respond_to?(:created_at).should be_true
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should have command attributes' do
|
34
|
+
@test_instance.respond_to?(:command).should be_true
|
35
|
+
@test_instance.respond_to?(:command=).should be_true
|
36
|
+
@test_instance.respond_to?(:command_id).should be_true
|
37
|
+
@test_instance.respond_to?(:command_id=).should be_true
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should respond to to_json' do
|
41
|
+
@test_instance.respond_to?(:to_json).should be_true
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'json should have _id attribute' do
|
45
|
+
json_data = @test_instance.to_json
|
46
|
+
json_hash = JSON.parse json_data
|
47
|
+
json_hash.key?('_id').should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'json should have _type attribute' do
|
51
|
+
json_data = @test_instance.to_json
|
52
|
+
json_hash = JSON.parse json_data
|
53
|
+
json_hash.key?('_type').should be_true
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'json should have created_at attribute' do
|
57
|
+
json_data = @test_instance.to_json
|
58
|
+
json_hash = JSON.parse json_data
|
59
|
+
json_hash.key?('created_at').should be_true
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'json should have command_id attribute' do
|
63
|
+
json_data = @test_instance.to_json
|
64
|
+
json_hash = JSON.parse json_data
|
65
|
+
json_hash.key?('command_id').should be_true
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe 'Ceb::Bus' do
|
4
|
+
|
5
|
+
it 'should acts_as_bus' do
|
6
|
+
class TestFoo
|
7
|
+
def initialize(valid)
|
8
|
+
@valid = valid
|
9
|
+
end
|
10
|
+
def valid?
|
11
|
+
@valid
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Test that we have the proper attributes and methods created with defaults.
|
16
|
+
controller_class = Class.new do
|
17
|
+
include Junkfood::Ceb::Bus
|
18
|
+
acts_as_bus :foo
|
19
|
+
end
|
20
|
+
controller_instance = controller_class.new
|
21
|
+
controller_instance.respond_to?(:send_foo).should be_true
|
22
|
+
controller_instance.respond_to?(:foo_executor).should be_true
|
23
|
+
controller_instance.respond_to?(:foo_executor=).should be_true
|
24
|
+
controller_instance.foo_executor.should be_kind_of(Proc)
|
25
|
+
|
26
|
+
# Now override the executor on the initialization
|
27
|
+
my_executor = mock('MyExecutor')
|
28
|
+
controller_class = Class.new do
|
29
|
+
include Junkfood::Ceb::Bus
|
30
|
+
acts_as_bus :foo, my_executor
|
31
|
+
end
|
32
|
+
controller_instance = controller_class.new
|
33
|
+
controller_instance.respond_to?(:send_foo).should be_true
|
34
|
+
controller_instance.respond_to?(:foo_executor).should be_true
|
35
|
+
controller_instance.respond_to?(:foo_executor=).should be_true
|
36
|
+
controller_instance.foo_executor.should eql(my_executor)
|
37
|
+
|
38
|
+
# Now test that we can override the executor, and that the
|
39
|
+
# bus creates and executes with an instane of the TestCommand
|
40
|
+
executor1 = mock('FooExecutor')
|
41
|
+
executor1.should_receive(:call).with(an_instance_of(TestFoo))
|
42
|
+
controller_instance.foo_executor = executor1
|
43
|
+
controller_instance.foo_executor.should eql(executor1)
|
44
|
+
controller_instance.send_foo 'test', true
|
45
|
+
|
46
|
+
# Now we make sure that the TestCommand is invalid, so the
|
47
|
+
# executor will not be called.
|
48
|
+
executor2 = mock('FooExecutor')
|
49
|
+
controller_instance.foo_executor = executor2
|
50
|
+
controller_instance.foo_executor.should eql(executor2)
|
51
|
+
controller_instance.send_foo 'test', false
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should acts_as_command_bus' do
|
55
|
+
class TestCommand
|
56
|
+
def initialize(valid)
|
57
|
+
@valid = valid
|
58
|
+
end
|
59
|
+
def valid?
|
60
|
+
@valid
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Test that we have the proper attributes and methods created
|
65
|
+
controller_class = Class.new do
|
66
|
+
include Junkfood::Ceb::Bus
|
67
|
+
acts_as_command_bus
|
68
|
+
end
|
69
|
+
controller_instance = controller_class.new
|
70
|
+
controller_instance.respond_to?(:send_command).should be_true
|
71
|
+
controller_instance.respond_to?(:command_executor).should be_true
|
72
|
+
controller_instance.respond_to?(:command_executor=).should be_true
|
73
|
+
controller_instance.command_executor.should be_kind_of(
|
74
|
+
Junkfood::Ceb::Executors::CommandExecutor)
|
75
|
+
|
76
|
+
# Test again that we have the proper attributes and methods created
|
77
|
+
my_executor = mock('MyExecutor')
|
78
|
+
controller_class = Class.new do
|
79
|
+
include Junkfood::Ceb::Bus
|
80
|
+
acts_as_command_bus my_executor
|
81
|
+
end
|
82
|
+
controller_instance = controller_class.new
|
83
|
+
controller_instance.respond_to?(:send_command).should be_true
|
84
|
+
controller_instance.respond_to?(:command_executor).should be_true
|
85
|
+
controller_instance.respond_to?(:command_executor=).should be_true
|
86
|
+
controller_instance.command_executor.should eql(my_executor)
|
87
|
+
|
88
|
+
# Now test that we can override the executor, and that the
|
89
|
+
# bus creates and executes with an instane of the TestCommand
|
90
|
+
executor1 = mock('CommandExecutor')
|
91
|
+
executor1.should_receive(:call).with(an_instance_of(TestCommand))
|
92
|
+
controller_instance.command_executor = executor1
|
93
|
+
controller_instance.command_executor.should eql(executor1)
|
94
|
+
controller_instance.send_command 'test', true
|
95
|
+
|
96
|
+
# Now we make sure that the TestCommand is invalid, so the
|
97
|
+
# executor will not be called.
|
98
|
+
executor2 = mock('CommandExecutor')
|
99
|
+
controller_instance.command_executor = executor2
|
100
|
+
controller_instance.command_executor.should eql(executor2)
|
101
|
+
controller_instance.send_command 'test', false
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should acts_as_event_bus' do
|
105
|
+
class TestEvent
|
106
|
+
def initialize(valid)
|
107
|
+
@valid = valid
|
108
|
+
end
|
109
|
+
def valid?
|
110
|
+
@valid
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Test that we have the proper attributes and methods created
|
115
|
+
controller_class = Class.new do
|
116
|
+
include Junkfood::Ceb::Bus
|
117
|
+
acts_as_event_bus
|
118
|
+
end
|
119
|
+
controller_instance = controller_class.new
|
120
|
+
controller_instance.respond_to?(:send_event).should be_true
|
121
|
+
controller_instance.respond_to?(:event_executor).should be_true
|
122
|
+
controller_instance.respond_to?(:event_executor=).should be_true
|
123
|
+
controller_instance.event_executor.should be_kind_of(
|
124
|
+
Junkfood::Ceb::Executors::EventExecutor)
|
125
|
+
|
126
|
+
# Test again that we have the proper attributes and methods created
|
127
|
+
my_executor = mock('MyExecutor')
|
128
|
+
controller_class = Class.new do
|
129
|
+
include Junkfood::Ceb::Bus
|
130
|
+
acts_as_event_bus my_executor
|
131
|
+
end
|
132
|
+
controller_instance = controller_class.new
|
133
|
+
controller_instance.respond_to?(:send_event).should be_true
|
134
|
+
controller_instance.respond_to?(:event_executor).should be_true
|
135
|
+
controller_instance.respond_to?(:event_executor=).should be_true
|
136
|
+
controller_instance.event_executor.should eql(my_executor)
|
137
|
+
|
138
|
+
# Now test that we can override the executor, and that the
|
139
|
+
# bus creates and executes with an instane of the TestEvent
|
140
|
+
executor1 = mock('EventExecutor')
|
141
|
+
executor1.should_receive(:call).with(an_instance_of(TestEvent))
|
142
|
+
controller_instance.event_executor = executor1
|
143
|
+
controller_instance.event_executor.should eql(executor1)
|
144
|
+
controller_instance.send_event 'test', true
|
145
|
+
|
146
|
+
# Now we make sure that the TestEvent is invalid, so the
|
147
|
+
# executor will not be called.
|
148
|
+
executor2 = mock('EventExecutor')
|
149
|
+
controller_instance.event_executor = executor2
|
150
|
+
controller_instance.event_executor.should eql(executor2)
|
151
|
+
controller_instance.send_event 'test', false
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
describe 'Ceb::Executors::CommandExecutor' do
|
4
|
+
it 'should save and perform the command (and return results)' do
|
5
|
+
expected_result = 'arbitrary return values'
|
6
|
+
command = mock('MyCommand')
|
7
|
+
command.should_receive(:new_record?).once.and_return(true)
|
8
|
+
command.should_receive(:save!).once
|
9
|
+
command.should_receive(:perform).once.and_return(expected_result)
|
10
|
+
executor = ::Junkfood::Ceb::Executors::CommandExecutor.new
|
11
|
+
result = executor.call command
|
12
|
+
result.should eql(expected_result)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should just perform the command (and return results) without saving' do
|
16
|
+
expected_result = 'arbitrary return values'
|
17
|
+
command = mock('MyCommand')
|
18
|
+
command.should_receive(:new_record?).once.and_return(false)
|
19
|
+
command.should_receive(:perform).once.and_return(expected_result)
|
20
|
+
executor = ::Junkfood::Ceb::Executors::CommandExecutor.new
|
21
|
+
result = executor.call command
|
22
|
+
result.should eql(expected_result)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
describe 'Ceb::Executors::EventExecutor' do
|
4
|
+
it 'should save event (new record)' do
|
5
|
+
event = mock('MyEvent')
|
6
|
+
event.should_receive(:new_record?).once.and_return(true)
|
7
|
+
event.should_receive(:save!).once
|
8
|
+
executor = ::Junkfood::Ceb::Executors::EventExecutor.new
|
9
|
+
executor.call event
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should not save event (not new record)' do
|
13
|
+
event = mock('Event')
|
14
|
+
event.should_receive(:new_record?).once.and_return(false)
|
15
|
+
executor = ::Junkfood::Ceb::Executors::EventExecutor.new
|
16
|
+
executor.call event
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "OneTime" do
|
4
|
+
|
5
|
+
it 'should pass RFC 4226 Appendix D Test Values' do
|
6
|
+
# Validates the first 10 OTPs for the RFC's test HOTP key (in RFC4226).
|
7
|
+
key = '12345678901234567890'
|
8
|
+
expected_results = [
|
9
|
+
'755224',
|
10
|
+
'287082',
|
11
|
+
'359152',
|
12
|
+
'969429',
|
13
|
+
'338314',
|
14
|
+
'254676',
|
15
|
+
'287922',
|
16
|
+
'162583',
|
17
|
+
'399871',
|
18
|
+
'520489',
|
19
|
+
]
|
20
|
+
for x in 0..9
|
21
|
+
Junkfood::OneTime.hotp(key, x).should eql(expected_results[x])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should bulk pass RFC 4226 Appendix D Test Values' do
|
26
|
+
# Validates the first 10 OTPs for the RFC's test HOTP key (in RFC4226).
|
27
|
+
key = '12345678901234567890'
|
28
|
+
expected_results = [
|
29
|
+
'755224',
|
30
|
+
'287082',
|
31
|
+
'359152',
|
32
|
+
'969429',
|
33
|
+
'338314',
|
34
|
+
'254676',
|
35
|
+
'287922',
|
36
|
+
'162583',
|
37
|
+
'399871',
|
38
|
+
'520489',
|
39
|
+
]
|
40
|
+
results = Junkfood::OneTime.hotp_multi(
|
41
|
+
key,
|
42
|
+
0...expected_results.size)
|
43
|
+
results.should eql(expected_results)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should provide low level details about algorithm values' do
|
47
|
+
key = '12345678901234567890'
|
48
|
+
expected_results = [
|
49
|
+
['755224', 1284755224, 'cc93cf18508d94934c64b65d8ba7667fb7cde4b0'],
|
50
|
+
['287082', 1094287082, '75a48a19d4cbe100644e8ac1397eea747a2d33ab'],
|
51
|
+
['359152', 137359152, '0bacb7fa082fef30782211938bc1c5e70416ff44'],
|
52
|
+
['969429', 1726969429, '66c28227d03a2d5529262ff016a1e6ef76557ece'],
|
53
|
+
['338314', 1640338314, 'a904c900a64b35909874b33e61c5938a8e15ed1c'],
|
54
|
+
['254676', 868254676, 'a37e783d7b7233c083d4f62926c7a25f238d0316'],
|
55
|
+
['287922', 1918287922, 'bc9cd28561042c83f219324d3c607256c03272ae'],
|
56
|
+
['162583', 82162583, 'a4fb960c0bc06e1eabb804e5b397cdc4b45596fa'],
|
57
|
+
['399871', 673399871, '1b3c89f65e6c9e883012052823443f048b4332db'],
|
58
|
+
['520489', 645520489, '1637409809a679dc698207310c8c7fc07290d9e5']
|
59
|
+
]
|
60
|
+
for counter in 0...(expected_results.size)
|
61
|
+
results = Junkfood::OneTime.hotp_raw(key, counter)
|
62
|
+
results.size.should eql(3)
|
63
|
+
# Our hmac digest is a binary string, but we want to convert it into
|
64
|
+
# readable hex strings that we have in this spec's expected results.
|
65
|
+
results[2] = results[2].unpack('H*').first
|
66
|
+
results.should eql(expected_results[counter])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should start counter at 0' do
|
71
|
+
key = '12345678901234567890'
|
72
|
+
one_time = Junkfood::OneTime.new key
|
73
|
+
one_time.counter.should eql(0)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'otp method should generate values without advancing counter' do
|
77
|
+
key = '12345678901234567890'
|
78
|
+
one_time = Junkfood::OneTime.new key
|
79
|
+
first = one_time.otp
|
80
|
+
first.should eql('755224')
|
81
|
+
second = one_time.otp
|
82
|
+
second.should eql('755224')
|
83
|
+
one_time.counter.should eql(0)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'bulk otp method should generate values without advancing counter' do
|
87
|
+
key = '12345678901234567890'
|
88
|
+
one_time = Junkfood::OneTime.new key
|
89
|
+
first = one_time.otp :range => 2
|
90
|
+
first.should eql(['755224', '287082'])
|
91
|
+
one_time.counter.should eql(0)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'otp! method should advance counter' do
|
95
|
+
key = '12345678901234567890'
|
96
|
+
one_time = Junkfood::OneTime.new key
|
97
|
+
first = one_time.otp!
|
98
|
+
first.should eql('755224')
|
99
|
+
one_time.counter.should eql(1)
|
100
|
+
second = one_time.otp!
|
101
|
+
second.should eql('287082')
|
102
|
+
one_time.counter.should eql(2)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'bulk otp! method should advance counter' do
|
106
|
+
key = '12345678901234567890'
|
107
|
+
one_time = Junkfood::OneTime.new key
|
108
|
+
first = one_time.otp! :range => 2
|
109
|
+
first.should eql(['755224', '287082'])
|
110
|
+
one_time.counter.should eql(2)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should generate counter from epoch for Time Based HOTP' do
|
114
|
+
# RFC:
|
115
|
+
# TOTP: Time-based One-time Password Algorithm
|
116
|
+
|
117
|
+
# Test time values taken from the TOTP RFC Draft 5, Appendix B
|
118
|
+
Junkfood::OneTime.epoch_counter(
|
119
|
+
:time => 59,
|
120
|
+
:step_size => 30).should eql(1)
|
121
|
+
Junkfood::OneTime.epoch_counter(
|
122
|
+
:time => 1111111109,
|
123
|
+
:step_size => 30).should eql(37037036)
|
124
|
+
Junkfood::OneTime.epoch_counter(
|
125
|
+
:time => 1111111111,
|
126
|
+
:step_size => 30).should eql(37037037)
|
127
|
+
Junkfood::OneTime.epoch_counter(
|
128
|
+
:time => 1234567890,
|
129
|
+
:step_size => 30).should eql(41152263)
|
130
|
+
Junkfood::OneTime.epoch_counter(
|
131
|
+
:time => 2000000000,
|
132
|
+
:step_size => 30).should eql(66666666)
|
133
|
+
|
134
|
+
# Now using the implicit default step size
|
135
|
+
Junkfood::OneTime::DEFAULT_STEP_SIZE.should eql(30)
|
136
|
+
Junkfood::OneTime.epoch_counter(
|
137
|
+
:time => 59).should eql(1)
|
138
|
+
Junkfood::OneTime.epoch_counter(
|
139
|
+
:time => 1111111109).should eql(37037036)
|
140
|
+
Junkfood::OneTime.epoch_counter(
|
141
|
+
:time => 1111111111).should eql(37037037)
|
142
|
+
Junkfood::OneTime.epoch_counter(
|
143
|
+
:time => 1234567890).should eql(41152263)
|
144
|
+
Junkfood::OneTime.epoch_counter(
|
145
|
+
:time => 2000000000).should eql(66666666)
|
146
|
+
|
147
|
+
# Testing alternate step sizes
|
148
|
+
Junkfood::OneTime.epoch_counter(
|
149
|
+
:time => 59,
|
150
|
+
:step_size => 60).should eql(0)
|
151
|
+
Junkfood::OneTime.epoch_counter(
|
152
|
+
:time => 59,
|
153
|
+
:step_size => 15).should eql(3)
|
154
|
+
Junkfood::OneTime.epoch_counter(
|
155
|
+
:time => 59,
|
156
|
+
:step_size => 59).should eql(1)
|
157
|
+
Junkfood::OneTime.epoch_counter(
|
158
|
+
:time => 59,
|
159
|
+
:step_size => 1).should eql(59)
|
160
|
+
Junkfood::OneTime.epoch_counter(
|
161
|
+
:time => 59,
|
162
|
+
:step_size => 2).should eql(29)
|
163
|
+
Junkfood::OneTime.epoch_counter(
|
164
|
+
:time => 2000000000,
|
165
|
+
:step_size => 15).should eql(133333333)
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe 'PaperclipStringIO' do
|
4
|
+
|
5
|
+
it 'should be a subclass of StringIO' do
|
6
|
+
io = Junkfood::PaperclipStringIo.new ''
|
7
|
+
io.kind_of?(StringIO).should eql(true)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should have the content_type attribute' do
|
11
|
+
io = Junkfood::PaperclipStringIo.new ''
|
12
|
+
io.respond_to? :content_type
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should have the original_filename attribute' do
|
16
|
+
io = Junkfood::PaperclipStringIo.new ''
|
17
|
+
io.respond_to? :original_filename
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should have default content_type attribute' do
|
21
|
+
io = Junkfood::PaperclipStringIo.new ''
|
22
|
+
io.content_type.should eql('application/octet-stream')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should have default original_filename attribute' do
|
26
|
+
io = Junkfood::PaperclipStringIo.new ''
|
27
|
+
io.original_filename.should eql('unnamed')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should be able to have overridden attributes' do
|
31
|
+
filename = 'test.png'
|
32
|
+
content_type = 'image/png'
|
33
|
+
io = Junkfood::PaperclipStringIo.new(
|
34
|
+
'',
|
35
|
+
:content_type => content_type,
|
36
|
+
:filename => filename)
|
37
|
+
io.content_type.should eql(content_type)
|
38
|
+
io.original_filename.should eql(filename)
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
begin
|
3
|
+
Bundler.setup(:default, :development)
|
4
|
+
rescue Bundler::BundlerError => e
|
5
|
+
$stderr.puts e.message
|
6
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
7
|
+
exit e.status_code
|
8
|
+
end
|
9
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
10
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
11
|
+
require 'junkfood'
|
12
|
+
require 'rspec/core'
|
13
|
+
|
14
|
+
# Requires supporting files with custom matchers and macros, etc,
|
15
|
+
# in ./support/ and its subdirectories.
|
16
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
|
20
|
+
end
|