test_core_io.odin 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. package test_core_io
  2. import "core:bufio"
  3. import "core:bytes"
  4. import "core:io"
  5. import "core:log"
  6. import "core:os"
  7. import "core:os/os2"
  8. import "core:strings"
  9. import "core:testing"
  10. Passed_Tests :: distinct io.Stream_Mode_Set
  11. _test_stream :: proc(
  12. t: ^testing.T,
  13. stream: io.Stream,
  14. buffer: []u8,
  15. reading_consumes: bool = false,
  16. resets_on_empty: bool = false,
  17. do_destroy: bool = true,
  18. loc := #caller_location
  19. ) -> (passed: Passed_Tests, ok: bool) {
  20. // We only test what the stream reports to support.
  21. mode_set := io.query(stream)
  22. // Can't feature-test anything if Query isn't supported.
  23. testing.expectf(t, .Query in mode_set, "stream does not support .Query: %v", mode_set, loc = loc) or_return
  24. passed += { .Query }
  25. size := i64(len(buffer))
  26. // Do some basic Seek sanity testing.
  27. if .Seek in mode_set {
  28. pos, err := io.seek(stream, 0, io.Seek_From(-1))
  29. testing.expectf(t, err == .Invalid_Whence,
  30. "Seek(-1) didn't fail with Invalid_Whence: %v, %v", pos, err, loc = loc) or_return
  31. pos, err = io.seek(stream, 0, .Start)
  32. testing.expectf(t, pos == 0 && err == nil,
  33. "Seek Start isn't 0: %v, %v", pos, err, loc = loc) or_return
  34. pos, err = io.seek(stream, 0, .Current)
  35. testing.expectf(t, pos == 0 && err == nil,
  36. "Seek Current isn't 0 at the start: %v, %v", pos, err, loc = loc) or_return
  37. pos, err = io.seek(stream, -1, .Start)
  38. testing.expectf(t, err == .Invalid_Offset,
  39. "Seek Start-1 wasn't Invalid_Offset: %v, %v", pos, err, loc = loc) or_return
  40. pos, err = io.seek(stream, -1, .Current)
  41. testing.expectf(t, err == .Invalid_Offset,
  42. "Seek Current-1 wasn't Invalid_Offset: %v, %v", pos, err, loc = loc) or_return
  43. pos, err = io.seek(stream, 0, .End)
  44. testing.expectf(t, pos == size && err == nil,
  45. "Seek End+0 failed: %v != size<%i>, %v", pos, size, err, loc = loc) or_return
  46. pos, err = io.seek(stream, 0, .Current)
  47. testing.expectf(t, pos == size && err == nil,
  48. "Seek Current isn't size<%v> at the End: %v, %v", size, pos, err, loc = loc) or_return
  49. // Seeking past the End is accepted throughout the API.
  50. //
  51. // It's _reading_ past the End which is erroneous.
  52. pos, err = io.seek(stream, 1, .End)
  53. testing.expectf(t, pos == size+1 && err == nil,
  54. "Seek End+1 failed: %v, %v", pos, err, loc = loc) or_return
  55. // Reset our position for future tests.
  56. pos, err = io.seek(stream, 0, .Start)
  57. testing.expectf(t, pos == 0 && err == nil,
  58. "Seek Start reset failed: %v, %v", pos, err, loc = loc) or_return
  59. passed += { .Seek }
  60. }
  61. // Test Size.
  62. if .Size in mode_set {
  63. api_size, size_err := io.size(stream)
  64. testing.expectf(t, api_size == size,
  65. "Size reports %v for its size; expected %v", api_size, size, loc = loc) or_return
  66. testing.expectf(t, size_err == nil,
  67. "Size expected no error: %v", size_err, loc = loc) or_return
  68. // Ensure Size does not move the underlying pointer from the start.
  69. //
  70. // Some implementations may use seeking to determine file sizes.
  71. if .Seek in mode_set {
  72. pos, seek_err := io.seek(stream, 0, .Current)
  73. testing.expectf(t, pos == 0 && seek_err == nil,
  74. "Size+Seek Current isn't 0 after getting size: %v, %v", pos, seek_err, loc = loc) or_return
  75. }
  76. passed += { .Size }
  77. }
  78. // Test Read_At.
  79. if .Read_At in mode_set {
  80. // Test reading into an empty buffer.
  81. {
  82. nil_slice: []u8
  83. bytes_read, err := io.read_at(stream, nil_slice, 0)
  84. testing.expectf(t, bytes_read == 0 && err == nil,
  85. "Read_At into empty slice failed: bytes_read<%v>, %v", bytes_read, err, loc = loc) or_return
  86. }
  87. read_buf, alloc_err := make([]u8, size)
  88. testing.expect_value(t, alloc_err, nil, loc = loc) or_return
  89. defer delete(read_buf)
  90. for start in 0..<size {
  91. for end in 1+start..<size {
  92. subsize := end - start
  93. bytes_read, err := io.read_at(stream, read_buf[:subsize], start)
  94. testing.expectf(t, i64(bytes_read) == subsize && err == nil,
  95. "Read_At(%i) of %v bytes failed: %v, %v", start, subsize, bytes_read, err, loc = loc) or_return
  96. testing.expectf(t, bytes.compare(read_buf[:subsize], buffer[start:end]) == 0,
  97. "Read_At buffer compare failed: read_buf<%v> != buffer<%v>", read_buf, buffer, loc = loc) or_return
  98. }
  99. }
  100. // Test empty streams and EOF.
  101. one_buf: [1]u8
  102. bytes_read, err := io.read_at(stream, one_buf[:], size)
  103. testing.expectf(t, err == .EOF,
  104. "Read_At at end of stream failed: %v, %v", bytes_read, err, loc = loc) or_return
  105. // Make sure size is still sane.
  106. if .Size in mode_set {
  107. api_size, size_err := io.size(stream)
  108. testing.expectf(t, api_size == size,
  109. "Read_At+Size reports %v for its size after Read_At tests; expected %v", api_size, size, loc = loc) or_return
  110. testing.expectf(t, size_err == nil,
  111. "Read_At+Size expected no error: %v", size_err, loc = loc) or_return
  112. }
  113. // Ensure Read_At does not move the underlying pointer from the start.
  114. if .Seek in mode_set {
  115. pos, seek_err := io.seek(stream, 0, .Current)
  116. testing.expectf(t, pos == 0 && seek_err == nil,
  117. "Read_At+Seek Current isn't 0 after reading: %v, %v", pos, seek_err, loc = loc) or_return
  118. }
  119. passed += { .Read_At }
  120. }
  121. // Test Read.
  122. if .Read in mode_set {
  123. // Test reading into an empty buffer.
  124. {
  125. nil_slice: []u8
  126. bytes_read, err := io.read(stream, nil_slice)
  127. testing.expectf(t, bytes_read == 0 && err == nil,
  128. "Read into empty slice failed: bytes_read<%v>, %v", bytes_read, err, loc = loc) or_return
  129. }
  130. if size > 0 {
  131. read_buf, alloc_err := make([]u8, size)
  132. testing.expectf(t, alloc_err == nil, "allocation failed", loc = loc) or_return
  133. defer delete(read_buf)
  134. bytes_read, err := io.read(stream, read_buf[:1])
  135. testing.expectf(t, bytes_read == 1 && err == nil,
  136. "Read 1 byte at start failed: %v, %v", bytes_read, err, loc = loc) or_return
  137. testing.expectf(t, read_buf[0] == buffer[0],
  138. "Read of first byte failed: read_buf[0]<%v> != buffer[0]<%v>", read_buf[0], buffer[0], loc = loc) or_return
  139. // Test rolling back the stream one byte then reading it again.
  140. if .Seek in mode_set {
  141. pos, seek_err := io.seek(stream, -1, .Current)
  142. testing.expectf(t, pos == 0 && err == nil,
  143. "Read+Seek Current-1 reset to 0 failed: %v, %v", pos, seek_err, loc = loc) or_return
  144. bytes_read, err = io.read(stream, read_buf[:1])
  145. testing.expectf(t, bytes_read == 1 && err == nil,
  146. "Read 1 byte at start after Seek reset failed: %v, %v", bytes_read, err, loc = loc) or_return
  147. testing.expectf(t, read_buf[0] == buffer[0] ,
  148. "re-Read of first byte failed: read_buf[0]<%v> != buffer[0]<%v>", read_buf[0], buffer[0], loc = loc) or_return
  149. }
  150. // Make sure size is still sane.
  151. if .Size in mode_set {
  152. api_size, size_err := io.size(stream)
  153. expected_api_size := size - 1 if reading_consumes else size
  154. testing.expectf(t, api_size == expected_api_size,
  155. "Read+Size reports %v for its size after Read tests; expected %v", api_size, expected_api_size, loc = loc) or_return
  156. testing.expectf(t, size_err == nil,
  157. "Read+Size expected no error: %v", size_err, loc = loc) or_return
  158. }
  159. // Read the rest.
  160. if size > 1 {
  161. bytes_read, err = io.read(stream, read_buf[1:])
  162. testing.expectf(t, i64(bytes_read) == size - 1 && err == nil,
  163. "Read rest of stream failed: %v != %v, %v", bytes_read, size-1, err, loc = loc) or_return
  164. testing.expectf(t, bytes.compare(read_buf, buffer) == 0,
  165. "Read buffer compare failed: read_buf<%v> != buffer<%v>", read_buf, buffer, loc = loc) or_return
  166. }
  167. }
  168. // Test empty streams and EOF.
  169. one_buf: [1]u8
  170. bytes_read, err := io.read(stream, one_buf[:])
  171. testing.expectf(t, err == .EOF,
  172. "Read at end of stream failed: %v, %v", bytes_read, err, loc = loc) or_return
  173. if !resets_on_empty && .Size in mode_set {
  174. // Make sure size is still sane.
  175. api_size, size_err := io.size(stream)
  176. testing.expectf(t, api_size == size,
  177. "Read+Size reports %v for its size after Read tests; expected %v", api_size, size, loc = loc) or_return
  178. testing.expectf(t, size_err == nil,
  179. "Read+Size expected no error: %v", size_err, loc = loc) or_return
  180. }
  181. passed += { .Read }
  182. }
  183. // Test Write_At.
  184. if .Write_At in mode_set {
  185. // Test writing from an empty buffer.
  186. {
  187. nil_slice: []u8
  188. bytes_written, err := io.write_at(stream, nil_slice, 0)
  189. testing.expectf(t, bytes_written == 0 && err == nil,
  190. "Write_At from empty slice failed: bytes_written<%v>, %v", bytes_written, err, loc = loc) or_return
  191. }
  192. // Ensure Write_At does not move the underlying pointer from the start.
  193. starting_offset : i64 = -1
  194. if .Seek in mode_set {
  195. pos, seek_err := io.seek(stream, 0, .Current)
  196. testing.expectf(t, pos >= 0 && seek_err == nil,
  197. "Write_At+Seek Current failed: %v, %v", pos, seek_err, loc = loc) or_return
  198. starting_offset = pos
  199. }
  200. if size > 0 {
  201. write_buf, write_buf_alloc_err := make([]u8, size)
  202. testing.expectf(t, write_buf_alloc_err == nil, "allocation failed", loc = loc) or_return
  203. defer delete(write_buf)
  204. for i in 0..<size {
  205. write_buf[i] = buffer[i] ~ 0xAA
  206. }
  207. bytes_written, write_err := io.write_at(stream, write_buf[:], 0)
  208. testing.expectf(t, i64(bytes_written) == size && write_err == nil,
  209. "Write_At failed: bytes_written<%v> != size<%v>: %v", bytes_written, size, write_err, loc = loc) or_return
  210. // Test reading what we've written.
  211. if .Read_At in mode_set {
  212. read_buf, read_buf_alloc_err := make([]u8, size)
  213. testing.expectf(t, read_buf_alloc_err == nil, "allocation failed", loc = loc) or_return
  214. defer delete(read_buf)
  215. bytes_read, read_err := io.read_at(stream, read_buf[:], 0)
  216. testing.expectf(t, i64(bytes_read) == size && read_err == nil,
  217. "Write_At+Read_At failed: bytes_read<%i> != size<%i>, %v", bytes_read, size, read_err, loc = loc) or_return
  218. testing.expectf(t, bytes.compare(read_buf, write_buf) == 0,
  219. "Write_At+Read_At buffer compare failed: write_buf<%v> != read_buf<%v>", write_buf, read_buf, loc = loc) or_return
  220. }
  221. } else {
  222. // Expect that it should be okay to write a single byte to an empty stream.
  223. x_buf: [1]u8 = { 'Z' }
  224. bytes_written, write_err := io.write_at(stream, x_buf[:], 0)
  225. testing.expectf(t, i64(bytes_written) == 1 && write_err == nil,
  226. "Write_At(0) with 'Z' on empty stream failed: bytes_written<%v>, %v", bytes_written, write_err, loc = loc) or_return
  227. // Test reading what we've written.
  228. if .Read_At in mode_set {
  229. x_buf[0] = 0
  230. bytes_read, read_err := io.read_at(stream, x_buf[:], 0)
  231. testing.expectf(t, i64(bytes_read) == 1 && read_err == nil,
  232. "Write_At(0)+Read_At(0) failed expectation: bytes_read<%v> != 1, %q != 'Z', %v", bytes_read, x_buf[0], read_err, loc = loc) or_return
  233. }
  234. }
  235. // Ensure Write_At does not move the underlying pointer from the start.
  236. if starting_offset != -1 && .Seek in mode_set {
  237. pos, seek_err := io.seek(stream, 0, .Current)
  238. testing.expectf(t, pos == starting_offset && seek_err == nil,
  239. "Write_At+Seek Current isn't %v after writing: %v, %v", starting_offset, pos, seek_err, loc = loc) or_return
  240. }
  241. passed += { .Write_At }
  242. }
  243. // Test Write.
  244. if .Write in mode_set {
  245. // Test writing from an empty buffer.
  246. {
  247. nil_slice: []u8
  248. bytes_written, err := io.write(stream, nil_slice)
  249. testing.expectf(t, bytes_written == 0 && err == nil,
  250. "Write from empty slice failed: bytes_written<%v>, %v", bytes_written, err, loc = loc) or_return
  251. }
  252. write_buf, write_buf_alloc_err := make([]u8, size)
  253. testing.expectf(t, write_buf_alloc_err == nil, "allocation failed", loc = loc) or_return
  254. defer delete(write_buf)
  255. for i in 0..<size {
  256. write_buf[i] = buffer[i] ~ 0xAA
  257. }
  258. pos: i64 = -1
  259. before_write_size: i64 = -1
  260. // Do a Seek sanity check after past tests.
  261. if .Seek in mode_set {
  262. seek_err: io.Error
  263. pos, seek_err = io.seek(stream, 0, .Current)
  264. testing.expectf(t, seek_err == nil,
  265. "Write+Seek(Current) failed: pos<%i>, %v", pos, seek_err) or_return
  266. }
  267. // Get the Size before writing.
  268. if .Size in mode_set {
  269. size_err: io.Error
  270. before_write_size, size_err = io.size(stream)
  271. testing.expectf(t, size_err == nil,
  272. "Write+Size failed: %v", size_err, loc = loc) or_return
  273. }
  274. bytes_written, write_err := io.write(stream, write_buf[:])
  275. testing.expectf(t, i64(bytes_written) == size && write_err == nil,
  276. "Write %i bytes failed: %i, %v", size, bytes_written, write_err, loc = loc) or_return
  277. // Size sanity check, part 2.
  278. if before_write_size >= 0 && .Size in mode_set {
  279. after_write_size, size_err := io.size(stream)
  280. testing.expectf(t, size_err == nil,
  281. "Write+Size.part_2 failed: %v", size_err, loc = loc) or_return
  282. testing.expectf(t, after_write_size == before_write_size + size,
  283. "Write+Size.part_2 failed: %v != %v + %v", after_write_size, before_write_size, size, loc = loc) or_return
  284. }
  285. // Test reading what we've written directly with Read_At.
  286. if pos >= 0 && .Read_At in mode_set {
  287. read_buf, read_buf_alloc_err := make([]u8, size)
  288. testing.expectf(t, read_buf_alloc_err == nil, "allocation failed", loc = loc) or_return
  289. defer delete(read_buf)
  290. bytes_read, read_err := io.read_at(stream, read_buf[:], pos)
  291. testing.expectf(t, i64(bytes_read) == size && read_err == nil,
  292. "Write+Read_At(%i) failed: bytes_read<%i> != size<%i>, %v", pos, bytes_read, size, read_err, loc = loc) or_return
  293. testing.expectf(t, bytes.compare(read_buf, write_buf) == 0,
  294. "Write+Read_At buffer compare failed: read_buf<%v> != write_buf<%v>", read_buf, write_buf, loc = loc) or_return
  295. }
  296. // Test resetting the pointer and reading what we've written with Read.
  297. if .Read in mode_set && .Seek in mode_set {
  298. seek_err: io.Error
  299. pos, seek_err = io.seek(stream, 0, .Start)
  300. testing.expectf(t, pos == 0 && seek_err == nil,
  301. "Write+Read+Seek(Start) failed: pos<%i>, %v", pos, seek_err) or_return
  302. read_buf, read_buf_alloc_err := make([]u8, size)
  303. testing.expectf(t, read_buf_alloc_err == nil, "allocation failed", loc = loc) or_return
  304. defer delete(read_buf)
  305. bytes_read, read_err := io.read(stream, read_buf[:])
  306. testing.expectf(t, i64(bytes_read) == size && read_err == nil,
  307. "Write+Read failed: bytes_read<%i> != size<%i>, %v", bytes_read, size, read_err, loc = loc) or_return
  308. testing.expectf(t, bytes.compare(read_buf, write_buf) == 0,
  309. "Write+Readbuffer compare failed: read_buf<%v> != write_buf<%v>", read_buf, write_buf, loc = loc) or_return
  310. }
  311. passed += { .Write }
  312. }
  313. // Test the other modes.
  314. if .Flush in mode_set {
  315. err := io.flush(stream)
  316. testing.expectf(t, err == nil, "stream failed to Flush: %v", err, loc = loc) or_return
  317. passed += { .Flush }
  318. }
  319. if .Close in mode_set {
  320. close_err := io.close(stream)
  321. testing.expectf(t, close_err == nil, "stream failed to Close: %v", close_err, loc = loc) or_return
  322. passed += { .Close }
  323. }
  324. if do_destroy && .Destroy in mode_set {
  325. err := io.destroy(stream)
  326. testing.expectf(t, err == nil, "stream failed to Destroy: %v", err, loc = loc) or_return
  327. passed += { .Destroy }
  328. }
  329. ok = true
  330. return
  331. }
  332. @test
  333. test_bytes_reader :: proc(t: ^testing.T) {
  334. buf: [32]u8
  335. for i in 0..<u8(len(buf)) {
  336. buf[i] = 'A' + i
  337. }
  338. br: bytes.Reader
  339. results: Passed_Tests
  340. ok: bool
  341. for end in 0..<i64(len(buf)) {
  342. results, ok =_test_stream(t, bytes.reader_init(&br, buf[:end]), buf[:end])
  343. if !ok {
  344. log.debugf("buffer[:%i] := %v", end, buf[:end])
  345. return
  346. }
  347. }
  348. log.debugf("%#v", results)
  349. }
  350. @test
  351. test_bytes_buffer_stream :: proc(t: ^testing.T) {
  352. buf: [32]u8
  353. for i in 0..<u8(len(buf)) {
  354. buf[i] = 'A' + i
  355. }
  356. results: Passed_Tests
  357. ok: bool
  358. for end in 0..<i64(len(buf)) {
  359. bb: bytes.Buffer
  360. // Mind that `bytes.buffer_init` copies the entire underlying slice.
  361. bytes.buffer_init(&bb, buf[:end])
  362. // `bytes.Buffer` has a behavior of decreasing its size with each read
  363. // until it eventually clears the underlying buffer when it runs out of
  364. // data to read.
  365. results, ok = _test_stream(t, bytes.buffer_to_stream(&bb), buf[:end],
  366. reading_consumes = true, resets_on_empty = true)
  367. if !ok {
  368. log.debugf("buffer[:%i] := %v", end, buf[:end])
  369. return
  370. }
  371. }
  372. log.debugf("%#v", results)
  373. }
  374. @test
  375. test_limited_reader :: proc(t: ^testing.T) {
  376. buf: [32]u8
  377. for i in 0..<u8(len(buf)) {
  378. buf[i] = 'A' + i
  379. }
  380. br: bytes.Reader
  381. bs := bytes.reader_init(&br, buf[:])
  382. lr: io.Limited_Reader
  383. results: Passed_Tests
  384. ok: bool
  385. for end in 0..<i64(len(buf)) {
  386. pos, seek_err := io.seek(bs, 0, .Start)
  387. if !testing.expectf(t, pos == 0 && seek_err == nil,
  388. "Pre-test Seek reset failed: pos<%v>, %v", pos, seek_err) {
  389. return
  390. }
  391. results, ok = _test_stream(t, io.limited_reader_init(&lr, bs, end), buf[:end])
  392. if !ok {
  393. log.debugf("buffer[:%i] := %v", end, buf[:end])
  394. return
  395. }
  396. }
  397. log.debugf("%#v", results)
  398. }
  399. @test
  400. test_section_reader :: proc(t: ^testing.T) {
  401. buf: [32]u8
  402. for i in 0..<u8(len(buf)) {
  403. buf[i] = 'A' + i
  404. }
  405. br: bytes.Reader
  406. bs := bytes.reader_init(&br, buf[:])
  407. sr: io.Section_Reader
  408. results: Passed_Tests
  409. ok: bool
  410. for start in 0..<i64(len(buf)) {
  411. for end in start..<i64(len(buf)) {
  412. results, ok = _test_stream(t, io.section_reader_init(&sr, bs, start, end-start), buf[start:end])
  413. if !ok {
  414. log.debugf("buffer[%i:%i] := %v", start, end, buf[start:end])
  415. return
  416. }
  417. }
  418. }
  419. log.debugf("%#v", results)
  420. }
  421. @test
  422. test_string_builder_stream :: proc(t: ^testing.T) {
  423. sb := strings.builder_make()
  424. defer strings.builder_destroy(&sb)
  425. // String builders do not support reading, so we'll have to set up a few
  426. // things outside the main test.
  427. buf: [32]u8
  428. expected_buf: [64]u8
  429. for i in 0..<u8(len(buf)) {
  430. buf[i] = 'A' + i
  431. expected_buf[i] = 'A' + i
  432. strings.write_byte(&sb, 'A' + i)
  433. }
  434. for i in 32..<u8(len(expected_buf)) {
  435. expected_buf[i] = ('A' + i-len(buf)) ~ 0xAA
  436. }
  437. results, _ := _test_stream(t, strings.to_stream(&sb), buf[:],
  438. do_destroy = false)
  439. testing.expectf(t, bytes.compare(sb.buf[:], expected_buf[:]) == 0, "string builder stream failed:\nbuilder<%q>\n!=\nbuffer <%q>", sb.buf[:], expected_buf[:])
  440. log.debugf("%#v", results)
  441. }
  442. @test
  443. test_os_file_stream :: proc(t: ^testing.T) {
  444. defer if !testing.failed(t) {
  445. testing.expect_value(t, os.remove(TEMPORARY_FILENAME), nil)
  446. }
  447. buf: [32]u8
  448. for i in 0..<u8(len(buf)) {
  449. buf[i] = 'A' + i
  450. }
  451. TEMPORARY_FILENAME :: "test_core_io_os_file_stream"
  452. fd, open_err := os.open(TEMPORARY_FILENAME, os.O_RDWR | os.O_CREATE | os.O_TRUNC, 0o644)
  453. if !testing.expectf(t, open_err == nil, "error on opening %q: %v", TEMPORARY_FILENAME, open_err) {
  454. return
  455. }
  456. stream := os.stream_from_handle(fd)
  457. bytes_written, write_err := io.write(stream, buf[:])
  458. if !testing.expectf(t, bytes_written == len(buf) && write_err == nil,
  459. "failed to Write initial buffer: bytes_written<%v> != len_buf<%v>, %v", bytes_written, len(buf), write_err) {
  460. return
  461. }
  462. flush_err := io.flush(stream)
  463. if !testing.expectf(t, flush_err == nil,
  464. "failed to Flush initial buffer: %v", write_err) {
  465. return
  466. }
  467. results, _ := _test_stream(t, stream, buf[:])
  468. log.debugf("%#v", results)
  469. }
  470. @test
  471. test_os2_file_stream :: proc(t: ^testing.T) {
  472. defer if !testing.failed(t) {
  473. testing.expect_value(t, os2.remove(TEMPORARY_FILENAME), nil)
  474. }
  475. buf: [32]u8
  476. for i in 0..<u8(len(buf)) {
  477. buf[i] = 'A' + i
  478. }
  479. TEMPORARY_FILENAME :: "test_core_io_os2_file_stream"
  480. fd, open_err := os2.open(TEMPORARY_FILENAME, {.Read, .Write, .Create, .Trunc})
  481. if !testing.expectf(t, open_err == nil, "error on opening %q: %v", TEMPORARY_FILENAME, open_err) {
  482. return
  483. }
  484. stream := os2.to_stream(fd)
  485. bytes_written, write_err := io.write(stream, buf[:])
  486. if !testing.expectf(t, bytes_written == len(buf) && write_err == nil,
  487. "failed to Write initial buffer: bytes_written<%v> != len_buf<%v>, %v", bytes_written, len(buf), write_err) {
  488. return
  489. }
  490. flush_err := io.flush(stream)
  491. if !testing.expectf(t, flush_err == nil,
  492. "failed to Flush initial buffer: %v", write_err) {
  493. return
  494. }
  495. // os2 file stream proc close and destroy are the same.
  496. results, _ := _test_stream(t, stream, buf[:], do_destroy = false)
  497. log.debugf("%#v", results)
  498. }
  499. @test
  500. test_bufio_buffered_writer :: proc(t: ^testing.T) {
  501. // Using a strings.Builder as the backing stream.
  502. sb := strings.builder_make()
  503. defer strings.builder_destroy(&sb)
  504. buf: [32]u8
  505. expected_buf: [64]u8
  506. for i in 0..<u8(len(buf)) {
  507. buf[i] = 'A' + i
  508. expected_buf[i] = 'A' + i
  509. strings.write_byte(&sb, 'A' + i)
  510. }
  511. for i in 32..<u8(len(expected_buf)) {
  512. expected_buf[i] = ('A' + i-len(buf)) ~ 0xAA
  513. }
  514. writer: bufio.Writer
  515. bufio.writer_init(&writer, strings.to_stream(&sb))
  516. defer bufio.writer_destroy(&writer)
  517. results, _ := _test_stream(t, bufio.writer_to_stream(&writer), buf[:],
  518. do_destroy = false)
  519. testing.expectf(t, bytes.compare(sb.buf[:], expected_buf[:]) == 0, "bufio buffered string builder stream failed:\nbuilder<%q>\n!=\nbuffer <%q>", sb.buf[:], expected_buf[:])
  520. log.debugf("%#v", results)
  521. }
  522. @test
  523. test_bufio_buffered_reader :: proc(t: ^testing.T) {
  524. // Using a bytes.Reader as the backing stream.
  525. buf: [32]u8
  526. for i in 0..<u8(len(buf)) {
  527. buf[i] = 'A' + i
  528. }
  529. results: Passed_Tests
  530. ok: bool
  531. for end in 0..<i64(len(buf)) {
  532. br: bytes.Reader
  533. bs := bytes.reader_init(&br, buf[:end])
  534. reader: bufio.Reader
  535. bufio.reader_init(&reader, bs)
  536. defer bufio.reader_destroy(&reader)
  537. results, ok = _test_stream(t, bufio.reader_to_stream(&reader), buf[:end])
  538. if !ok {
  539. log.debugf("buffer[:%i] := %v", end, buf[:end])
  540. return
  541. }
  542. }
  543. log.debugf("%#v", results)
  544. }
  545. @test
  546. test_bufio_buffered_read_writer :: proc(t: ^testing.T) {
  547. // Using an os2.File as the backing stream for both reader & writer.
  548. defer if !testing.failed(t) {
  549. testing.expect_value(t, os2.remove(TEMPORARY_FILENAME), nil)
  550. }
  551. buf: [32]u8
  552. for i in 0..<u8(len(buf)) {
  553. buf[i] = 'A' + i
  554. }
  555. TEMPORARY_FILENAME :: "test_core_io_bufio_read_writer_os2_file_stream"
  556. fd, open_err := os2.open(TEMPORARY_FILENAME, {.Read, .Write, .Create, .Trunc})
  557. if !testing.expectf(t, open_err == nil, "error on opening %q: %v", TEMPORARY_FILENAME, open_err) {
  558. return
  559. }
  560. defer testing.expect_value(t, os2.close(fd), nil)
  561. stream := os2.to_stream(fd)
  562. bytes_written, write_err := io.write(stream, buf[:])
  563. if !testing.expectf(t, bytes_written == len(buf) && write_err == nil,
  564. "failed to Write initial buffer: bytes_written<%v> != len_buf<%v>, %v", bytes_written, len(buf), write_err) {
  565. return
  566. }
  567. flush_err := io.flush(stream)
  568. if !testing.expectf(t, flush_err == nil,
  569. "failed to Flush initial buffer: %v", write_err) {
  570. return
  571. }
  572. // bufio.Read_Writer isn't capable of seeking, so we have to reset the os2
  573. // stream back to the start here.
  574. pos, seek_err := io.seek(stream, 0, .Start)
  575. if !testing.expectf(t, pos == 0 && seek_err == nil,
  576. "Pre-test Seek reset failed: pos<%v>, %v", pos, seek_err) {
  577. return
  578. }
  579. reader: bufio.Reader
  580. writer: bufio.Writer
  581. read_writer: bufio.Read_Writer
  582. bufio.reader_init(&reader, stream)
  583. defer bufio.reader_destroy(&reader)
  584. bufio.writer_init(&writer, stream)
  585. defer bufio.writer_destroy(&writer)
  586. bufio.read_writer_init(&read_writer, &reader, &writer)
  587. // os2 file stream proc close and destroy are the same.
  588. results, _ := _test_stream(t, bufio.read_writer_to_stream(&read_writer), buf[:], do_destroy = false)
  589. log.debugf("%#v", results)
  590. }