junkfood 0.1.0
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.
- 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
|