cosmos 3.3.3 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.travis.yml +2 -1
  4. data/Gemfile +4 -3
  5. data/Manifest.txt +22 -0
  6. data/autohotkey/tools/handbook_creator.ahk +9 -0
  7. data/autohotkey/tools/packet_viewer.ahk +4 -0
  8. data/bin/exchndl20-x64.dll +0 -0
  9. data/bin/exchndl20.dll +0 -0
  10. data/bin/exchndl21-x64.dll +0 -0
  11. data/bin/exchndl21.dll +0 -0
  12. data/bin/exchndl22-x64.dll +0 -0
  13. data/bin/exchndl22.dll +0 -0
  14. data/bin/mgwhelp-x64.dll +0 -0
  15. data/bin/mgwhelp.dll +0 -0
  16. data/cosmos.gemspec +1 -0
  17. data/data/crc.txt +30 -24
  18. data/demo/config/data/crc.txt +3 -3
  19. data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +3 -1
  20. data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +3 -1
  21. data/demo/procedures/cosmos_api_test.rb +1 -1
  22. data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +4 -0
  23. data/ext/cosmos/ext/platform/platform.c +22 -2
  24. data/ext/cosmos/ext/structure/structure.c +631 -104
  25. data/ext/cosmos/ext/telemetry/telemetry.c +3 -2
  26. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +71 -92
  27. data/lib/cosmos/gui/line_graph/overview_graph.rb +1 -1
  28. data/lib/cosmos/gui/qt.rb +38 -24
  29. data/lib/cosmos/gui/text/ruby_editor.rb +1 -1
  30. data/lib/cosmos/packets/binary_accessor.rb +1 -288
  31. data/lib/cosmos/packets/telemetry.rb +2 -1
  32. data/lib/cosmos/script/cmd_tlm_server.rb +110 -0
  33. data/lib/cosmos/script/commands.rb +166 -0
  34. data/lib/cosmos/script/extract.rb +2 -2
  35. data/lib/cosmos/script/limits.rb +108 -0
  36. data/lib/cosmos/script/script.rb +28 -1487
  37. data/lib/cosmos/script/scripting.rb +889 -0
  38. data/lib/cosmos/script/telemetry.rb +174 -0
  39. data/lib/cosmos/script/tools.rb +138 -0
  40. data/lib/cosmos/streams/stream_protocol.rb +9 -6
  41. data/lib/cosmos/system/target.rb +55 -38
  42. data/lib/cosmos/tools/cmd_tlm_server/api.rb +6 -3
  43. data/lib/cosmos/tools/cmd_tlm_server/connections.rb +0 -1
  44. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +17 -7
  45. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +15 -4
  46. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +15 -8
  47. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +41 -13
  48. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +18 -1
  49. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +1 -1
  50. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +1 -1
  51. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +1 -1
  52. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +1 -1
  53. data/lib/cosmos/top_level.rb +1 -1
  54. data/lib/cosmos/utilities/ruby_lex_utils.rb +1 -1
  55. data/lib/cosmos/version.rb +5 -5
  56. data/spec/gui/line_graph/line_clip_spec.rb +6 -6
  57. data/spec/gui/qt_spec.rb +102 -0
  58. data/spec/interfaces/interface_spec.rb +9 -9
  59. data/spec/interfaces/linc_interface_spec.rb +72 -15
  60. data/spec/interfaces/serial_interface_spec.rb +9 -9
  61. data/spec/interfaces/simulated_target_interface_spec.rb +7 -7
  62. data/spec/interfaces/stream_interface_spec.rb +4 -4
  63. data/spec/interfaces/tcpip_client_interface_spec.rb +8 -8
  64. data/spec/interfaces/tcpip_server_interface_spec.rb +9 -9
  65. data/spec/interfaces/udp_interface_spec.rb +20 -20
  66. data/spec/io/json_drb_spec.rb +4 -4
  67. data/spec/io/raw_logger_pair_spec.rb +20 -20
  68. data/spec/io/raw_logger_spec.rb +3 -3
  69. data/spec/io/tcpip_server_spec.rb +9 -9
  70. data/spec/io/udp_sockets_spec.rb +2 -2
  71. data/spec/io/win32_serial_driver_spec.rb +2 -2
  72. data/spec/packets/binary_accessor_spec.rb +143 -6
  73. data/spec/packets/commands_spec.rb +5 -5
  74. data/spec/packets/limits_spec.rb +15 -15
  75. data/spec/packets/packet_config_spec.rb +19 -19
  76. data/spec/packets/packet_item_limits_spec.rb +3 -3
  77. data/spec/packets/packet_item_spec.rb +4 -4
  78. data/spec/packets/packet_spec.rb +33 -33
  79. data/spec/packets/structure_item_spec.rb +19 -19
  80. data/spec/packets/telemetry_spec.rb +6 -6
  81. data/spec/script/cmd_tlm_server_spec.rb +110 -0
  82. data/spec/script/commands_disconnect_spec.rb +270 -0
  83. data/spec/script/commands_spec.rb +288 -0
  84. data/spec/script/limits_spec.rb +153 -0
  85. data/spec/script/script_spec.rb +32 -696
  86. data/spec/script/scripting_spec.rb +436 -0
  87. data/spec/script/telemetry_spec.rb +130 -0
  88. data/spec/script/tools_spec.rb +117 -0
  89. data/spec/spec_helper.rb +10 -5
  90. data/spec/streams/preidentified_stream_protocol_spec.rb +4 -4
  91. data/spec/streams/serial_stream_spec.rb +8 -8
  92. data/spec/streams/stream_protocol_spec.rb +4 -4
  93. data/spec/streams/tcpip_client_stream_spec.rb +3 -3
  94. data/spec/streams/tcpip_socket_stream_spec.rb +7 -7
  95. data/spec/streams/template_stream_protocol_spec.rb +1 -1
  96. data/spec/system/system_spec.rb +6 -6
  97. data/spec/system/target_spec.rb +2 -0
  98. data/spec/tools/cmd_tlm_server/api_spec.rb +17 -17
  99. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +5 -5
  100. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +3 -3
  101. data/spec/top_level/top_level_spec.rb +8 -8
  102. data/spec/utilities/csv_spec.rb +3 -3
  103. data/spec/utilities/message_log_spec.rb +3 -3
  104. data/spec/utilities/ruby_lex_utils_spec.rb +7 -7
  105. data/test/performance/config/tools/launcher/launcher_threads.txt +8 -1
  106. data/test/performance/tools/CmdTlmServerMemProf +1 -1
  107. data/test/performance/tools/TlmGrapherMemProf +19 -0
  108. data/test/performance/tools/TlmGrapherMemProf.bat +59 -0
  109. metadata +38 -2
