// SPDX-License-Identifier: GPL-2.0
/*
 * C++ stream style string formatter and printer used in KUnit for outputting
 * KUnit messages.
 *
 * Copyright (C) 2019, Google LLC.
 * Author: Brendan Higgins <brendanhiggins@google.com>
 */

#include <kunit/test.h>
#include <kunit/kunit-stream.h>
#include <kunit/string-stream.h>

static const char *kunit_stream_get_level(struct kunit_stream *this)
{
	unsigned long flags;
	const char *level;

	spin_lock_irqsave(&this->lock, flags);
	level = this->level;
	spin_unlock_irqrestore(&this->lock, flags);

	return level;
}

void kunit_stream_set_level(struct kunit_stream *this, const char *level)
{
	unsigned long flags;

	spin_lock_irqsave(&this->lock, flags);
	this->level = level;
	spin_unlock_irqrestore(&this->lock, flags);
}

void kunit_stream_add(struct kunit_stream *this, const char *fmt, ...)
{
	va_list args;
	struct string_stream *stream = this->internal_stream;

	va_start(args, fmt);

	if (string_stream_vadd(stream, fmt, args) < 0)
		kunit_err(this->test, "Failed to allocate fragment: %s\n", fmt);

	va_end(args);
}

void kunit_stream_append(struct kunit_stream *this,
				struct kunit_stream *other)
{
	struct string_stream *other_stream = other->internal_stream;
	const char *other_content;

	other_content = string_stream_get_string(other_stream);

	if (!other_content) {
		kunit_err(this->test,
			  "Failed to get string from second argument for appending.\n");
		return;
	}

	kunit_stream_add(this, other_content);
}

void kunit_stream_clear(struct kunit_stream *this)
{
	string_stream_clear(this->internal_stream);
}

void kunit_stream_commit(struct kunit_stream *this)
{
	struct string_stream *stream = this->internal_stream;
	struct string_stream_fragment *fragment;
	const char *level;
	char *buf;

	level = kunit_stream_get_level(this);
	if (!level) {
		kunit_err(this->test,
			  "Stream was committed without a specified log level.\n");
		level = KERN_ERR;
		kunit_stream_set_level(this, level);
	}

	buf = string_stream_get_string(stream);
	if (!buf) {
		kunit_err(this->test,
			 "Could not allocate buffer, dumping stream:\n");
		list_for_each_entry(fragment, &stream->fragments, node) {
			kunit_err(this->test, fragment->fragment);
		}
		kunit_err(this->test, "\n");
		goto cleanup;
	}

	kunit_printk(level, this->test, buf);
	kfree(buf);

cleanup:
	kunit_stream_clear(this);
}

static int kunit_stream_init(struct kunit_resource *res, void *context)
{
	struct kunit *test = context;
	struct kunit_stream *stream;

	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
	if (!stream)
		return -ENOMEM;

	res->allocation = stream;
	stream->test = test;
	spin_lock_init(&stream->lock);
	stream->internal_stream = new_string_stream();

	if (!stream->internal_stream) {
		kfree(stream);
		return -ENOMEM;
	}

	return 0;
}

static void kunit_stream_free(struct kunit_resource *res)
{
	struct kunit_stream *stream = res->allocation;

	if (!string_stream_is_empty(stream->internal_stream)) {
		kunit_err(stream->test,
			 "End of test case reached with uncommitted stream entries.\n");
		kunit_stream_commit(stream);
	}

	destroy_string_stream(stream->internal_stream);
	kfree(stream);
}

struct kunit_stream *kunit_new_stream(struct kunit *test)
{
	struct kunit_resource *res;

	res = kunit_alloc_resource(test,
				   kunit_stream_init,
				   kunit_stream_free,
				   test);

	if (res)
		return res->allocation;
	else
		return NULL;
}
