hybridgroup-crubyflie 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +5 -0
  5. data/LICENSE.txt +674 -0
  6. data/README.md +127 -0
  7. data/Rakefile +15 -0
  8. data/bin/crubyflie +94 -0
  9. data/configs/joystick_default.yaml +106 -0
  10. data/crubyflie.gemspec +50 -0
  11. data/examples/params_and_logging.rb +87 -0
  12. data/lib/crubyflie/crazyflie/commander.rb +54 -0
  13. data/lib/crubyflie/crazyflie/console.rb +67 -0
  14. data/lib/crubyflie/crazyflie/log.rb +383 -0
  15. data/lib/crubyflie/crazyflie/log_conf.rb +57 -0
  16. data/lib/crubyflie/crazyflie/param.rb +220 -0
  17. data/lib/crubyflie/crazyflie/toc.rb +239 -0
  18. data/lib/crubyflie/crazyflie/toc_cache.rb +87 -0
  19. data/lib/crubyflie/crazyflie.rb +282 -0
  20. data/lib/crubyflie/crazyradio/crazyradio.rb +301 -0
  21. data/lib/crubyflie/crazyradio/radio_ack.rb +48 -0
  22. data/lib/crubyflie/crubyflie_logger.rb +74 -0
  23. data/lib/crubyflie/driver/crtp_packet.rb +146 -0
  24. data/lib/crubyflie/driver/radio_driver.rb +363 -0
  25. data/lib/crubyflie/exceptions.rb +36 -0
  26. data/lib/crubyflie/input/input_reader.rb +190 -0
  27. data/lib/crubyflie/input/joystick_input_reader.rb +328 -0
  28. data/lib/crubyflie/version.rb +22 -0
  29. data/lib/crubyflie.rb +36 -0
  30. data/spec/commander_spec.rb +67 -0
  31. data/spec/console_spec.rb +76 -0
  32. data/spec/crazyflie_spec.rb +176 -0
  33. data/spec/crazyradio_spec.rb +228 -0
  34. data/spec/crtp_packet_spec.rb +79 -0
  35. data/spec/crubyflie_logger_spec.rb +39 -0
  36. data/spec/crubyflie_spec.rb +21 -0
  37. data/spec/input_reader_spec.rb +136 -0
  38. data/spec/joystick_cfg.yaml +44 -0
  39. data/spec/joystick_input_reader_spec.rb +323 -0
  40. data/spec/log_spec.rb +266 -0
  41. data/spec/param_spec.rb +166 -0
  42. data/spec/radio_ack_spec.rb +43 -0
  43. data/spec/radio_driver_spec.rb +227 -0
  44. data/spec/spec_helper.rb +53 -0
  45. data/spec/toc_cache_spec.rb +87 -0
  46. data/spec/toc_spec.rb +187 -0
  47. data/tools/sdl-joystick-axis.rb +69 -0
  48. metadata +225 -0
