cosmos 3.3.3 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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