/* 
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * 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; version 2 of the
 * License.
 * 
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "tut_stdafx.h"

#ifndef _WIN32
#include <sstream>
#include <fstream>
#endif


#include "testgrt.h"
#include "grt_test_utility.h"
#include "grts/structs.db.mgmt.h"
#include "grts/structs.db.mysql.h"
#include "grts/structs.workbench.physical.h"
#include "wbvalidation.h"
#include "grt/grt_manager.h"
#include "wb_module_validation.h"
#include "wb_helpers.h"

using namespace std;

BEGIN_TEST_DATA_CLASS(test_wbmodulevalidation)
public:
  GRTManagerTest grtm;
  WbModuleValidationImpl *module;
  GRT *grt;
END_TEST_DATA_CLASS

TEST_MODULE(test_wbmodulevalidation, "WB Module Validation");

TEST_FUNCTION(1)
{
  grt= grtm.get_grt();

  module= grt->get_native_module<WbModuleValidationImpl>();
  ensure("WbValidation module initialization", NULL != module);
  ensure("physicalView must be defined",false);
}

/*
struct TestModel
{
  workbench_physical_ModelRef model;
  workbench_physical_ViewRef physicalView;

  db_CatalogRef catalog;
  db_SchemaRef schema;
  db_TableRef table;
  db_ColumnRef column;
  db_ColumnRef column2;
  db_IndexRef primaryKey;
  db_IndexColumnRef indexColumn;
  db_ForeignKeyRef foreignKey;
  db_TriggerRef trigger;
  db_ViewRef view;
  db_RoutineRef routine;
  db_RoutineGroupRef routineGroup;
  db_UserRef user;
  db_RoleRef role;

  db_RolePrivilegeRef tablePrivilege;
  db_RolePrivilegeRef viewPrivilege;
  db_RolePrivilegeRef routinePrivilege;

  workbench_physical_TableFigureRef tableFigure;
  workbench_physical_ViewFigureRef viewFigure;
  workbench_physical_RoutineGroupFigureRef routineGroupFigure;

  TestModel(GRT* grt)
    : model(grt),
    catalog(grt),
    physicalView(grt),
    schema(grt),
    table(grt),
    column(grt),
    column2(grt),
    primaryKey(grt),
    indexColumn(grt),
    trigger(grt),
    foreignKey(grt),
    view(grt),
    routine(grt),
    routineGroup(grt),
    user(grt),
    role(grt),
    tablePrivilege(grt),
    viewPrivilege(grt),
    routinePrivilege(grt),
    tableFigure(grt),
    viewFigure(grt),
    routineGroupFigure(grt)
  {
    model->catalog(catalog);             catalog->owner(model);
    model->views().insert(physicalView); physicalView->owner(model);

    db_mgmt_RdbmsRef rdbms= db_mgmt_RdbmsRef::cast_from(grt->unserialize("../../modules/db.mysql/res/mysql_rdbms_info.xml"));
    ensure("db_mgmt_RdbmsRef initialization", rdbms.is_valid());
    model->rdbms(rdbms);

    catalog->name("ValidateEmptyContentCatalog");
    catalog->schemata().insert(schema); schema->owner(catalog);
    catalog->users().insert(user);      user->owner(catalog);
    catalog->roles().insert(role);      role->owner(catalog);

    schema->name("ValidateEmptyContentDb");
    schema->tables().insert(table);     table->owner(schema);
    schema->views().insert(view);       view->owner(schema);
    schema->routines().insert(routine); routine->owner(schema);
    schema->routineGroups().insert(routineGroup);  routineGroup->owner(schema);

    table->name("t1");
    table->columns().insert(column);    column->owner(table);
    table->columns().insert(column2);    column2->owner(table);
    table->indices().insert(primaryKey); primaryKey->owner(table);
    table->foreignKeys().insert(foreignKey);  foreignKey->owner(table);
    table->primaryKey(primaryKey);
    table->triggers().insert(trigger);   trigger->owner(table);

    view->name("v1");
    view->sqlDefinition("select * from t1");

    routine->name("r1");
    routine->sqlDefinition("getcurrentdatetime();");

    routineGroup->name("group1");
    routineGroup->routines().insert(routine);

    column->name("id");
    column->simpleType(model->rdbms()->simpleDatatypes().get(0));

    column2->name("parent_id");
    column2->simpleType(model->rdbms()->simpleDatatypes().get(0));

    primaryKey->name("PK");
    primaryKey->columns().insert(indexColumn);
    primaryKey->isPrimary(1);

    indexColumn->owner(primaryKey);
    indexColumn->referencedColumn(column);

    foreignKey->name("FK");
    foreignKey->columns().insert(column2);
    foreignKey->referencedColumns().insert(column);
    foreignKey->referencedTable(table);

    trigger->name("trig");
    trigger->sqlDefinition("CREATE "
      "TRIGGER trig BEFORE INSERT "
      "ON t1 FOR EACH ROW SET id = new.id;");

    user->name("User1");
    user->roles().insert(role);

    role->name("Role1");
    role->privileges().insert(tablePrivilege);  
    tablePrivilege->owner(role);
    
    role->privileges().insert(viewPrivilege);   
    viewPrivilege->owner(role);
    
    role->privileges().insert(routinePrivilege);
    routinePrivilege->owner(role);

    // Privileges.
    tablePrivilege->databaseObject(table);
    tablePrivilege->privileges().insert("ALL");

    viewPrivilege->databaseObject(view);
    viewPrivilege->privileges().insert("ALL");

    routinePrivilege->databaseObject(routine);
    routinePrivilege->privileges().insert("ALL");

    // Figures.
    tableFigure->owner(physicalView);
    tableFigure->table(table);
    tableFigure->name("t1");
    physicalView->figures().insert(tableFigure);

    viewFigure->owner(physicalView);
    viewFigure->view(view);
    viewFigure->name("v1");
    physicalView->figures().insert(viewFigure);
    
    routineGroupFigure->owner(physicalView);
    routineGroupFigure->routineGroup(routineGroup);
    routineGroupFigure->name("group1");
    physicalView->figures().insert(routineGroupFigure);
  }
};

TEST_FUNCTION(2)
{
  // test validateEmptyContent
  TestModel model(grt);
  ensure_equals("Empty content validation", module->validateEmptyContent(model.model), 0);
}

TEST_FUNCTION(3)
{
  // test validateTableEfficiency
  TestModel model(grt);
  ensure_equals("Table efficiency validation", module->validateTableEfficiency(model.model), 0);
}

TEST_FUNCTION(4)
{
  // test validateDuplicateIdentifiers
  TestModel model(grt);
  ensure_equals("Duplicate ids validations", module->validateDuplicateIdentifiers(model.model), 0);
}

TEST_FUNCTION(5)
{
  // test validateConsistency
  TestModel model(grt);
  ensure_equals("Consistency validation", module->validateConsistency(model.model), 0);
}

TEST_FUNCTION(6)
{
  // test validateLogic
  TestModel model(grt);
  ensure_equals("Logic validation", module->validateLogic(model.model), 0);
}

TEST_FUNCTION(7)
{
  // test validateAll
  TestModel model(grt);
  ensure_equals("Validate All", module->validateAll(model.model), 0);
}

TEST_FUNCTION(8)
{
  // test validateTableHasColumns
  TestModel model(grt);
  ensure_equals("validateTableHasColumns_1", module->validateEmptyContent(model.model), 0);

  model.table->columns().remove_all();
  ensure_equals("validateTableHasColumns_2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(9)
{
  // test validateViewHasCode
  TestModel model(grt);
  ensure_equals("validateViewHasCode", module->validateEmptyContent(model.model), 0);
  
  model.view->sqlDefinition("");
  ensure_equals("validateViewHasCode2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(10)
{
  // test validateRoutineGroupHasMembers
  TestModel model(grt);
  ensure_equals("validateRoutineGroupHasMembers", module->validateEmptyContent(model.model), 0);
  
  model.routineGroup->routines().remove_all();
  ensure_equals("validateRoutineGroupHasMembers2", module->validateEmptyContent(model.model), 2);
}

TEST_FUNCTION(11)
{
  // test validateRoutineHasCode
  TestModel model(grt);
  ensure_equals("validateRoutineHasCode", module->validateEmptyContent(model.model), 0);
  
  model.routine->sqlDefinition("");
  ensure_equals("validateRoutineHasCode2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(12)
{
  // test validateAllObjectsWithPrivileges
  TestModel model(grt);
  ensure_equals("validateAllObjectsWithPrivileges", module->validateEmptyContent(model.model), 0);
  
  model.tablePrivilege->privileges().remove_all();
  ensure_equals("validateAllObjectsWithPrivileges2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(13)
{
  // test validateTableIsReferencedByRole
  TestModel model(grt);
  ensure_equals("validateTableIsReferencedByRole", module->validateEmptyContent(model.model), 0);
  
  model.tablePrivilege->databaseObject(db_DatabaseObjectRef());
  ensure_equals("validateTableIsReferencedByRole2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(14)
{
  // test validateViewIsReferencedByRole
  TestModel model(grt);
  ensure_equals("validateViewIsReferencedByRole", module->validateEmptyContent(model.model), 0);
  
  model.viewPrivilege->databaseObject(db_DatabaseObjectRef());
  ensure_equals("validateViewIsReferencedByRole2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(15)
{
  // test validateRoutineIsReferencedByRole
  TestModel model(grt);
  ensure_equals("validateRoutineIsReferencedByRole", module->validateEmptyContent(model.model), 0);
  
  model.routinePrivilege->databaseObject(db_DatabaseObjectRef());
  ensure_equals("validateRoutineIsReferencedByRole2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(16)
{
  // test validateUserHasRoles
  TestModel model(grt);
  ensure_equals("validateUserHasRoles", module->validateEmptyContent(model.model), 0);
  
  model.user->roles().remove_all();
  ensure_equals("validateUserHasRoles2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(17)
{
  // test validateRoleHasPrivileges
  TestModel model(grt);
  ensure_equals("validateRoleHasPrivileges", module->validateEmptyContent(model.model), 0);
  
  model.role->privileges().remove_all();
  ensure_equals("validateRoleHasPrivileges2", module->validateEmptyContent(model.model), 4);
}

TEST_FUNCTION(18)
{
  // test validatePrivilegeHasObjects
  TestModel model(grt);
  ensure_equals("validatePrivilegeHasObjects", module->validateEmptyContent(model.model), 0);
  
  model.tablePrivilege->privileges().remove_all();
  ensure_equals("validatePrivilegeHasObjects2", module->validateEmptyContent(model.model), 1);
}

//TEST_FUNCTION(21)
//{// test validatePrivilegeHasObjects
//  TestModel model(grt);
//  ENSURE_PASS(validatePrivilegeHasObjects, validateEmptyContent);
//  // TODO
//  ENSURE_FAIL(validatePrivilegeHasObjects, validateEmptyContent);
//}

TEST_FUNCTION(19)
{
  // test validateTableIsUsedByView
  TestModel model(grt);
  ensure_equals("validateTableIsUsedByView", module->validateEmptyContent(model.model), 0);
  
  model.tableFigure->table(db_TableRef());
  ensure_equals("validateTableIsUsedByView2", module->validateEmptyContent(model.model), 1);
}

TEST_FUNCTION(20)
{
  // test validateViewIsUsedByView
  TestModel model(grt);
  ensure_equals("validateViewIsUsedByView", module->validateAll(model.model), 0);
  
  model.viewFigure->view(db_ViewRef());
  ensure_equals("validateViewIsUsedByView2", module->validateAll(model.model), 1);
}

TEST_FUNCTION(21)
{
  // test validateRoutineIsUsedByView
  TestModel model(grt);
  ensure_equals("validateRoutineIsUsedByView", module->validateAll(model.model), 0);
  
  model.routineGroup->routines().remove_all();
  ensure_equals("validateRoutineIsUsedByView2", module->validateAll(model.model), 2);
}

TEST_FUNCTION(22)
{
  // test validateRoutineGroupIsUsedByView
  TestModel model(grt);
  ensure_equals("validateRoutineGroupIsUsedByView", module->validateAll(model.model), 0);
  
  model.routineGroupFigure->routineGroup(db_RoutineGroupRef());
  ensure_equals("validateRoutineGroupIsUsedByView2", module->validateAll(model.model), 1);
}

TEST_FUNCTION(23)
{
  // test validateTableHasPrimaryKey
  TestModel model(grt);
  ensure_equals("validateTableHasPrimaryKey", module->validateTableEfficiency(model.model), 0);
  
  model.table->primaryKey(db_IndexRef());
  ensure_equals("validateTableHasPrimaryKey2", module->validateTableEfficiency(model.model), 1);
}

TEST_FUNCTION(24)
{
  // test validatePrimaryKeyIsIntBased
  TestModel model(grt);
  ensure_equals("validatePrimaryKeyIsIntBased", module->validateTableEfficiency(model.model), 0);
  
  model.column->simpleType()->numericScale(1); // TODO - fix this
  ensure_equals("validatePrimaryKeyIsIntBased2", module->validateTableEfficiency(model.model), 1);
}

TEST_FUNCTION(25)
{
  // test validateForeignKeyType
  TestModel model(grt);
  model.column->simpleType()->numericScale(0); // TODO - fix this (required because of test#27)
  ensure_equals("validateForeignKeyType", module->validateTableEfficiency(model.model), 0);
  
  model.column2->simpleType(model.model->rdbms()->simpleDatatypes().get(8)); // 8 - string
  ensure_equals("validateForeignKeyType2", module->validateTableEfficiency(model.model), 1);
}

TEST_FUNCTION(26)
{
  // test validateDuplicateTableName
  TestModel model(grt);
  ensure_equals("validateDuplicateTableName", module->validateDuplicateIdentifiers(model.model), 0);
  
  db_TableRef table(grt);
  table->owner(model.schema);
  table->name(model.table->name());
  model.schema->tables().insert(table);
  ensure_equals("validateDuplicateTableName2", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(27)
{
  // test validateDuplicateColumnName
  TestModel model(grt);
  ensure_equals("validateDuplicateColumnName", module->validateDuplicateIdentifiers(model.model), 0);
  
  model.column2->name(model.column->name());
  ensure_equals("validateDuplicateColumnName", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(28)
{
  // test validateDuplicateIndexName
  TestModel model(grt);
  ensure_equals("validateDuplicateIndexName", module->validateDuplicateIdentifiers(model.model), 0);
  
  db_IndexRef index(grt);
  db_IndexColumnRef indexColumn(grt);
  model.table->indices().insert(index); 
  index->owner(model.table);
  index->name(model.primaryKey->name());
  index->columns().insert(indexColumn);

  indexColumn->owner(index);
  indexColumn->referencedColumn(model.column2);

  index->name(model.primaryKey->name());

  ensure_equals("validateDuplicateIndexName2", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(29)
{
  // test validateDuplicateTriggerName
  TestModel model(grt);
  ensure_equals("validateDuplicateTriggerName", module->validateDuplicateIdentifiers(model.model), 0);
  
  db_TriggerRef trigger(grt);
  trigger->owner(model.table);
  trigger->name(model.trigger->name());
  model.table->triggers().insert(trigger);
  ensure_equals("validateDuplicateTriggerName2", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(30)
{
  // test validateDuplicateViewName
  TestModel model(grt);
  ensure_equals("validateDuplicateViewName", module->validateDuplicateIdentifiers(model.model), 0);
  
  db_ViewRef view(grt);
  view->owner(model.schema);
  view->name(model.view->name());
  model.schema->views().insert(view);
  ensure_equals("validateDuplicateViewName2", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(31)
{
  // test validateDuplicateRoutineName
  TestModel model(grt);
  ensure_equals("validateDuplicateRoutineName", module->validateDuplicateIdentifiers(model.model), 0);
  
  db_RoutineRef routine(grt);
  routine->owner(model.schema);
  routine->name(model.routine->name());
  model.schema->routines().insert(routine);
  ensure_equals("validateDuplicateRoutineName2", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(32)
{
  // test validateDuplicateRoutineGroupName
  TestModel model(grt);
  ensure_equals("validateDuplicateRoutineGroupName", module->validateDuplicateIdentifiers(model.model), 0);
  
  db_RoutineGroupRef routineGroup(grt);
  routineGroup->owner(model.schema);
  routineGroup->name(model.routineGroup->name());
  model.schema->routineGroups().insert(routineGroup);
  ensure_equals("validateDuplicateRoutineGroupName2", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(33)
{
  // test validateDuplicateRoleName
  TestModel model(grt);
  ensure_equals("validateDuplicateRoleName", module->validateDuplicateIdentifiers(model.model), 0);
  
  db_RoleRef role(grt);
  role->owner(model.schema);
  role->name(model.role->name());
  model.catalog->roles().insert(role);
  ensure_equals("validateDuplicateRoleName2", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(34)
{
  // test validateDuplicateUserName
  TestModel model(grt);
  ensure_equals("validateDuplicateUserName", module->validateDuplicateIdentifiers(model.model), 0);
  
  db_UserRef user(grt);
  user->owner(model.schema);
  user->name(model.user->name());
  model.catalog->users().insert(user);
  ensure_equals("validateDuplicateUserName2", module->validateDuplicateIdentifiers(model.model), 1);
}

TEST_FUNCTION(35)
{
  // test validateDataTypeConsistencyByColumnName
  TestModel model(grt);
  ensure_equals("validateDataTypeConsistencyByColumnName", module->validateConsistency(model.model), 0);
  
  db_TableRef table(grt);
  table->owner(model.schema);
  table->name("temptable");
  model.schema->tables().insert(table);

  db_ColumnRef column(grt);
  column->owner(table);
  column->name(model.column->name());
  column->simpleType(model.model->rdbms()->simpleDatatypes().get(1));
  
  table->columns().insert(column);
  ensure_equals("validateDataTypeConsistencyByColumnName2", module->validateConsistency(model.model), 1);
}

TEST_FUNCTION(36)
{
  // test validateForeignKeysRefersPrimaryKey
  TestModel model(grt);
  ensure_equals("validateForeignKeysRefersPrimaryKey", module->validateLogic(model.model), 0);
  
  model.foreignKey->referencedColumns().remove_all();
  model.foreignKey->referencedColumns().insert(model.column2);
  ensure_equals("validateForeignKeysRefersPrimaryKey2", module->validateLogic(model.model), 1);
}

TEST_FUNCTION(37)
{
  // test validateTableIsWriteable
  TestModel model(grt);
  ensure_equals("validateTableIsWriteable", module->validateLogic(model.model), 0);
  
  model.tablePrivilege->privileges().remove_all();
  model.tablePrivilege->privileges().insert("SELECT");
  ensure_equals("validateTableIsWriteable2", module->validateLogic(model.model), 1);
}

TEST_FUNCTION(38)
{
  // test validateNoStubTables
  TestModel model(grt);
  ensure_equals("validateNoStubTables", module->validateLogic(model.model), 0);
  
  model.table->isStub(1);
  ensure_equals("validateNoStubTables2", module->validateLogic(model.model), 1);
}
*/

END_TESTS
