feedx 0.12.7 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -37
  3. data/.golangci.yml +13 -4
  4. data/.rubocop.yml +8 -14
  5. data/.tool-versions +1 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +54 -68
  8. data/Makefile +3 -3
  9. data/README.md +3 -1
  10. data/compression.go +29 -0
  11. data/compression_test.go +73 -61
  12. data/consumer.go +96 -152
  13. data/consumer_test.go +124 -59
  14. data/example_test.go +140 -0
  15. data/feedx.gemspec +2 -10
  16. data/feedx.go +16 -31
  17. data/feedx_ext_test.go +13 -3
  18. data/feedx_test.go +24 -26
  19. data/format.go +29 -19
  20. data/format_test.go +84 -56
  21. data/go.mod +11 -7
  22. data/go.sum +16 -138
  23. data/incremental.go +122 -0
  24. data/incremental_test.go +62 -0
  25. data/lib/feedx/cache/abstract.rb +3 -3
  26. data/lib/feedx/cache/value.rb +6 -6
  27. data/lib/feedx/compression/abstract.rb +2 -2
  28. data/lib/feedx/compression/gzip.rb +4 -4
  29. data/lib/feedx/consumer.rb +8 -8
  30. data/lib/feedx/format/abstract.rb +6 -6
  31. data/lib/feedx/format/json.rb +2 -2
  32. data/lib/feedx/format/protobuf.rb +6 -6
  33. data/lib/feedx/format.rb +1 -3
  34. data/lib/feedx/producer.rb +11 -11
  35. data/lib/feedx/stream.rb +2 -2
  36. data/lib/feedx.rb +2 -3
  37. data/manifest.go +65 -0
  38. data/producer.go +34 -137
  39. data/producer_test.go +46 -60
  40. data/reader.go +142 -41
  41. data/reader_test.go +86 -35
  42. data/scheduler.go +176 -0
  43. data/scheduler_test.go +128 -0
  44. data/writer.go +13 -13
  45. data/writer_test.go +61 -44
  46. metadata +12 -137
  47. data/.github/workflows/lint.yml +0 -18
  48. data/ext/parquet/decoder.go +0 -59
  49. data/ext/parquet/decoder_test.go +0 -88
  50. data/ext/parquet/encoder.go +0 -27
  51. data/ext/parquet/encoder_test.go +0 -70
  52. data/ext/parquet/go.mod +0 -12
  53. data/ext/parquet/go.sum +0 -193
  54. data/ext/parquet/parquet.go +0 -78
  55. data/ext/parquet/parquet_test.go +0 -28
  56. data/ext/parquet/testdata/alltypes_plain.parquet +0 -0
  57. data/lib/feedx/format/parquet.rb +0 -102
  58. data/spec/feedx/cache/memory_spec.rb +0 -23
  59. data/spec/feedx/cache/value_spec.rb +0 -19
  60. data/spec/feedx/compression/gzip_spec.rb +0 -17
  61. data/spec/feedx/compression/none_spec.rb +0 -15
  62. data/spec/feedx/compression_spec.rb +0 -19
  63. data/spec/feedx/consumer_spec.rb +0 -49
  64. data/spec/feedx/format/abstract_spec.rb +0 -21
  65. data/spec/feedx/format/json_spec.rb +0 -27
  66. data/spec/feedx/format/parquet_spec.rb +0 -30
  67. data/spec/feedx/format/protobuf_spec.rb +0 -23
  68. data/spec/feedx/format_spec.rb +0 -21
  69. data/spec/feedx/producer_spec.rb +0 -74
  70. data/spec/feedx/stream_spec.rb +0 -109
  71. data/spec/spec_helper.rb +0 -57
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a8328c3af95657d103cf62048d13cb5a14cc50466351f2178082612c347a8cf
4
- data.tar.gz: f2fdb20a577c88f165f2cbac3dadf217889716b67b9ae20e4941ed9ef396e864
3
+ metadata.gz: c1978c7def650e2a2630e36fc0bfc59b9eb66c5ead0f7dda9cc83e773a85c1d8
4
+ data.tar.gz: 548208072baf9e6f84a7541df5e8a22a5960982007bce4385c7fa538e0290e94
5
5
  SHA512:
