From 9db4bdfda3214332f0070dba744fd05a92c9915c Mon Sep 17 00:00:00 2001 From: Jeffrey Phillips Freeman <jeffrey.freeman@syncleus.com> Date: Sat, 1 Oct 2016 14:26:30 -0400 Subject: [PATCH] Added test classes for AprsKiss, and fixed a few bugs. --- lib/aprs/aprs_kiss.rb | 58 +++++++++++++++++++-------------------- lib/kiss/constants.rb | 2 +- lib/kiss/kiss_abstract.rb | 14 +++++----- lib/kiss/kiss_serial.rb | 6 ++-- test/kiss_mock.rb | 41 +++++++++++++++++++++++++++ test/tc_aprs_kiss.rb | 56 +++++++++++++++++++++++++++++++++++++ test/tc_kiss.rb | 50 ++++----------------------------- 7 files changed, 143 insertions(+), 84 deletions(-) create mode 100644 test/kiss_mock.rb create mode 100644 test/tc_aprs_kiss.rb diff --git a/lib/aprs/aprs_kiss.rb b/lib/aprs/aprs_kiss.rb index 8433b6f..60f2716 100644 --- a/lib/aprs/aprs_kiss.rb +++ b/lib/aprs/aprs_kiss.rb @@ -1,7 +1,7 @@ require_relative '../kiss/constants' -module APRS - class APRSKiss +module Aprs + class AprsKiss protected def initialize(data_stream) @@ -20,13 +20,13 @@ module APRS if raw_frame[raw_slice] & 0x01 and ((raw_slice + 1) % 7) == 0 i = (raw_slice.to_f + 1.0) / 7.0 # Less than 2 callsigns? - if 1.0 < i < 11.0 + if 1.0 < i and i < 11.0 if raw_frame[raw_slice + 1] & 0x03 == 0x03 and [0xf0, 0xcf].include? raw_frame[raw_slice + 2] - text_as_array = raw_frame[raw_slice + 3..-1].map { |b| chr(b) } - frame['text'] = text_as_array.join - frame['destination'] = identity_as_string(extract_callsign(raw_frame)) - frame['source'] = identity_as_string(__extract_callsign(raw_frame[7..-1])) - frame['path'] = extract_path(i.to_i, raw_frame) + text_as_array = raw_frame[raw_slice + 3..-1].map { |b| b.chr } + frame[:text] = text_as_array.join + frame[:destination] = identity_as_string(extract_callsign(raw_frame)) + frame[:source] = identity_as_string(extract_callsign(raw_frame[7..-1])) + frame[:path] = extract_path(i.to_i, raw_frame) return frame end end @@ -55,36 +55,36 @@ module APRS private def self.extract_callsign(raw_frame) - callsign_as_array = raw_frame[0...6].map { |x| chr(x >> 1) } + callsign_as_array = raw_frame[0...6].map { |x| (x >> 1).chr } callsign = callsign_as_array.join.strip ssid = (raw_frame[6] >> 1) & 0x0f - return {'callsign': callsign, 'ssid': ssid} + return {:callsign => callsign, :ssid => ssid} end private def self.identity_as_string(identity) - if identity['ssid'] > 0 - return [identity['callsign'], identity['ssid'].to_s].join('-') + if identity[:ssid] + return [identity[:callsign], identity[:ssid].to_s].join('-') else - return identity['callsign'] + return identity[:callsign] end end private def self.encode_frame(frame) - enc_frame = encode_callsign(parse_identity_string(frame['destination'])) + encode_callsign(parse_identity_string(frame['source'])) - frame['path'].each do |p| + enc_frame = encode_callsign(parse_identity_string(frame[:destination])) + encode_callsign(parse_identity_string(frame[:source])) + frame[:path].each do |p| enc_frame += encode_callsign(parse_identity_string(p)) end - return enc_frame[0..-1] + [enc_frame[-1] | 0x01] + [KISS::SLOT_TIME] + [0xf0] + frame['text'].map { |c| ord(c) } + return enc_frame[0..-1] + [enc_frame[-1] | 0x01] + [Kiss::SLOT_TIME] + [0xf0] + frame[:text].chars.map { |c| c.ord } end private def self.encode_callsign(callsign) - call_sign = callsign['callsign'] + call_sign = callsign[:callsign] - enc_ssid = (callsign['ssid'] << 1) | 0x60 + enc_ssid = (callsign[:ssid] << 1) | 0x60 if call_sign.include? '*' call_sign.gsub!(/\*/,'') @@ -95,7 +95,7 @@ module APRS call_sign = [call_sign, ' '].join end - return call_sign.map { |p| ord(p) << 1 } + [enc_ssid] + return call_sign.chars.map { |p| p.ord << 1 } + [enc_ssid] end private @@ -112,7 +112,7 @@ module APRS ssid = 0 end - return {'callsign': call_sign, 'ssid': int(ssid)} + return {:callsign => call_sign, :ssid => ssid.to_i} end public @@ -125,24 +125,24 @@ module APRS @data_stream.close(*args, **kwargs) end - public - def write(frame, *args, **kwargs) - @lock.synchronize do - encoded_frame = encode_frame(frame) - @data_stream.write(encoded_frame, *args, **kwargs) - end - end - public def read(*args, **kwargs) @lock.synchronize do frame = @data_stream.read(*args, **kwargs) if frame&.length - return decode_frame(frame) + return AprsKiss.decode_frame(frame) else return nil end end end + + public + def write(frame, *args, **kwargs) + @lock.synchronize do + encoded_frame = AprsKiss.encode_frame(frame) + @data_stream.write(encoded_frame, *args, **kwargs) + end + end end end \ No newline at end of file diff --git a/lib/kiss/constants.rb b/lib/kiss/constants.rb index 2ebcfcb..371f358 100644 --- a/lib/kiss/constants.rb +++ b/lib/kiss/constants.rb @@ -1,4 +1,4 @@ -module KISS +module Kiss # KISS Special Characters # http://en.wikipedia.org/wiki/KISS_(TNC)#Special_Characters FEND = 0xC0 diff --git a/lib/kiss/kiss_abstract.rb b/lib/kiss/kiss_abstract.rb index 7ba7917..ede0cc0 100644 --- a/lib/kiss/kiss_abstract.rb +++ b/lib/kiss/kiss_abstract.rb @@ -2,8 +2,8 @@ require 'thread' require 'abstraction' require_relative 'constants' -module KISS - class KISSAbstract +module Kiss + class KissAbstract abstract protected @@ -113,7 +113,7 @@ module KISS new_frames.each do |new_frame| if new_frame.length > 0 and new_frame[0] == 0 if @strip_df_start - new_frame = KISSAbstract.strip_df_start(new_frame) + new_frame = KissAbstract.strip_df_start(new_frame) end @frame_buffer << new_frame end @@ -129,7 +129,7 @@ module KISS end public - def read + def read(*args, **kwargs) @lock.synchronize do if @frame_buffer.length == 0 fill_buffer @@ -146,10 +146,10 @@ module KISS end public - def write(frame_bytes, port=0) + def write(frame_bytes, port=0, *args, **kwargs) @lock.synchronize do - kiss_packet = [FEND] + [KISSAbstract.command_byte_combine(port, DATA_FRAME)] + - KISSAbstract.escape_special_codes(frame_bytes) + [FEND] + kiss_packet = [FEND] + [KissAbstract.command_byte_combine(port, DATA_FRAME)] + + KissAbstract.escape_special_codes(frame_bytes) + [FEND] write_interface(kiss_packet) end diff --git a/lib/kiss/kiss_serial.rb b/lib/kiss/kiss_serial.rb index c69468b..6b51996 100644 --- a/lib/kiss/kiss_serial.rb +++ b/lib/kiss/kiss_serial.rb @@ -1,8 +1,8 @@ require 'serialport' require_relative 'kiss_abstract' -module KISS - class KISSSerial < KISSAbstract +module Kiss + class KissSerial < KissAbstract DEFAULT_READ_BYTES = 1000 SERIAL_READ_TIMEOUT = -1 @@ -31,7 +31,7 @@ module KISS protected def read_interface read_data = @serial.read(@read_bytes) - read_data.map { |c| ord(c) } + read_data.map { |c| c.ord } end protected diff --git a/test/kiss_mock.rb b/test/kiss_mock.rb new file mode 100644 index 0000000..f585e4c --- /dev/null +++ b/test/kiss_mock.rb @@ -0,0 +1,41 @@ +require_relative '../lib/kiss/kiss_abstract' + +module Kiss + class KissMock < KissAbstract + + def initialize(strip_df_start=true) + super(strip_df_start) + @read_from_interface = [] + @sent_to_interface = [] + end + + protected + def read_interface + if @read_from_interface.length == 0 + return nil + end + return @read_from_interface.shift + end + + protected + def write_interface(data) + @sent_to_interface << data + end + + public + def clear_interface + @read_from_interface = [] + @sent_to_interface = [] + end + + public + def add_read_from_interface(raw_frame) + @read_from_interface << raw_frame + end + + public + def get_sent_to_interface + return @sent_to_interface + end + end +end \ No newline at end of file diff --git a/test/tc_aprs_kiss.rb b/test/tc_aprs_kiss.rb new file mode 100644 index 0000000..33a182c --- /dev/null +++ b/test/tc_aprs_kiss.rb @@ -0,0 +1,56 @@ +require 'test/unit' +require_relative 'kiss_mock' +require_relative '../lib/aprs/aprs_kiss' + +module Aprs + DECODED_FRAME_KISS = { + 'source': 'W2GMD-1', + 'destination': 'OMG', + 'path': ['WIDE1-1', 'WIDE2-2'], + 'text': 'test_encode_frame' + } + ENCODED_FRAME_KISS = [192, 0, 158, 154, 142, 64, 64, 64, 96, 174, 100, 142, 154, 136, 64, 98, 174, 146, 136, 138, 98, + 64, 98, 174, 146, 136, 138, 100, 64, 101, 3, 240, 116, 101, 115, 116, 95, 101, 110, 99, 111, 100, + 101, 95, 102, 114, 97, 109, 101, 192] + + DECODED_FRAME_KISS_INVALID = { + 'source': 'KG6WTF', + 'destination': 'S7TSUV', + 'path': ['MTOSO-2', 'WIDE2*' 'qAR', 'KF6FIR-10'], + 'text': '`17El#X-/kg6wtf@gosselinfamily.com' + } + ENCODED_FRAME_KISS_INVALID = [192, 0, 166, 110, 168, 166, 170, 172, 96, 150, 142, 108, 174, 168, 140, 96, 154, 168, 158, + 166, 158, 64, 100, 174, 146, 136, 138, 100, 226, 130, 164, 224, 150, 140, 108, 140, 146, 164, + 117, 3, 240, 96, 49, 55, 69, 108, 35, 88, 45, 47, 107, 103, 54, 119, 116, 102, 64, 103, 111, + 115, 115, 101, 108, 105, 110, 102, 97, 109, 105, 108, 121, 46, 99, 111, 109, 192] + + class TestKiss < Test::Unit::TestCase + def test_read + kiss_mock = Kiss::KissMock.new + aprs_kiss = AprsKiss.new(kiss_mock) + + kiss_mock.clear_interface + kiss_mock.add_read_from_interface(ENCODED_FRAME_KISS) + translated_frame = nil + iter_left = 1000 + while iter_left > 0 and not translated_frame + translated_frame = aprs_kiss.read + iter_left -= 1 + end + + assert_equal DECODED_FRAME_KISS, translated_frame + end + + def test_write + kiss_mock = Kiss::KissMock.new + aprs_kiss = AprsKiss.new(kiss_mock) + + kiss_mock.clear_interface + aprs_kiss.write(DECODED_FRAME_KISS) + + all_raw_frames = kiss_mock.get_sent_to_interface + + assert_equal ENCODED_FRAME_KISS, all_raw_frames[0] + end + end +end \ No newline at end of file diff --git a/test/tc_kiss.rb b/test/tc_kiss.rb index 329bccb..3a27e2d 100644 --- a/test/tc_kiss.rb +++ b/test/tc_kiss.rb @@ -1,7 +1,7 @@ require 'test/unit' -require_relative '../lib/kiss/kiss_abstract' +require_relative 'kiss_mock' -module KISS +module Kiss # KG6WTF>S7TSUV,MTOSO-2,WIDE2*,qAR,KF6FIR-10:`17El#X-/kg6wtf@gosselinfamily.com ENCODED_FRAME = [192, 0, 75, 71, 54, 87, 84, 70, 62, 83, 55, 84, 83, 85, 86, 44, 77, 84, 79, 83, 79, 45, 50, 44, 87, 73, 68, 69, 50, 42, 44, 113, 65, 82, 44, 75, 70, 54, 70, 73, 82, 45, 49, 48, 58, 96, 49, 55, 69, 108, 35, @@ -12,61 +12,23 @@ module KISS 88, 45, 47, 107, 103, 54, 119, 116, 102, 64, 103, 111, 115, 115, 101, 108, 105, 110, 102, 97, 109, 105, 108, 121, 46, 99, 111, 109] - class KISSMock < KISSAbstract - - def initialize(strip_df_start=true) - super(strip_df_start) - @read_from_interface = [] - @sent_to_interface = [] - end - - protected - def read_interface - if @read_from_interface.length == 0 - return nil - end - return @read_from_interface.shift - end - - protected - def write_interface(data) - @sent_to_interface << data - end - - public - def clear_interface - @read_from_interface = [] - @sent_to_interface = [] - end - - public - def add_read_from_interface(raw_frame) - @read_from_interface << raw_frame - end - - public - def get_sent_to_interface - return @sent_to_interface - end - end - - class TestKISS < Test::Unit::TestCase + class TestKiss < Test::Unit::TestCase def test_read - kiss_mock = KISSMock.new + kiss_mock = KissMock.new kiss_mock.add_read_from_interface(ENCODED_FRAME) translated_frame = kiss_mock.read assert_equal DECODED_FRAME, translated_frame end def test_write - kiss_mock = KISSMock.new + kiss_mock = KissMock.new kiss_mock.write(DECODED_FRAME) all_raw_frames = kiss_mock.get_sent_to_interface assert_equal ENCODED_FRAME, all_raw_frames[0] end def test_new_abstract_kiss - assert_raise(AbstractClassError) { KISSAbstract.new } + assert_raise(AbstractClassError) { KissAbstract.new } end end end \ No newline at end of file -- GitLab