Skip to content

Commit

Permalink
test: add tests that passes data through Plug.Parsers (#16)
Browse files Browse the repository at this point in the history
* test: add tests that passes data through Plug.Parsers

This also adds tests for `identity` content encoding and for situation
when there is no content encoding header at all.

* fix: handle duplicated headers
  • Loading branch information
hauleth authored Jan 4, 2024
1 parent 9167b8e commit 4c4a19f
Show file tree
Hide file tree
Showing 12 changed files with 418 additions and 67 deletions.
1 change: 1 addition & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Used by "mix format"
[
import_deps: [:stream_data],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
3 changes: 3 additions & 0 deletions lib/plug_caisson.ex
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ defmodule PlugCaisson do
_ ->
{:error, :not_supported}
end

[_ | _] ->
{:error, :not_supported}
end
end

Expand Down
6 changes: 5 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ defmodule PlugCaisson.MixProject do
start_permanent: Mix.env() == :prod,
deps: deps(),
package: package(),
test_coverage: [
ignore_modules: [TestUtils]
],
docs: [
extras: ~w[README.md],
main: "readme",
Expand Down Expand Up @@ -38,7 +41,8 @@ defmodule PlugCaisson.MixProject do
{:ezstd, "~> 1.0", optional: true},
{:jason, ">= 0.0.0", only: [:dev, :test]},
{:ex_doc, ">= 0.0.0", only: [:dev]},
{:credo, ">= 0.0.0", only: [:dev, :test]}
{:credo, ">= 0.0.0", only: [:dev, :test]},
{:stream_data, "~> 0.6.0", only: [:dev, :test]}
]
end

Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"plug": {:hex, :plug, "1.15.2", "94cf1fa375526f30ff8770837cb804798e0045fd97185f0bb9e5fcd858c792a3", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02731fa0c2dcb03d8d21a1d941bdbbe99c2946c0db098eee31008e04c6283615"},
"plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"},
"stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
}
40 changes: 40 additions & 0 deletions test/plug_caisson/brotli_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
defmodule PlugCaisson.BrotliTest do
use ExUnit.Case, async: true
use Plug.Test
use ExUnitProperties

import TestUtils

Expand Down Expand Up @@ -27,6 +29,44 @@ defmodule PlugCaisson.BrotliTest do
assert raw == Enum.join(body_stream(conn, length: 10))
end

property "data is returned as is" do
check all raw <- binary() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end
end

property "length can be set to custom value" do
check all raw <- binary(),
length <- positive_integer() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn, length: length))
end
end

test "Plug.Parser" do
pipeline =
pipeline([
{Plug.Parsers,
parsers: [:json], json_decoder: Jason, body_reader: {PlugCaisson, :read_body, []}},
{&echo_plug/2, encoder: &Jason.encode!/1}
])

value = for _i <- 1..2000, do: %{"hello" => "world"}
payload = compress(Jason.encode!(value))

assert {200, _, body} =
post({"application/json", payload}, @content_type)
|> pipeline.()
|> sent_resp()

assert {:ok, %{"_json" => [%{"hello" => "world"} | _]}} = Jason.decode(body)
end

describe "corpus tests" do
for {path, content} <- corpus() do
test "#{path}" do
Expand Down
40 changes: 40 additions & 0 deletions test/plug_caisson/deflate_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
defmodule PlugCaisson.DeflateTest do
use ExUnit.Case, async: true
use Plug.Test
use ExUnitProperties

import TestUtils

Expand All @@ -24,6 +26,44 @@ defmodule PlugCaisson.DeflateTest do
assert raw == Enum.join(body_stream(conn, length: 10))
end

property "data is returned as is" do
check all raw <- binary() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end
end

property "length can be set to custom value" do
check all raw <- binary(),
length <- positive_integer() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn, length: length))
end
end

test "Plug.Parser" do
pipeline =
pipeline([
{Plug.Parsers,
parsers: [:json], json_decoder: Jason, body_reader: {PlugCaisson, :read_body, []}},
{&echo_plug/2, encoder: &Jason.encode!/1}
])

value = for _i <- 1..2000, do: %{"hello" => "world"}
payload = compress(Jason.encode!(value))

assert {200, _, body} =
post({"application/json", payload}, @content_type)
|> pipeline.()
|> sent_resp()

assert {:ok, %{"_json" => [%{"hello" => "world"} | _]}} = Jason.decode(body)
end

describe "corpus tests" do
for {path, content} <- corpus() do
test "#{path}" do
Expand Down
40 changes: 40 additions & 0 deletions test/plug_caisson/gzip_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
defmodule PlugCaisson.GzipTest do
use ExUnit.Case, async: true
use Plug.Test
use ExUnitProperties

