live_f1-core 0.0.1

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