Skip to content

Commit

Permalink
Merge d8c762a into 527fca2
Browse files Browse the repository at this point in the history
  • Loading branch information
gausby committed Aug 26, 2018
2 parents 527fca2 + d8c762a commit 6b7aa14
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 11 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## [Unreleased]

### Fixed

- As according to the specification, an unsubscribe package can no
longer be encoded if it has no topic filters defined.

## 0.8.1 - 2018-08-25

### Added
Expand Down
20 changes: 11 additions & 9 deletions lib/tortoise/package/subscribe.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,14 @@ defmodule Tortoise.Package.Subscribe do

# PROTOCOLS ==========================================================
defimpl Tortoise.Encodable do
def encode(%Package.Subscribe{identifier: identifier} = t)
when identifier in 0x0001..0xFFFF do
def encode(
%Package.Subscribe{
identifier: identifier,
# a valid subscribe package has at least one topic/qos pair
topics: [{<<_topic_filter::binary>>, qos} | _]
} = t
)
when identifier in 0x0001..0xFFFF and qos in 0..2 do
[
Package.Meta.encode(t.__META__),
Package.variable_length_encode([
Expand Down Expand Up @@ -87,13 +93,9 @@ defmodule Tortoise.Package.Subscribe do
{Enum.into(topics, %{}),
fn
acc, {:cont, {<<topic::binary>>, qos}} when qos in 0..2 ->
Map.update(acc, topic, qos, fn
current_qos when qos > current_qos ->
qos

current_qos ->
current_qos
end)
# if a topic filter repeat in the input we will pick the
# biggest one
Map.update(acc, topic, qos, &max(&1, qos))

acc, {:cont, <<topic::binary>>} ->
Map.put_new(acc, topic, 0)
Expand Down
8 changes: 7 additions & 1 deletion lib/tortoise/package/unsubscribe.ex
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ defmodule Tortoise.Package.Unsubscribe do

# Protocols ----------------------------------------------------------
defimpl Tortoise.Encodable do
def encode(%Package.Unsubscribe{identifier: identifier} = t)
def encode(
%Package.Unsubscribe{
identifier: identifier,
# a valid unsubscribe package has at least one topic filter
topics: [_topic_filter | _]
} = t
)
when identifier in 0x0001..0xFFFF do
[
Package.Meta.encode(t.__META__),
Expand Down
2 changes: 1 addition & 1 deletion test/test_helper.exs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ defmodule Tortoise.TestGenerators do
def gen_unsubscribe() do
let unsubscribe <- %Package.Unsubscribe{
identifier: gen_identifier(),
topics: list(gen_topic_filter())
topics: non_empty(list(gen_topic_filter()))
} do
unsubscribe
end
Expand Down
17 changes: 17 additions & 0 deletions test/tortoise/package/subscribe_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defmodule Tortoise.Package.SubscribeTest do
import Tortoise.TestGenerators, only: [gen_subscribe: 0]

alias Tortoise.Package
alias Tortoise.Package.Subscribe

property "encoding and decoding subscribe messages" do
forall subscribe <- gen_subscribe() do
Expand All @@ -17,4 +18,20 @@ defmodule Tortoise.Package.SubscribeTest do
)
end
end

describe "Collectable" do
test "Pick the largest QoS when topic filters repeat in input" do
topic_filters = [{"a", 2}, {"a", 1}, {"a", 0}]
assert %Subscribe{topics: [{"a", 2}]} = Enum.into(topic_filters, %Subscribe{})

topic_filters = [{"a", 0}, {"a", 1}, {"a", 2}]
assert %Subscribe{topics: [{"a", 2}]} = Enum.into(topic_filters, %Subscribe{})

topic_filters = [{"a", 1}, {"a", 0}]
assert %Subscribe{topics: [{"a", 1}]} = Enum.into(topic_filters, %Subscribe{})

topic_filters = [{"a", 0}, {"a", 0}]
assert %Subscribe{topics: [{"a", 0}]} = Enum.into(topic_filters, %Subscribe{})
end
end
end

0 comments on commit 6b7aa14

Please sign in to comment.