@@ -16,6 +16,12 @@ import (
16
16
"testing"
17
17
)
18
18
19
+ // Verify interface implementations
20
+ var _ io.Reader = & SQLiteBlob {}
21
+ var _ io.Writer = & SQLiteBlob {}
22
+ var _ io.Seeker = & SQLiteBlob {}
23
+ var _ io.Closer = & SQLiteBlob {}
24
+
19
25
func blobTestData (dbname string , rowid int64 , blob []byte ) (* sql.DB , * SQLiteConn , error ) {
20
26
db , err := sql .Open ("sqlite3" , "file:" + dbname + "?mode=memory&cache=shared" )
21
27
if err != nil {
@@ -54,11 +60,11 @@ func blobTestData(dbname string, rowid int64, blob []byte) (*sql.DB, *SQLiteConn
54
60
return db , driverConn , nil
55
61
}
56
62
57
- func TestBlobIO (t * testing.T ) {
63
+ func TestBlobRead (t * testing.T ) {
58
64
rowid := int64 (6581 )
59
65
expected := []byte ("I ❤️ SQLite in \x00 \x01 \x02 …" )
60
66
61
- db , driverConn , err := blobTestData ("testblobio " , rowid , expected )
67
+ db , driverConn , err := blobTestData ("testblobread " , rowid , expected )
62
68
if err != nil {
63
69
t .Fatal ("Failed to get raw connection:" , err )
64
70
}
@@ -109,3 +115,137 @@ func TestBlobIO(t *testing.T) {
109
115
t .Error ("Expected EOF" , err )
110
116
}
111
117
}
118
+
119
+ func TestBlobWrite (t * testing.T ) {
120
+ rowid := int64 (8580 )
121
+ expected := []byte {
122
+ // Random data from /dev/urandom
123
+ 0xe5 , 0x48 , 0x94 , 0xad , 0xa6 , 0x7c , 0x81 , 0xa2 , 0x70 , 0x07 , 0x79 , 0x60 ,
124
+ 0x33 , 0xbc , 0x64 , 0x33 , 0x8f , 0x48 , 0x43 , 0xa6 , 0x33 , 0x5c , 0x08 , 0x32 ,
125
+ }
126
+
127
+ // Allocate a zero blob
128
+ data := make ([]byte , len (expected ))
129
+ db , driverConn , err := blobTestData ("testblobwrite" , rowid , data )
130
+ if err != nil {
131
+ t .Fatal ("Failed to get raw connection:" , err )
132
+ }
133
+ defer driverConn .Close ()
134
+ defer db .Close ()
135
+
136
+ // Open blob for read/write
137
+ blob , err := driverConn .Blob ("main" , "data" , "value" , rowid , 1 )
138
+ if err != nil {
139
+ t .Error ("failed" , err )
140
+ }
141
+ defer blob .Close ()
142
+
143
+ // Write blob incrementally
144
+ middle := len (expected ) / 2
145
+ first := expected [:middle ]
146
+ second := expected [middle :]
147
+
148
+ // Write part Ⅰ
149
+ n1 , err := blob .Write (first )
150
+
151
+ if err != nil || n1 != len (first ) {
152
+ t .Errorf ("Failed to write %d bytes" , n1 )
153
+ }
154
+
155
+ // Write part Ⅱ
156
+ n2 , err := blob .Write (second )
157
+
158
+ if err != nil || n2 != len (second ) {
159
+ t .Errorf ("Failed to write %d bytes" , n2 )
160
+ }
161
+
162
+ // EOF
163
+ b3 := make ([]byte , 10 )
164
+ n3 , err := blob .Write (b3 )
165
+
166
+ if err != io .EOF || n3 != 0 {
167
+ t .Error ("Expected EOF" , err )
168
+ }
169
+
170
+ // Verify written data
171
+ _ , err = blob .Seek (0 , io .SeekStart )
172
+ if err != nil {
173
+ t .Fatal ("Failed to seek:" , err )
174
+ }
175
+
176
+ b4 := make ([]byte , len (expected ))
177
+ n4 , err := blob .Read (b4 )
178
+
179
+ if err != nil || n4 != len (b4 ) {
180
+ t .Errorf ("Failed to read %d bytes" , n4 )
181
+ }
182
+
183
+ if bytes .Compare (expected , b4 ) != 0 {
184
+ t .Error ("Expected\n " , expected , "got\n " , b4 )
185
+ }
186
+ }
187
+
188
+ func TestBlobSeek (t * testing.T ) {
189
+ rowid := int64 (6510 )
190
+ data := make ([]byte , 1000 )
191
+
192
+ db , driverConn , err := blobTestData ("testblobseek" , rowid , data )
193
+ if err != nil {
194
+ t .Fatal ("Failed to get raw connection:" , err )
195
+ }
196
+ defer driverConn .Close ()
197
+ defer db .Close ()
198
+
199
+ // Open blob
200
+ blob , err := driverConn .Blob ("main" , "data" , "value" , rowid , 0 )
201
+ if err != nil {
202
+ t .Error ("failed" , err )
203
+ }
204
+ defer blob .Close ()
205
+
206
+ // Test data
207
+ begin := int64 (0 )
208
+ middle := int64 (len (data ) / 2 )
209
+ end := int64 (len (data ) - 1 )
210
+ eof := int64 (len (data ))
211
+
212
+ tests := []struct {
213
+ offset int64
214
+ whence int
215
+ expected int64
216
+ }{
217
+ {offset : begin , whence : io .SeekStart , expected : begin },
218
+ {offset : middle , whence : io .SeekStart , expected : middle },
219
+ {offset : end , whence : io .SeekStart , expected : end },
220
+ {offset : eof , whence : io .SeekStart , expected : eof },
221
+
222
+ {offset : - 1 , whence : io .SeekCurrent , expected : middle - 1 },
223
+ {offset : 0 , whence : io .SeekCurrent , expected : middle },
224
+ {offset : 1 , whence : io .SeekCurrent , expected : middle + 1 },
225
+ {offset : - middle , whence : io .SeekCurrent , expected : begin },
226
+
227
+ {offset : - 2 , whence : io .SeekEnd , expected : end - 1 },
228
+ {offset : - 1 , whence : io .SeekEnd , expected : end },
229
+ {offset : 0 , whence : io .SeekEnd , expected : eof },
230
+ {offset : 1 , whence : io .SeekEnd , expected : eof + 1 },
231
+ {offset : - eof , whence : io .SeekEnd , expected : begin },
232
+ }
233
+
234
+ for _ , tc := range tests {
235
+ // Start in the middle
236
+ _ , err := blob .Seek (middle , io .SeekStart )
237
+ if err != nil {
238
+ t .Fatal ("Failed to seek:" , err )
239
+ }
240
+
241
+ // Test
242
+ got , err := blob .Seek (tc .offset , tc .whence )
243
+ if err != nil {
244
+ t .Fatal ("Failed to seek:" , err )
245
+ }
246
+
247
+ if tc .expected != got {
248
+ t .Error ("For" , tc , "expected" , tc .expected , "got" , got )
249
+ }
250
+ }
251
+ }
0 commit comments