live_f1-core 0.0.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.
Files changed (109) hide show
  1. data/.autotest +23 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +65 -0
  6. data/Guardfile +11 -0
  7. data/README.rdoc +62 -0
  8. data/Rakefile +11 -0
  9. data/bin/live_f1_example +74 -0
  10. data/features/fixtures/sessions/2012.03.china.qualifying/7136/keyframes.yaml +32722 -0
  11. data/features/fixtures/sessions/2012.03.china.qualifying/7136/session.key +1 -0
  12. data/features/fixtures/sessions/2012.03.china.qualifying/session.bin +0 -0
  13. data/features/fixtures/sessions/2012.04.bahrain.practice.2/7164/keyframes.yaml +22403 -0
  14. data/features/fixtures/sessions/2012.04.bahrain.practice.2/7164/session.key +1 -0
  15. data/features/fixtures/sessions/2012.04.bahrain.practice.2/session.bin +0 -0
  16. data/features/fixtures/sessions/2012.05.bahrain.race.post/7167/keyframes.yaml +1204 -0
  17. data/features/fixtures/sessions/2012.05.bahrain.race.post/7167/session.key +1 -0
  18. data/features/fixtures/sessions/2012.05.bahrain.race.post/session.bin +0 -0
  19. data/features/live_f1.feature +14 -0
  20. data/features/step_definitions/live_f1_steps.rb +69 -0
  21. data/features/support/env.rb +9 -0
  22. data/lib/live_f1/debug.rb +6 -0
  23. data/lib/live_f1/enum.rb +9 -0
  24. data/lib/live_f1/event.rb +23 -0
  25. data/lib/live_f1/packet/car/best_lap_time.rb +10 -0
  26. data/lib/live_f1/packet/car/driver.rb +14 -0
  27. data/lib/live_f1/packet/car/gap.rb +10 -0
  28. data/lib/live_f1/packet/car/interval.rb +10 -0
  29. data/lib/live_f1/packet/car/lap_count.rb +10 -0
  30. data/lib/live_f1/packet/car/lap_time.rb +10 -0
  31. data/lib/live_f1/packet/car/num_pits.rb +10 -0
  32. data/lib/live_f1/packet/car/number.rb +14 -0
  33. data/lib/live_f1/packet/car/period_1.rb +11 -0
  34. data/lib/live_f1/packet/car/period_2.rb +11 -0
  35. data/lib/live_f1/packet/car/period_3.rb +11 -0
  36. data/lib/live_f1/packet/car/pit_count.rb +18 -0
  37. data/lib/live_f1/packet/car/pit_lap_1.rb +10 -0
  38. data/lib/live_f1/packet/car/pit_lap_2.rb +10 -0
  39. data/lib/live_f1/packet/car/pit_lap_3.rb +10 -0
  40. data/lib/live_f1/packet/car/position.rb +14 -0
  41. data/lib/live_f1/packet/car/position_history.rb +14 -0
  42. data/lib/live_f1/packet/car/position_update.rb +13 -0
  43. data/lib/live_f1/packet/car/sector_1.rb +11 -0
  44. data/lib/live_f1/packet/car/sector_2.rb +11 -0
  45. data/lib/live_f1/packet/car/sector_3.rb +11 -0
  46. data/lib/live_f1/packet/car.rb +13 -0
  47. data/lib/live_f1/packet/decryptable.rb +22 -0
  48. data/lib/live_f1/packet/header.rb +127 -0
  49. data/lib/live_f1/packet/sector_time.rb +28 -0
  50. data/lib/live_f1/packet/sys/commentary.rb +33 -0
  51. data/lib/live_f1/packet/sys/copyright.rb +9 -0
  52. data/lib/live_f1/packet/sys/key_frame.rb +17 -0
  53. data/lib/live_f1/packet/sys/notice.rb +10 -0
  54. data/lib/live_f1/packet/sys/reset.rb +9 -0
  55. data/lib/live_f1/packet/sys/session_start.rb +25 -0
  56. data/lib/live_f1/packet/sys/speed.rb +29 -0
  57. data/lib/live_f1/packet/sys/timestamp.rb +23 -0
  58. data/lib/live_f1/packet/sys/track_status.rb +18 -0
  59. data/lib/live_f1/packet/sys/weather.rb +33 -0
  60. data/lib/live_f1/packet/sys.rb +10 -0
  61. data/lib/live_f1/packet.rb +129 -0
  62. data/lib/live_f1/source/keyframe.rb +30 -0
  63. data/lib/live_f1/source/live.rb +163 -0
  64. data/lib/live_f1/source/log.rb +29 -0
  65. data/lib/live_f1/source/session.rb +41 -0
  66. data/lib/live_f1/source.rb +83 -0
  67. data/lib/live_f1/version.rb +3 -0
  68. data/lib/live_f1.rb +32 -0
  69. data/live_f1-core.gemspec +26 -0
  70. data/spec/live_f1/event_spec.rb +5 -0
  71. data/spec/live_f1/packet/car/best_lap_time_spec.rb +19 -0
  72. data/spec/live_f1/packet/car/driver_spec.rb +20 -0
  73. data/spec/live_f1/packet/car/gap_spec.rb +20 -0
  74. data/spec/live_f1/packet/car/interval_spec.rb +20 -0
  75. data/spec/live_f1/packet/car/lap_count_spec.rb +20 -0
  76. data/spec/live_f1/packet/car/lap_time_spec.rb +20 -0
  77. data/spec/live_f1/packet/car/number_spec.rb +20 -0
  78. data/spec/live_f1/packet/car/period_1_spec.rb +21 -0
  79. data/spec/live_f1/packet/car/period_2_spec.rb +21 -0
  80. data/spec/live_f1/packet/car/period_3_spec.rb +21 -0
  81. data/spec/live_f1/packet/car/pit_count_spec.rb +20 -0
  82. data/spec/live_f1/packet/car/pit_lap_1_spec.rb +20 -0
  83. data/spec/live_f1/packet/car/pit_lap_2_spec.rb +20 -0
  84. data/spec/live_f1/packet/car/pit_lap_3_spec.rb +20 -0
  85. data/spec/live_f1/packet/car/position_history_spec.rb +20 -0
  86. data/spec/live_f1/packet/car/position_spec.rb +20 -0
  87. data/spec/live_f1/packet/car/position_update_spec.rb +19 -0
  88. data/spec/live_f1/packet/car/sector_1_spec.rb +21 -0
  89. data/spec/live_f1/packet/car/sector_2_spec.rb +21 -0
  90. data/spec/live_f1/packet/car/sector_3_spec.rb +21 -0
  91. data/spec/live_f1/packet/header_spec.rb +148 -0
  92. data/spec/live_f1/packet/sys/commentary_spec.rb +45 -0
  93. data/spec/live_f1/packet/sys/copyright_spec.rb +19 -0
  94. data/spec/live_f1/packet/sys/key_frame_spec.rb +39 -0
  95. data/spec/live_f1/packet/sys/notice_spec.rb +20 -0
  96. data/spec/live_f1/packet/sys/reset_spec.rb +26 -0
  97. data/spec/live_f1/packet/sys/session_start_spec.rb +31 -0
  98. data/spec/live_f1/packet/sys/speed_spec.rb +20 -0
  99. data/spec/live_f1/packet/sys/timestamp_spec.rb +34 -0
  100. data/spec/live_f1/packet/sys/track_status_spec.rb +20 -0
  101. data/spec/live_f1/packet/sys/weather_spec.rb +20 -0
  102. data/spec/live_f1/packet_spec.rb +112 -0
  103. data/spec/live_f1/source/keyframe_spec.rb +56 -0
  104. data/spec/live_f1/source/live_spec.rb +106 -0
  105. data/spec/live_f1/source/session_spec.rb +39 -0
  106. data/spec/live_f1/source_spec.rb +140 -0
  107. data/spec/spec_helper.rb +10 -0
  108. data/spec/support/packet_type_examples.rb +122 -0
  109. metadata +337 -0
