Skip to content

Commit

Permalink
input stream tests - peek / skip
Browse files Browse the repository at this point in the history
  • Loading branch information
radeusgd committed Jun 7, 2024
1 parent db0c98c commit a059d88
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ type Managed_Resource
function once it is no longer in use.

Arguments:
- resource: The resource to register.
- function: The action to be executed on resource to clean it up when
it is no longer in use.

Returns:
A `Managed_Resource` object that can be used to access the resource.
register : Any -> (Any -> Nothing) -> Managed_Resource
register resource function = @Builtin_Method "Managed_Resource.register"

Expand Down
4 changes: 4 additions & 0 deletions std-bits/base/src/main/java/org/enso/base/Stream_Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class Stream_Utils {
public static byte[] peek(InputStream stream, int n) throws IOException {
Expand All @@ -19,6 +20,9 @@ public static byte[] peek(InputStream stream, int n) throws IOException {
offset += read;
}
stream.reset();
if (offset < n) {
buffer = Arrays.copyOf(buffer, offset);
}
return buffer;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.enso.base_test_helpers;

import java.io.IOException;
import java.io.InputStream;

/** A generic stream used for tests. */
public class RangeStream extends InputStream {
private final int end;
private int current;

public RangeStream(int start, int end) {
assert 0 <= start && start <= end && end <= 255;
this.end = end;
this.current = start;
}

@Override
public int read() throws IOException {
if (current >= end) {
return -1;
} else {
return current++;
}
}
}
69 changes: 69 additions & 0 deletions test/Base_Tests/src/System/Input_Stream_Spec.enso
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from Standard.Base import all
import Standard.Base.Errors.Illegal_State.Illegal_State
import Standard.Base.Runtime.Managed_Resource.Managed_Resource
import Standard.Base.System.Input_Stream.Input_Stream

from Standard.Test import all

polyglot java import org.enso.base_test_helpers.RangeStream

main filter=Nothing =
suite = Test.build suite_builder->
add_specs suite_builder
suite.run_with_filter filter

add_specs suite_builder = suite_builder.group "Input Stream" group_builder->
group_builder.specify "should be peekable if backed by memory" <|
Managed_Resource.bracket (Input_Stream.from_bytes [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) (.close) stream->
stream.is_peekable . should_be_true

stream.peek_bytes 3 . should_equal [1, 2, 3]
stream.peek_bytes 3 . should_equal [1, 2, 3]
# After the peek operation, read still starts from beginning
stream.read_n_bytes 3 . should_equal [1, 2, 3]

# Further peek after a read, starts from where the next read would start
stream.peek_bytes 3 . should_equal [4, 5, 6]
stream.read_n_bytes 3 . should_equal [4, 5, 6]
stream.read_n_bytes 5 . should_equal [7, 8, 9, 10]

group_builder.specify "should allow to skip bytes" <|
Managed_Resource.bracket (Input_Stream.from_bytes [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) (.close) stream->
stream.skip_n_bytes 3
stream.read_n_bytes 1 . should_equal [4]
stream.peek_bytes 3 . should_equal [5, 6, 7]
stream.skip_n_bytes 3
stream.read_n_bytes 4 . should_equal [8, 9, 10]

group_builder.specify "should not be peekable if generic stream is provided" <|
error_handler x = x
generic_stream = Input_Stream.new (RangeStream.new 100 120) error_handler
generic_stream.is_peekable . should_be_false
generic_stream.peek_bytes 3 . should_fail_with Illegal_State

group_builder.specify "should be possible to make peekable" <|
error_handler x = x
generic_stream = Input_Stream.new (RangeStream.new 100 120) error_handler
generic_stream.read_n_bytes 4 . should_equal [100, 101, 102, 103]

promoted_stream = generic_stream.as_peekable_stream
# The new stream starts at the same position as the old one was left
promoted_stream.peek_bytes 4 . should_equal [104, 105, 106, 107]
promoted_stream.read_n_bytes 4 . should_equal [104, 105, 106, 107]
promoted_stream.peek_bytes 2 . should_equal [108, 109]
promoted_stream.peek_bytes 2 . should_equal [108, 109]

# After converting the stream, the old reference is no longer valid
r = generic_stream.read_n_bytes 2
# TODO this does not fail
IO.println r
r.should_fail_with Any

group_builder.specify "should allow to peek beyond EOF, still correctly restarting afterwards" <|
error_handler x = x
generic_stream = Input_Stream.new (RangeStream.new 100 105) error_handler
promoted_stream = generic_stream.as_peekable_stream
promoted_stream.peek_bytes 10 . should_equal [100, 101, 102, 103, 104]
promoted_stream.peek_bytes 10 . should_equal [100, 101, 102, 103, 104]
# The read still succeeds - ensuring there isn't some early EOF
promoted_stream.read_n_bytes 10 . should_equal [100, 101, 102, 103, 104]

0 comments on commit a059d88

Please sign in to comment.