@@ -22,17 +22,17 @@ module Cosmos
22
22
  it "is not writeable if no write port given" do
23
23
  i = UdpInterface.new('localhost','nil','8889')
24
24
  expect(i.name).to eql "Cosmos::UdpInterface"
25
- expect(i.write_allowed?).to be_falsey
26
- expect(i.write_raw_allowed?).to be_falsey
27
- expect(i.read_allowed?).to be_truthy
25
+ expect(i.write_allowed?).to be false
26
+ expect(i.write_raw_allowed?).to be false
27
+ expect(i.read_allowed?).to be true
28
28
  end
29
29
 
30
30
  it "is not readable if no read port given" do
31
31
  i = UdpInterface.new('localhost','8888','nil')
32
32
  expect(i.name).to eql "Cosmos::UdpInterface"
33
- expect(i.write_allowed?).to be_truthy
34
- expect(i.write_raw_allowed?).to be_truthy
35
- expect(i.read_allowed?).to be_falsey
33
+ expect(i.write_allowed?).to be true
34
+ expect(i.write_raw_allowed?).to be true
35
+ expect(i.read_allowed?).to be false
36
36
  end
37
37
  end
38
38
 
@@ -47,11 +47,11 @@ module Cosmos
47
47
  expect(UdpWriteSocket).to receive(:new).and_return(write)
48
48
  expect(UdpReadSocket).to receive(:new).and_return(read)
49
49
  i = UdpInterface.new('localhost','8888','8889')
50
- expect(i.connected?).to be_falsey
50
+ expect(i.connected?).to be false
51
51
  i.connect
52
- expect(i.connected?).to be_truthy
52
+ expect(i.connected?).to be true
53
53
  i.disconnect
54
- expect(i.connected?).to be_falsey
54
+ expect(i.connected?).to be false
55
55
  end
56
56
 
57
57
  it "creates a UdpWriteSocket if write port given" do
@@ -61,11 +61,11 @@ module Cosmos
61
61
  expect(UdpWriteSocket).to receive(:new).and_return(write)
62
62
  expect(UdpReadSocket).to_not receive(:new)
63
63
  i = UdpInterface.new('localhost','8888','nil')
64
- expect(i.connected?).to be_falsey
64
+ expect(i.connected?).to be false
65
65
  i.connect
66
- expect(i.connected?).to be_truthy
66
+ expect(i.connected?).to be true
67
67
  i.disconnect
68
- expect(i.connected?).to be_falsey
68
+ expect(i.connected?).to be false
69
69
  end
70
70
 
71
71
  it "creates a UdpReadSocket if read port given" do
@@ -75,11 +75,11 @@ module Cosmos
75
75
  expect(UdpWriteSocket).to_not receive(:new)
76
76
  expect(UdpReadSocket).to receive(:new).and_return(read)
77
77
  i = UdpInterface.new('localhost','nil','8889')