@@ -0,0 +1,166 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'crazyflie/param'
20
+
21
+
22
+
23
+ describe LogTOCElement do
24
+ describe "#initialize" do
25
+ it "should initialize correctly" do
26
+ data = [5, 23].pack('C*') + ['hello', 'world'].pack('Z*Z*')
27
+ lte = ParamTOCElement.new(data)
28
+ lte.ident.should == 5
29
+ lte.group.should == 'hello'
30
+ lte.name.should == 'world'
31
+ lte.ctype.should == 'double'
32
+ lte.directive.should == 'E'
33
+ lte.access.should == 0x10
34
+ end
35
+ end
36
+ end
37
+
38
+
39
+ describe Param do
40
+ before :each do
41
+ @crazyflie = double("Crazyflie")
42
+ @queue = Queue.new
43
+ allow(@crazyflie).to receive(:crtp_queues).and_return({:param =>
44
+ @queue})
45
+ allow(@crazyflie).to receive(:cache_folder).and_return(nil)
46
+
47
+ @param = Param.new(@crazyflie)
48
+ @logger = @param.logger
49
+ end
50
+
51
+ describe "#initialize" do
52
+ it "should initialize the Param instance" do
53
+ param = Param.new(@crazyflie)
54
+ @param.toc.toc.should == {}
55
+ end
56
+ end
57
+
58
+ describe "#refresh_toc" do
59
+ it "send the packet and fetch the TOC from the crazyflie" do
60
+ port = Crazyflie::CRTP_PORTS[:param]
61
+ channel = Param::TOC_CHANNEL
62
+ expect(@param.toc).to receive(:fetch_from_crazyflie).with(
63
+ @crazyflie,
64
+ port,
65
+ @queue)
66
+ @param.refresh_toc()
67
+ end
68
+ end
69
+
70
+ describe "#set_value" do
71
+ it "should not do anything if the element is not in the TOC" do
72
+ expect(@logger).to receive(:error).with("Param abc not in TOC!")
73
+ expect(@crazyflie).not_to receive(:send_packet)
74
+ @param.set_value('abc', 45)
75
+ end
76
+
77
+ it "should set the value of a parameter and yield the response" do
78
+ toc_elem = TOCElement.new({
79
+ :ident => 3,
80
+ :group => "gr",
81
+ :name => "name",
82
+ :ctype => "int32_t",
83
+ :directive => "l<"
84
+ })
85
+
86
+ name = 'gr.name'
87
+ expect(@param.toc).to receive(:[]).with(name).and_return(toc_elem)
88
+
89
+ expect(@crazyflie).to receive(:send_packet) { |packet, expect|
90
+ packet.port.should == CRTP_PORTS[:param]
91
+ packet.channel == PARAM_WRITE_CHANNEL
92
+ packet.data.should == [3, 1, 0, 0, 0]
93
+ expect.should == true
94
+ }
95
+
96
+ res = CRTPPacket.new()
97
+ expect(@queue).to receive(:pop).and_return(res)
98
+
99
+ @param.set_value('gr.name', 1) do |response|
100
+ response.should == res
101
+ end
102
+ end
103
+
104
+ it "should set the value of a parameter without a block_given" do
105
+ toc_elem = TOCElement.new({
106
+ :ident => 3,
107
+ :group => "gr",
108
+ :name => "name",
109
+ :ctype => "int32_t",
110
+ :directive => "l<"
111
+ })
112
+
113
+ name = 'gr.name'
114
+ expect(@param.toc).to receive(:[]).with(name).and_return(toc_elem)
115
+
116
+ expect(@crazyflie).to receive(:send_packet) { |packet, expect|
117
+ packet.port.should == CRTP_PORTS[:param]
118
+ packet.channel == PARAM_WRITE_CHANNEL
119
+ packet.data.should == [3, 1, 0, 0, 0]
120
+ expect.should == true
121
+ }
122
+
123
+ res = CRTPPacket.new()
124
+ expect(@queue).to receive(:pop).and_return(res)
125
+
126
+ m = "Got answer to setting param 'gr.name' with '1'"
127
+ expect(@logger).to receive(:debug).with(m)
128
+ @param.set_value('gr.name', 1)
129
+ end
130
+ end
131
+
132
+ describe "#get_value" do
133
+ it "should not do anything if the element is not in the TOC" do
134
+ m = "Cannot update gr.name, not in TOC"
135
+ expect(@logger).to receive(:error).with(m)
136
+
137
+ @param.get_value('gr.name') {}
138
+ end
139
+
140
+ it "should request an element and yield the value" do
141
+ toc_elem = TOCElement.new({
142
+ :ident => 3,
143
+ :group => "gr",
144
+ :name => "name",
145
+ :ctype => "int32_t",
146
+ :directive => "l<"
147
+ })
148
+
149
+ name = 'gr.name'
150
+ expect(@param.toc).to receive(:[]).with(name).and_return(toc_elem)
151
+
152
+ expect(@crazyflie).to receive(:send_packet) do |packet|
153
+ packet.port.should == CRTP_PORTS[:param]
154
+ packet.channel.should == PARAM_READ_CHANNEL
155
+ packet.data.should == [3]
156
+ end
157
+
158
+ res = CRTPPacket.new()
159
+ res.data = [3, 5, 0, 0, 0]
160
+ expect(@queue).to receive(:pop).and_return(res)
161
+ @param.get_value('gr.name') do |value|
162
+ value.should == 5
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'crazyradio/radio_ack'
20
+
21
+ describe RadioAck do
22
+ describe "#initialize" do
23
+ it "should initialize a RadioAck" do
24
+ rack = RadioAck.new(true, 1, 5, [1,2,3])
25
+ rack.ack.should == true
26
+ rack.powerDet.should == 1
27
+ rack.retry_count.should == 5
28
+ rack.data.should == [1,2,3]
29
+ end
30
+ end
31
+ describe "#from_raw" do
32
+ it "should create a radio ack from raw USB data" do
33
+ header = 0b11110101 # ack = 1, powerDet = 0, retry_c = 1111
34
+ data = [0xFF] * 31
35
+ packet = [header].concat(data)
36
+ rack = RadioAck.from_raw(packet.pack('C*'))
37
+ rack.ack.should == true
38
+ rack.powerDet.should == false
39
+ rack.retry_count.should == 15
40
+ rack.data == data
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,227 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'driver/radio_driver'
20
+
21
+ describe RadioDriver do
22
+ before :each do
23
+ @radiodriver = RadioDriver.new()
24
+ @link_error_cb = Proc.new {|m| m}
25
+ @link_quality_cb = Proc.new {|m| m}
26
+ @connect_params = ['radio://0/2/1M',{
27
+ :link_quality_cb => @link_quality_cb,
28
+ :link_error_cb => @link_error_cb
29
+ }]
30
+ @crazyradio = double("Crazyradio")
31
+ allow(@crazyradio).to receive(:close)
32
+ @ack = RadioAck.new(true, true, 3, [1,2,3])
33
+ allow(@crazyradio).to receive(:send_packet).and_return(@ack)
34
+ allow(Crazyradio).to receive(:new).and_return(@crazyradio)
35
+ allow(Crazyradio).to receive(:factory).and_return(@crazyradio)
36
+
37
+ end
38
+
39
+ describe "#initialize" do
40
+ it "should intialize the radio driver" do
41
+ rd = RadioDriver.new()
42
+ rd.should be_an_instance_of RadioDriver
43
+ rd.uri.should be_nil
44
+ end
45
+ end
46
+
47
+ describe "#connect" do
48
+ it "should connect" do
49
+ expect(@radiodriver).to receive(:start_radio_thread)
50
+
51
+ @radiodriver.connect(*@connect_params)
52
+
53
+ expected_retries = RadioDriver::RETRIES_BEFORE_DISCONNECT
54
+ expected_queue_size = RadioDriver::OUT_QUEUE_MAX_SIZE
55
+ @radiodriver.retries_before_disconnect.should == expected_retries
56
+ @radiodriver.out_queue_max_size.should == expected_queue_size
57
+ @radiodriver.disconnect()
58
+ end
59
+
60
+
61
+ it "should raise an exception if the link is active" do
62
+ @radiodriver.connect(*@connect_params)
63
+ mesg = "Active link to radio://0/2/1M. Disconnect first"
64
+ expect {
65
+ @radiodriver.connect('radio://1/2/2M')
66
+ }.to raise_exception(OpenLink, mesg)
67
+ @radiodriver.disconnect()
68
+ end
69
+
70
+ it "should raise an exception a callback is missing" do
71
+ expect {
72
+ @radiodriver.connect('radio://1/2/2M', {
73
+ :link_quality_cb => Proc.new {}
74
+ })
75
+ }.to raise_exception(CallbackMissing,
76
+ "Callback link_error_cb mandatory")
77
+ end
78
+ end
79
+
80
+ describe "#disconnect" do
81
+ it "should disconnect if it is not connected" do
82
+ expect(@crazyradio).not_to receive(:close)
83
+ @radiodriver.disconnect()
84
+ end
85
+
86
+ it "should disconnect if it is connected" do
87
+ expect(@crazyradio).to receive(:close)
88
+ @radiodriver.connect(*@connect_params)
89
+ @radiodriver.disconnect()
90
+ end
91
+
92
+ it "should kill the thread if disconnect is called with true" do
93
+ expect_any_instance_of(Thread).to receive(:kill)
94
+ @radiodriver.connect(*@connect_params)
95
+ @radiodriver.disconnect(true)
96
+ end
97
+ end
98
+
99
+ describe "#send_packet" do
100
+ it "should do nothing when not connected" do
101
+ #expect_any_instance_of(Queue).not_to receive(:push)
102
+ @radiodriver.send_packet([1,2,3])
103
+ end
104
+
105
+ it "should push a packet to the queue and send it" do
106
+ #expect_any_instance_of(Queue).to receive(:push)
107
+ expect(@crazyradio).to receive(:send_packet)
108
+ @radiodriver.connect(*@connect_params)
109
+ @radiodriver.send_packet(CRTPPacket.unpack([1,2,3]))
110
+ @radiodriver.disconnect()
111
+ end
112
+
113
+ it "should call the link error callback if max size is reached" do
114
+ # prevent consuming packages
115
+ expect(@radiodriver).to receive(:start_radio_thread)
116
+ @radiodriver.connect(*@connect_params)
117
+ max = @radiodriver.out_queue_max_size
118
+ m = "Reached #{max} elements in outgoing queue"
119
+ # When it reaches 50 it disconnects and not send anymore
120
+ expect(@link_error_cb).to receive(:call).with(m).once
121
+ (1..52).each do
122
+ @radiodriver.send_packet([4,5,6])
123
+ end
124
+ @radiodriver.disconnect()
125
+ end
126
+ end
127
+
128
+ describe "#receive_packet" do
129
+ # note that thread sends control packages all the time
130
+ it "should receive nil if queue is empty" do
131
+ @radiodriver.connect(*@connect_params)
132
+ @radiodriver.disconnect() #empty queues
133
+ @radiodriver.receive_packet(true).should be_nil
134
+ end
135
+
136
+ it "should raise error if Crazyradio complains" do
137
+ e = USBDongleException
138
+ expect(@crazyradio).to receive(:send_packet).and_raise(e, "aa")
139
+ m = "Error talking to Crazyradio: aa"
140
+ expect(@link_error_cb).to receive(:call).with(m)
141
+ @radiodriver.connect(*@connect_params)
142
+ sleep 0.1
143
+ @radiodriver.disconnect()
144
+ end
145
+
146
+ it "should raise error if nil is returned as response" do
147
+ allow(@crazyradio).to receive(:send_packet).and_return(nil)
148
+ m = "Dongle communication error (ack is nil)"
149
+ expect(@link_error_cb).to receive(:call).with(m)
150
+ @radiodriver.connect(*@connect_params)
151
+ sleep 0.1
152
+ @radiodriver.disconnect()
153
+ end
154
+
155
+ it "should suicide if too many packets are lost" do
156
+ allow(@ack).to receive(:ack).and_return(false)
157
+ m = "Too many packets lost"
158
+ expect(@link_error_cb).to receive(:call).with(m).once
159
+ @radiodriver.connect(*@connect_params)
160
+ sleep 0.1
161
+ @radiodriver.disconnect()
162
+ end
163
+
164
+ it "should receive a packet" do
165
+ expect(@link_quality_cb).to receive(:call).with(70).at_least(:once)
166
+ @radiodriver.connect(*@connect_params)
167
+ @radiodriver.send_packet(CRTPPacket.unpack([1,2,3]))
168
+ packet = @radiodriver.receive_packet(false)
169
+ # send package returns an ack with [1,2,3] as data
170
+ expect(packet).to be_an_instance_of CRTPPacket
171
+ packet.size.should == 2
172
+ packet.header.should == 1
173
+ packet.data.should == [2,3]
174
+ @radiodriver.disconnect()
175
+ end
176
+ end
177
+
178
+ describe "#scan_interface" do
179
+ it "should complain if link is open" do
180
+ @radiodriver.connect(*@connect_params)
181
+ expect {
182
+ @radiodriver.scan_interface()
183
+ }.to raise_exception(OpenLink, "Cannot scan when link is open")
184
+ @radiodriver.disconnect()
185
+ end
186
+
187
+ it "should return the found some uris" do
188
+ allow(@crazyradio).to receive(:scan_channels).and_return([1,2,3],
189
+ [7,8,9],
190
+ [21,22,4])
191
+ expect(@crazyradio).to receive(:[]=).with(:arc, 1)
192
+ expect(@crazyradio).to receive(:[]=).with(:data_rate,
193
+ Crazyradio::DR_250KPS)
194
+ expect(@crazyradio).to receive(:[]=).with(:data_rate,
195
+ Crazyradio::DR_1MPS)
196
+ expect(@crazyradio).to receive(:[]=).with(:data_rate,
197
+ Crazyradio::DR_2MPS)
198
+ expect(@crazyradio).to receive(:close)
199
+ @radiodriver.scan_interface().should == [
200
+ 'radio://0/1/250K',
201
+ 'radio://0/2/250K',
202
+ 'radio://0/3/250K',
203
+ 'radio://0/7/1M',
204
+ 'radio://0/8/1M',
205
+ 'radio://0/9/1M',
206
+ 'radio://0/21/2M',
207
+ 'radio://0/22/2M',
208
+ 'radio://0/4/2M']
209
+ end
210
+
211
+ it "should raise a usb dongle exception it it happens" do
212
+ e = USBDongleException
213
+ allow(@crazyradio).to receive(:scan_channels).and_raise(e)
214
+ allow(@crazyradio).to receive(:[]=)
215
+ expect {
216
+ @radiodriver.scan_interface()
217
+ }.to raise_exception(e)
218
+ end
219
+ end
220
+
221
+ describe "#get_status" do
222
+ it "should get status" do
223
+ allow(Crazyradio).to receive(:status).and_return("hola")
224
+ @radiodriver.get_status.should == "hola"
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'simplecov'
20
+ require 'coveralls'
21
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
22
+ SimpleCov.at_exit do
23
+ SimpleCov.minimum_coverage 95
24
+ SimpleCov.result.format!
25
+ end
26
+ SimpleCov.start do
27
+ add_group "Libraries", "lib"
28
+ add_group "Specs", "spec"
29
+ end
30
+
31
+
32
+ $: << File.join(File.dirname(__FILE__), "lib")
33
+ $: << File.join(File.dirname(__FILE__))
34
+
35
+ require 'crubyflie'
36
+ include Crubyflie
37
+ include CRTPConstants
38
+
39
+ require 'radio_ack_spec'
40
+ require 'crtp_packet_spec'
41
+ require 'crazyradio_spec'
42
+ require 'radio_driver_spec'
43
+ require 'radio_ack_spec'
44
+ require 'toc_cache_spec'
45
+ require 'toc_spec'
46
+ require 'crazyflie_spec'
47
+ require 'log_spec'
48
+ require 'param_spec'
49
+ require 'console_spec'
50
+ require 'commander_spec'
51
+ require 'joystick_input_reader_spec'
52
+ require 'input_reader_spec'
53
+ require 'crubyflie_logger_spec'
@@ -0,0 +1,87 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'crazyflie/toc_cache'
20
+
21
+ describe TOCCache do
22
+
23
+ before :each do
24
+ allow_any_instance_of(TOCCache).to receive(:warn)
25
+
26
+
27
+ allow(File).to receive(:exist?).with('baa').and_return(true)
28
+ allow(File).to receive(:directory?).with('baa').and_return(true)
29
+ expect(FileUtils).to receive(:touch)
30
+ expect(FileUtils).to receive(:rm)
31
+ @cache = TOCCache.new('baa')
32
+ end
33
+
34
+ describe "#initialize" do
35
+ it "shoud not create a folder where it does not have permissions" do
36
+ allow(File).to receive(:exist?).with('baa').and_return(false)
37
+ do_this = receive(:mkdir_p).with('baa').and_raise(Errno::EACCES)
38
+ expect(FileUtils).to do_this
39
+ m = "Deactivating cache. Cannot create folder"
40
+ expect_any_instance_of(TOCCache).to receive(:warn).with(m)
41
+ cache = TOCCache.new('baa')
42
+ end
43
+
44
+ it "should veryfy the cache folder is a directory" do
45
+ allow(File).to receive(:exist?).with('baa').and_return(true)
46
+ allow(File).to receive(:directory?).with('baa').and_return(false)
47
+ m = "Deactivating cache. Folder is not a directory"
48
+ expect_any_instance_of(TOCCache).to receive(:warn).with(m)
49
+ cache = TOCCache.new('baa')
50
+ end
51
+
52
+ it "should test if the cache folder is writable" do
53
+ allow(File).to receive(:exist?).with('baa').and_return(true)
54
+ allow(File).to receive(:directory?).with('baa').and_return(true)
55
+ allow(FileUtils).to receive(:touch).and_raise(Errno::EACCES)
56
+ expect(FileUtils).not_to receive(:rm)
57
+ m = "Deactivating cache. Cannot write to folder"
58
+ expect_any_instance_of(TOCCache).to receive(:warn).with(m)
59
+ cache = TOCCache.new('baa')
60
+ end
61
+
62
+ it "initialize correctly otherwise" do
63
+ allow(File).to receive(:exist?).with('baa').and_return(true)
64
+ allow(File).to receive(:directory?).with('baa').and_return(true)
65
+ expect(FileUtils).not_to receive(:mkdir_p)
66
+ expect(FileUtils).to receive(:touch)
67
+ expect(FileUtils).to receive(:rm)
68
+ cache = TOCCache.new('baa')
69
+ end
70
+ end
71
+
72
+ describe "#fetch" do
73
+ it "should return nil if file does not exist" do
74
+ allow(File).to receive(:open).and_raise(Errno::ENOENT)
75
+ expect(Marshal).not_to receive(:load)
76
+ @cache.fetch("123").should be_nil
77
+ end
78
+ end
79
+
80
+ describe "#insert" do
81
+ it "should do nothing if an error happens" do
82
+ allow(File).to receive(:open).and_raise(Errno::EACCES)
83
+ expect(Marshal).not_to receive(:dump)
84
+ @cache.insert("123",{})
85
+ end
86
+ end
87
+ end