/*
 * testLogging.cpp
 *
 *  Created on: Jun 23, 2015
 *      Author: pgess
 */

#include <pass/loggerpass.h>
#include "gtest/gtest.h"
#include "passmanager.h"
#include "llvmlayer.h"
#include "Parser.h"

using namespace std;
using namespace xreate;

TEST(LoggerPass, simpleInjection){
	PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int. return x}");

	man->runWithoutCompilation();
	CompilePass* compiler = new CompilePass(man);
	compiler->run();

	compilation::FunctionUnit* fTest = compiler->getFunctionUnit(man->root->findFunction("test"));
	ASSERT_NE(fTest, nullptr);
	compilation::CodeScopeUnit* scopeUnitTest = fTest->getEntry();
	CodeScope* scopeTest = scopeUnitTest->scope;
	Symbol symbX = scopeTest->findSymbol("x");
	TypeAnnotation typX = scopeTest->findDefinition(symbX);

	llvm::Value* retRaw = scopeUnitTest->compile();
	llvm::BasicBlock& blockTestRaw = fTest->raw->getEntryBlock();

	LLVMLayer* llvm = man->llvm;
	//llvm->builder.SetInsertPoint(&blockTestRaw);
	compilation::Context params{fTest, scopeUnitTest, compiler};

	LoggerPass l(man);
	l.inject(symbX, params);


	llvm->initJit();
	int (*f)() = (int(*)()) llvm->getFunctionPointer(fTest->raw);
	testing::internal::CaptureStdout();
	f();
	std::string&& output = testing::internal::GetCapturedStdout();
	EXPECT_STREQ("10\n", output.c_str());
}

TEST(LoggerPass, simpleInjection2){
	PassManager* man = PassManager::prepareForCode("test= function():: int; entry{x = 2+8::int; logging. x}");

	man->runWithoutCompilation();
	CompilePass* compiler= new CompilePass(man);
	compiler->run();

	LoggerPass* logger = new LoggerPass(man);
	logger->initDependencies(compiler);
	logger->run();

	man->llvm->initJit();
	man->llvm->print();
	int (*f)() = (int(*)()) man->llvm->getFunctionPointer(compiler->getEntryFunction());
	testing::internal::CaptureStdout();
	f();
	std::string&& output = testing::internal::GetCapturedStdout();
	EXPECT_STREQ("10\n", output.c_str());
}

TEST(LoggerPass, simpleInjection3){
	FILE* input = fopen("scripts/cases/log.xreate","r");
	assert(input);

	std::unique_ptr<PassManager> program(PassManager::prepareForCode(input));
	void* mainPtr = program->run();
	int (*main)() = (int (*)())(intptr_t)mainPtr;

	int answer = main();

	fclose(input);
}




