/**
 *  Set of tests for `Command` class.
 *      Copyright 2023 Anton Tarasenko
 *------------------------------------------------------------------------------
 * This file is part of Acedia.
 *
 * Acedia is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License, or
 * (at your option) any later version.
 *
 * Acedia is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Acedia.  If not, see <https://www.gnu.org/licenses/>.
 */
class TEST_Unflect extends TestCase
    abstract;

protected static function TESTS() {
    local MockInitialClass obj;

    obj = MockInitialClass(__().memory.Allocate(class'MockInitialClass'));
    Context("Replacing functions with `UnflectApi`");
    Test_InitialReplacement(obj);
    Test_SecondReplacement(obj);
    Test_ReplacementWithSelf(obj);
    Test_RevertingReplacement(obj);
}

protected static function Test_InitialReplacement(MockInitialClass obj) {
    Issue("Functions aren't being replaced correctly the first time.");
    TEST_ExpectTrue(__().unflect.ReplaceFunction_S(
        "AcediaCore.MockInitialClass.DoIt",
        "AcediaCore.MockReplacerClass.DoIt2",
        "testing"));
    TEST_ExpectTrue(obj.DoIt() == -2);
    TEST_ExpectTrue(obj.counter == 2);
    TEST_ExpectTrue(obj.DoIt() == -4);
    TEST_ExpectTrue(obj.counter == 4);
}

protected static function Test_SecondReplacement(MockInitialClass obj) {
    Issue("Functions aren't being replaced correctly in case they were already replaced.");
    TEST_ExpectTrue(__().unflect.ReplaceFunction_S(
        "AcediaCore.MockInitialClass.DoIt",
        "AcediaCore.MockReplacerClass.DoIt3",
        "testing"));
    TEST_ExpectTrue(obj.DoIt() == 7);
    TEST_ExpectTrue(obj.counter == 3);
    TEST_ExpectTrue(obj.DoIt() == 7);
    TEST_ExpectTrue(obj.counter == 2);
}

protected static function Test_ReplacementWithSelf(MockInitialClass obj) {
    Issue("Attempting to replacing function with itself makes unexpected change.");
    TEST_ExpectFalse(__().unflect.ReplaceFunction_S(
        "AcediaCore.MockInitialClass.DoIt",
        "AcediaCore.MockInitialClass.DoIt",
        "testing"));
    TEST_ExpectTrue(obj.DoIt() == 7);
    TEST_ExpectTrue(obj.counter == 1);
}

protected static function Test_RevertingReplacement(MockInitialClass obj) {
    Issue("Reverting replaced function doesn't work.");
    TEST_ExpectTrue(__().unflect.RevertFunction_S("AcediaCore.MockInitialClass.DoIt"));
    TEST_ExpectTrue(obj.DoIt() == 2);
    TEST_ExpectTrue(obj.counter == 2);
    TEST_ExpectTrue(obj.DoIt() == 3);
    TEST_ExpectTrue(obj.counter == 3);

    Issue("Reverting already reverted function ends in success.");
    TEST_ExpectFalse(__().unflect.RevertFunction_S("AcediaCore.MockInitialClass.DoIt"));

    Issue("Reverting already reverted function leads to unexpected results.");
    TEST_ExpectTrue(obj.DoIt() == 4);
    TEST_ExpectTrue(obj.counter == 4);
}

defaultproperties {
    caseName = "Function replacement"
    caseGroup = "Unflect"
}