/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/
 *
 * AST-Transcend Correspondence Tests
 *
 * Created on: Dec 2, 2018
 * Author: pgess <v.melnychenko@xreate.org>
 */

#include <pass/cfapass.h>
#include "xreatemanager.h"
#include "pass/dfapass.h"
#include "supplemental/docutils.h"

#include <boost/algorithm/string.hpp>
#include "gtest/gtest.h"

using namespace xreate;
using namespace std;

struct TestRec {
  string refExample;
  string refOutput;
  PassId pass;
};

std::list<TestRec> tests = {
  {"ExprAnn_1",           "Output_ExprAnn_1",         PassId::DFAPass},
  {"CodeBlock_1",         "Output_CodeBlock_1",       PassId::CFAPass},
  {"CodeBlockAnns_1",     "Output_CodeBlockAnns_1",   PassId::CFAPass},
  {"CodeBlockBinds_1",    "Output_CodeBlockBinds_1",  PassId::CFAPass},
  {"CodeBlockParents_1",  "Output_CodeBlockParents_1",PassId::CFAPass},
  {"Fn_1",                "Output_Fn_1",              PassId::CFAPass},
  {"FnAnns_1",            "Output_FnAnns_1",          PassId::CFAPass},
  {"FnSpecs_1",           "Output_FnSpecs_1",         PassId::CFAPass},
  {"FnEntry_1",           "Output_FnEntry_1",         PassId::CFAPass},
  {"FnResult_1",          "Output_FnResult_1",        PassId::CFAPass},
  {"OpInvoc_1",           "Output_OpInvoc_1",         (PassId) 1000},
  {"OpLoops_1",           "Output_OpLoops_1",         PassId::DFAPass} 
};

TEST(ASTCorrespondence, Doc_BasicTests) {
  for(auto test: tests) {
    string program = getDocumentationExampleById("documentation/Transcend/ast-api.xml", test.refExample);
    string outputExpected = getDocumentationExampleById("documentation/Transcend/ast-api.xml", test.refOutput);

    std::unique_ptr<details::tier2::XreateManager> man(details::tier2::XreateManager::prepare(move(program)));
    switch(test.pass) {
    case PassId::CFAPass:
      man->registerPass(new cfa::CFAPass(man.get()), test.pass);
      break;
    case PassId::DFAPass:
      man->registerPass(new dfa::DFAPass(man.get()), test.pass);
      break;
    default:
      man->registerPass(new dfa::DFAPass(man.get()), PassId::DFAPass);
      man->registerPass(new cfa::CFAPass(man.get()), PassId::CFAPass);
      break;
    }
    man->registerPass(new dfa::DFAPass(man.get()), test.pass);
    man->executePasses();

    cout << "Test: " << test.refExample << endl;
    testing::internal::CaptureStdout();
    man->analyse();
    std::string outputActual = testing::internal::GetCapturedStdout();
    //cout << outputActual << endl;

    //check every line independently if outputActual is multi-line string
    std::vector<std::string> lines;
    boost::split(lines, outputExpected, [](char c){return c == '\n';});
    for(auto line: lines) {
      ASSERT_NE(std::string::npos, outputActual.find(line));
    }
  }
}

