kunit-stream.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * C++ stream style string formatter and printer used in KUnit for outputting
  4. * KUnit messages.
  5. *
  6. * Copyright (C) 2020, Google LLC.
  7. * Author: Brendan Higgins <[email protected]>
  8. */
  9. #include <kunit/test.h>
  10. #include <kunit/kunit-stream.h>
  11. #include <kunit/string-stream.h>
  12. void kunit_stream_add(struct kunit_stream *kstream, const char *fmt, ...)
  13. {
  14. va_list args;
  15. struct string_stream *stream = kstream->internal_stream;
  16. va_start(args, fmt);
  17. if (string_stream_vadd(stream, fmt, args))
  18. kunit_err(kstream->test,
  19. "Failed to allocate fragment: %s\n",
  20. fmt);
  21. va_end(args);
  22. }
  23. EXPORT_SYMBOL_GPL(kunit_stream_add);
  24. void kunit_stream_append(struct kunit_stream *kstream,
  25. struct kunit_stream *other)
  26. {
  27. int ret;
  28. ret = string_stream_append(kstream->internal_stream,
  29. other->internal_stream);
  30. if (ret)
  31. kunit_err(kstream->test,
  32. "Failed to append other stream: %d\n", ret);
  33. }
  34. void kunit_stream_clear(struct kunit_stream *kstream)
  35. {
  36. string_stream_clear(kstream->internal_stream);
  37. }
  38. EXPORT_SYMBOL_GPL(kunit_stream_clear);
  39. void kunit_stream_commit(struct kunit_stream *kstream)
  40. {
  41. struct string_stream *stream = kstream->internal_stream;
  42. struct string_stream_fragment *fragment;
  43. struct kunit *test = kstream->test;
  44. char *buf;
  45. buf = string_stream_get_string(stream);
  46. if (!buf) {
  47. kunit_err(test,
  48. "Could not allocate buffer, dumping stream:\n");
  49. list_for_each_entry(fragment, &stream->fragments, node) {
  50. kunit_err(test, "%s", fragment->fragment);
  51. }
  52. kunit_err(test, "\n");
  53. } else {
  54. kunit_err(test, "%s", buf);
  55. }
  56. kunit_stream_clear(kstream);
  57. }
  58. EXPORT_SYMBOL_GPL(kunit_stream_commit);
  59. struct kunit_stream_alloc_context {
  60. struct kunit *test;
  61. gfp_t gfp;
  62. };
  63. static int kunit_stream_init(struct kunit_resource *res, void *context)
  64. {
  65. struct kunit_stream_alloc_context *ctx = context;
  66. struct kunit_stream *stream;
  67. stream = kunit_kzalloc(ctx->test, sizeof(*stream), ctx->gfp);
  68. if (!stream)
  69. return -ENOMEM;
  70. stream->test = ctx->test;
  71. stream->internal_stream = alloc_string_stream(ctx->test, ctx->gfp);
  72. if (!stream->internal_stream)
  73. return -ENOMEM;
  74. res->data = stream;
  75. return 0;
  76. }
  77. static void kunit_stream_free(struct kunit_resource *res)
  78. {
  79. /* Do nothing because cleanup is handled by KUnit managed resources */
  80. }
  81. struct kunit_stream *alloc_kunit_stream(struct kunit *test,
  82. gfp_t gfp)
  83. {
  84. struct kunit_stream_alloc_context ctx = {
  85. .test = test,
  86. .gfp = gfp
  87. };
  88. return kunit_alloc_resource(test,
  89. kunit_stream_init,
  90. kunit_stream_free,
  91. gfp,
  92. &ctx);
  93. }
  94. EXPORT_SYMBOL_GPL(alloc_kunit_stream);