6
- metadata.gz: 6cf78b2fb0917c7afb33014e6b3e30d045ffca874f4c8463092f25a7b22b268ab9f2cbd03a1dfda9df7a9314fe213d11c332ff965eb7b81436768cb94d80bf83
7
- data.tar.gz: 9131ba95738e600ab4e731546b6e876cae77120782e148a6eac6e3ea4b90e398975f15f2af00b325e86f3fc73a79c39c4a6be25e80bc7298881ff636d61d150b
6
+ metadata.gz: a5b0be41feeafabbffcbbda6ccc1b12df4d24b8d9a9f03f4b8d04ce2fec7b644b99f15db98e67a79294dca1c3b56c072a67ab20b8cbffaed25ec502e74de9ca2
7
+ data.tar.gz: d3434d54accaf281ec5e06e25753de74a052d1386a63badf97ff8bfa8a1426162528d8256cbd288969ef1c348d24cf9358c0827b4c7b1af500c71e5349900b63
@@ -8,41 +8,6 @@ on:
8
8
  - main
9
9
  jobs:
10
10
  go:
11
- runs-on: ubuntu-latest
12
- strategy:
13
- matrix:
14
- go-version: [1.16.x, 1.17.x]
15
- steps:
16
- - name: Checkout
17
- uses: actions/checkout@v2
18
- - name: Cache dependencies
19
- uses: actions/cache@v2
20
- with:
21
- path: ~/go/pkg/mod
22
- key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
23
- restore-keys: |
24
- ${{ runner.os }}-go-
25
- - name: Setup Go
26
- uses: actions/setup-go@v2
27
- with:
28
- go-version: ${{ matrix.go-version }}
29
- - name: Run tests
30
- run: make test
11
+ uses: bsm/misc/.github/workflows/test-go.yml@main
31
12
  ruby:
32
- runs-on: ubuntu-latest
33
- strategy:
34
- matrix:
35
- ruby-version: ["2.7", "3.0", "3.1"]
36
- steps:
37
- - name: Install libarrow
38
- run: |
39
- wget https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb
40
- sudo apt install -y -V ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb
41
- sudo apt update
42
- sudo apt install -y libarrow-dev libarrow-glib-dev libarrow-dataset-dev libplasma-dev libplasma-glib-dev libgandiva-dev libgandiva-glib-dev libparquet-dev libparquet-glib-dev
43
- - uses: actions/checkout@v2
44
- - uses: ruby/setup-ruby@v1
45
- with:
46
- ruby-version: ${{ matrix.ruby-version }}
47
- bundler-cache: true
48
- - run: bundle exec rake
13
+ uses: bsm/misc/.github/workflows/test-ruby.yml@main
data/.golangci.yml CHANGED
@@ -1,4 +1,13 @@
1
- linters-settings:
2
- errcheck:
3
- exclude-functions:
4
- - (*github.com/bsm/feedx.Writer).Discard
1
+ version: "2"
2
+ linters:
3
+ settings:
4
+ errcheck:
5
+ exclude-functions:
6
+ - (*github.com/bsm/feedx.Writer).Discard
7
+ - (*github.com/bsm/feedx.Reader).Close
8
+ - (github.com/bsm/feedx.Consumer).Close
9
+ - (*github.com/bsm/feedx.IncrementalProducer).Close
10
+ - (*github.com/bsm/feedx.Producer).Close
11
+ - (*github.com/bsm/bfs.InMem).Close
12
+ - (*github.com/bsm/bfs.Object).Close
13
+ - (github.com/bsm/bfs.Writer).Discard
data/.rubocop.yml CHANGED
@@ -1,17 +1,11 @@
1
- inherit_gem:
2
- rubocop-bsm:
3
- - default.yml
1
+ plugins:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+
5
+ inherit_from:
6
+ - https://raw.githubusercontent.com/bsm/misc/refs/heads/main/rubocop/default.yml
7
+ - https://raw.githubusercontent.com/bsm/misc/refs/heads/main/rubocop/rspec.yml
8
+
4
9
  inherit_mode:
5
10
  merge:
6
11
  - Exclude
