--[[----------------------------------------------------------------------------

WFSQLiteDatabaseSchemaTest.lua

--------------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2015 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remains the property of
Adobe Systems Incorporated and its suppliers, if any. The intellectual and
technical concepts contained herein are proprietary to Adobe Systems
Incorporated and its suppliers and are protected by all applicable
intellectual property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

--------------------------------------------------------------------------------

NOTE: This test is a little bit grungy in that the only client that reads anything
from WFSQLiteDatabaseSchema is WFSQLiteDatabase, so we mimic the patterns that WFSQLiteDatabase
expects to use. In other words, we get values directly from the instance
variables, rather than using accessors.

----------------------------------------------------------------------------]]--

	-- WF.core.self_test
local WFRxTestCase = require 'WFRxTestCase'

	-- WF.sqlite.database
local WFSQLiteDatabaseSchema = require 'WFSQLiteDatabaseSchema'


--============================================================================--

local WFSQLiteDatabaseSchemaTest = {}

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestInit( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectEqual( {}, schema._tables )
	rxTest:expectEqual( {}, schema._indexes )

	rxTest:expectEqual( '0', schema._currentVersion )
	rxTest:expectEqual( '0', schema._backwardCompatibleToVersion )

	local curr, back = schema:currentAndBackwardCompatibleVersions()

	rxTest:expectEqual( '0', curr )
	rxTest:expectEqual( '0', back )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestInitWithCurrentVersion( rxTest )

	local schema = WFSQLiteDatabaseSchema( '4' )

	rxTest:expectEqual( {}, schema._tables )
	rxTest:expectEqual( {}, schema._indexes )

	rxTest:expectEqual( '4', schema._currentVersion )
	rxTest:expectEqual( '4', schema._backwardCompatibleToVersion )

	local curr, back = schema:currentAndBackwardCompatibleVersions()

	rxTest:expectEqual( '4', curr )
	rxTest:expectEqual( '4', back )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestInitWithCurrentAndBackwardVersion( rxTest )

	local schema = WFSQLiteDatabaseSchema( '4', '2' )

	rxTest:expectEqual( {}, schema._tables )
	rxTest:expectEqual( {}, schema._indexes )

	rxTest:expectEqual( '4', schema._currentVersion )
	rxTest:expectEqual( '2', schema._backwardCompatibleToVersion )

	local curr, back = schema:currentAndBackwardCompatibleVersions()

	rxTest:expectEqual( '4', curr )
	rxTest:expectEqual( '2', back )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestUseWAL( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectEqual( false, schema._useWAL )

	rxTest:expectEqual( schema, schema:useWAL() )

	rxTest:expectEqual( true, schema._useWAL )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestUseForeignKeys( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectEqual( false, schema._useForeignKeys )

	rxTest:expectEqual( schema, schema:useForeignKeys() )

	rxTest:expectEqual( true, schema._useForeignKeys )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestSetSynchronous( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectEqual( false, schema._synchronous )

	rxTest:expectEqual( schema, schema:setSynchronous( 'full' ) )

	rxTest:expectEqual( 'full', schema._synchronous )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestSetPageSize( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectEqual( false, schema._pageSize )

	rxTest:expectEqual( schema, schema:setPageSize( 8192 ) )

	rxTest:expectEqual( 8192, schema._pageSize )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestAddTable( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectEqual( {}, schema._tables, {} )

	local localStateDesc = schema:addTable
		[[CREATE TABLE localState( name UNIQUE NOT NULL, dataType, value )]]

	local tempDocIdsDesc = schema:addTable
		[[CREATE TEMPORARY TABLE TEMP_docIds( docId )]]

	rxTest:expectEqual(
		{
			localState = localStateDesc,
			TEMP_docIds = tempDocIdsDesc,
		},
		schema._tables )

	rxTest:expectEqual( 'localState', localStateDesc._tableName )
	rxTest:expectEqual(
		[[CREATE TABLE localState( name UNIQUE NOT NULL, dataType, value )]],
		localStateDesc._sql )

	rxTest:expectEqual( 'TEMP_docIds', tempDocIdsDesc._tableName )
	rxTest:expectEqual(
		[[CREATE TEMPORARY TABLE TEMP_docIds( docId )]],
		tempDocIdsDesc._sql )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestAddTable_errorBadSQL( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectError( function()
		schema:addTable
			[[CREATE BOGUS THING blah]]
	end )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestAddTable_onConflict( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	local localStateDesc = schema:addTable
		[[CREATE TABLE localState( name UNIQUE NOT NULL, dataType, value )]]
		:onConflict( 'replace' )

	rxTest:expectEqual(
		{
			localState = localStateDesc,
		},
		schema._tables )

	rxTest:expectEqual( 'localState', localStateDesc._tableName )
	rxTest:expectEqual(
		[[CREATE TABLE localState( name UNIQUE NOT NULL, dataType, value )]],
		localStateDesc._sql )

	rxTest:expectEqual( 'replace', localStateDesc._onConflict )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestAddTable_errorBadConflictPolicy( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectError( function()
		schema:addTable
			[[CREATE TABLE localState( name UNIQUE NOT NULL, dataType, value )]]
			:onConflict( 'bogus' )
	end )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestDropTable( rxTest )

	local schema = WFSQLiteDatabaseSchema()
	
	rxTest:expectEqual( {}, schema._tablesToDrop )
	
	schema:dropTable( 'dropThisTable' )
	
	rxTest:expectEqual( { 'dropThisTable' }, schema._tablesToDrop )
	
	schema:dropTable( 'dropThisTableToo' )
	
	rxTest:expectEqual( { 'dropThisTable', 'dropThisTableToo' }, schema._tablesToDrop )
	
end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestAddIndex( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectEqual( {}, schema._indexes )

	local localStateNameDesc = schema:addIndex
		[[CREATE INDEX localState_name ON localState( name )]]

	local bodyContentHashDesc = schema:addIndex
		[[CREATE INDEX documents_bodyContentHash ON documents( bodyContentHash )]]

	rxTest:expectEqual(
		{
			localState_name = localStateNameDesc,
			documents_bodyContentHash = bodyContentHashDesc,
		},
		schema._indexes )

	rxTest:expectEqual( 'localState_name', localStateNameDesc._indexName )
	rxTest:expectEqual(
		[[CREATE INDEX localState_name ON localState( name )]],
		localStateNameDesc._sql )

	rxTest:expectEqual( 'documents_bodyContentHash', bodyContentHashDesc._indexName )
	rxTest:expectEqual(
		[[CREATE INDEX documents_bodyContentHash ON documents( bodyContentHash )]],
		bodyContentHashDesc._sql )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestAddIndex_errorBadSQL( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	rxTest:expectError( function()
		schema:addIndex
			[[CREATE BOGUS THING blah]]
	end )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestAddTable_onConflict_alter( rxTest )

	local schema = WFSQLiteDatabaseSchema()

	local localStateDesc = schema:addTable
		[[CREATE TABLE localState( name UNIQUE NOT NULL, dataType, value, foo, bar )]]
			:onConflict( 'alter', { 
				'ALTER TABLE localState ADD COLUMN foo TEXT',
				'ALTER TABLE localState ADD COLUMN bar TEXT'
			} )

	rxTest:expectEqual(
		{
			localState = localStateDesc,
		},
		schema._tables )

	rxTest:expectEqual( 'localState', localStateDesc._tableName )
	
	rxTest:expectEqual(
		[[CREATE TABLE localState( name UNIQUE NOT NULL, dataType, value, foo, bar )]],
		localStateDesc._sql )

	rxTest:expectEqual( 'alter', localStateDesc._onConflict )

	rxTest:expectEqual( 
			{
				'ALTER TABLE localState ADD COLUMN foo TEXT',
				'ALTER TABLE localState ADD COLUMN bar TEXT'
			},
			localStateDesc._onConflictAlterSqlTable )

end

--------------------------------------------------------------------------------

function WFSQLiteDatabaseSchemaTest.rxTestAllowMultipleConnections( rxTest )

	local schema = WFSQLiteDatabaseSchema()
	schema:useWAL()
	
	rxTest:expectEqual( false, schema._allowMultipleConnections )
	
	schema:allowMultipleConnections()
	
	rxTest:expectEqual( true, schema._allowMultipleConnections )

end

--------------------------------------------------------------------------------

return WFRxTestCase.wrapSuite( 'WFSQLiteDatabaseSchemaTest', WFSQLiteDatabaseSchemaTest )
