Use read_nonblock instead of readpartial to account for SSL socket buffer
diff --git a/lib/rb/spec/socket_spec_shared.rb b/lib/rb/spec/socket_spec_shared.rb
index 2015ac0..163d0c2 100644
--- a/lib/rb/spec/socket_spec_shared.rb
+++ b/lib/rb/spec/socket_spec_shared.rb
@@ -74,31 +74,94 @@
   it "should support the timeout accessor for read" do
     @socket.timeout = 3
     @socket.open
-    expect(IO).to receive(:select).with([@handle], nil, nil, 3).and_return([[@handle], [], []])
-    expect(@handle).to receive(:readpartial).with(17).and_return("test data")
+    expect(@handle).to receive(:read_nonblock).with(17).and_raise(IO::EAGAINWaitReadable)
+    expect(IO).to receive(:select) do |rd, wr, err, timeout|
+      expect(rd).to eq([@handle])
+      expect(wr).to be_nil
+      expect(err).to be_nil
+      expect(timeout).to be > 0
+      expect(timeout).to be <= 3
+      [[@handle], [], []]
+    end
+    expect(@handle).to receive(:read_nonblock).with(17).and_return("test data")
     expect(@socket.read(17)).to eq("test data")
   end
 
   it "should support the timeout accessor for write" do
     @socket.timeout = 3
     @socket.open
-    expect(IO).to receive(:select).with(nil, [@handle], nil, 3).twice.and_return([[], [@handle], []])
-    expect(@handle).to receive(:write_nonblock).with("test data").and_return(4)
-    expect(@handle).to receive(:write_nonblock).with(" data").and_return(5)
+    write_calls = 0
+    expect(@handle).to receive(:write_nonblock).exactly(3).times do |chunk|
+      write_calls += 1
+      case write_calls
+      when 1
+        expect(chunk).to eq("test data")
+        raise IO::EAGAINWaitWritable
+      when 2
+        expect(chunk).to eq("test data")
+        4
+      when 3
+        expect(chunk).to eq(" data")
+        5
+      end
+    end
+    expect(IO).to receive(:select) do |rd, wr, err, timeout|
+      expect(rd).to be_nil
+      expect(wr).to eq([@handle])
+      expect(err).to be_nil
+      expect(timeout).to be > 0
+      expect(timeout).to be <= 3
+      [[], [@handle], []]
+    end
     expect(@socket.write("test data")).to eq(9)
   end
 
   it "should raise an error when read times out" do
     @socket.timeout = 0.5
     @socket.open
-    expect(IO).to receive(:select).once {sleep(0.5); nil}
+    expect(@handle).to receive(:read_nonblock).with(17).and_raise(IO::EAGAINWaitReadable)
+    expect(IO).to receive(:select).once { sleep(0.6); nil }
     expect { @socket.read(17) }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::TIMED_OUT) }
   end
 
   it "should raise an error when write times out" do
     @socket.timeout = 0.5
     @socket.open
-    allow(IO).to receive(:select).with(nil, [@handle], nil, 0.5).and_return(nil)
+    expect(@handle).to receive(:write_nonblock).with("test data").and_raise(IO::EAGAINWaitWritable)
+    expect(IO).to receive(:select).once { sleep(0.6); nil }
     expect { @socket.write("test data") }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::TIMED_OUT) }
   end
+
+  it "should read buffered SSL data without waiting on the raw socket again" do
+    @socket.timeout = 1
+    @socket.open
+
+    expect(@handle).to receive(:read_nonblock).with(4).ordered.and_raise(IO::EAGAINWaitReadable)
+    expect(IO).to receive(:select).once.ordered do |rd, wr, err, timeout|
+      expect(rd).to eq([@handle])
+      expect(wr).to be_nil
+      expect(err).to be_nil
+      expect(timeout).to be > 0
+      expect(timeout).to be <= 1
+      [[@handle], [], []]
+    end
+    expect(@handle).to receive(:read_nonblock).with(4).ordered.and_return("ABCD")
+    expect(@handle).to receive(:read_nonblock).with(5).ordered.and_return("12345")
+
+    expect(@socket.read(4)).to eq("ABCD")
+    expect(@socket.read(5)).to eq("12345")
+  end
+
+  it "should read without timeout using the blocking path" do
+    @socket.timeout = nil
+    @socket.open
+
+    expect(IO).not_to receive(:select)
+    expect(@handle).not_to receive(:read_nonblock)
+    expect(@handle).to receive(:readpartial).with(4).ordered.and_return("ABCD")
+    expect(@handle).to receive(:readpartial).with(5).ordered.and_return("12345")
+
+    expect(@socket.read(4)).to eq("ABCD")
+    expect(@socket.read(5)).to eq("12345")
+  end
 end