From 595a98eeccbdbb528b2a3a62b14e7e0777ea7e1c Mon Sep 17 00:00:00 2001
From: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Date: Tue, 15 Aug 2023 21:29:12 -0400
Subject: [PATCH] Added some specs for KissSerial

---
 lib/kiss/kiss_abstract.rb     |   2 +-
 spec/kiss/kiss_serial_spec.rb | 159 ++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+), 1 deletion(-)
 create mode 100644 spec/kiss/kiss_serial_spec.rb

diff --git a/lib/kiss/kiss_abstract.rb b/lib/kiss/kiss_abstract.rb
index 914e148..fd96b61 100644
--- a/lib/kiss/kiss_abstract.rb
+++ b/lib/kiss/kiss_abstract.rb
@@ -265,7 +265,7 @@ module Kiss
 
         protected
         def write_setting(command, value)
-            write_interface([FEND] + [command] + escape_special_codes(value) + [FEND])
+            write_interface([FEND] + [command] + KissAbstract.escape_special_codes(value) + [FEND])
         end
 
         public
diff --git a/spec/kiss/kiss_serial_spec.rb b/spec/kiss/kiss_serial_spec.rb
new file mode 100644
index 0000000..4e8e6e2
--- /dev/null
+++ b/spec/kiss/kiss_serial_spec.rb
@@ -0,0 +1,159 @@
+require_relative '../../lib/kiss'
+require 'abstractify'
+require 'serialport'
+
+ENCODED_FRAME = [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 = {
+                  :source => "W2GMD-1",
+                  :destination => "OMG",
+                  :payload => "test_encode_frame",
+                  :path => ['WIDE1-1', 'WIDE2-2']
+                }
+
+describe Kiss::KissSerial do
+
+  describe ".new" do
+    context "Given valid arguments" do
+      it "is successfully instantiated" do
+        kiss_serial = Kiss::KissSerial.new("/dev/ttyUSB-scs")
+        expect(kiss_serial).to_not be_nil
+      end
+    end
+  end
+
+  describe ".connect" do
+    context "Given nil for mode_init, and no kwargs/extra arguments" do
+      let( :serial_port ) { double(SerialPort) }
+      let( :kiss_serial ) { Kiss::KissSerial.new("/dev/ttyUSB-scs") }
+      it "sets read_timeout on underlying serial port" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        expect(serial_port).to receive(:read_timeout=).with(-1).once
+        kiss_serial.connect
+      end
+      it "does not call write_interface" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=).with(-1).once
+        expect(kiss_serial).to_not receive(:write_interface)
+        kiss_serial.connect
+      end
+      it "does not call write_setting" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=).with(-1).once
+        expect(kiss_serial).to_not receive(:write_setting)
+        kiss_serial.connect
+      end
+    end
+
+    context "Given an arbitrary string for mode_init, and no kwargs/extra arguments" do
+      let( :serial_port ) { double(SerialPort) }
+      let( :kiss_serial ) { Kiss::KissSerial.new("/dev/ttyUSB-scs") }
+      it "sets read_timeout on underlying serial port" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        expect(serial_port).to receive(:read_timeout=).with(-1).once
+        allow(serial_port).to receive(:write).with(Kiss::MODE_INIT_W8DED.map { |b| b.chr }.join)
+        kiss_serial.connect(Kiss::MODE_INIT_W8DED)
+      end
+      it "calls write_interface" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=).with(-1).once
+        expect(kiss_serial).to receive(:write_interface)
+        allow(serial_port).to receive(:write).with(Kiss::MODE_INIT_W8DED.map { |b| b.chr }.join)
+        kiss_serial.connect(Kiss::MODE_INIT_W8DED)
+      end
+      it "calls write_setting" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=).with(-1).once
+        expect(kiss_serial).to_not receive(:write_setting)
+        allow(serial_port).to receive(:write).with(Kiss::MODE_INIT_W8DED.map { |b| b.chr }.join)
+        kiss_serial.connect(Kiss::MODE_INIT_W8DED)
+      end
+      it "calls write on underlying serial device with proper values" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=).with(-1).once
+        expect(serial_port).to receive(:write).with(Kiss::MODE_INIT_W8DED.map { |b| b.chr }.join).once
+        kiss_serial.connect(Kiss::MODE_INIT_W8DED)
+      end
+    end
+  end
+
+  describe ".close" do
+    context "Given an underlying connection with mode_init set" do
+      let( :serial_port ) { double(SerialPort) }
+      let( :kiss_serial ) { Kiss::KissSerial.new("/dev/ttyUSB-scs") }
+
+      it "ends KISS mode" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=)
+        allow(serial_port).to receive(:write).with(Kiss::MODE_INIT_W8DED.map { |b| b.chr }.join)
+        kiss_serial.connect(Kiss::MODE_INIT_W8DED)
+
+        allow(serial_port).to receive(:closed?).and_return(false)
+        allow(serial_port).to receive(:close)
+        expect(serial_port).to receive(:write).with(Kiss::MODE_END.map { |b| b.chr }.join)
+        kiss_serial.close
+      end
+
+      it "closes underlying serial port" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=)
+        allow(serial_port).to receive(:write).with(Kiss::MODE_INIT_W8DED.map { |b| b.chr }.join)
+        kiss_serial.connect(Kiss::MODE_INIT_W8DED)
+
+        allow(serial_port).to receive(:closed?).and_return(false)
+        expect(serial_port).to receive(:close)
+        allow(serial_port).to receive(:write).with(Kiss::MODE_END.map { |b| b.chr }.join)
+        kiss_serial.close
+      end
+    end
+
+    context "Given an underlying connection without mode_init set" do
+      let( :serial_port ) { double(SerialPort) }
+      let( :kiss_serial ) { Kiss::KissSerial.new("/dev/ttyUSB-scs") }
+
+      it "does not attempt to exit KISS mode" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=)
+        kiss_serial.connect
+
+        allow(serial_port).to receive(:closed?).and_return(false)
+        allow(serial_port).to receive(:close)
+        expect(serial_port).to_not receive(:write)
+        kiss_serial.close
+      end
+
+      it "closes underlying serial port" do
+        allow( SerialPort ).to receive(:new).and_return(serial_port)
+        allow(serial_port).to receive(:read_timeout=)
+        kiss_serial.connect
+
+        allow(serial_port).to receive(:closed?).and_return(false)
+        expect(serial_port).to receive(:close)
+        kiss_serial.close
+      end
+    end
+  end
+
+  # describe ".read" do
+  #   context "Given an encoded frame as bytes on the underlying interface" do
+  #     let(:kiss_mock) {KissMock.new}
+  #     it "successfully decoded and parsed the frame" do
+  #       kiss_mock.add_read_from_interface(ENCODED_FRAME)
+  #       translated_frame = kiss_mock.read
+  #       expect(translated_frame).to eql(DECODED_FRAME)
+  #     end
+  #   end
+  # end
+  #
+  # describe ".write" do
+  #   context "Given a decoded frame" do
+  #     let(:kiss_mock) {KissMock.new}
+  #     it "successfully encodes to the underlying interface" do
+  #       kiss_mock.write(DECODED_FRAME)
+  #       all_raw_frames = kiss_mock.get_sent_to_interface
+  #       expect(all_raw_frames[0]).to eql(ENCODED_FRAME)
+  #     end
+  #   end
+  # end
+
+end
-- 
GitLab