78
- expect(i.connected?).to be_falsey
78
+ expect(i.connected?).to be false
79
79
  i.connect
80
- expect(i.connected?).to be_truthy
80
+ expect(i.connected?).to be true
81
81
  i.disconnect
82
- expect(i.connected?).to be_falsey
82
+ expect(i.connected?).to be false
83
83
  end
84
84
  end
85
85
 
@@ -94,11 +94,11 @@ module Cosmos
94
94
  expect(UdpWriteSocket).to receive(:new).and_return(write)
95
95
  expect(UdpReadSocket).to receive(:new).and_return(read)
96
96
  i = UdpInterface.new('localhost','8888','8889')
97
- expect(i.connected?).to be_falsey
97
+ expect(i.connected?).to be false
98
98
  i.connect
99
- expect(i.connected?).to be_truthy
99
+ expect(i.connected?).to be true
100
100
  i.disconnect
101
- expect(i.connected?).to be_falsey
101
+ expect(i.connected?).to be false
102
102
  end
103
103
  end
104
104
 
@@ -107,7 +107,7 @@ module Cosmos
107
107
  i = UdpInterface.new('localhost','8888','nil')
108
108
  thread = Thread.new { i.read }
109
109
  sleep 0.1
110
- expect(thread.stop?).to be_truthy
110
+ expect(thread.stop?).to be true
111
111
  Cosmos.kill_thread(nil, thread)
112
112
  end
113
113
 
@@ -119,7 +119,7 @@ module Cosmos
119
119
  i.connect
120
120
  thread = Thread.new { i.read }
121
121
  sleep 0.1
122
- expect(thread.stop?).to be_truthy
122
+ expect(thread.stop?).to be true
123
123
  Cosmos.kill_thread(nil, thread)
124
124
  end
125
125
 
@@ -86,7 +86,7 @@ module Cosmos
86
86
  it "creates a single listen thread" do
87
87
  expect(@json.thread).to be_nil
88
88
  @json.start_service('127.0.0.1', 7777, self)
89
- expect(@json.thread.alive?).to be_truthy
89
+ expect(@json.thread.alive?).to be true
90
90
  expect { @json.start_service('127.0.0.1', 7777, self) }.to raise_error(/Error binding to port/)
91
91
  @json.stop_service
92
92
  sleep(0.1)
@@ -114,7 +114,7 @@ module Cosmos
114
114
  @json.start_service('127.0.0.1', 7777, self)
115
115
  socket = TCPSocket.open('127.0.0.1',7777)
116
116
  sleep 0.1
117
- expect(socket.eof?).to be_truthy
117
+ expect(socket.eof?).to be true
118
118
  socket.close
119
119
  @json.stop_service
120
120
  sleep(0.1)
@@ -300,9 +300,9 @@ module Cosmos
300
300
  describe "debug, debug?" do
301
301
  it "sets the debug level" do
302
302
  JsonDRb.debug = true
303
- expect(JsonDRb.debug?).to be_truthy
303
+ expect(JsonDRb.debug?).to be true
304
304
  JsonDRb.debug = false
305
- expect(JsonDRb.debug?).to be_falsey
305
+ expect(JsonDRb.debug?).to be false
306
306
  end
307
307
  end
308
308
 
@@ -20,14 +20,14 @@ module Cosmos
20
20
  pair = RawLoggerPair.new('MYINT')
21
21
  expect(pair.read_logger).not_to be_nil
22
22
  expect(pair.write_logger).not_to be_nil
23
- expect(pair.read_logger.logging_enabled).to be_falsey
24
- expect(pair.write_logger.logging_enabled).to be_falsey
23
+ expect(pair.read_logger.logging_enabled).to be false
24
+ expect(pair.write_logger.logging_enabled).to be false
25
25
 
26
26
  pair = RawLoggerPair.new('MYINT2', ['raw_logger.rb', true, 100000, './'])
27
27
  expect(pair.read_logger).not_to be_nil
28
28
  expect(pair.write_logger).not_to be_nil
29
- expect(pair.read_logger.logging_enabled).to be_truthy
30
- expect(pair.write_logger.logging_enabled).to be_truthy
29
+ expect(pair.read_logger.logging_enabled).to be true
30
+ expect(pair.write_logger.logging_enabled).to be true
31
31
  end
32
32
  end
33
33
 
@@ -35,8 +35,8 @@ module Cosmos
35
35
  it "starts logging" do
36
36
  pair = RawLoggerPair.new('MYINT')
37
37
  pair.start
38
- expect(pair.write_logger.logging_enabled).to be_truthy
39
- expect(pair.read_logger.logging_enabled).to be_truthy
38
+ expect(pair.write_logger.logging_enabled).to be true
39
+ expect(pair.read_logger.logging_enabled).to be true
40
40
  end
41
41
  end
42
42
 
