#!/usr/bin/perl
use strict;

my ( $tags_common, $tags, @content, @tests, $vopt, $ccopt );
my $testcase = $ARGV[0];
my $dir = $ARGV[0];
$dir =~ s,^(.*)/.*?$,$1,;
$testcase =~ s,^.*/(.*?)[.]bt,$1,;
my $src = "$ENV{SRC_ROOT}/bricks/$testcase";
my $helper = "$dir/cxa_demangle.helper.cpp";

{
    local $/; # slurp
    open BT, $ARGV[0];
    open TC, $src;
    my $bt = <BT>;
    $tags_common = $1 if $bt =~ /TAGS: (.*)/;

    @content = split /\n/, <TC>;
    close BT;
    close TC;
}

for (@content)
{
    push @tests, $1 if /^\s+TEST\((.*?)\)/ && !/TODO/;
}

for my $unit (@tests)
{
    $unit =~ s,^\s*(.*?)\s*$,$1,;
    # nofail/simfail, throwing assert/aborting assert
    for my $variant ("nfta", "nfaa", "sfaa")
    {
        $tags = $tags_common;
        $ccopt = "-std=c++17";
        if ($variant =~ /^nf/) { $vopt = "-o nofail:malloc" } else { $tags .= " big"; }
        if ($variant =~ /aa$/) { $ccopt .= " -DBRICK_NOTHROW_ASSERTS"; } else { $tags .= " ext"; }
        if ($variant eq "sfaa") { $ccopt .= " -DIGNORE_TERMINATE $helper"; }

        open F, ">$unit.$variant.cpp";
        print F <<EOF
/* TAGS: $tags */
/* CC_OPTS: $ccopt -I$ENV{SRC_ROOT}/bricks/ */
/* VERIFY_OPTS: $vopt */
/* PROGRAM_OPTS: $unit */

#define BRICK_UNITTEST_REG
#define NVALGRIND
#define BRICK_UNITTEST_MAIN
#include "brick-unittest"
#undef BRICK_UNITTEST_MAIN
#include <stdlib.h>

#ifdef IGNORE_TERMINATE
__attribute__((constructor(0))) static void _test_set_terminate_handler()
{
    std::set_terminate( [] { exit( 0 ); __builtin_unreachable(); } );
}
#endif

#include <$testcase>
EOF
        ; close F;
    }
}
