bio_readbuffer_test.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <openssl/bio.h>
  10. #include "testutil.h"
  11. static const char *filename = NULL;
  12. /*
  13. * Test that a BIO_f_readbuffer() with a BIO_new_file() behaves nicely if
  14. * BIO_gets() and BIO_read_ex() are both called.
  15. * Since the BIO_gets() calls buffer the reads, the BIO_read_ex() should
  16. * still be able to read the buffered data if we seek back to the start.
  17. *
  18. * The following cases are tested using tstid:
  19. * 0 : Just use BIO_read_ex().
  20. * 1 : Try a few reads using BIO_gets() before using BIO_read_ex()
  21. * 2 : Read the entire file using BIO_gets() before using BIO_read_ex().
  22. */
  23. static int test_readbuffer_file_bio(int tstid)
  24. {
  25. int ret = 0, len, partial;
  26. BIO *in = NULL, *in_bio = NULL, *readbuf_bio = NULL;
  27. char buf[255];
  28. char expected[4096];
  29. size_t readbytes = 0, bytes = 0, count = 0;
  30. /* Open a file BIO and read all the data */
  31. if (!TEST_ptr(in = BIO_new_file(filename, "r"))
  32. || !TEST_int_eq(BIO_read_ex(in, expected, sizeof(expected),
  33. &readbytes), 1)
  34. || !TEST_int_lt(readbytes, sizeof(expected)))
  35. goto err;
  36. BIO_free(in);
  37. in = NULL;
  38. /* Create a new file bio that sits under a readbuffer BIO */
  39. if (!TEST_ptr(readbuf_bio = BIO_new(BIO_f_readbuffer()))
  40. || !TEST_ptr(in_bio = BIO_new_file(filename, "r")))
  41. goto err;
  42. in_bio = BIO_push(readbuf_bio, in_bio);
  43. readbuf_bio = NULL;
  44. if (!TEST_int_eq(BIO_tell(in_bio), 0))
  45. goto err;
  46. if (tstid != 0) {
  47. partial = 4;
  48. while (!BIO_eof(in_bio)) {
  49. len = BIO_gets(in_bio, buf, sizeof(buf));
  50. if (len == 0) {
  51. if (!TEST_true(BIO_eof(in_bio)))
  52. goto err;
  53. } else {
  54. if (!TEST_int_gt(len, 0)
  55. || !TEST_int_le(len, (int)sizeof(buf) - 1))
  56. goto err;
  57. if (!TEST_true(buf[len] == 0))
  58. goto err;
  59. if (len > 1
  60. && !BIO_eof(in_bio)
  61. && len != ((int)sizeof(buf) - 1)
  62. && !TEST_true(buf[len - 1] == '\n'))
  63. goto err;
  64. }
  65. if (tstid == 1 && --partial == 0)
  66. break;
  67. }
  68. }
  69. if (!TEST_int_eq(BIO_seek(in_bio, 0), 1))
  70. goto err;
  71. len = 8; /* Do a small partial read to start with */
  72. while (!BIO_eof(in_bio)) {
  73. if (!TEST_int_eq(BIO_read_ex(in_bio, buf, len, &bytes), 1))
  74. break;
  75. if (!TEST_mem_eq(buf, bytes, expected + count, bytes))
  76. goto err;
  77. count += bytes;
  78. len = sizeof(buf); /* fill the buffer on subsequent reads */
  79. }
  80. if (!TEST_int_eq(count, readbytes))
  81. goto err;
  82. ret = 1;
  83. err:
  84. BIO_free(in);
  85. BIO_free_all(in_bio);
  86. BIO_free(readbuf_bio);
  87. return ret;
  88. }
  89. typedef enum OPTION_choice {
  90. OPT_ERR = -1,
  91. OPT_EOF = 0,
  92. OPT_TEST_ENUM
  93. } OPTION_CHOICE;
  94. const OPTIONS *test_get_options(void)
  95. {
  96. static const OPTIONS test_options[] = {
  97. OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("file\n"),
  98. { OPT_HELP_STR, 1, '-', "file\tFile to run tests on.\n" },
  99. { NULL }
  100. };
  101. return test_options;
  102. }
  103. int setup_tests(void)
  104. {
  105. OPTION_CHOICE o;
  106. while ((o = opt_next()) != OPT_EOF) {
  107. switch (o) {
  108. case OPT_TEST_CASES:
  109. break;
  110. default:
  111. return 0;
  112. }
  113. }
  114. filename = test_get_argument(0);
  115. ADD_ALL_TESTS(test_readbuffer_file_bio, 3);
  116. return 1;
  117. }