@@ -44,30 +44,30 @@ module Cosmos
44
44
  it "stops logging" do
45
45
  pair = RawLoggerPair.new('MYINT')
46
46
  pair.start
47
- expect(pair.write_logger.logging_enabled).to be_truthy
48
- expect(pair.read_logger.logging_enabled).to be_truthy
47
+ expect(pair.write_logger.logging_enabled).to be true
48
+ expect(pair.read_logger.logging_enabled).to be true
49
49
  pair.stop
50
- expect(pair.write_logger.logging_enabled).to be_falsey
51
- expect(pair.read_logger.logging_enabled).to be_falsey
50
+ expect(pair.write_logger.logging_enabled).to be false
51
+ expect(pair.read_logger.logging_enabled).to be false
52
52
  end
53
53
  end
54
54
 
55
55
  describe "clone" do
56
56
  it "clones itself including logging state" do
57
57
  pair = RawLoggerPair.new('MYINT')
58
- expect(pair.write_logger.logging_enabled).to be_falsey
59
- expect(pair.read_logger.logging_enabled).to be_falsey
58
+ expect(pair.write_logger.logging_enabled).to be false
59
+ expect(pair.read_logger.logging_enabled).to be false
60
60
  pair_clone1 = pair.clone
61
61
  pair.start
62
- expect(pair.write_logger.logging_enabled).to be_truthy
63
- expect(pair.read_logger.logging_enabled).to be_truthy
64
- expect(pair_clone1.write_logger.logging_enabled).to be_falsey
65
- expect(pair_clone1.read_logger.logging_enabled).to be_falsey
62
+ expect(pair.write_logger.logging_enabled).to be true
63
+ expect(pair.read_logger.logging_enabled).to be true
64
+ expect(pair_clone1.write_logger.logging_enabled).to be false
65
+ expect(pair_clone1.read_logger.logging_enabled).to be false
66
66
  pair_clone2 = pair.clone
67
- expect(pair_clone1.write_logger.logging_enabled).to be_falsey
68
- expect(pair_clone1.read_logger.logging_enabled).to be_falsey
69
- expect(pair_clone2.write_logger.logging_enabled).to be_truthy
70
- expect(pair_clone2.read_logger.logging_enabled).to be_truthy
67
+ expect(pair_clone1.write_logger.logging_enabled).to be false
68
+ expect(pair_clone1.read_logger.logging_enabled).to be false
69
+ expect(pair_clone2.write_logger.logging_enabled).to be true
70
+ expect(pair_clone2.read_logger.logging_enabled).to be true
71
71
  end
72
72
  end
73
73
 
@@ -117,12 +117,12 @@ module Cosmos
117
117
  describe "start and stop" do
118
118
  it "enables and disable logging" do
119
119
  raw_logger = RawLogger.new('MYINT', :WRITE, false, 200, nil)
120
- expect(raw_logger.logging_enabled).to be_falsey
120
+ expect(raw_logger.logging_enabled).to be false
121
121
  raw_logger.start
122
- expect(raw_logger.logging_enabled).to be_truthy
122
+ expect(raw_logger.logging_enabled).to be true
123
123
  raw_logger.write("\x00\x01\x02\x03")
124
124
  raw_logger.stop
125
- expect(raw_logger.logging_enabled).to be_falsey
125
+ expect(raw_logger.logging_enabled).to be false
126
126
  file = Dir[File.join(@log_path,"*.bin")][-1]
127
127
  expect(File.size(file)).not_to eql 0
128
128
  end
@@ -35,12 +35,12 @@ module Cosmos
35
35
  server = TcpipServer.new(nil,8889,nil,nil,'Burst')
36
36
  server.connect
37
37
  sleep 0.2
38
- expect(server.connected?).to be_truthy
38
+ expect(server.connected?).to be true
39
39
  # 2 because the RSpec main thread plus the listener
40
40
  expect(Thread.list.length).to eql 2
41
41
  server.disconnect
42
42
  sleep 0.2
43
- expect(server.connected?).to be_falsey
43
+ expect(server.connected?).to be false
44
44
  expect(Thread.list.length).to eql 1
45
45
  end
46
46
 
@@ -48,13 +48,13 @@ module Cosmos
48
48
  server = TcpipServer.new(8888,nil,nil,nil,'Burst')
49
49
  server.connect
50
50
  sleep 0.2
51
- expect(server.connected?).to be_truthy
51
+ expect(server.connected?).to be true
52
52
  # 3 because the RSpec main thread plus the listener
53
53
  # plus one for the write thread
54
54
  expect(Thread.list.length).to eql 3
55
55
  server.disconnect
56
56
  sleep 0.2
57
- expect(server.connected?).to be_falsey
57
+ expect(server.connected?).to be false
58
58
  expect(Thread.list.length).to eql 1
59
59
  end
60
60
 
