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

KSOptionsTest.lua

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

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

NOTICE: All information contained herein is, and remain 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 may be covered by U.S. and Foreign
Patents, patents in process, and are protected by trade secret or copyright
law.  Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

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

local KSOptionsTest = {}

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

function KSOptionsTest.testOptionsParsing()

	local KSOptions = assert( require "KSOptions" )

	local parse = assert( KSOptions.parse, "No definition for KSOptions.parse" )

	do
		local options = parse( "foo | baz" )
	
		assert( options.foo, "foo not present" )
		assert( options.baz, "baz not present" )
	end

	-- FIXME [mhamburg 2010-11-09]: Add new tests to respond to below feedback:
	-- (Or move the table equality function out of KSViewTree and use that.)
	
	-- [erwright 2010-11-03]: how about asserting # of entries in the table == # of options passed in?
	-- Perhaps something like this (though this currently fails):
	--
	-- local count = 0
	-- for _ in pairs(options) do count = count + 1 end
	-- assert( count == 2, "unexpected entries in options table" )

	local options = parse( "foo | baz", "foo | baz | bleen" )

	assert( options.foo, "foo not present" )
	assert( options.baz, "baz not present" )
	assert( not options.bleen, "bleen should not be present" )
	
	assert( pcall( parse, "bleen", "foo" ) == false, "Invalid option should have failed." )
	
end

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

function KSOptionsTest.testOptionsParsingTables()

	local KSOptions = assert( require "KSOptions" )

	local parse = assert( KSOptions.parse, "No definition for KSOptions.parse" )

	do
		local options = parse( { foo = true, baz = true } )
	
		assert( options.foo, "foo not present" )
		assert( options.baz, "baz not present" )
	end

	local options = parse( "foo | baz", { foo = true, baz = true, bleen = true } )

	assert( options.foo, "foo not present" )
	assert( options.baz, "baz not present" )
	assert( not options.bleen, "bleen should not be present" )

	assert( pcall( parse, "bleen", { foo = true } ) == false, "Invalid option should have failed." )
	
	assert( pcall( parse, { bleen = true }, { foo = true } ) == false, "Invalid option should have failed." )
	
end

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

function KSOptionsTest.testOptionsParsingEmpty()

	local KSOptions = assert( require "KSOptions" )

	local parse = assert( KSOptions.parse, "No definition for KSOptions.parse" )

	for k in pairs( parse() ) do
		assert( false, "Empty options should result in an empty set" )
	end

	for k in pairs( parse "" ) do
		assert( false, "Empty options string should result in an empty set" )
	end
	
	assert( pcall( function( empty ) empty.x = 'hello' end, parse "" ) == false,
				"We should disallow writing to the empty table." )
	
end

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

function KSOptionsTest.testOptionsTablesWriteProtected()

	local KSOptions = assert( require "KSOptions" )

	local parse = assert( KSOptions.parse, "No definition for KSOptions.parse" )
	
	assert( pcall( function( options ) options.x = 'hello' end, parse "foo" ) == false,
				"We should disallow writing to options table." )
	
end

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

function KSOptionsTest.testOptionsParser()

	local KSOptions = assert( require "KSOptions" )

	assert( KSOptions.parser, "No definition for KSOptions.parser" )
	
	local parser = KSOptions.parser "foo | baz"

	local options = parser "foo"

	assert( options.foo, "foo not present" )
	assert( not options.baz, "baz should not be present" )

	assert( pcall( parser, "bleen" ) == false, "Invalid option should have failed." )
	
end

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

function KSOptionsTest.testOptionsParserFromTable()

	local KSOptions = assert( require "KSOptions" )

	assert( KSOptions.parser, "No definition for KSOptions.parser" )
	
	local parser = KSOptions.parser{ foo = true, baz = true }

	local options = parser "foo"

	assert( options.foo, "foo not present" )
	assert( not options.baz, "baz should not be present" )

	assert( pcall( parser, "bleen" ) == false, "Invalid option should have failed." )
	
end

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

function KSOptionsTest.testExactlyOneOf()

	local KSOptions = assert( require "KSOptions" )
	
	local exactlyOneOf = assert( KSOptions.exactlyOneOf, "No definition for exactlyOneOf" )
	
	assert( exactlyOneOf( 'a', 'a | b | c' ) == 'a', "a in a | b | c failed" )
	assert( exactlyOneOf( 'b', 'a | b | c' ) == 'b', "b in a | b | c failed" )
	assert( exactlyOneOf( 'c', 'a | b | c' ) == 'c', "c in a | b | c failed" )

	assert( exactlyOneOf( 'a | x', 'a | b | c' ) == 'a', "a | x in a | b | c failed" )

	assert( exactlyOneOf( { a = true }, 'a | b | c' ) == 'a',
				"{ a = true } in a | b | c failed" )

	assert( exactlyOneOf( 'a', { a = true, b = true } ) == 'a',
				"a in { a = true, b = true } failed" )

	assert( exactlyOneOf( { a = true }, { a = true, b = true } ) == 'a',
				"{ a = true }  in { a = true, b = true } failed" )
				
	assert( false == pcall( exactlyOneOf, 'a | b', 'a | b | c' ),
			"a | b in a | b | c should have failed" )
			
	assert( false == pcall( exactlyOneOf, 'a | b | x', 'a | b | c' ),
			"a | b | x in a | b | c should have failed" )
			
	assert( false == pcall( exactlyOneOf, 'x', 'a | b | c' ),
			"x in a | b | c should have failed" )

end

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

return KSOptionsTest
