Skip to content

Commit

Permalink
test: added some Processor tests
Browse files Browse the repository at this point in the history
Also: added debug data for various errors (DATA, PING, WINDOW_UPDATE)
  • Loading branch information
hpopp committed May 13, 2018
1 parent f31c00d commit a9c98b2
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 11 deletions.
4 changes: 2 additions & 2 deletions lib/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,12 @@ defmodule Kadabra.Connection do
{:ok, state} ->
{:noreply, [], state}

{:connection_error, error, state} ->
{:connection_error, error, reason, state} ->
code = Error.code(error)

bin =
state.flow_control.stream_set.stream_id
|> Goaway.new(code)
|> Goaway.new(code, reason)
|> Encodable.to_bin()

Socket.send(config.socket, bin)
Expand Down
20 changes: 12 additions & 8 deletions lib/connection/processor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ defmodule Kadabra.Connection.Processor do
| Continuation.t()

@spec process(frame, Connection.t()) ::
{:ok, Connection.t()} | {:connection_error, atom, Connection.t()}
{:ok, Connection.t()}
| {:connection_error, atom, binary, Connection.t()}
def process(bin, state) when is_binary(bin) do
Logger.info("Got binary: #{inspect(bin)}")
state
end

def process(%Data{stream_id: 0}, state) do
# This is an error
{:ok, state}
reason = "Recv DATA with stream ID of 0"
{:connection_error, :PROTOCOL_ERROR, reason, state}
end

def process(%Data{stream_id: stream_id} = frame, %{config: config} = state) do
Expand All @@ -70,7 +71,7 @@ defmodule Kadabra.Connection.Processor do
{:ok, state}

{:connection_error, error} ->
{:connection_error, error, state}
{:connection_error, error, nil, state}
end
end

Expand Down Expand Up @@ -163,11 +164,13 @@ defmodule Kadabra.Connection.Processor do
end

def process(%Ping{stream_id: sid}, state) when sid != 0 do
{:connection_error, :PROTOCOL_ERROR, state}
reason = "Recv PING with stream ID of #{sid}"
{:connection_error, :PROTOCOL_ERROR, reason, state}
end

def process(%Ping{data: data}, state) when byte_size(data) != 8 do
{:connection_error, :FRAME_SIZE_ERROR, state}
reason = "Recv PING with payload of #{byte_size(data)} bytes"
{:connection_error, :FRAME_SIZE_ERROR, reason, state}
end

def process(%Ping{ack: false}, %{config: config} = state) do
Expand All @@ -182,12 +185,13 @@ defmodule Kadabra.Connection.Processor do

def process(%Goaway{} = frame, state) do
log_goaway(frame)
{:connection_error, :NO_ERROR, state}
{:connection_error, :NO_ERROR, nil, state}
end

def process(%WindowUpdate{stream_id: 0, window_size_increment: inc}, state)
when inc <= 0 do
{:connection_error, :PROTOCOL_ERROR, state}
reason = "Recv WINDOW_UPDATE with increment of #{inc}"
{:connection_error, :PROTOCOL_ERROR, reason, state}
end

def process(%WindowUpdate{stream_id: 0, window_size_increment: inc}, state) do
Expand Down
7 changes: 6 additions & 1 deletion lib/frame/goaway.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,14 @@ defmodule Kadabra.Frame.Goaway do
end

def new(stream_id, error_code) when is_integer(stream_id) do
new(stream_id, error_code, nil)
end

def new(stream_id, error_code, reason) when is_integer(stream_id) do
%__MODULE__{
last_stream_id: stream_id,
error_code: error_code
error_code: error_code,
debug_data: reason
}
end
end
Expand Down
3 changes: 3 additions & 0 deletions lib/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ defmodule Kadabra.Request do
Useful when queueing multiple requests at once through
`Kadabra.request/2`
"""

defstruct headers: [], body: nil, on_response: nil

alias Kadabra.Stream.Response

@type t :: %__MODULE__{
headers: [],
body: binary,
Expand Down
51 changes: 51 additions & 0 deletions test/connection/processor_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
defmodule Kadabra.Connection.ProcessorTest do
use ExUnit.Case

alias Kadabra.Connection
alias Kadabra.Connection.Processor
alias Kadabra.Frame.{Data, Ping, WindowUpdate}

defp conn do
%Connection{
config: %{
client: self()
},
flow_control: %Connection.FlowControl{}
}
end

test "throws connection error on non-zero DATA stream_id" do
bad = %Data{stream_id: 0}

assert {:connection_error, :PROTOCOL_ERROR, _, _} =
Processor.process(bad, conn())
end

describe "process PING" do
test "throws connection error on non-zero stream_id" do
bad = %Ping{stream_id: 1}

assert {:connection_error, :PROTOCOL_ERROR, _, _} =
Processor.process(bad, conn())
end

test "throws connection error if payload not 8 bytes" do
bad = %Ping{data: <<0, 1>>}

assert {:connection_error, :FRAME_SIZE_ERROR, _, _} =
Processor.process(bad, conn())
end
end

describe "process WINDOW_UPDATE" do
test "throws connection error zero or negative increment" do
bad = %WindowUpdate{window_size_increment: 0, stream_id: 0}
bad_2 = %WindowUpdate{window_size_increment: -5, stream_id: 0}

for b <- [bad, bad_2] do
assert {:connection_error, :PROTOCOL_ERROR, _, _} =
Processor.process(b, conn())
end
end
end
end

0 comments on commit a9c98b2

Please sign in to comment.