@@ -62,13 +62,13 @@ module Cosmos
62
62
  server = TcpipServer.new(8888,8888,nil,nil,'Burst')
63
63
  server.connect
64
64
  sleep 0.2
65
- expect(server.connected?).to be_truthy
65
+ expect(server.connected?).to be true
66
66
  # 3 because the RSpec main thread plus the listener
67
67
  # plus one for the write thread
68
68
  expect(Thread.list.length).to eql 3
69
69
  server.disconnect
70
70
  sleep 0.2
71
- expect(server.connected?).to be_falsey
71
+ expect(server.connected?).to be false
72
72
  expect(Thread.list.length).to eql 1
73
73
  end
74
74
 
@@ -76,13 +76,13 @@ module Cosmos
76
76
  server = TcpipServer.new(8888,8889,nil,nil,'Burst')
77
77
  server.connect
78
78
  sleep 0.2
79
- expect(server.connected?).to be_truthy
79
+ expect(server.connected?).to be true
80
80
  # 4 because the RSpec main thread plus the two listeners
81
81
  # plus one for the write thread
82
82
  expect(Thread.list.length).to eql 4
83
83
  server.disconnect
84
84
  sleep 0.2
85
- expect(server.connected?).to be_falsey
85
+ expect(server.connected?).to be false
86
86
  expect(Thread.list.length).to eql 1
87
87
  end
88
88
 
@@ -152,7 +152,7 @@ module Cosmos
152
152
  socket = TCPSocket.open("127.0.0.1",8889)
153
153
  sleep 0.2
154
154
  expect(server.num_clients).to eql 0
155
- expect(socket.eof?).to be_truthy
155
+ expect(socket.eof?).to be true
156
156
  server.disconnect
157
157
  sleep 0.2
158
158
  socket.close
@@ -50,8 +50,8 @@ module Cosmos
50
50
 
51
51
  describe "multicast" do
52
52
  it "determines if a host is multicast" do
53
- expect(UdpWriteSocket.multicast?('127.0.0.1')).to be_falsey
54
- expect(UdpWriteSocket.multicast?('224.0.1.1')).to be_truthy
53
+ expect(UdpWriteSocket.multicast?('127.0.0.1')).to be false
54
+ expect(UdpWriteSocket.multicast?('224.0.1.1')).to be true
55
55
  end
56
56
  end
57
57
 
@@ -46,9 +46,9 @@ module Cosmos
46
46
  it "closes the handle" do
47
47
  expect(Win32).to receive(:close_handle)
48
48
  driver = Win32SerialDriver.new('COM1',9600)
49
- expect(driver.closed?).to be_falsey
49
+ expect(driver.closed?).to be false
50
50
  driver.close
51
- expect(driver.closed?).to be_truthy
51
+ expect(driver.closed?).to be true
52
52
  end
53
53
  end
54
54
 
@@ -16,7 +16,7 @@ module Cosmos
16
16
 
17
17
  describe BinaryAccessor do
18
18
 
19
- describe "read" do
19
+ describe "read only" do
20
20
 
21
21
  before(:each) do
22
22
  @data = "\x80\x81\x82\x83\x84\x85\x86\x87\x00\x09\x0A\x0B\x0C\x0D\x0E\x0F"
@@ -240,6 +240,21 @@ module Cosmos
240
240
  expect(BinaryAccessor.read(65, bit_size, :INT, @data, :BIG_ENDIAN)).to eql(expected[1])
241
241
  end
242
242
 
243
+ it "reads 67-bit unsigned integers" do
244
+ expected = [0x808182838485868700 >> 5, 0x8700090A0B0C0D0E0F >> 5]
245
+ bit_size = 67
246
+ expect(BinaryAccessor.read(0, bit_size, :UINT, @data, :BIG_ENDIAN)).to eql(expected[0])
247
+ expect(BinaryAccessor.read(56, bit_size, :UINT, @data, :BIG_ENDIAN)).to eql(expected[1])
248
+ end
249
+
250
+ it "reads 67-bit signed integers" do
251
+ expected = [0x808182838485868700 >> 5, 0x8700090A0B0C0D0E0F >> 5]
252
+ bit_size = 67
253
+ expected.each_with_index { |value, index| expected[index] = value - 2**bit_size if value >= 2**(bit_size - 1) }
254
+ expect(BinaryAccessor.read(0, bit_size, :INT, @data, :BIG_ENDIAN)).to eql(expected[0])
255
+ expect(BinaryAccessor.read(56, bit_size, :INT, @data, :BIG_ENDIAN)).to eql(expected[1])
256
+ end
257
+
243
258
  it "reads aligned 64-bit unsigned integers" do
244
259
  expected_array = [0x8081828384858687, 0x00090A0B0C0D0E0F]
245
260
  index = 0