7
-
8
- AllCops:
9
- TargetRubyVersion: 2.7
10
- Naming/MethodParameterName:
11
- MinNameLength: 2
12
- Naming/MemoizedInstanceVariableName:
13
- Enabled: false
14
- Naming/FileName:
15
- Exclude: [lib/sortable-by.rb]
16
- Metrics/ParameterLists:
17
- Max: 8
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.4.7
data/Gemfile CHANGED
@@ -1,2 +1,10 @@
1
1
  source 'https://rubygems.org'
2
+
2
3
  gemspec
4
+ gem 'bundler'
5
+ gem 'pbio'
6
+ gem 'rake'
7
+ gem 'rspec'
8
+ gem 'rubocop'
9
+ gem 'rubocop-rake'
10
+ gem 'rubocop-rspec'
data/Gemfile.lock CHANGED
@@ -1,82 +1,67 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- feedx (0.12.7)
4
+ feedx (0.14.0)
5
5
  bfs (>= 0.8.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- ast (2.4.2)
11
- bfs (0.9.0)
12
- bigdecimal (3.1.1)
13
- diff-lcs (1.5.0)
14
- extpp (0.1.0)
15
- gio2 (3.4.9)
16
- gobject-introspection (= 3.4.9)
17
- glib2 (3.4.9)
18
- native-package-installer (>= 1.0.3)
19
- pkg-config (>= 1.3.5)
20
- gobject-introspection (3.4.9)
21
- glib2 (= 3.4.9)
22
- google-protobuf (3.19.2)
23
- native-package-installer (1.1.1)
24
- parallel (1.21.0)
25
- parser (3.1.0.0)
10
+ ast (2.4.3)
11
+ bfs (0.9.1)
12
+ diff-lcs (1.6.2)
13
+ google-protobuf (3.25.8)
14
+ json (2.16.0)
15
+ language_server-protocol (3.17.0.5)
16
+ lint_roller (1.1.0)
17
+ parallel (1.27.0)
18
+ parser (3.3.10.0)
26
19
  ast (~> 2.4.1)
27
- pbio (0.3.0)
28
- google-protobuf
29
- pkg-config (1.4.6)
30
- rainbow (3.0.0)
31
- rake (13.0.6)
32
- red-arrow (3.0.0)
33
- bigdecimal (>= 2.0.3)
34
- extpp (>= 0.0.7)
35
- gio2 (>= 3.3.6)
36
- native-package-installer
37
- pkg-config
38
- red-parquet (3.0.0)
39
- red-arrow (= 3.0.0)
40
- regexp_parser (2.2.0)
41
- rexml (3.2.5)
42
- rspec (3.10.0)
43
- rspec-core (~> 3.10.0)
44
- rspec-expectations (~> 3.10.0)
45
- rspec-mocks (~> 3.10.0)
46
- rspec-core (3.10.1)
47
- rspec-support (~> 3.10.0)
48
- rspec-expectations (3.10.1)
20
+ racc
21
+ pbio (0.4.0)
22
+ google-protobuf (> 3, < 4)
23
+ prism (1.6.0)
24
+ racc (1.8.1)
25
+ rainbow (3.1.1)
26
+ rake (13.3.1)
27
+ regexp_parser (2.11.3)
28
+ rspec (3.13.2)
29
+ rspec-core (~> 3.13.0)
30
+ rspec-expectations (~> 3.13.0)
31
+ rspec-mocks (~> 3.13.0)
32
+ rspec-core (3.13.6)
33
+ rspec-support (~> 3.13.0)
34
+ rspec-expectations (3.13.5)
49
35
  diff-lcs (>= 1.2.0, < 2.0)
50
- rspec-support (~> 3.10.0)
51
- rspec-mocks (3.10.2)
36
+ rspec-support (~> 3.13.0)
37
+ rspec-mocks (3.13.7)
52
38
  diff-lcs (>= 1.2.0, < 2.0)
53
- rspec-support (~> 3.10.0)
54
- rspec-support (3.10.3)
55
- rubocop (1.24.1)
39
+ rspec-support (~> 3.13.0)
40
+ rspec-support (3.13.6)
41
+ rubocop (1.81.7)
42
+ json (~> 2.3)
43
+ language_server-protocol (~> 3.17.0.2)
44
+ lint_roller (~> 1.1.0)
56
45
  parallel (~> 1.10)
57
- parser (>= 3.0.0.0)
46
+ parser (>= 3.3.0.2)
58
47
  rainbow (>= 2.2.2, < 4.0)
59
- regexp_parser (>= 1.8, < 3.0)
60
- rexml
61
- rubocop-ast (>= 1.15.1, < 2.0)
48
+ regexp_parser (>= 2.9.3, < 3.0)
49
+ rubocop-ast (>= 1.47.1, < 2.0)
62
50
  ruby-progressbar (~> 1.7)
63
- unicode-display_width (>= 1.4.0, < 3.0)
64
- rubocop-ast (1.15.1)
65
- parser (>= 3.0.1.1)
66
- rubocop-bsm (0.6.0)
67
- rubocop (~> 1.0)
68
- rubocop-performance
69
- rubocop-rake
70
- rubocop-rspec
71
- rubocop-performance (1.13.1)
72
- rubocop (>= 1.7.0, < 2.0)
73
- rubocop-ast (>= 0.4.0)
74
- rubocop-rake (0.6.0)
75
- rubocop (~> 1.0)
76
- rubocop-rspec (2.7.0)
77
- rubocop (~> 1.19)
78
- ruby-progressbar (1.11.0)
79
- unicode-display_width (2.1.0)
51
+ unicode-display_width (>= 2.4.0, < 4.0)
52
+ rubocop-ast (1.48.0)
53
+ parser (>= 3.3.7.2)
54
+ prism (~> 1.4)
55
+ rubocop-rake (0.7.1)
56
+ lint_roller (~> 1.1)
57
+ rubocop (>= 1.72.1)
58
+ rubocop-rspec (3.7.0)
59
+ lint_roller (~> 1.1)
60
+ rubocop (~> 1.72, >= 1.72.1)
61
+ ruby-progressbar (1.13.0)
62
+ unicode-display_width (3.2.0)
63
+ unicode-emoji (~> 4.1)
64
+ unicode-emoji (4.1.0)
80
65
 
81
66
  PLATFORMS
82
67
  ruby
@@ -86,9 +71,10 @@ DEPENDENCIES
86
71
  feedx!
87
72
  pbio
88
73
  rake
89
- red-parquet (>= 3.0, < 4.0)
90
74
  rspec
91
- rubocop-bsm
75
+ rubocop
76
+ rubocop-rake
77
+ rubocop-rspec
92
78
 
93
79
  BUNDLED WITH
94
- 2.2.27
80
+ 2.3.16
data/Makefile CHANGED
@@ -1,9 +1,9 @@
1
1
  default: test
2
2
 
3
- .common.makefile:
4
- curl -fsSL -o $@ https://gitlab.com/bsm/misc/raw/master/make/go/common.makefile
3
+ .minimal.makefile:
4
+ curl -fsSL -o $@ https://gitlab.com/bsm/misc/raw/master/make/go/minimal.makefile
5
5
 
6
- include .common.makefile
6
+ include .minimal.makefile
7
7
 
8
8
  proto: internal/testdata/testdata.pb.go
9
9
 
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Feedx
2
2
 
3
- [![Test](https://github.com/bsm/feedx/actions/workflows/test.yml/badge.svg)](https://github.com/bsm/feedx/actions/workflows/test.yml)
3
+ [![Go reference](https://pkg.go.dev/badge/github.com/bsm/feedx.svg)](https://pkg.go.dev/github.com/bsm/feedx)
4
+ [![GitHub release](https://img.shields.io/github/tag/bsm/feedx.svg?label=release)](https://github.com/bsm/feedx/releases)
5
+ [![Go Report Card](https://goreportcard.com/badge/github.com/bsm/feedx)](https://goreportcard.com/report/github.com/bsm/feedx)
4
6
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
7
 
6
8
  Feed-based data exchange between services.
data/compression.go CHANGED
@@ -5,6 +5,8 @@ import (
5
5
  "compress/gzip"
6
6
  "io"
7
7
  "path"
8
+
9
+ "github.com/klauspost/compress/zstd"
8
10
  )
9
11
 
10
12
  // Compression represents the data compression.
@@ -23,6 +25,8 @@ func DetectCompression(name string) Compression {
23
25
  return GZipCompression
24
26
  } else if ext == ".flate" {
25
27
  return FlateCompression
28
+ } else if ext == ".zst" {
29
+ return ZstdCompression
26
30
  }
27
31
  }
28
32
  return NoCompression
@@ -79,3 +83,28 @@ func (flateCompression) NewReader(r io.Reader) (io.ReadCloser, error) {
79
83
  func (flateCompression) NewWriter(w io.Writer) (io.WriteCloser, error) {
80
84
  return flate.NewWriter(w, flate.BestSpeed)
81
85
  }
86
+
87
+ // --------------------------------------------------------------------
88
+
89
+ // ZstdCompression supports zstd compression format.
90
+ var ZstdCompression = zstdCompression{}
91
+
92
+ type zstdCompression struct{}
93
+
94
+ func (zstdCompression) NewReader(r io.Reader) (io.ReadCloser, error) {
95
+ zr, err := zstd.NewReader(r)
96
+ if err != nil {
97
+ return nil, err
98
+ }
99
+ return zstdDecoder{Decoder: zr}, nil
100
+ }
101
+
102
+ func (zstdCompression) NewWriter(w io.Writer) (io.WriteCloser, error) {
103
+ return zstd.NewWriter(w)
104
+ }
105
+
106
+ type zstdDecoder struct {
107
+ *zstd.Decoder
108
+ }
109
+
110
+ func (zstdDecoder) Close() error { return nil }
data/compression_test.go CHANGED
@@ -2,77 +2,89 @@ package feedx_test
2
2
 
3
3
  import (
4
4
  "bytes"
5
+ "testing"
5
6
 
6
7
  "github.com/bsm/feedx"
7
- . "github.com/bsm/ginkgo"
8
- . "github.com/bsm/gomega"
9
8
  )
10
9
 
11
- var _ = Describe("Compression", func() {
12
- var data = bytes.Repeat([]byte("wxyz"), 1024)
13
-
14
- runSharedTest := func(subject feedx.Compression) {
15
- buf := new(bytes.Buffer)
16
-
17
- w, err := subject.NewWriter(buf)
18
- Expect(err).NotTo(HaveOccurred())
19
- defer w.Close()
20
-
21
- Expect(w.Write(data)).To(Equal(4096))
22
- Expect(w.Write(data)).To(Equal(4096))
23
- Expect(w.Close()).To(Succeed())
24
-
25
- r, err := subject.NewReader(buf)
26
- Expect(err).NotTo(HaveOccurred())
27
- defer r.Close()
28
-
29
- p := make([]byte, 20)
30
- Expect(r.Read(p)).To(Equal(20))
31
- Expect(string(p)).To(Equal("wxyzwxyzwxyzwxyzwxyz"))
32
- Expect(r.Close()).To(Succeed())
10
+ func TestDetectCompression(t *testing.T) {
11
+ examples := []struct {
12
+ Input string
13
+ Exp feedx.Compression
14
+ }{
15
+ {Input: "/path/to/file.json", Exp: feedx.NoCompression},
16
+ {Input: "/path/to/file.json.gz", Exp: feedx.GZipCompression},
17
+ {Input: "/path/to/file.jsonz", Exp: feedx.GZipCompression},
18
+ {Input: "/path/to/file.pb", Exp: feedx.NoCompression},
19
+ {Input: "/path/to/file.pb.gz", Exp: feedx.GZipCompression},
20
+ {Input: "/path/to/file.pbz", Exp: feedx.GZipCompression},
21
+ {Input: "/path/to/file.flate", Exp: feedx.FlateCompression},
22
+ {Input: "/path/to/file.whatever.flate", Exp: feedx.FlateCompression},
23
+ {Input: "/path/to/file.zst", Exp: feedx.ZstdCompression},
24
+ {Input: "", Exp: feedx.NoCompression},
25
+ {Input: "/path/to/file", Exp: feedx.NoCompression},
26
+ {Input: "/path/to/file.txt", Exp: feedx.NoCompression},
33
27
  }
28
+ for _, x := range examples {
29
+ if got := feedx.DetectCompression(x.Input); got != x.Exp {
30
+ t.Errorf("expected %s for %q, but got %s", x.Exp, x.Input, got)
31
+ }
32
+ }
33
+ }
34
34
 
35
- It("detects the format", func() {
36
- Expect(feedx.DetectCompression("/path/to/file.json")).To(Equal(feedx.NoCompression))
37
- Expect(feedx.DetectCompression("/path/to/file.json.gz")).To(Equal(feedx.GZipCompression))
38
- Expect(feedx.DetectCompression("/path/to/file.jsonz")).To(Equal(feedx.GZipCompression))
39
-
40
- Expect(feedx.DetectCompression("/path/to/file.pb")).To(Equal(feedx.NoCompression))
41
- Expect(feedx.DetectCompression("/path/to/file.pb.gz")).To(Equal(feedx.GZipCompression))
42
- Expect(feedx.DetectCompression("/path/to/file.pbz")).To(Equal(feedx.GZipCompression))
43
-
44
- Expect(feedx.DetectCompression("/path/to/file.flate")).To(Equal(feedx.FlateCompression))
45
- Expect(feedx.DetectCompression("/path/to/file.whatever.flate")).To(Equal(feedx.FlateCompression))
35
+ func TestCompression(t *testing.T) {
36
+ data := bytes.Repeat([]byte("wxyz"), 1024)
46
37
 
47
- Expect(feedx.DetectCompression("")).To(Equal(feedx.NoCompression))
48
- Expect(feedx.DetectCompression("/path/to/file")).To(Equal(feedx.NoCompression))
49
- Expect(feedx.DetectCompression("/path/to/file.txt")).To(Equal(feedx.NoCompression))
38
+ t.Run("no compression", func(t *testing.T) {
39
+ testCompression(t, feedx.NoCompression, data)
50
40
  })
51
-
52
- Describe("NoCompression", func() {
53
- var subject = feedx.NoCompression
54
- var _ feedx.Compression = subject
55
-
56
- It("writes/reads", func() {
57
- runSharedTest(subject)
58
- })
41
+ t.Run("gzip", func(t *testing.T) {
42
+ testCompression(t, feedx.GZipCompression, data)
43
+ })
44
+ t.Run("flate", func(t *testing.T) {
45
+ testCompression(t, feedx.FlateCompression, data)
59
46
  })
47
+ t.Run("zstd", func(t *testing.T) {
48
+ testCompression(t, feedx.ZstdCompression, data)
49
+ })
50
+ }
60
51
 
61
- Describe("GZipCompression", func() {
62
- var subject = feedx.GZipCompression
63
- var _ feedx.Compression = subject
52
+ func testCompression(t *testing.T, c feedx.Compression, data []byte) {
53
+ t.Helper()
54
+ buf := new(bytes.Buffer)
64
55
 
65
- It("writes/reads", func() {
66
- runSharedTest(subject)
67
- })
68
- })
56
+ w, err := c.NewWriter(buf)
57
+ if err != nil {
58
+ t.Fatal("expected no error, got", err)
59
+ }
60
+ defer func() { _ = w.Close() }()
69
61
 
70
- Describe("FlateCompression", func() {
71
- var subject = feedx.FlateCompression
72
- var _ feedx.Compression = subject
62
+ if _, err := w.Write(data); err != nil {
63
+ t.Fatal("expected no error, got", err)
64
+ }
65
+ if _, err := w.Write(data); err != nil {
66
+ t.Fatal("expected no error, got", err)
67
+ }
68
+ if err := w.Close(); err != nil {
69
+ t.Fatal("expected no error, got", err)
70
+ }
73
71
 
74
- It("writes/reads", func() {
75
- runSharedTest(subject)
76
- })
77
- })
78
- })
72
+ r, err := c.NewReader(buf)
73
+ if err != nil {
74
+ t.Fatal("expected no error, got", err)
75
+ }
76
+ defer func() { _ = r.Close() }()
77
+
78
+ p := make([]byte, 20)
79
+ if n, err := r.Read(p); err != nil {
80
+ t.Fatal("expected no error, got", err)
81
+ } else if n != 20 {
82
+ t.Errorf("expected to read 20 bytes, got %d", n)
83
+ } else if exp, got := "wxyzwxyzwxyzwxyzwxyz", string(p); exp != got {
84
+ t.Errorf("expected %q, got %q", exp, got)
85
+ }
86
+
87
+ if err := r.Close(); err != nil {
88
+ t.Fatal("expected no error, got", err)
89
+ }
90
+ }