import TestUtils

Expand All @@ -24,13 +26,51 @@ defmodule PlugCaisson.GzipTest do
assert raw == Enum.join(body_stream(conn, length: 10))
end

property "data is returned as is" do
check all raw <- binary() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end
end

property "length can be set to custom value" do
check all raw <- binary(),
length <- positive_integer() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn, length: length))
end
end

test "when hit lenght limit it do not decompress further, even with zipbomb" do
data = File.read!(Path.join(__DIR__, "gzip_test/bomb.gz"))
conn = post(data, @content_type)

assert {:more, _, _} = PlugCaisson.read_body(conn)
end

test "Plug.Parser" do
pipeline =
pipeline([
{Plug.Parsers,
parsers: [:json], json_decoder: Jason, body_reader: {PlugCaisson, :read_body, []}},
{&echo_plug/2, encoder: &Jason.encode!/1}
])

value = for _i <- 1..2000, do: %{"hello" => "world"}
payload = compress(Jason.encode!(value))

assert {200, _, body} =
post({"application/json", payload}, @content_type)
|> pipeline.()
|> sent_resp()

assert {:ok, %{"_json" => [%{"hello" => "world"} | _]}} = Jason.decode(body)
end

describe "corpus tests" do
for {path, content} <- corpus() do
test "#{path}" do
Expand Down
78 changes: 78 additions & 0 deletions test/plug_caisson/identity_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
defmodule PlugCaisson.IdentityTest do
use ExUnit.Case, async: true
use Plug.Test
use ExUnitProperties

import TestUtils

@content_type "identity"

defp compress(data), do: data

test "simple test" do
raw = "Chrzęszczyrzewoszyckie chrząszcze chrobotliwie chrzeszczą w haszczach"
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end

test "partial inflation" do
raw = "Chrzęszczyrzewoszyckie chrząszcze chrobotliwie chrzeszczą w haszczach"

data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn, length: 10))
end

property "data is returned as is" do
check all raw <- binary() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end
end

property "length can be set to custom value" do
check all raw <- binary(),
length <- positive_integer() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn, length: length))
end
end

test "Plug.Parser" do
pipeline =
pipeline([
{Plug.Parsers,
parsers: [:json], json_decoder: Jason, body_reader: {PlugCaisson, :read_body, []}},
{&echo_plug/2, encoder: &Jason.encode!/1}
])

value = for _i <- 1..2000, do: %{"hello" => "world"}
payload = compress(Jason.encode!(value))

assert {200, _, body} =
post({"application/json", payload}, @content_type)
|> pipeline.()
|> sent_resp()

assert {:ok, %{"_json" => [%{"hello" => "world"} | _]}} = Jason.decode(body)
end

describe "corpus tests" do
for {path, content} <- corpus() do
test "#{path}" do
raw = unquote(content)
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end
end
end
end
78 changes: 78 additions & 0 deletions test/plug_caisson/no_header_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
defmodule PlugCaisson.NoHeaderTest do
use ExUnit.Case, async: true
use Plug.Test
use ExUnitProperties

import TestUtils

@content_type nil

defp compress(data), do: data

test "simple test" do
raw = "Chrzęszczyrzewoszyckie chrząszcze chrobotliwie chrzeszczą w haszczach"
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end

test "partial inflation" do
raw = "Chrzęszczyrzewoszyckie chrząszcze chrobotliwie chrzeszczą w haszczach"

data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn, length: 10))
end

property "data is returned as is" do
check all raw <- binary() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end
end

property "length can be set to custom value" do
check all raw <- binary(),
length <- positive_integer() do
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn, length: length))
end
end

test "Plug.Parser" do
pipeline =
pipeline([
{Plug.Parsers,
parsers: [:json], json_decoder: Jason, body_reader: {PlugCaisson, :read_body, []}},
{&echo_plug/2, encoder: &Jason.encode!/1}
])

value = for _i <- 1..2000, do: %{"hello" => "world"}
payload = compress(Jason.encode!(value))

assert {200, _, body} =
post({"application/json", payload}, @content_type)
|> pipeline.()
|> sent_resp()

assert {:ok, %{"_json" => [%{"hello" => "world"} | _]}} = Jason.decode(body)
end

describe "corpus tests" do
for {path, content} <- corpus() do
test "#{path}" do
raw = unquote(content)
data = compress(raw)
conn = post(data, @content_type)

assert raw == Enum.join(body_stream(conn))
end
end
end
end
Loading

0 comments on commit 4c4a19f

Please sign in to comment.