@@ -404,6 +419,19 @@ module Cosmos
404
419
  expect(BinaryAccessor.read(57, bit_size, :INT, @data, :LITTLE_ENDIAN)).to eql(expected[1])
405
420
  end
406
421
 
422
+ it "reads 67-bit unsigned integers" do
423
+ expected = [0x0F0E0D0C0B0A090087 >> 5]
424
+ bit_size = 67
425
+ expect(BinaryAccessor.read(120, bit_size, :UINT, @data, :LITTLE_ENDIAN)).to eql(expected[0])
426
+ end
427
+
428
+ it "reads 67-bit signed integers" do
429
+ expected = [0x0F0E0D0C0B0A090087 >> 5]
430
+ bit_size = 67
431
+ expected.each_with_index { |value, index| expected[index] = value - 2**bit_size if value >= 2**(bit_size - 1) }
432
+ expect(BinaryAccessor.read(120, bit_size, :INT, @data, :LITTLE_ENDIAN)).to eql(expected[0])
433
+ end
434
+
407
435
  it "reads aligned 64-bit unsigned integers" do
408
436
  expected_array = [0x8786858483828180, 0x0F0E0D0C0B0A0900]
409
437
  index = 0
@@ -677,7 +705,7 @@ module Cosmos
677
705
  end # given big endian data
678
706
  end # describe "read_array"
679
707
 
680
- describe "write" do
708
+ describe "write only" do
681
709
 
682
710
  before(:each) do
683
711
  @data = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
@@ -804,6 +832,36 @@ module Cosmos
804
832
  expect { BinaryAccessor.write(@baseline_data, 8, 800, :STRING, @data, :BIG_ENDIAN, :ERROR) }.to raise_error(ArgumentError, "16 byte buffer insufficient to write STRING at bit_offset 8 with bit_size 800")
805
833
  end
806
834
 
835
+ it "truncates the buffer for 0 bitsize" do
836
+ expect(@data.length).to eql 16
837
+ BinaryAccessor.write("\x01\x02\x03", 8, 0, :BLOCK, @data, :BIG_ENDIAN, :ERROR)
838
+ expect(@data).to eql("\x00\x01\x02\x03")
839
+ expect(@data.length).to eql 4
840
+ end
841
+
842
+ it "expands the buffer for 0 bitsize" do
843
+ expect(@data.length).to eql 16
844
+ BinaryAccessor.write("\x01\x02\x03", (14 * 8), 0, :BLOCK, @data, :BIG_ENDIAN, :ERROR)
845
+ expect(@data).to eql("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03")
846
+ expect(@data.length).to eql 17
847
+ end
848
+
849
+ it "writes a frozen string" do
850
+ buffer = "BLANKxxxWORLD"
851
+ string = "HELLO".freeze
852
+ # Specify 3 more bytes than given to exercise the padding logic
853
+ string = BinaryAccessor.write(string, 0, (string.length + 3)*8, :STRING, buffer, :BIG_ENDIAN, :ERROR)
854
+ expect(buffer).to eql("HELLO\x00\x00\x00WORLD")
855
+ expect(string).to eql("HELLO")
856
+ expect(string.frozen?).to be true
857
+ end
858
+
859
+ it "complains about writing a frozen buffer" do
860
+ buffer = "BLANK WORLD".freeze
861
+ string = "HELLO"
862
+ expect {BinaryAccessor.write(string, 0, string.length*8, :STRING, buffer, :BIG_ENDIAN, :ERROR) }.to raise_error(RuntimeError, "can't modify frozen String")
863
+ end
864
+
807
865
  it "writes aligned 8-bit unsigned integers" do
808
866
  0.step((@data.length - 1) * 8, 8) do |bit_offset|
809
867
  @data = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
@@ -824,6 +882,27 @@ module Cosmos
824
882
  end
825
883
  end
826
884
 
