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