Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
gitlab-ce
Commits
8a1c2bc4
Commit
8a1c2bc4
authored
Mar 30, 2018
by
Shinya Maeda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add tests for ChunkStore::Database too
parent
1a05c60e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
499 additions
and
467 deletions
+499
-467
lib/gitlab/ci/trace/chunked_file/chunk_store/base.rb
lib/gitlab/ci/trace/chunked_file/chunk_store/base.rb
+4
-0
lib/gitlab/ci/trace/chunked_file/chunked_io.rb
lib/gitlab/ci/trace/chunked_file/chunked_io.rb
+8
-1
spec/lib/gitlab/ci/trace/chunked_file/chunked_io_spec.rb
spec/lib/gitlab/ci/trace/chunked_file/chunked_io_spec.rb
+12
-462
spec/support/chunked_io/chunked_io_helpers.rb
spec/support/chunked_io/chunked_io_helpers.rb
+7
-4
spec/support/shared_examples/lib/gitlab/ci/trace/chunked_file/chunked_io_shared_examples.rb
...itlab/ci/trace/chunked_file/chunked_io_shared_examples.rb
+468
-0
No files found.
lib/gitlab/ci/trace/chunked_file/chunk_store/base.rb
View file @
8a1c2bc4
...
@@ -30,6 +30,10 @@ module Gitlab
...
@@ -30,6 +30,10 @@ module Gitlab
raise
NotImplementedError
raise
NotImplementedError
end
end
def
append!
(
data
)
raise
NotImplementedError
end
def
truncate!
(
offset
)
def
truncate!
(
offset
)
raise
NotImplementedError
raise
NotImplementedError
end
end
...
...
lib/gitlab/ci/trace/chunked_file/chunked_io.rb
View file @
8a1c2bc4
...
@@ -15,6 +15,7 @@ module Gitlab
...
@@ -15,6 +15,7 @@ module Gitlab
end
end
end
end
BUFFER_SIZE
=
128
.
kilobytes
WriteError
=
Class
.
new
(
StandardError
)
WriteError
=
Class
.
new
(
StandardError
)
FailedToGetChunkError
=
Class
.
new
(
StandardError
)
FailedToGetChunkError
=
Class
.
new
(
StandardError
)
...
@@ -134,6 +135,8 @@ module Gitlab
...
@@ -134,6 +135,8 @@ module Gitlab
writable_space
=
BUFFER_SIZE
-
chunk_offset
writable_space
=
BUFFER_SIZE
-
chunk_offset
writing_size
=
[
writable_space
,
data
.
length
].
min
writing_size
=
[
writable_space
,
data
.
length
].
min
break
unless
writing_size
>
0
if
store
.
size
>
0
if
store
.
size
>
0
written_size
=
store
.
append!
(
data
.
slice!
(
0
...
writing_size
))
written_size
=
store
.
append!
(
data
.
slice!
(
0
...
writing_size
))
else
else
...
@@ -228,7 +231,11 @@ module Gitlab
...
@@ -228,7 +231,11 @@ module Gitlab
end
end
def
chunks_count
def
chunks_count
(
size
/
BUFFER_SIZE
)
+
1
(
size
/
BUFFER_SIZE
)
+
(
has_extra?
?
1
:
0
)
end
def
has_extra?
(
size
%
BUFFER_SIZE
)
>
0
end
end
def
last_chunk?
def
last_chunk?
...
...
spec/lib/gitlab/ci/trace/chunked_file/chunked_io_spec.rb
View file @
8a1c2bc4
...
@@ -4,478 +4,28 @@ describe Gitlab::Ci::Trace::ChunkedFile::ChunkedIO, :clean_gitlab_redis_cache do
...
@@ -4,478 +4,28 @@ describe Gitlab::Ci::Trace::ChunkedFile::ChunkedIO, :clean_gitlab_redis_cache do
include
ChunkedIOHelpers
include
ChunkedIOHelpers
let
(
:chunked_io
)
{
described_class
.
new
(
job_id
,
size
,
mode
)
}
let
(
:chunked_io
)
{
described_class
.
new
(
job_id
,
size
,
mode
)
}
let
(
:job_id
)
{
1
}
let
(
:job
)
{
create
(
:ci_build
)
}
let
(
:job_id
)
{
job
.
id
}
let
(
:size
)
{
sample_trace_size
}
let
(
:size
)
{
sample_trace_size
}
let
(
:mode
)
{
'rb'
}
let
(
:mode
)
{
'rb'
}
let
(
:buffer_size
)
{
128
.
kilobytes
}
let
(
:chunk_store
)
{
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkStore
::
Redis
}
before
do
describe
'ChunkStore is Redis'
,
:partial_support
do
allow_any_instance_of
(
described_class
).
to
receive
(
:chunk_store
).
and_return
(
chunk_store
)
let
(
:chunk_store
)
{
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkStore
::
Redis
}
stub_const
(
"Gitlab::Ci::Trace::ChunkedFile::ChunkedIO::BUFFER_SIZE"
,
buffer_size
)
end
describe
'#new'
do
context
'when mode is read'
do
let
(
:mode
)
{
'rb'
}
it
'raises no exception'
do
described_class
.
new
(
job_id
,
size
,
mode
)
expect
{
described_class
.
new
(
job_id
,
size
,
mode
)
}.
not_to
raise_error
end
end
context
'when mode is write'
do
let
(
:mode
)
{
'a+b'
}
it
'raises an exception'
do
described_class
.
new
(
job_id
,
size
,
mode
)
expect
{
described_class
.
new
(
job_id
,
size
,
mode
)
}.
to
raise_error
(
'Already opened by another process'
)
end
context
'when closed after open'
do
it
'does not raise an exception'
do
described_class
.
new
(
job_id
,
size
,
mode
).
close
expect
{
described_class
.
new
(
job_id
,
size
,
mode
)
}.
not_to
raise_error
end
end
end
end
describe
'#seek'
do
subject
{
chunked_io
.
seek
(
pos
,
where
)
}
context
'when moves pos to end of the file'
do
let
(
:pos
)
{
0
}
let
(
:where
)
{
IO
::
SEEK_END
}
it
{
is_expected
.
to
eq
(
size
)
}
end
context
'when moves pos to middle of the file'
do
let
(
:pos
)
{
size
/
2
}
let
(
:where
)
{
IO
::
SEEK_SET
}
it
{
is_expected
.
to
eq
(
size
/
2
)
}
end
context
'when moves pos around'
do
it
'matches the result'
do
expect
(
chunked_io
.
seek
(
0
)).
to
eq
(
0
)
expect
(
chunked_io
.
seek
(
100
,
IO
::
SEEK_CUR
)).
to
eq
(
100
)
expect
{
chunked_io
.
seek
(
size
+
1
,
IO
::
SEEK_CUR
)
}.
to
raise_error
(
'new position is outside of file'
)
end
end
end
describe
'#eof?'
do
subject
{
chunked_io
.
eof?
}
context
'when current pos is at end of the file'
do
before
do
chunked_io
.
seek
(
size
,
IO
::
SEEK_SET
)
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when current pos is not at end of the file'
do
before
do
chunked_io
.
seek
(
0
,
IO
::
SEEK_SET
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#each_line'
do
before
do
let
(
:buffer_size
)
{
128
.
kilobytes
}
allow_any_instance_of
(
described_class
).
to
receive
(
:chunk_store
).
and_return
(
chunk_store
)
let
(
:string_io
)
{
StringIO
.
new
(
sample_trace_raw
)
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'yields lines'
do
expect
{
|
b
|
described_class
.
new
(
job_id
,
size
,
'rb'
).
each_line
(
&
b
)
}
.
to
yield_successive_args
(
*
string_io
.
each_line
.
to_a
)
end
end
end
context
'when BUFFER_SIZE is larger than file size'
do
it_behaves_like
'ChunkedIO shared tests'
let
(
:buffer_size
)
{
size
+
1000
}
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'calls get_chunk only once'
do
expect
(
chunk_store
).
to
receive
(
:open
).
once
.
and_call_original
described_class
.
new
(
job_id
,
size
,
'rb'
).
each_line
{
|
line
|
}
end
end
end
end
describe
'#read'
do
describe
'ChunkStore is Database'
do
subject
{
described_class
.
new
(
job_id
,
size
,
'rb'
).
read
(
length
)
}
let
(
:chunk_store
)
{
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkStore
::
Database
}
context
'when read whole size'
do
let
(
:length
)
{
nil
}
context
'when BUFFER_SIZE is smaller than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
)
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
)
end
end
end
context
'when read only first 100 bytes'
do
let
(
:length
)
{
100
}
context
'when BUFFER_SIZE is smaller than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
[
0
,
length
])
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:clean_gitlab_redis_cache
do
before
do
before
do
allow_any_instance_of
(
described_class
).
to
receive
(
:chunk_store
).
and_return
(
chunk_store
)
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
[
0
,
length
])
end
end
end
context
'when tries to read oversize'
do
let
(
:length
)
{
size
+
1000
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
)
end
end
context
'when BUFFER_SIZE is larger than file size'
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
)
end
end
end
end
context
'when tries to read 0 bytes'
do
it_behaves_like
'ChunkedIO shared tests'
let
(
:length
)
{
0
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
be_empty
end
end
context
'when BUFFER_SIZE is larger than file size'
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
be_empty
end
end
end
context
'when chunk store failed to get chunk'
do
let
(
:length
)
{
nil
}
before
do
fill_trace_to_chunks
(
sample_trace_raw
)
stub_chunk_store_redis_get_failed
end
it
'reads a trace'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkedIO
::
FailedToGetChunkError
)
end
end
end
describe
'#readline'
do
subject
{
chunked_io
.
readline
}
let
(
:string_io
)
{
StringIO
.
new
(
sample_trace_raw
)
}
shared_examples
'all line matching'
do
it
'reads a line'
do
(
0
...
sample_trace_raw
.
lines
.
count
).
each
do
expect
(
chunked_io
.
readline
).
to
eq
(
string_io
.
readline
)
end
end
end
context
'when chunk store failed to get chunk'
do
let
(
:length
)
{
nil
}
before
do
fill_trace_to_chunks
(
sample_trace_raw
)
stub_chunk_store_redis_get_failed
end
it
'reads a trace'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkedIO
::
FailedToGetChunkError
)
end
end
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it_behaves_like
'all line matching'
end
context
'when BUFFER_SIZE is larger than file size'
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it_behaves_like
'all line matching'
end
context
'when pos is at middle of the file'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
chunked_io
.
seek
(
size
/
2
)
string_io
.
seek
(
size
/
2
)
end
it
'reads from pos'
do
expect
(
chunked_io
.
readline
).
to
eq
(
string_io
.
readline
)
end
end
end
describe
'#write'
do
subject
{
chunked_io
.
write
(
data
)
}
let
(
:data
)
{
sample_trace_raw
}
context
'when write mdoe'
do
let
(
:mode
)
{
'wb'
}
context
'when BUFFER_SIZE is smaller than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_smaller_buffer_size_than
(
size
)
end
it
'writes a trace'
do
is_expected
.
to
eq
(
data
.
length
)
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkedIO
.
open
(
job_id
,
size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
data
)
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
stream
.
send
(
:chunks_count
))
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
data
.
length
)
end
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_larger_buffer_size_than
(
size
)
end
it
'writes a trace'
do
is_expected
.
to
eq
(
data
.
length
)
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkedIO
.
open
(
job_id
,
size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
data
)
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
stream
.
send
(
:chunks_count
))
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
data
.
length
)
end
end
end
context
'when data is nil'
do
let
(
:data
)
{
nil
}
it
'writes a trace'
do
expect
{
subject
}
.
to
raise_error
(
'Could not write empty data'
)
end
end
end
context
'when append mdoe'
do
let
(
:original_data
)
{
'original data'
}
let
(
:total_size
)
{
original_data
.
length
+
data
.
length
}
context
'when BUFFER_SIZE is smaller than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
original_data
)
end
it
'appends a trace'
do
described_class
.
open
(
job_id
,
original_data
.
length
,
'a+b'
)
do
|
stream
|
expect
(
stream
.
write
(
data
)).
to
eq
(
data
.
length
)
end
described_class
.
open
(
job_id
,
total_size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
original_data
+
data
)
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
stream
.
send
(
:chunks_count
))
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
total_size
)
end
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
original_data
)
end
it
'appends a trace'
do
described_class
.
open
(
job_id
,
original_data
.
length
,
'a+b'
)
do
|
stream
|
expect
(
stream
.
write
(
data
)).
to
eq
(
data
.
length
)
end
described_class
.
open
(
job_id
,
total_size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
original_data
+
data
)
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
stream
.
send
(
:chunks_count
))
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
total_size
)
end
end
end
end
end
describe
'#truncate'
do
context
'when data exists'
do
context
'when BUFFER_SIZE is smaller than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'truncates a trace'
do
described_class
.
open
(
job_id
,
size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
sample_trace_raw
)
end
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
stream
.
truncate
(
0
)
end
described_class
.
open
(
job_id
,
0
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
be_empty
end
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
0
)
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
0
)
end
context
'when offset is negative'
,
:clean_gitlab_redis_cache
do
it
'raises an error'
do
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
expect
{
stream
.
truncate
(
-
1
)
}.
to
raise_error
(
'Offset is out of bound'
)
end
end
end
context
'when offset is larger than file size'
,
:clean_gitlab_redis_cache
do
it
'raises an error'
do
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
expect
{
stream
.
truncate
(
size
+
1
)
}.
to
raise_error
(
'Offset is out of bound'
)
end
end
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:clean_gitlab_redis_cache
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'truncates a trace'
do
described_class
.
open
(
job_id
,
size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
sample_trace_raw
)
end
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
stream
.
truncate
(
0
)
end
described_class
.
open
(
job_id
,
0
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
be_empty
end
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
0
)
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
0
)
end
end
end
context
'when data does not exist'
do
before
do
set_smaller_buffer_size_than
(
size
)
end
it
'truncates a trace'
do
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
stream
.
truncate
(
0
)
expect
(
stream
.
send
(
:tell
)).
to
eq
(
0
)
expect
(
stream
.
send
(
:size
)).
to
eq
(
0
)
end
end
end
end
end
end
end
spec/support/chunked_io/chunked_io_helpers.rb
View file @
8a1c2bc4
...
@@ -6,16 +6,19 @@ module ChunkedIOHelpers
...
@@ -6,16 +6,19 @@ module ChunkedIOHelpers
end
end
def
sample_trace_raw
def
sample_trace_raw
@sample_trace_raw
||=
File
.
read
(
expand_fixture_path
(
'trace/sample_trace'
))
if
chunk_store
==
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkStore
::
Redis
File
.
read
(
expand_fixture_path
(
'trace/sample_trace'
))
else
'01234567'
*
32
end
end
end
def
sample_trace_size
def
sample_trace_size
sample_trace_raw
.
length
sample_trace_raw
.
length
end
end
def
stub_chunk_store_redis_get_failed
def
stub_chunk_store_get_failed
allow_any_instance_of
(
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkStore
::
Redis
)
allow_any_instance_of
(
chunk_store
).
to
receive
(
:get
).
and_return
(
nil
)
.
to
receive
(
:get
).
and_return
(
nil
)
end
end
def
set_smaller_buffer_size_than
(
file_size
)
def
set_smaller_buffer_size_than
(
file_size
)
...
...
spec/support/shared_examples/lib/gitlab/ci/trace/chunked_file/chunked_io_shared_examples.rb
0 → 100644
View file @
8a1c2bc4
shared_examples
"ChunkedIO shared tests"
do
around
(
:each
,
:partial_support
)
do
|
example
|
example
.
run
if
chunk_store
==
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkStore
::
Redis
end
describe
'#new'
do
context
'when mode is read'
do
let
(
:mode
)
{
'rb'
}
it
'raises no exception'
do
described_class
.
new
(
job_id
,
size
,
mode
)
expect
{
described_class
.
new
(
job_id
,
size
,
mode
)
}.
not_to
raise_error
end
end
context
'when mode is write'
do
let
(
:mode
)
{
'a+b'
}
it
'raises an exception'
do
described_class
.
new
(
job_id
,
size
,
mode
)
expect
{
described_class
.
new
(
job_id
,
size
,
mode
)
}.
to
raise_error
(
'Already opened by another process'
)
end
context
'when closed after open'
do
it
'does not raise an exception'
do
described_class
.
new
(
job_id
,
size
,
mode
).
close
expect
{
described_class
.
new
(
job_id
,
size
,
mode
)
}.
not_to
raise_error
end
end
end
end
describe
'#seek'
do
subject
{
chunked_io
.
seek
(
pos
,
where
)
}
context
'when moves pos to end of the file'
do
let
(
:pos
)
{
0
}
let
(
:where
)
{
IO
::
SEEK_END
}
it
{
is_expected
.
to
eq
(
size
)
}
end
context
'when moves pos to middle of the file'
do
let
(
:pos
)
{
size
/
2
}
let
(
:where
)
{
IO
::
SEEK_SET
}
it
{
is_expected
.
to
eq
(
size
/
2
)
}
end
context
'when moves pos around'
do
it
'matches the result'
do
expect
(
chunked_io
.
seek
(
0
)).
to
eq
(
0
)
expect
(
chunked_io
.
seek
(
100
,
IO
::
SEEK_CUR
)).
to
eq
(
100
)
expect
{
chunked_io
.
seek
(
size
+
1
,
IO
::
SEEK_CUR
)
}.
to
raise_error
(
'new position is outside of file'
)
end
end
end
describe
'#eof?'
do
subject
{
chunked_io
.
eof?
}
context
'when current pos is at end of the file'
do
before
do
chunked_io
.
seek
(
size
,
IO
::
SEEK_SET
)
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when current pos is not at end of the file'
do
before
do
chunked_io
.
seek
(
0
,
IO
::
SEEK_SET
)
end
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#each_line'
do
let
(
:string_io
)
{
StringIO
.
new
(
sample_trace_raw
)
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'yields lines'
do
expect
{
|
b
|
described_class
.
new
(
job_id
,
size
,
'rb'
).
each_line
(
&
b
)
}
.
to
yield_successive_args
(
*
string_io
.
each_line
.
to_a
)
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:partial_support
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'calls get_chunk only once'
do
expect
(
chunk_store
).
to
receive
(
:open
).
once
.
and_call_original
described_class
.
new
(
job_id
,
size
,
'rb'
).
each_line
{
|
line
|
}
end
end
end
describe
'#read'
do
subject
{
described_class
.
new
(
job_id
,
size
,
'rb'
).
read
(
length
)
}
context
'when read whole size'
do
let
(
:length
)
{
nil
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
)
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:partial_support
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
)
end
end
end
context
'when read only first 100 bytes'
do
let
(
:length
)
{
100
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
[
0
,
length
])
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:partial_support
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
[
0
,
length
])
end
end
end
context
'when tries to read oversize'
do
let
(
:length
)
{
size
+
1000
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
)
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:partial_support
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
eq
(
sample_trace_raw
)
end
end
end
context
'when tries to read 0 bytes'
do
let
(
:length
)
{
0
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
be_empty
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:partial_support
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'reads a trace'
do
is_expected
.
to
be_empty
end
end
end
context
'when chunk store failed to get chunk'
do
let
(
:length
)
{
nil
}
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
stub_chunk_store_get_failed
end
it
'reads a trace'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkedIO
::
FailedToGetChunkError
)
end
end
end
describe
'#readline'
do
subject
{
chunked_io
.
readline
}
let
(
:string_io
)
{
StringIO
.
new
(
sample_trace_raw
)
}
shared_examples
'all line matching'
do
it
'reads a line'
do
(
0
...
sample_trace_raw
.
lines
.
count
).
each
do
expect
(
chunked_io
.
readline
).
to
eq
(
string_io
.
readline
)
end
end
end
context
'when chunk store failed to get chunk'
do
let
(
:length
)
{
nil
}
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
stub_chunk_store_get_failed
end
it
'reads a trace'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkedIO
::
FailedToGetChunkError
)
end
end
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it_behaves_like
'all line matching'
end
context
'when BUFFER_SIZE is larger than file size'
,
:partial_support
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it_behaves_like
'all line matching'
end
context
'when pos is at middle of the file'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
chunked_io
.
seek
(
size
/
2
)
string_io
.
seek
(
size
/
2
)
end
it
'reads from pos'
do
expect
(
chunked_io
.
readline
).
to
eq
(
string_io
.
readline
)
end
end
end
describe
'#write'
do
subject
{
chunked_io
.
write
(
data
)
}
let
(
:data
)
{
sample_trace_raw
}
context
'when write mdoe'
do
let
(
:mode
)
{
'wb'
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
end
it
'writes a trace'
do
is_expected
.
to
eq
(
data
.
length
)
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkedIO
.
open
(
job_id
,
size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
data
)
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
stream
.
send
(
:chunks_count
))
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
data
.
length
)
end
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:partial_support
do
before
do
set_larger_buffer_size_than
(
size
)
end
it
'writes a trace'
do
is_expected
.
to
eq
(
data
.
length
)
Gitlab
::
Ci
::
Trace
::
ChunkedFile
::
ChunkedIO
.
open
(
job_id
,
size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
data
)
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
stream
.
send
(
:chunks_count
))
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
data
.
length
)
end
end
end
context
'when data is nil'
do
let
(
:data
)
{
nil
}
it
'writes a trace'
do
expect
{
subject
}
.
to
raise_error
(
'Could not write empty data'
)
end
end
end
context
'when append mdoe'
,
:partial_support
do
let
(
:original_data
)
{
'original data'
}
let
(
:total_size
)
{
original_data
.
length
+
data
.
length
}
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
original_data
)
end
it
'appends a trace'
do
described_class
.
open
(
job_id
,
original_data
.
length
,
'a+b'
)
do
|
stream
|
expect
(
stream
.
write
(
data
)).
to
eq
(
data
.
length
)
end
described_class
.
open
(
job_id
,
total_size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
original_data
+
data
)
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
stream
.
send
(
:chunks_count
))
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
total_size
)
end
end
end
context
'when BUFFER_SIZE is larger than file size'
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
original_data
)
end
it
'appends a trace'
do
described_class
.
open
(
job_id
,
original_data
.
length
,
'a+b'
)
do
|
stream
|
expect
(
stream
.
write
(
data
)).
to
eq
(
data
.
length
)
end
described_class
.
open
(
job_id
,
total_size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
original_data
+
data
)
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
stream
.
send
(
:chunks_count
))
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
total_size
)
end
end
end
end
end
describe
'#truncate'
do
context
'when data exists'
do
context
'when BUFFER_SIZE is smaller than file size'
do
before
do
set_smaller_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'truncates a trace'
do
described_class
.
open
(
job_id
,
size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
sample_trace_raw
)
end
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
stream
.
truncate
(
0
)
end
described_class
.
open
(
job_id
,
0
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
be_empty
end
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
0
)
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
0
)
end
context
'when offset is negative'
do
it
'raises an error'
do
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
expect
{
stream
.
truncate
(
-
1
)
}.
to
raise_error
(
'Offset is out of bound'
)
end
end
end
context
'when offset is larger than file size'
do
it
'raises an error'
do
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
expect
{
stream
.
truncate
(
size
+
1
)
}.
to
raise_error
(
'Offset is out of bound'
)
end
end
end
end
context
'when BUFFER_SIZE is larger than file size'
,
:partial_support
do
before
do
set_larger_buffer_size_than
(
size
)
fill_trace_to_chunks
(
sample_trace_raw
)
end
it
'truncates a trace'
do
described_class
.
open
(
job_id
,
size
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
eq
(
sample_trace_raw
)
end
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
stream
.
truncate
(
0
)
end
described_class
.
open
(
job_id
,
0
,
'rb'
)
do
|
stream
|
expect
(
stream
.
read
).
to
be_empty
end
expect
(
chunk_store
.
chunks_count
(
job_id
)).
to
eq
(
0
)
expect
(
chunk_store
.
chunks_size
(
job_id
)).
to
eq
(
0
)
end
end
end
context
'when data does not exist'
do
before
do
set_smaller_buffer_size_than
(
size
)
end
it
'truncates a trace'
do
described_class
.
open
(
job_id
,
size
,
'wb'
)
do
|
stream
|
stream
.
truncate
(
0
)
expect
(
stream
.
send
(
:tell
)).
to
eq
(
0
)
expect
(
stream
.
send
(
:size
)).
to
eq
(
0
)
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment