Skip to content

Commit

Permalink
more tests. 100% coverage!!
Browse files Browse the repository at this point in the history
  • Loading branch information
alextwoods committed Aug 9, 2024
1 parent 4010658 commit b6fc12f
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 49 deletions.
21 changes: 2 additions & 19 deletions hearth/lib/hearth/event_stream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,8 @@
module Hearth
# Module for EventStreams.
module EventStream
# Raised when reading bytes exceed buffer total bytes
class ReadBytesExceedLengthError < RuntimeError; end
class MessageDecodeError < StandardError; end

# Raised when insufficient bytes of a message is received
class IncompleteMessageError < RuntimeError; end

# Raised when there is a prelude checksum mismatch.
class PreludeChecksumError < RuntimeError; end

# Raised when there is a message checksum mismatch.
class MessageChecksumError < RuntimeError; end

# Raised when an event payload exceeds the maximum allowed length.
class EventPayloadLengthExceedError < RuntimeError; end

# Raised when event headers exceed maximum allowed length.
class EventHeadersLengthExceedError < RuntimeError; end

# Raised when event streams parsers encounter are unable to parse a message.
class EventStreamParserError < RuntimeError; end
class MessageEncodeError < StandardError; end
end
end
22 changes: 4 additions & 18 deletions hearth/lib/hearth/event_stream/binary/message_decoder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def decode_message(raw_message)
def validate_checksum!(prelude, content, checksum)
return if Zlib.crc32([prelude, content].pack('a*a*'), 0) == checksum

raise MessageChecksumError
raise MessageDecodeError, 'Message checksum mismatch'
end

def decode_prelude(prelude)
Expand All @@ -80,7 +80,9 @@ def decode_prelude(prelude)
content, checksum = prelude.unpack(
"a#{PRELUDE_LENGTH - CRC32_LENGTH}N"
)
raise PreludeChecksumError unless Zlib.crc32(content, 0) == checksum
unless Zlib.crc32(content, 0) == checksum
raise MessageDecodeError, 'Prelude checksum mismatch'
end

content.unpack('N*')
end
Expand Down Expand Up @@ -137,24 +139,8 @@ def extract_header_value(scanner, unpack_pattern, value_length)
# rubocop:enable Metrics

def extract_payload(encoded)
if encoded.bytesize <= ONE_MEGABYTE
payload_stringio(encoded)
else
payload_tempfile(encoded)
end
end

def payload_stringio(encoded)
StringIO.new(encoded)
end

def payload_tempfile(encoded)
payload = Tempfile.new
payload.binmode
payload.write(encoded)
payload.rewind
payload
end
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions hearth/lib/hearth/event_stream/binary/message_encoder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def encode_headers(headers)

def encode_content(message, encoded_header)
if message.payload.length > MAX_PAYLOAD_LENGTH
raise EventPayloadLengthExceedError
raise MessageEncodeError, 'Payload exceeds maximum payload length'
end

header_length = encoded_header.bytesize
Expand Down Expand Up @@ -102,7 +102,7 @@ def validate_and_join!(header_entries)
break encoded_header
end

raise EventHeadersLengthExceedError
raise MessageEncodeError, 'Encoded headers exceed maximum length'
end
end

Expand Down
4 changes: 3 additions & 1 deletion hearth/lib/hearth/event_stream/binary/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ module Types

def self.encode_info(type)
pattern = PATTERN[type]
raise EventStreamParserError unless pattern
unless pattern
raise MessageEncodeError, "Unexpected header type: #{type}"
end

pattern
end
Expand Down
4 changes: 0 additions & 4 deletions hearth/lib/hearth/http2/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,6 @@ def setup_stream_handlers(response, stream)
response.body.write(data)
end

stream.on(:half_closed) do
log_debug("Stream half closed. Stream: #{stream.inspect}")
end

stream.on(:close) do
log_debug('Stream closed, sending stream-closed to ' \
"sync_queue. Stream: #{stream.inspect}")
Expand Down
4 changes: 2 additions & 2 deletions hearth/sig/lib/hearth/event_stream/message.rbs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module Hearth
module EventStream
class Message
def initialize: (headers: Hash[Symbol, HeaderValue], payload: IO) -> void
def initialize: (headers: Hash[String, HeaderValue], payload: IO) -> void

attr_accessor headers: Hash[Symbol, HeaderValue]
attr_accessor headers: Hash[String, HeaderValue]

# @return [IO] payload of a message, size not exceed 16MB.
attr_accessor payload: IO
Expand Down
67 changes: 66 additions & 1 deletion hearth/spec/hearth/event_stream/binary/encode_decode_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,72 @@ def build_headers(headers)
end
end

# TODO: Negative tests
Dir.glob(File.expand_path('fixtures/decoded/negative/*', __dir__))
.each do |decode_path|
suit_name = File.basename(decode_path)
encoded_path = File.join(
File.expand_path('fixtures/encoded/negative', __dir__), suit_name
)

next unless File.exist?(encoded_path)

context suit_name do
let(:encoded_bytes) { File.read(encoded_path, mode: 'rb') }
let(:error_message) { File.read(decode_path) }
it 'raises errors decoding' do
expect do
MessageDecoder.new.decode(encoded_bytes)
end.to raise_error(MessageDecodeError, error_message)
end
end
end
end

context 'large payloads' do
let(:payload) { 'a' * 16_777_217 }
let(:message) do
Message.new(
payload: StringIO.new(payload)
)
end
it 'encoder raises when headers exceed maximum size' do
expect do
MessageEncoder.new.encode(message)
end.to raise_error(MessageEncodeError)
end
end

context 'large headers' do
let(:large_header) { 'a' * 131_072 }
let(:message) do
Message.new(
headers: {
'header' => HeaderValue.new(type: 'string', value: large_header)
}
)
end

it 'encoder raises when payloads exceed maximum size' do
expect do
MessageEncoder.new.encode(message)
end.to raise_error(MessageEncodeError)
end
end

context 'invalid header type' do
let(:message) do
Message.new(
headers: {
'header' => HeaderValue.new(type: 'invalid', value: 'value')
}
)
end

it 'encoder raises when payloads exceed maximum size' do
expect do
MessageEncoder.new.encode(message)
end.to raise_error(MessageEncodeError)
end
end
end
end
Expand Down
3 changes: 1 addition & 2 deletions hearth/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
require 'simplecov'

unless ENV['NO_COVERAGE']
# TODO: set back to 100 once event stream specs have been completed
SimpleCov.minimum_coverage 99 unless defined?(JRUBY_VERSION)
SimpleCov.minimum_coverage 100 unless defined?(JRUBY_VERSION)
SimpleCov.start do
add_filter %r{/spec/}
end
Expand Down

0 comments on commit b6fc12f

Please sign in to comment.