@@ -0,0 +1,39 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ extend PacketTypeExamples
5
+
6
+ describe LiveF1::Packet::Sys::KeyFrame do
7
+ it_behaves_like LiveF1::Packet::Type::Short
8
+
9
+ subject { packet }
10
+
11
+ let(:source) { mock(:source) }
12
+ let(:header) { mock(:header) }
13
+ let(:data) { "" }
14
+ let(:packet) do
15
+ packet = described_class.new(source, header)
16
+ packet.send :set_data, data
17
+ packet
18
+ end
19
+
20
+ describe "#number" do
21
+ # `data` for a KeyFrame packet represents a little-endian integer
22
+ it "reads its keyframe number from the data" do
23
+ # Binary: "00000000/00000011"
24
+ subject.data = [3,0].pack("c*")
25
+ subject.number.should == 3
26
+
27
+ # Binary: "00000001/00000011"
28
+ subject.data = [3,1].pack("c*")
29
+ subject.number.should == 259
30
+ end
31
+ end
32
+
33
+ # describe "#inspect" do
34
+ # it "returns a string representation of the keyframe" do
35
+ # subject.stub(:number) { 25 }
36
+ # subject.inspect.should == "Keyframe 25"
37
+ # end
38
+ # end
39
+ end
@@ -0,0 +1,20 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ extend PacketTypeExamples
5
+
6
+ describe LiveF1::Packet::Sys::Notice do
7
+ it_behaves_like LiveF1::Packet::Type::Long
8
+ it_behaves_like LiveF1::Packet::Decryptable
9
+
10
+ subject { packet }
11
+
12
+ let(:source) { mock(:source) }
13
+ let(:header) { mock(:header) }
14
+ let(:data) { "" }
15
+ let(:packet) do
16
+ packet = described_class.new(source, header)
17
+ packet.send :set_data, data
18
+ packet
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ extend PacketTypeExamples
5
+
6
+ describe LiveF1::Packet::Sys::Reset do
7
+ it_behaves_like LiveF1::Packet::Type::Special
8
+
9
+ subject { packet }
10
+
11
+ let(:source) { mock(:source) }
12
+ let(:header) { mock(:header) }
13
+ let(:data) { "" }
14
+ let(:packet) do
15
+ packet = described_class.new(source, header)
16
+ packet.send :set_data, data
17
+ packet
18
+ end
19
+
20
+ # describe "#inspect" do
21
+ # it "returns a string representation of the keyframe" do
22
+ # subject.stub(:number) { 25 }
23
+ # subject.inspect.should == "Keyframe 25"
24
+ # end
25
+ # end
26
+ end
@@ -0,0 +1,31 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ extend PacketTypeExamples
5
+
6
+ describe LiveF1::Packet::Sys::SessionStart do
7
+ it_behaves_like LiveF1::Packet::Type::Short
8
+
9
+ subject { packet }
10
+
11
+ let(:source) { mock(:source) }
12
+ let(:header) { mock(:header, :data => "0000010".to_i(2)) }
13
+ let(:data) { "\x005678" }
14
+ let(:packet) do
15
+ described_class.new(source, header).tap do |packet|
16
+ packet.send :set_data, data
17
+ end
18
+ end
19
+
20
+ describe "#session_number" do
21
+ it "reads a session number from the data" do
22
+ subject.session_number.should == 5678
23
+ end
24
+ end
25
+
26
+ describe "#event_type" do
27
+ it "returns the event type indicated in the first data byte" do
28
+ subject.event_type.should == 2
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ extend PacketTypeExamples
5
+
6
+ describe LiveF1::Packet::Sys::Speed do
7
+ it_behaves_like LiveF1::Packet::Type::Long
8
+ it_behaves_like LiveF1::Packet::Decryptable
9
+
10
+ subject { packet }
11
+
12
+ let(:source) { mock(:source) }
13
+ let(:header) { mock(:header) }
14
+ let(:data) { "" }
15
+ let(:packet) do
16
+ packet = described_class.new(source, header)
17
+ packet.send :set_data, data
18
+ packet
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ extend PacketTypeExamples
5
+
6
+ describe LiveF1::Packet::Sys::Timestamp do
7
+ it_behaves_like LiveF1::Packet::Type::Timestamp
8
+ it_behaves_like LiveF1::Packet::Decryptable
9
+
10
+ subject { packet }
11
+
12
+ let(:source) { mock(:source) }
13
+ let(:header) { mock(:header) }
14
+ let(:data) { "\x03\x00" }
15
+ let(:packet) do
16
+ packet = described_class.new(source, header)
17
+ packet.send :set_data, data
18
+ packet
19
+ end
20
+
21
+ describe "#number" do
22
+ # `data` for a KeyFrame packet represents a little-endian integer
23
+ it "read a session number from the data" do
24
+ # Binary: "00000000/00000011"
25
+ subject.send :set_data, [3,0].pack("c*")
26
+ subject.number.should == 3
27
+
28
+
29
+ # Binary: "00000001/00000011"
30
+ subject.send :set_data, [3,1].pack("c*")
31
+ subject.number.should == 259
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ extend PacketTypeExamples
5
+
6
+ describe LiveF1::Packet::Sys::TrackStatus do
7
+ it_behaves_like LiveF1::Packet::Type::Short
8
+ it_behaves_like LiveF1::Packet::Decryptable
9
+
10
+ subject { packet }
11
+
12
+ let(:source) { mock(:source) }
13
+ let(:header) { mock(:header) }
14
+ let(:data) { "" }
15
+ let(:packet) do
16
+ packet = described_class.new(source, header)
17
+ packet.send :set_data, data
18
+ packet
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ extend PacketTypeExamples
5
+
6
+ describe LiveF1::Packet::Sys::Weather do
7
+ it_behaves_like LiveF1::Packet::Type::Short
8
+ it_behaves_like LiveF1::Packet::Decryptable
9
+
10
+ subject { packet }
11
+
12
+ let(:source) { mock(:source) }
13
+ let(:header) { mock(:header) }
14
+ let(:data) { "" }
15
+ let(:packet) do
16
+ packet = described_class.new(source, header)
17
+ packet.send :set_data, data
18
+ packet
19
+ end
20
+ end
@@ -0,0 +1,112 @@
1
+ require 'live_f1/packet'
2
+ require 'spec_helper'
3
+
4
+ module LiveF1
5
+ class Packet
6
+ module Spec
7
+ class Base < Packet; def length; 0; end; end
8
+ class Decryptable < Packet; include Packet::Type::Short; include Packet::Decryptable; end
9
+ class Short < Packet; include Packet::Type::Short; end
10
+ class Long < Packet; include Packet::Type::Long; end
11
+ class Special < Packet; include Packet::Type::Special; end
12
+ class Timestamp < Packet; include Packet::Type::Timestamp; end
13
+ end
14
+ end
15
+ end
16
+
17
+ def mock_packet stubs = {}
18
+ base_stubs = {
19
+ :data => "",
20
+ :data= => nil,
21
+ :length => 0
22
+ }
23
+ mock("packet", base_stubs.merge(stubs))
24
+ end
25
+
26
+ extend PacketTypeExamples
27
+
28
+ describe LiveF1::Packet do
29
+ describe "::from_source" do
30
+ let(:source) { mock("source", :read_bytes => "") }
31
+ let(:header) { mock("header", :packet_klass => LiveF1::Packet::Spec::Base) }
32
+ let(:packet) { mock_packet :length => 7 }
33
+ let(:event_type) { LiveF1::Event::QUALIFYING }
34
+ before do
35
+ LiveF1::Packet::Header.stub(:from_source).with(source, event_type) { header }
36
+ end
37
+
38
+ it "extracts a packet header from the source" do
39
+ LiveF1::Packet::Header.should_receive(:from_source).with(source, event_type) { header }
40
+
41
+ described_class.from_source(source, event_type)
42
+ end
43
+
44
+ it "returns the kind of packet specified in the header" do
45
+ described_class.from_source(source, event_type).should be_a_kind_of(LiveF1::Packet::Spec::Base)
46
+ end
47
+
48
+ it "reads bytes from the source depending on its determined length" do
49
+ described_class.stub(:new) { packet }
50
+
51
+ source.should_receive(:read_bytes).with(7) { " " }
52
+
53
+ described_class.from_source(source, event_type)
54
+ end
55
+
56
+ it "sets the packet data to the data read from the source" do
57
+ described_class.stub(:new) { packet }
58
+ source.stub(:read_bytes).with(7) { "abcdefg" }
59
+
60
+ packet.should_receive(:data=).with("abcdefg")
61
+
62
+ described_class.from_source(source, event_type)
63
+ end
64
+ end
65
+
66
+ describe "(constructor)" do
67
+ let(:source) { mock("source") }
68
+ let(:header) { mock("header") }
69
+ let(:packet) { LiveF1::Packet::Spec::Base.new(source, header) }
70
+
71
+ it "sets the source property" do
72
+ packet.source.should == source
73
+ end
74
+
75
+ it "sets the header property" do
76
+ packet.header.should == header
77
+ end
78
+ end
79
+
80
+ describe "(instance methods)" do
81
+ subject { packet }
82
+ let(:source) { mock("source") }
83
+ let(:header) { mock("header", :packet_type => 0, :data => 0) }
84
+ let(:packet) { LiveF1::Packet::Spec::Base.new(source, header) }
85
+
86
+ describe "#inspect" do
87
+ it "include the class name" do
88
+ subject.inspect.should include("Spec::Base")
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ describe LiveF1::Packet::Spec::Decryptable do
95
+ it_behaves_like LiveF1::Packet::Decryptable
96
+ end
97
+
98
+ describe LiveF1::Packet::Spec::Long do
99
+ it_behaves_like LiveF1::Packet::Type::Long
100
+ end
101
+
102
+ describe LiveF1::Packet::Spec::Short do
103
+ it_behaves_like LiveF1::Packet::Type::Short
104
+ end
105
+
106
+ describe LiveF1::Packet::Spec::Special do
107
+ it_behaves_like LiveF1::Packet::Type::Special
108
+ end
109
+
110
+ describe LiveF1::Packet::Spec::Timestamp do
111
+ it_behaves_like LiveF1::Packet::Type::Timestamp
112
+ end
@@ -0,0 +1,56 @@
1
+ require 'live_f1/source'
2
+
3
+ describe LiveF1::Source::Keyframe do
4
+ let(:io) { mock(:io) }
5
+ let(:parent) { mock(:source) }
6
+
7
+ describe "(constructor)" do
8
+ let(:source) { described_class.new(io, parent) }
9
+ let(:data) { "" }
10
+
11
+ it "takes an io object as the first parameter" do
12
+ source.io.should == io
13
+ end
14
+
15
+ it "takes a password as the second parameter" do
16
+ source.parent.should == parent
17
+ end
18
+ end
19
+
20
+ describe "(instance methods)" do
21
+ let(:source) { described_class.new(io, parent) }
22
+
23
+ describe "#read_bytes" do
24
+ it "reads from the keyframe data" do
25
+ io.should_receive(:read).with(2) { "xx" }
26
+
27
+ source.read_bytes(2)
28
+ end
29
+ end
30
+
31
+ describe "#session" do
32
+ it "uses its parent source's session" do
33
+ session = mock(:session)
34
+ parent.stub(:session) { session }
35
+ source.session.should == session
36
+ end
37
+ end
38
+
39
+ describe "#session=" do
40
+ it "sets its parent source's session" do
41
+ session = mock(:session)
42
+ parent.should_receive(:session=).with(session)
43
+
44
+ source.session = session
45
+ end
46
+ end
47
+
48
+ describe "#decryption_key" do
49
+ it "uses its parent source's decryption key" do
50
+ parent.should_receive(:decryption_key).with(1234) { "5caff01d" }
51
+
52
+ source.decryption_key(1234).should == "5caff01d"
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+ require 'live_f1/source'
3
+
4
+ describe LiveF1::Source::Live do
5
+ let(:username) { "username@example.com" }
6
+ let(:password) { "swordfish" }
7
+
8
+ describe "(constructor)" do
9
+ let(:source) { described_class.new(username, password) }
10
+
11
+ it "takes a username as the first parameter" do
12
+ source.username.should == username
13
+ end
14
+
15
+ it "takes a password as the second parameter" do
16
+ source.password.should == password
17
+ end
18
+ end
19
+
20
+ describe "(instance methods)" do
21
+ let(:source) { described_class.new(username, password) }
22
+
23
+ describe "#read_bytes" do
24
+ let(:socket) { mock(:socket) }
25
+ it "reads from the live f1 socket" do
26
+ source.stub(:socket) { socket }
27
+ socket.should_receive(:read).with(2) { "xx" }
28
+
29
+ source.read_bytes(2)
30
+ end
31
+ end
32
+
33
+ describe "#socket" do
34
+ it "opens a TCPSocket to the live timing server" do
35
+ TCPSocket.should_receive(:open).with("80.231.178.249", 4321) { mock("socket") }
36
+ source.send(:socket)
37
+ end
38
+
39
+ it "uses an existing socket if available" do
40
+ TCPSocket.should_receive(:open).once { mock("socket") }
41
+ source.send(:socket)
42
+ source.send(:socket)
43
+ end
44
+ end
45
+
46
+ describe "#keyframe" do
47
+ let(:io) { mock(:io, :read => "", :rewind => 0) }
48
+
49
+ context "without a keyframe number" do
50
+ it "returns a Keyframe source initialised with the correct URL and parent source" do
51
+ source.should_receive(:open).with("http://80.231.178.249/keyframe.bin") { io }
52
+ LiveF1::Source::Keyframe.should_receive(:new).with(io, source)
53
+
54
+ source.keyframe
55
+ end
56
+ end
57
+
58
+ context "with a keyframe number" do
59
+ it "returns a Keyframe source initialised with the correct URL and parent source" do
60
+ source.should_receive(:open).with("http://80.231.178.249/keyframe_00012.bin") { io }
61
+ LiveF1::Source::Keyframe.should_receive(:new).with(io, source)
62
+
63
+ source.keyframe(12)
64
+ end
65
+ end
66
+
67
+ context "on SocketError" do
68
+ before do
69
+ source.stub(:open).and_raise(SocketError)
70
+ end
71
+
72
+ it "raises ConnectionError" do
73
+ lambda { source.keyframe }.should raise_error(LiveF1::Source::Live::ConnectionError)
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "#decryption_key" do
79
+ let(:decryption_url) { "http://80.231.178.249/reg/getkey/1234.asp?auth=ABC123DEF" }
80
+
81
+ before do
82
+ source.stub(:auth) { "ABC123DEF" }
83
+ end
84
+
85
+ it "uses the live source's authorization to request decryption key from the live timing servers" do
86
+ source.should_receive(:open).with(decryption_url) { mock(:io, :read => "5caff01d") }
87
+ source.decryption_key(1234).should == "5caff01d".to_i(16)
88
+ end
89
+
90
+ it "raises a ConnectionError when decryption key service returns 0" do
91
+ source.should_receive(:open).with(decryption_url) { mock(:io, :read => "0") }
92
+ lambda { source.decryption_key(1234) }.should raise_error(LiveF1::Source::Live::ConnectionError, /session key/)
93
+ end
94
+ end
95
+
96
+ describe "#auth" do
97
+ before do
98
+ FakeWeb.register_uri :post, "http://80.231.178.249/reg/login", :set_cookie => "USER=abcdef"
99
+ end
100
+
101
+ it "loads authentication from the live timing servers" do
102
+ source.send(:auth).should == "abcdef"
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,39 @@
1
+ require 'live_f1/source/session'
2
+
3
+ describe LiveF1::Source::Session do
4
+ describe "(constructor)" do
5
+ let(:session) { described_class.new(1, 2, 3) }
6
+
7
+ it "sets the session number, event type and decryption key" do
8
+ session.number.should == 1
9
+ session.event_type.should == 2
10
+ session.decryption_key.should == 3
11
+ end
12
+
13
+ it "initializes the decryption salt" do
14
+ session.decryption_salt.should == 0x55555555
15
+ end
16
+ end
17
+
18
+ describe "(instance methods)" do
19
+ let(:session) { described_class.new(1, 2, 3) }
20
+
21
+ describe "#decrypt" do
22
+ let(:decryption_key) { "B247A746".to_i(16) }
23
+ let(:encrypted) { "\xBC\x9A\x1E\x9AH>\xCB\xE4\xFE\xE0v!h\r\xF9" }
24
+ let(:decrypted) { "Please Wait ..." }
25
+ it "decrypts data" do
26
+ session.stub(:decryption_key) { decryption_key }
27
+ session.decrypt(encrypted).should == decrypted
28
+ end
29
+ end
30
+
31
+ describe "#reset_decryption_salt!" do
32
+ it "resets the decryption salt" do
33
+ session.decryption_salt = 0x01010101
34
+ session.reset_decryption_salt!
35
+ session.decryption_salt.should == 0x55555555
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,140 @@
1
+ require 'live_f1/source'
2
+
3
+ class TestSource < LiveF1::Source
4
+ end
5
+
6
+ module LiveF1
7
+ class Packet
8
+ end
9
+ end
10
+
11
+ describe LiveF1::Source do
12
+ describe "(instance methods)" do
13
+ let(:source) { TestSource.new }
14
+ let(:session) { mock(:session) }
15
+
16
+ before do
17
+ source.stub(:session) { session }
18
+ end
19
+
20
+ describe "#run" do
21
+ let(:packets) { [mock("packet"),mock("packet"),mock("packet")] }
22
+
23
+ before do
24
+ p = packets ? packets.dup : []
25
+ source.stub(:read_packet) { p.shift }
26
+ end
27
+
28
+ context "with keyframes available" do
29
+ let(:keyframe_source) { mock("keyframe source") }
30
+ before do
31
+ source.stub(:keyframe) { keyframe_source }
32
+ end
33
+
34
+ it "runs the keyframe" do
35
+ keyframe_source.should_receive(:run)
36
+
37
+ source.run { }
38
+ end
39
+ end
40
+
41
+ it "reads packets" do
42
+ source.should_receive(:read_packet) { nil }
43
+ source.run { }
44
+ end
45
+
46
+ it "yields as many packets as are available" do
47
+ @packets = []
48
+ source.run do |p|
49
+ @packets << p
50
+ end
51
+ @packets.should == packets
52
+ end
53
+
54
+ describe "running" do
55
+ let(:header) { mock("header") }
56
+ let(:decryption_key) { "5caff01d".to_i(16) }
57
+ let(:session_number) { 1234 }
58
+
59
+ before do
60
+ source.stub(:decryption_key).with(session_number) { decryption_key }
61
+ end
62
+
63
+ context "when an SessionStart packet is yielded" do
64
+ let(:packets) do
65
+ packet = LiveF1::Packet::Sys::SessionStart.new(source, header)
66
+ packet.stub(:session_number) { session_number }
67
+ packet.stub(:event_type) { 3 }
68
+ [packet]
69
+ end
70
+
71
+ it "creates a source session with the correct data" do
72
+ LiveF1::Source::Session.should_receive(:new).with(1234, 3, decryption_key) { mock(:session) }
73
+
74
+ source.run { }
75
+ end
76
+
77
+ it "sets the source's session to the new session object" do
78
+ LiveF1::Source::Session.stub(:new) { session }
79
+ source.should_receive(:session=).with(session)
80
+
81
+ source.run { }
82
+ end
83
+ end
84
+
85
+ context "when an KeyFrame packet is yielded" do
86
+ let(:packets) do
87
+ packet = LiveF1::Packet::Sys::KeyFrame.new(source, header)
88
+ packet.stub(:number) { 123 }
89
+ [packet]
90
+ end
91
+ let(:session) { mock(:session, :reset_decryption_salt! => true) }
92
+
93
+ before do
94
+ source.stub(:session) { session }
95
+ end
96
+
97
+ it "resets the session's decryption data" do
98
+ session.should_receive(:reset_decryption_salt!) { true }
99
+ source.run { }
100
+ end
101
+
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "#read_packet" do
107
+ let(:packet) { mock("packet") }
108
+ let(:session) { mock(:session, :event_type => 3) }
109
+
110
+ before do
111
+ LiveF1::Packet.stub(:from_source).with(source, 3) { packet }
112
+ source.session = session
113
+ end
114
+
115
+ it "extracts a packet from itself" do
116
+ LiveF1::Packet.should_receive(:from_source).with(source, 3) { packet }
117
+
118
+ source.read_packet
119
+ end
120
+
121
+ it "returns the extracted packet" do
122
+ source.read_packet.should == packet
123
+ end
124
+ end
125
+
126
+ describe "#decrypt" do
127
+ let(:input) { "encrypted" }
128
+ let(:output) { "plaintext" }
129
+ it "calls its session's decryptor" do
130
+ session.should_receive(:decrypt).with(input)
131
+ source.decrypt(input)
132
+ end
133
+
134
+ it "returns the decrypted bytes" do
135
+ session.stub(:decrypt) { output }
136
+ source.decrypt(input).should == output
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,10 @@
1
+ require 'fakeweb'
2
+
3
+ Dir["spec/support/**/*.rb"].each { |f| require File.join(File.expand_path(File.dirname(__FILE__)),"..",f) }
4
+
5
+ RSpec.configure do |config|
6
+ config.treat_symbols_as_metadata_keys_with_true_values = true
7
+ config.run_all_when_everything_filtered = true
8
+ end
9
+
10
+ FakeWeb.allow_net_connect = false