/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   This program 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; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
/** @file
 * This file is a test script.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgtestmacro.h"

/**
 * To check the progress
 */
static int previousProgress = 0;

/**
 * To test progress
 * @param iPos the current position
 * @return 0
 */
int progress1(int iPos, qint64 /*iTime*/, const QString& /*iName*/, void* /*iData*/)
{
    if (previousProgress > iPos) {
        return 1;
    }
    previousProgress = iPos;
    return 0;
}

/**
 * To test progress
 * @param iPos the current position
 * @return 1
 */
int progress2(int iPos, qint64 /*iTime*/, const QString& /*iName*/, void* /*iData*/)
{
    if (iPos > 50) {
        return 1;
    }
    return 0;
}
/**
 * The main function of the unit test
 * @param argc the number of arguments
 * @param argv the list of arguments
 */
int main(int argc, char** argv)
{
    Q_UNUSED(argc);
    Q_UNUSED(argv);

    // Init test
    SKGINITTEST(true);

    // test class SKGDocument / COMMIT / ROLLBACK
    {
        SKGDocument document1;
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 0);
        SKGTESTERROR("TRANS.beginTransaction(transaction1)", document1.beginTransaction("transaction1"), false);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 0);
        SKGTESTERROR("TRANS.initialize", document1.initialize(), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 0);
        SKGTESTERROR("TRANS.beginTransaction(transaction1)", document1.beginTransaction("transaction1"), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 1);
        SKGTESTERROR("TRANS.endTransaction", document1.endTransaction(false), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 0);
        SKGTESTERROR("TRANS.beginTransaction(transaction2)", document1.beginTransaction("transaction2"), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 1);
        SKGTESTERROR("TRANS.setParameter", document1.setParameter("ATT1", "VAL1"), true);
        SKGTESTERROR("TRANS.endTransaction", document1.endTransaction(true), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 0);
        SKGTESTERROR("TRANS.endTransaction TOO MANY !", document1.endTransaction(true), false);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 0);

        // Test rollback
        SKGTESTERROR("TRANS.beginTransaction", document1.beginTransaction("transaction3"), true);
        SKGTESTERROR("TRANS.setParameter", document1.setParameter("ATT1", "VAL2"), true);
        SKGTESTERROR("TRANS.endTransaction", document1.endTransaction(false), true);
        SKGTEST("TRANS.getParameter", document1.getParameter("ATT1"), "VAL1");

        // Test multi transaction in cascade
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 0);
        SKGTESTERROR("TRANS.beginTransaction", document1.beginTransaction("transaction4"), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 1);
        SKGTESTERROR("TRANS.beginTransaction", document1.beginTransaction("transaction'5"), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 2);
        SKGTESTERROR("TRANS.setParameter", document1.setParameter("ATT1", "VAL2"), true);
        SKGTESTERROR("TRANS.endTransaction", document1.endTransaction(false), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 1);
        SKGTEST("TRANS.getParameter", document1.getParameter("ATT1"), "VAL2");
        SKGTESTERROR("TRANS.endTransaction", document1.endTransaction(false), true);
        SKGTEST("TRANS.getDepthTransaction", document1.getDepthTransaction(), 0);
        SKGTEST("TRANS.getParameter", document1.getParameter("ATT1"), "VAL1");

        SKGPropertyObject prop(&document1);
        SKGTESTERROR("PROP.getParameter", prop.setName("ATT1"), true);
        SKGTESTERROR("PROP.load", prop.load(), true);
        SKGTEST("PROP.getValue", prop.getValue(), "VAL1");
        prop.getParentId();

        SKGPropertyObject prop2(prop);
        SKGPropertyObject prop3(static_cast<SKGObjectBase>(prop));
        SKGPropertyObject prop4;
        prop4 = static_cast<SKGObjectBase>(prop);
    }

    // test class SKGDocument / COMMIT / ROLLBACK with SKGTransactionMng
    {
        // Test with a succeeded transaction
        SKGError err;
        SKGDocument document1;
        SKGTESTERROR("TRANSMNG.initialize()", document1.initialize(), true);
        SKGTEST("TRANSMNG.getNbTransaction", document1.getNbTransaction(), 0);
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "T1", err);

            // The code here
            IFOK(err) {
                SKGTEST("TRANSMNG.getDepthTransaction", document1.getDepthTransaction(), 1);

                // Example; an error is generated
                err = SKGError(1, "Error1");
            }

            // A rollback is done here because the scope is close
        }
        SKGTESTERROR("TRANSMNG.err", err, false);
        SKGTEST("TRANSMNG.getNbTransaction", document1.getNbTransaction(), 0);
        SKGTEST("TRANSMNG.getDepthTransaction", document1.getDepthTransaction(), 0);
    }

    {
        // Test with a succeeded transaction
        SKGError err;
        SKGDocument document1;
        SKGTESTERROR("TRANSMNG.initialize()", document1.initialize(), true);
        SKGTEST("TRANSMNG.getNbTransaction", document1.getNbTransaction(), 0);
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "T1", err);

            // The code here
            IFOK(err) {
                SKGTEST("TRANSMNG.getDepthTransaction", document1.getDepthTransaction(), 1);

                // Example; operation succeeded
                SKGTESTERROR("TRANS.setParameter", document1.setParameter("ATT1", "VAL2"), true);
            }

            // A commit is done here because the scope is close
        }
        SKGTESTERROR("TRANSMNG.err", err, true);
        SKGTEST("TRANSMNG.getNbTransaction", document1.getNbTransaction(), 1);
        SKGTEST("TRANSMNG.getDepthTransaction", document1.getDepthTransaction(), 0);
    }

    {
        // Test undo on parameters
        SKGDocument document1;
        SKGTESTERROR("TRANSUNDO.initialize()", document1.initialize(), true);
        SKGError err;
        SKGTEST("TRANSUNDO.getParameter", document1.getParameter("ATT1"), "");

        {
            // In a scope to the then endTransaction automatically
            SKGBEGINTRANSACTION(document1, "T1", err);
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT1", "VAL1_1"), true);  // To test undo on more than one modification of an object in a transaction
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT1", "VAL1_2"), true);  // To test undo on more than one modification of an object in a transaction
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT1", "VAL1"), true);
        }
        SKGTEST("TRANSUNDO.getParameter", document1.getParameter("ATT1"), "VAL1");
        SKGTEST("TRANSUNDO.getNbTransaction", document1.getNbTransaction(), 1);
        SKGTEST("TRANSUNDO.getNbTransaction(SKGDocument::REDO))", document1.getNbTransaction(SKGDocument::REDO), 0);

        {
            // In a scope to the then endTransaction automatically
            SKGBEGINTRANSACTION(document1, "T2", err);
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT1", "VAL2_1"), true);  // To test undo on more than one modification of an object in a transaction
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT1", "VAL2_2"), true);  // To test undo on more than one modification of an object in a transaction

            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT1", "VAL2"), true);
        }
        SKGTEST("TRANSUNDO.getParameter", document1.getParameter("ATT1"), "VAL2");
        SKGTEST("TRANSUNDO.getNbTransaction", document1.getNbTransaction(), 2);
        SKGTEST("TRANSUNDO.getNbTransaction(SKGDocument::REDO))", document1.getNbTransaction(SKGDocument::REDO), 0);

        QStringList oResult;
        int nbitemexpected = 6;
        SKGTESTERROR("TRANSUNDO.getDistinctValues", document1.getDistinctValues("doctransactionitem", "id", oResult), true);
        SKGTEST("TRANSUNDO.oResult.size", oResult.size(), nbitemexpected);

        SKGTESTERROR("TRANSUNDO.undoRedoTransaction(T2, SKGDocument::UNDO)", document1.undoRedoTransaction(), true);
        SKGTEST("TRANSUNDO.getParameter", document1.getParameter("ATT1"), "VAL1");
        SKGTEST("TRANSUNDO.getNbTransaction", document1.getNbTransaction(), 1);
        SKGTEST("TRANSUNDO.getNbTransaction(SKGDocument::REDO))", document1.getNbTransaction(SKGDocument::REDO), 1);

        SKGTESTERROR("TRANSUNDO.getDistinctValues", document1.getDistinctValues("doctransactionitem", "id", oResult), true);
        SKGTEST("TRANSUNDO.oResult.size", oResult.size(), nbitemexpected);

        SKGTESTERROR("TRANSUNDO.undoRedoTransaction(T1, SKGDocument::UNDO)", document1.undoRedoTransaction(), true);
        SKGTEST("TRANSUNDO.getParameter", document1.getParameter("ATT1"), "");
        SKGTEST("TRANSUNDO.getNbTransaction", document1.getNbTransaction(), 0);
        SKGTEST("TRANSUNDO.getNbTransaction(SKGDocument::REDO))", document1.getNbTransaction(SKGDocument::REDO), 2);

        SKGTESTERROR("TRANSUNDO.getDistinctValues", document1.getDistinctValues("doctransactionitem", "id", oResult), true);
        SKGTEST("TRANSUNDO.oResult.size", oResult.size(), nbitemexpected);

        SKGTESTERROR("TRANSUNDO.undoRedoTransaction(T1, SKGDocument::REDO)", document1.undoRedoTransaction(SKGDocument::REDO), true);
        SKGTEST("TRANSUNDO.getParameter", document1.getParameter("ATT1"), "VAL1");
        SKGTEST("TRANSUNDO.getNbTransaction", document1.getNbTransaction(), 1);
        SKGTEST("TRANSUNDO.getNbTransaction(SKGDocument::REDO))", document1.getNbTransaction(SKGDocument::REDO), 1);

        SKGTESTERROR("TRANSUNDO.getDistinctValues", document1.getDistinctValues("doctransactionitem", "id", oResult), true);
        SKGTEST("TRANSUNDO.oResult.size", oResult.size(), nbitemexpected);

        SKGTESTERROR("TRANSUNDO.undoRedoTransaction(T2, SKGDocument::REDO)", document1.undoRedoTransaction(SKGDocument::REDO), true);
        SKGTEST("TRANSUNDO.getParameter", document1.getParameter("ATT1"), "VAL2");
        SKGTEST("TRANSUNDO.getNbTransaction", document1.getNbTransaction(), 2);
        SKGTEST("TRANSUNDO.getNbTransaction(SKGDocument::REDO))", document1.getNbTransaction(SKGDocument::REDO), 0);
        SKGTESTERROR("TRANSUNDO.getDistinctValues", document1.getDistinctValues("doctransactionitem", "id", oResult), true);
        SKGTEST("TRANSUNDO.oResult.size", oResult.size(), nbitemexpected);
    }

    {
        // Test max depth for transaction
        SKGDocument document1;
        SKGTESTERROR("MAXDEPTH.initialize()", document1.initialize(), true);
        SKGError err;
        SKGTEST("MAXDEPTH.getNbTransaction", document1.getNbTransaction(), 0);
        {
            SKGBEGINTRANSACTION(document1, "MAXDEPTH 1", err);
            SKGTESTERROR("MAXDEPTH.setParameter", document1.setParameter("SKG_UNDO_MAX_DEPTH", "3"), true);
        }
        SKGTEST("MAXDEPTH.getNbTransaction", document1.getNbTransaction(), 1);
        {
            SKGBEGINTRANSACTION(document1, "MAXDEPTH 2", err);
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT", "VAL"), true);
        }
        SKGTESTERROR("MAXDEPTH.endTransaction", err, true);
        SKGTEST("MAXDEPTH.getNbTransaction", document1.getNbTransaction(), 2);
        {
            SKGBEGINTRANSACTION(document1, "MAXDEPTH 3", err);
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT", "VAL"), true);
        }
        SKGTESTERROR("MAXDEPTH.endTransaction", err, true);
        SKGTEST("MAXDEPTH.getNbTransaction", document1.getNbTransaction(), 3);
        {
            SKGBEGINTRANSACTION(document1, "MAXDEPTH 4", err);
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT", "VAL"), true);
        }
        SKGTESTERROR("MAXDEPTH.endTransaction", err, true);
        SKGTEST("MAXDEPTH.getNbTransaction", document1.getNbTransaction(), 3);
        {
            SKGBEGINTRANSACTION(document1, "MAXDEPTH 5", err);
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT", "VAL"), true);
            SKGTESTERROR("TRANSUNDO.setParameter", document1.setParameter("ATT5", "VAL"), true);
        }
        SKGTESTERROR("MAXDEPTH.endTransaction", err, true);
        SKGTEST("MAXDEPTH.getNbTransaction", document1.getNbTransaction(), 3);

        SKGDocument::SKGObjectModificationList oModifications;
        SKGTESTERROR("MAXDEPTH.getModifications", document1.getModifications(document1.getTransactionToProcess(), oModifications), true);
        SKGTEST("MAXDEPTH.oModifications.count", oModifications.count(), 2);
        SKGTEST("MAXDEPTH.oModifications.id", oModifications[0].id, 7);
        SKGTEST("MAXDEPTH.oModifications.table", oModifications[0].table, "parameters");
        SKGTEST("MAXDEPTH.oModifications.type", static_cast<unsigned int>(oModifications[0].type), static_cast<unsigned int>(SKGDocument::U));
        SKGTEST("MAXDEPTH.oModifications.id", oModifications[1].id, 8);
        SKGTEST("MAXDEPTH.oModifications.table", oModifications[1].table, "parameters");
        SKGTEST("MAXDEPTH.oModifications.type", static_cast<unsigned int>(oModifications[1].type), static_cast<unsigned int>(SKGDocument::I));
    }

    {
        // Redo delete after new transaction
        SKGDocument document1;
        SKGTESTERROR("REDO.initialize()", document1.initialize(), true);
        SKGError err;
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(), 0);
        {
            SKGBEGINTRANSACTION(document1, "SKGDocument::REDO 1", err);
            SKGTESTERROR("REDO.setParameter", document1.setParameter("ATT", "VAL"), true);
        }
        {
            SKGBEGINTRANSACTION(document1, "SKGDocument::REDO 2", err);
            SKGTESTERROR("REDO.setParameter", document1.setParameter("ATT", "VAL"), true);
        }
        {
            SKGBEGINTRANSACTION(document1, "SKGDocument::REDO 3", err);
            SKGTESTERROR("REDO.setParameter", document1.setParameter("ATT", "VAL"), true);
        }
        {
            SKGBEGINTRANSACTION(document1, "SKGDocument::REDO 4", err);
            SKGTESTERROR("REDO.setParameter", document1.setParameter("ATT", "VAL"), true);
        }
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(), 4);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 0);

        SKGTESTERROR("REDO.undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(), 3);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 1);

        SKGTESTERROR("REDO.undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(), 2);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 2);

        SKGTESTERROR("REDO.undoRedoTransaction", document1.undoRedoTransaction(SKGDocument::REDO), true);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(), 3);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 1);

        SKGTESTERROR("REDO.undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(), 2);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 2);

        {
            SKGBEGINTRANSACTION(document1, "SKGDocument::REDO 5", err);
            SKGTESTERROR("REDO.setParameter", document1.setParameter("ATT", "VAL"), true);
        }

        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(), 3);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 0);

        SKGTESTERROR("REDO.undoRedoTransaction", document1.undoRedoTransaction(SKGDocument::UNDOLASTSAVE), true);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(), 0);
        SKGTEST("REDO.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 1);
    }

    {
        // Test progress
        SKGDocument document1;
        SKGTESTERROR("PROGRESS.initialize()", document1.initialize(), true);
        SKGTESTERROR("PROGRESS.setProgressCallback", document1.setProgressCallback(&progress1), true);
        SKGTESTERROR("PROGRESS.beginTransaction", document1.beginTransaction("PROGRESS1", 5), true);
        for (int i = 1; i <= 5; ++i) {
            SKGTESTERROR("PROGRESS.stepForward", document1.stepForward(i), true);
            SKGTESTERROR("PROGRESS.beginTransaction", document1.beginTransaction("PROGRESS2", 3), true);
            for (int j = 1; j <= 3; j++) {
                SKGTESTERROR("PROGRESS.stepForward", document1.stepForward(j), true);
            }
            SKGTESTERROR("PROGRESS.endTransaction", document1.endTransaction(true), true);
        }
        SKGTESTERROR("PROGRESS.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("PROGRESS.setProgressCallback", document1.setProgressCallback(&progress2), true);
        SKGTESTERROR("PROGRESS.beginTransaction", document1.beginTransaction("PROGRESS1", 5), true);
        for (int i = 1; i <= 5; ++i) {
            SKGTESTERROR("PROGRESS.stepForward", document1.stepForward(i), (i < 3));
            SKGTESTERROR("PROGRESS.beginTransaction", document1.beginTransaction("PROGRESS2", 3), (i < 3));
            for (int j = 1; j <= 3; j++) {
                SKGTESTERROR("PROGRESS.stepForward", document1.stepForward(j), (3 * i + j - 3 < 5));
            }
            SKGTESTERROR("PROGRESS.endTransaction", document1.endTransaction(true), true);
        }
        SKGTESTERROR("PROGRESS.endTransaction", document1.endTransaction(true), true);
    }

    {
        // Test progress
        SKGDocument document1;
        SKGTESTERROR("PROGRESS.initialize()", document1.initialize(), true);
        SKGTESTERROR("PROGRESS.beginTransaction", document1.beginTransaction("T1"), true);
        SKGTESTERROR("PROGRESS.setParameter", document1.setParameter("ATT", "VAL"), true);

        SKGTESTERROR("PROGRESS.endTransaction", document1.endTransaction(true), true);
        SKGTEST("PROGRESS.getNbTransaction", document1.getNbTransaction(), 1);

        SKGTESTERROR("PROGRESS.beginTransaction", document1.beginTransaction("T2"), true);
        SKGTESTERROR("PROGRESS.setParameter", document1.setParameter("ATT", "VAL"), true);
        SKGTESTERROR("PROGRESS.endTransaction", document1.endTransaction(true), true);
        SKGTEST("PROGRESS.getNbTransaction", document1.getNbTransaction(), 2);

        SKGTESTERROR("PROGRESS.beginTransaction", document1.beginTransaction("T3"), true);
        SKGTESTERROR("PROGRESS.setParameter", document1.setParameter("ATT", "VAL"), true);
        SKGTESTERROR("PROGRESS.endTransaction", document1.endTransaction(false), true);
        SKGTEST("PROGRESS.getNbTransaction", document1.getNbTransaction(), 2);

        // Transaction failed with existing name
        SKGTESTERROR("PROGRESS.beginTransaction", document1.beginTransaction("T2"), true);
        SKGTESTERROR("PROGRESS.setParameter", document1.setParameter("ATT", "VAL"), true);
        SKGTESTERROR("PROGRESS.endTransaction", document1.endTransaction(false), true);
        SKGTEST("PROGRESS.getNbTransaction", document1.getNbTransaction(), 2);
    }

    {
        // Test group of transactions on U
        SKGDocument document1;
        SKGTESTERROR("GROUP.initialize()", document1.initialize(), true);
        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T1"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL1"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T2"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL2"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T3"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL3"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T4"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL4"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.groupTransactions(", document1.groupTransactions(3, 5), true);
        SKGTEST("GROUP.getNbTransaction", document1.getNbTransaction(), 2);
        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTEST("GROUP.getParameter", document1.getParameter("ATT"), "VAL1");

        // Remove all transaction
        SKGTEST("GROUP.getNbTransaction", document1.getNbTransaction(SKGDocument::UNDO), 1);
        SKGTEST("GROUP.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 1);
        SKGTESTERROR("GROUP.removeAllTransactions", document1.removeAllTransactions(), true);
        SKGTEST("GROUP.getNbTransaction", document1.getNbTransaction(SKGDocument::UNDO), 0);
        SKGTEST("GROUP.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 0);
    }

    {
        // Test group of transactions on R
        SKGDocument document1;
        SKGTESTERROR("GROUP.initialize()", document1.initialize(), true);
        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T1"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL1"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T2"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL2"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T3"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL3"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T4"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL4"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(), true);

        SKGTESTERROR("GROUP.groupTransactions(", document1.groupTransactions(7, 9), true);
        SKGTEST("GROUP.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 2);
//      document1.dump(DUMPTRANSACTIONS);
        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(SKGDocument::REDO), true);
        SKGTEST("GROUP.getParameter", document1.getParameter("ATT"), "VAL3");
    }

    {
        // Test group of transactions on U and R
        SKGDocument document1;
        SKGTESTERROR("GROUP.initialize()", document1.initialize(), true);
        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T1"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL1"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T2"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL2"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T3"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL3"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T4"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL4"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(), true);

        SKGTESTERROR("GROUP.groupTransactions(", document1.groupTransactions(3, 6), false);
//      document1.dump(DUMPTRANSACTIONS);
        SKGTEST("GROUP.getNbTransaction", document1.getNbTransaction(SKGDocument::UNDO), 2);
        SKGTEST("GROUP.getNbTransaction", document1.getNbTransaction(SKGDocument::REDO), 2);
    }

    {
        // Test group of transactions on R
        SKGDocument document1;
        SKGTESTERROR("GROUP.initialize()", document1.initialize(), true);
        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T1"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL1"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T2"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL2"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        QString filename1 = SKGTest::getTestPath("OUT") % "/filename1.skg";
        SKGTESTERROR("GROUP.saveAs", document1.saveAs(filename1, true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T3"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL3"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("GROUP.beginTransaction", document1.beginTransaction("T4"), true);
        SKGTESTERROR("GROUP.setParameter", document1.setParameter("ATT", "VAL4"), true);
        SKGTESTERROR("GROUP.endTransaction", document1.endTransaction(true), true);

        document1.dump(DUMPTRANSACTIONS);
        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(SKGDocument::UNDOLASTSAVE), true);
        SKGTEST("GROUP.getParameter", document1.getParameter("ATT"), "VAL2");
        SKGTESTERROR("GROUP.undoRedoTransaction", document1.undoRedoTransaction(SKGDocument::REDO), true);
        SKGTEST("GROUP.getParameter", document1.getParameter("ATT"), "VAL4");

        QStringList oResult;
        SKGTESTERROR("SKGServices::dumpSelectSqliteOrder", document1.dumpSelectSqliteOrder("SELECT * from doctransaction", oResult), true);
    }

    {
        // Test error
        SKGDocument document1;
        SKGTESTERROR("ERROR.initialize()", document1.initialize(), true);
        SKGTESTERROR("ERROR.undoRedoTransaction", document1.undoRedoTransaction(SKGDocument::UNDO), false);  // No transaction

        SKGTESTERROR("ERROR.beginTransaction", document1.beginTransaction("T1"), true);
        SKGTEST("ERROR.getCurrentTransaction", document1.getCurrentTransaction(), 2);

        SKGTESTERROR("ERROR.groupTransactions", document1.groupTransactions(1, 1), false);  // Not authorized into a transaction
        SKGTESTERROR("ERROR.undoRedoTransaction", document1.undoRedoTransaction(SKGDocument::UNDO), false);  // Not authorized into a transaction
        SKGTESTERROR("ERROR.saveAs", document1.saveAs(SKGTest::getTestPath("OUT") % "/filename1.skg", true), false);  // Not authorized into a transaction

        SKGTESTERROR("ERROR.endTransaction", document1.endTransaction(true), true);
    }

    {
        // Test messages
        SKGDocument document1;
        SKGTESTERROR("MSG.initialize()", document1.initialize(), true);
        SKGTESTERROR("MSG.sendMessage", document1.sendMessage("Information", SKGDocument::Information), true);
        SKGTESTERROR("MSG.sendMessage", document1.sendMessage("Warning", SKGDocument::Warning), true);
        SKGTESTERROR("MSG.sendMessage", document1.sendMessage("Positive", SKGDocument::Positive), true);
        SKGTESTERROR("MSG.sendMessage", document1.sendMessage("Error", SKGDocument::Error), true);
        SKGTESTERROR("MSG.sendMessage", document1.sendMessage("Hidden", SKGDocument::Hidden), true);

        SKGTESTERROR("MSG.beginTransaction", document1.beginTransaction("T1"), true);
        SKGTESTERROR("MSG.setParameter", document1.setParameter("ATT", "VAL"), true);
        SKGTESTERROR("MSG.sendMessage", document1.sendMessage("Hello"), true);
        SKGTESTERROR("MSG.sendMessage", document1.sendMessage("World"), true);
        SKGTESTERROR("MSG.endTransaction", document1.endTransaction(true), true);

        QList<SKGDocument::SKGMessage> msg;
        SKGTESTERROR("MSG.getMessages", document1.getMessages(document1.getTransactionToProcess(SKGDocument::UNDO), msg), true);
        SKGTEST("MSG.msg.count", msg.count(), 6);
        SKGTEST("MSG.msg", msg.at(0).Text, "Information"); SKGTEST("MSG.type", static_cast<unsigned int>(msg.at(0).Type), static_cast<unsigned int>(SKGDocument::Information));
        SKGTEST("MSG.msg", msg.at(1).Text, "Warning"); SKGTEST("MSG.type", static_cast<unsigned int>(msg.at(1).Type), static_cast<unsigned int>(SKGDocument::Warning));
        SKGTEST("MSG.msg", msg.at(2).Text, "Positive"); SKGTEST("MSG.type", static_cast<unsigned int>(msg.at(2).Type), static_cast<unsigned int>(SKGDocument::Positive));
        SKGTEST("MSG.msg", msg.at(3).Text, "Error"); SKGTEST("MSG.type", static_cast<unsigned int>(msg.at(3).Type), static_cast<unsigned int>(SKGDocument::Error));
        SKGTEST("MSG.msg", msg.at(4).Text, "Hello"); SKGTEST("MSG.type", static_cast<unsigned int>(msg.at(4).Type), static_cast<unsigned int>(SKGDocument::Information));
        SKGTEST("MSG.msg", msg.at(5).Text, "World"); SKGTEST("MSG.type", static_cast<unsigned int>(msg.at(5).Type), static_cast<unsigned int>(SKGDocument::Information));
    }

    {
        // Test clean after save
        SKGDocument document1;
        SKGTESTERROR("CLEAN.initialize()", document1.initialize(), true);

        SKGTESTERROR("CLEAN.beginTransaction", document1.beginTransaction("T1"), true);
        SKGTESTERROR("CLEAN.setParameter", document1.setParameter("SKG_UNDO_CLEAN_AFTER_SAVE", "Y"), true);
        SKGTESTERROR("CLEAN.setParameter", document1.setParameter("ATT", "VAL1"), true);
        SKGTESTERROR("CLEAN.endTransaction", document1.endTransaction(true), true);

        SKGTESTERROR("CLEAN.beginTransaction", document1.beginTransaction("T2"), true);
        SKGTESTERROR("CLEAN.setParameter", document1.setParameter("ATT", "VAL2"), true);
        SKGTESTERROR("CLEAN.endTransaction", document1.endTransaction(true), true);

        SKGTEST("CLEAN.getNbTransaction", document1.getNbTransaction(SKGDocument::UNDO), 2);

        QString filename1 = SKGTest::getTestPath("OUT") % "/filename1.skg";
        SKGTESTERROR("CLEAN.saveAs", document1.saveAs(filename1, true), true);
        SKGTEST("CLEAN.getNbTransaction", document1.getNbTransaction(SKGDocument::UNDO), 0);
    }
    // End test
    SKGENDTEST();
}