885
+ it "converts floats when writing integers" do
886
+ @data = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
887
+ BinaryAccessor.write(1.0, 0, 8, :UINT, @data, :BIG_ENDIAN, :ERROR)
888
+ BinaryAccessor.write(2.5, 8, 8, :INT, @data, :BIG_ENDIAN, :ERROR)
889
+ BinaryAccessor.write(4.99, 16, 8, :UINT, @data, :BIG_ENDIAN, :ERROR)
890
+ expect(@data).to eql("\x01\x02\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
891
+ end
892
+
893
+ it "converts integer strings when writing integers" do
894
+ @data = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
895
+ BinaryAccessor.write("1", 0, 8, :UINT, @data, :BIG_ENDIAN, :ERROR)
896
+ BinaryAccessor.write("2", 8, 8, :INT, @data, :BIG_ENDIAN, :ERROR)
897
+ BinaryAccessor.write("4", 16, 8, :UINT, @data, :BIG_ENDIAN, :ERROR)
898
+ expect(@data).to eql("\x01\x02\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
899
+ end
900
+
901
+ it "complains about non-integer strings when writing integers" do
902
+ expect { BinaryAccessor.write("1.0", 0, 8, :UINT, @data, :BIG_ENDIAN, :ERROR) }.to raise_error(ArgumentError)
903
+ expect { BinaryAccessor.write("abc123", 0, 8, :UINT, @data, :BIG_ENDIAN, :ERROR) }.to raise_error(ArgumentError)
904
+ end
905
+
827
906
  describe "given big endian data" do
828
907
 
829
908
  it "writes 1-bit unsigned integers" do
@@ -834,10 +913,12 @@ module Cosmos
834
913
  end
835
914
 
836
915
  it "writes 1-bit signed integers" do
916
+ @data[1] = "\x55"
837
917
  BinaryAccessor.write(0x1, 8, 1, :INT, @data, :BIG_ENDIAN, :ERROR)
838
918
  BinaryAccessor.write(0x0, 9, 1, :INT, @data, :BIG_ENDIAN, :ERROR)
839
919
  BinaryAccessor.write(0x1, 10, 1, :INT, @data, :BIG_ENDIAN, :ERROR)
840
- expect(@data).to eql("\x00\xA0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
920
+ BinaryAccessor.write(0x0, 11, 1, :INT, @data, :BIG_ENDIAN, :ERROR)
921
+ expect(@data).to eql("\x00\xA5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
841
922
  end
842
923
 
843
924
  it "writes 7-bit unsigned integers" do
@@ -916,6 +997,11 @@ module Cosmos
916
997
  expect(@data).to eql(@baseline_data)
917
998
  end
918
999
 
1000
+ it "writes aligned 32-bit negative integers" do
1001
+ BinaryAccessor.write(-2147483648, 0, 32, :INT, @data, :BIG_ENDIAN, :ERROR_ALLOW_HEX)
1002
+ expect(@data).to eql("\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
1003
+ end
1004
+
919
1005
  it "writes aligned 32-bit floats" do
920
1006
  expected_array = [-1.189360e-038, -3.139169e-036, 8.301067e-040, 1.086646e-031]
921
1007
  BinaryAccessor.write(expected_array[0], 0, 32, :FLOAT, @data, :BIG_ENDIAN, :ERROR)
@@ -941,9 +1027,12 @@ module Cosmos
941
1027
  end
942
1028
 
943
1029
  it "writes 63-bit unsigned integers" do
1030
+ @data[-1] = "\xFF"
944
1031
  BinaryAccessor.write(0x8081828384858687 >> 1, 0, 63, :UINT, @data, :BIG_ENDIAN, :ERROR)
945
- BinaryAccessor.write(0x00090A0B0C0D0E0F, 65, 63, :UINT, @data, :BIG_ENDIAN, :ERROR)
946
- expect(@data).to eql("\x80\x81\x82\x83\x84\x85\x86\x86\x00\x09\x0A\x0B\x0C\x0D\x0E\x0F")
1032
+ expect(@data).to eql("\x80\x81\x82\x83\x84\x85\x86\x86\x00\x00\x00\x00\x00\x00\x00\xFF")
1033
+ @data[0] = "\xFF"
1034
+ BinaryAccessor.write(0x08090A0B0C0D0E0F, 65, 63, :UINT, @data, :BIG_ENDIAN, :ERROR)
1035
+ expect(@data).to eql("\xFF\x81\x82\x83\x84\x85\x86\x86\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F")
947
1036
  end
948
1037
 
949
1038
  it "writes 63-bit signed integers" do
@@ -952,6 +1041,16 @@ module Cosmos
952
1041
  expect(@data).to eql("\x80\x81\x82\x83\x84\x85\x86\x86\x00\x09\x0A\x0B\x0C\x0D\x0E\x0F")
953
1042
  end
954
1043
 
1044
+ it "writes 67-bit unsigned integers" do
1045
+ BinaryAccessor.write(0x8081828384858687FF >> 5, 0, 67, :UINT, @data, :BIG_ENDIAN, :ERROR)
1046
+ expect(@data).to eql("\x80\x81\x82\x83\x84\x85\x86\x87\xE0\x00\x00\x00\x00\x00\x00\x00")
1047
+ end
1048
+
1049
+ it "writes 67-bit signed integers" do
1050
+ BinaryAccessor.write((0x8081828384858687FF >> 5) - 2**67, 0, 67, :INT, @data, :BIG_ENDIAN, :ERROR)
1051
+ expect(@data).to eql("\x80\x81\x82\x83\x84\x85\x86\x87\xE0\x00\x00\x00\x00\x00\x00\x00")
1052
+ end
1053
+
955
1054
  it "writes aligned 64-bit unsigned integers" do
956
1055
  expected_array = [0x8081828384858687, 0x00090A0B0C0D0E0F]
957
1056
  index = 0
@@ -982,6 +1081,32 @@ module Cosmos
982
1081
  expect(BinaryAccessor.read(64, 64, :FLOAT, @data, :BIG_ENDIAN)).to be_within(1.0e-308).of(expected_array[1])
983
1082
  end
984
1083
 
1084
+ it "converts integers to floats" do
1085
+ BinaryAccessor.write(1, 0, 32, :FLOAT, @data, :BIG_ENDIAN, :ERROR)
1086
+ value = BinaryAccessor.read(0, 32, :FLOAT, @data, :BIG_ENDIAN)
1087
+ expect(value).to eql(1.0)
1088
+ expect(value).to be_a(Float)
1089
+ BinaryAccessor.write(4, 32, 64, :FLOAT, @data, :BIG_ENDIAN, :ERROR)
1090
+ value = BinaryAccessor.read(32, 64, :FLOAT, @data, :BIG_ENDIAN)
1091
+ expect(value).to eql(4.0)
1092
+ expect(value).to be_a(Float)
1093
+ end
1094
+
1095
+ it "converts strings when writing floats" do
1096
+ BinaryAccessor.write("1", 0, 32, :FLOAT, @data, :BIG_ENDIAN, :ERROR)
1097
+ value = BinaryAccessor.read(0, 32, :FLOAT, @data, :BIG_ENDIAN)
1098
+ expect(value).to eql(1.0)
1099
+ expect(value).to be_a(Float)
1100
+ BinaryAccessor.write("4.5", 32, 64, :FLOAT, @data, :BIG_ENDIAN, :ERROR)
1101
+ value = BinaryAccessor.read(32, 64, :FLOAT, @data, :BIG_ENDIAN)
1102
+ expect(value).to eql(4.5)
1103
+ expect(value).to be_a(Float)
1104
+ end
1105
+
1106
+ it "complains about non-float strings when writing floats" do
1107
+ expect { BinaryAccessor.write("abc123", 0, 32, :FLOAT, @data, :BIG_ENDIAN, :ERROR) }.to raise_error(ArgumentError)
1108
+ end
1109
+
985
1110
  it "complains about unaligned floats" do
986
1111
  expect { BinaryAccessor.write(0.0, 17, 32, :FLOAT, @data, :BIG_ENDIAN, :ERROR) }.to raise_error(ArgumentError, "bit_offset 17 is not byte aligned for data_type FLOAT")
987
1112
  end
@@ -999,10 +1124,12 @@ module Cosmos
999
1124
  end
1000
1125
 
1001
1126
  it "writes 1-bit unsigned integers" do
1127
+ @data[1] = "\x55"
1002
1128
  BinaryAccessor.write(0x1, 8, 1, :UINT, @data, :LITTLE_ENDIAN, :ERROR)
1003
1129
  BinaryAccessor.write(0x0, 9, 1, :UINT, @data, :LITTLE_ENDIAN, :ERROR)
1004
1130
  BinaryAccessor.write(0x1, 10, 1, :UINT, @data, :LITTLE_ENDIAN, :ERROR)
1005
- expect(@data).to eql("\x00\xA0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
1131
+ BinaryAccessor.write(0x0, 11, 1, :INT, @data, :BIG_ENDIAN, :ERROR)
1132
+ expect(@data).to eql("\x00\xA5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
1006
1133
  end
1007
1134
 
1008
1135
  it "writes 1-bit signed integers" do
@@ -1124,6 +1251,16 @@ module Cosmos
1124
1251
  expect(@data).to eql("\x80\x81\x82\x83\x84\x85\x86\x47\x00\x09\x0A\x0B\x0C\x0D\x0E\x0F")
1125
1252
  end
1126
1253
 
1254
+ it "writes 67-bit unsigned integers" do
1255
+ BinaryAccessor.write(0x0F0E0D0C0B0A0900FF >> 5, 120, 67, :UINT, @data, :LITTLE_ENDIAN, :ERROR)
1256
+ expect(@data).to eql("\x00\x00\x00\x00\x00\x00\x00\xE0\x00\x09\x0A\x0B\x0C\x0D\x0E\x0F")
1257
+ end
1258
+
1259
+ it "writes 67-bit signed integers" do
1260
+ BinaryAccessor.write(0x0F0E0D0C0B0A0900FF >> 5, 120, 67, :INT, @data, :LITTLE_ENDIAN, :ERROR)
1261
+ expect(@data).to eql("\x00\x00\x00\x00\x00\x00\x00\xE0\x00\x09\x0A\x0B\x0C\x0D\x0E\x0F")
1262
+ end
1263
+
1127
1264
  it "writes aligned 64-bit unsigned integers" do
1128
1265
  expected_array = [0x8786858483828180, 0x0F0E0D0C0B0A0900]
1129
1266
  index = 0