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

WFZStringTest.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2011 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.

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

Heads up: We want to prevent the ZString harvester from finding these strings,
so we use string concatenation in ways that wouldn't normally be done.

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

	-- wichitafoundation.core.strings
local WFZString = require 'WFZString'

	-- wichitafoundation.core.utils
local KSTestUtils = require 'KSTestUtils'


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

local WFZStringTest = {}

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

local function checkEqualZStrings( zstr, expectedString, resultString )

	if expectedString ~= resultString then
		error( string.format( "\n\tZString is '%s'\n\tand expected '%s'\n\tbut result string was '%s'",
							  zstr, expectedString, tostring( resultString ) ) )
	end

end

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

function WFZStringTest.testFromZString()

	local WFZString_DEBUG_LOCALIZATION = WFZString.DEBUG_LOCALIZATION

	local zPostFix = ""
	
	if WFZString_DEBUG_LOCALIZATION then
		zPostFix = "_ZZZ"
	end

	-- Plain ZString:
	
    local zKey = "$".."$$/ZString/test/plainString="
    local zValue = "This is a plain old vanilla English string"
    local result = WFZString.fromZString( zKey .. zValue )
    checkEqualZStrings( zKey .. zValue, zValue .. zPostFix, result )
		
    zKey = "$".."$$/test2/plainString2="
    zValue = "This is another plain old vanilla English string"
    result = WFZString.fromZString( zKey .. zValue )
    checkEqualZStrings( zKey .. zValue, zValue .. zPostFix, result )

	-- Quoted ZString:

    zKey = "$".."$$/ZString/test/plainString="
    zValue = [[This is a plain old vanilla English string with a \"Quote\" in it]]
    result = WFZString.fromZString( zKey .. zValue )
	local zExpectedResult = [[This is a plain old vanilla English string with a "Quote" in it]]
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

	-- Hat at end ZString:

    zKey = "$".."$$/ZString/test/plainString="
    zValue = "Simple ^1 string with a hat at the end^"
    result = WFZString.fromZString( zKey .. zValue, "test" )
	zExpectedResult = "Simple test string with a hat at the end^"
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

	-- Empty ZString:
	
	zKey = "$".."$$/ZString/test/emptyString="
	zValue = ""
	result = WFZString.fromZString( zKey .. zValue )
	checkEqualZStrings( zKey .. zValue, zValue .. zPostFix, result )

	-- Malformed ZStrings: No key should error out.
	
	KSTestUtils.testFails( function()
		zValue = "A plain string with no ZString key"
		result = WFZString.fromZString( zValue )
		checkEqualZStrings( zValue, zValue .. zPostFix, result )
	end )

	-- Malformed ZStrings: Bad key with a single $ sign should error out.
	
	KSTestUtils.testFails( function()
		zKey = "$/ZString/test/oneDollarSignKey="
		zValue = "A ZString with a bad key that has only one $ sign."
		result = WFZString.fromZString( zKey .. zValue)
		checkEqualZStrings( zKey .. zValue, zKey .. zValue .. zPostFix, result )
	end )

	-- Malformed ZStrings: Bad key with no $ signs should error out.
	
	KSTestUtils.testFails( function()
		zKey = "/ZString/test/noDollarSignKey="
		zValue = "A ZString with a bad key that has no $ signs."
		result = WFZString.fromZString( zKey .. zValue )
		checkEqualZStrings( zKey .. zValue, zKey .. zValue .. zPostFix, result )
	end )
	
	-- Malformed ZStrings: Bad key with no = signs should error out.
	
	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/noEqualSignKey"
		zValue = "A ZString with a bad key that has no equal sign."
		result = WFZString.fromZString( zKey .. zValue )
		checkEqualZStrings( zKey .. zValue, zKey .. zValue .. zPostFix, result )
	end )
	
    -- Malformed ZStrings: High ASCII should error out.
	
	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/highASCII="
		zValue= "\255\255\255\255"
		result = WFZString.fromZString( zKey .. zValue )
		checkEqualZStrings( zKey .. zValue, zKey .. zValue .. zPostFix, result )
	end )
	
	-- Malformed ZStrings: Uses \n instead of ^n
	
	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/backslashnUsage="
		zValue = "A ZString with backslash n \n"
		result = WFZString.fromZString( zKey .. zValue )
		checkEqualZStrings( zKey .. zValue, zKey .. zValue .. zPostFix, result )
	end )

	-- Hat substitutions: Replacement points.
	
	zKey = "$".."$$/ZString/test/plainHatSubstitution="
	zValue = "A ZString with ^1 ^2 ^3 substitution^4."
	local zHat1 = "a"
	local zHat2 = "few"
	local zHat3 = "hat"
	local zHat4 = "s"
	zExpectedResult = "A ZString with a few hat substitutions."
	result = WFZString.fromZString( zKey .. zValue, zHat1, zHat2, zHat3, zHat4 )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	
	zKey = "$".."$$/ZString/test/plainHatSubstitution="
	zValue = "A ZString with {one} {two} {three} substitution{four}."
	zHat1 = "a"
	zHat2 = "few"
	zHat3 = "hat"
	zHat4 = "s"
	zExpectedResult = "A ZString with a few hat substitutions."
	result = WFZString.fromZString{ zKey .. zValue, one = zHat1, two = zHat2, three = zHat3, four = zHat4 }
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	
	-- Hat substitutions: Predefined hat sequences, low ASCII.
	
	zKey = "$".."$$/ZString/test/preassignedHatSequence1="
	zValue = "A ZString with carriage return,^rand a line feed^nin the string"
	zExpectedResult = "A ZString with carriage return,\013and a line feed\010in the string"
	result = WFZString.fromZString( zKey .. zValue )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

	-- Hat substitutions: Predefined hat sequences, UTF-8,

	zKey = "$".."$$/ZString/test/preassignedHatSequence2="
	zValue = "A ZString with a bullet ^B, copy right symbol ^C, degree sign ^D, increment ^I, registered sign ^R, summation ^S, trademark ^T, not sign ^!"
	zExpectedResult = "A ZString with a bullet " .. string.char( 226, 128, 162 ) ..
						", copy right symbol " .. string.char( 194, 169 ) ..
						", degree sign " .. string.char( 194, 176 ) ..
						", increment " .. string.char( 226, 136, 134 ) ..
						", registered sign " .. string.char( 194, 174 ) ..
						", summation " .. string.char( 226, 136, 145 ) ..
						", trademark " ..  string.char( 226, 132, 162 ) ..
						", not sign " .. string.char( 194, 172 )
	result = WFZString.fromZString( zKey .. zValue )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

	-- Hash substitutions: Predefined hash sequences, UTF-8,

	zKey = "$".."$$/ZString/test/preassignedHashSequence="
	zValue = "A ZString with a quote #{quot}, left double quote #{ldquo}, right double quote #{rdquo}, copyright symbol #{copy}, degree sign #{deg}"
	zExpectedResult = "A ZString with a quote " .. string.char( 34 ) ..
						", left double quote " .. string.char( 226, 128, 156 ) ..
						", right double quote " .. string.char( 226, 128, 157 ) ..
						", copyright symbol " .. string.char( 194, 169 ) ..
						", degree sign " .. string.char( 194, 176 )
	result = WFZString.fromZString( zKey .. zValue )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

 	-- Hat substitutions: repeated hat sequences.
	
	zKey = "$".."$$/ZString/test/repeatedHatSequence="
	zValue = "A ZString with ^1 hat sequences ^1 hat sequences"
	zHat1 = "repeated"
	zExpectedResult = "A ZString with repeated hat sequences repeated hat sequences"
	result = WFZString.fromZString( zKey .. zValue, zHat1 )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	
	zKey = "$".."$$/ZString/test/repeatedHatSequence="
	zValue = "A ZString with {test} hat sequences {test} hat sequences"
	zHat1 = "repeated"
	zExpectedResult = "A ZString with repeated hat sequences repeated hat sequences"
	result = WFZString.fromZString{ zKey .. zValue, test = zHat1 }
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	
	-- Hat substitutions: Unicode code points.

	zKey = "$".."$$/ZString/test/hatSequence/unicode="
	zValue = "A ZString with Japanese, ^U+65E5^U+672C^U+8A9E"
	zExpectedResult = "A ZString with Japanese, \230\151\165\230\156\172\232\170\158"
	result = WFZString.fromZString( zKey .. zValue )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	
	-- Hat substitutions: Unicode code points. (using lower case hex chars)

	zKey = "$".."$$/ZString/test/hatSequence/unicode="
	zValue = "A ZString with Japanese, ^U+65e5^U+672c^U+8a9e"
	zExpectedResult = "A ZString with Japanese, \230\151\165\230\156\172\232\170\158"
	result = WFZString.fromZString( zKey .. zValue )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

   -- Malformed ZStrings: Hat substitutions with less replacements than substitution points.
	
	zKey = "$".."$$/ZString/test/badHatSubstitution/missingReplacements="
	zValue = "A ZString with ^1 ^2 ^3 substitution^4."
	zHat1 = "too"
	zHat2 = "few"
	zExpectedResult = "A ZString with too few ^3 substitution^4."
	result = WFZString.fromZString( zKey .. zValue, zHat1, zHat2 )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

	zKey = "$".."$$/ZString/test/badHatSubstitution/missingReplacements="
	zValue = "A ZString with {one} {two} {three} substitution{four}."
	zHat1 = "too"
	zHat2 = "few"
	zExpectedResult = "A ZString with too few {three} substitution{four}."
	result = WFZString.fromZString{ zKey .. zValue, one = zHat1, two = zHat2 }
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

    -- Malformed ZStrings: Hat substitutions with more replacements than substitution points.
	
	zKey = "$".."$$/ZString/test/badHatSubstitution/tooManyReplacements="
	zValue = "A ZString with ^1 ^2 replacements."
	zHat1 = "too"
	zHat2 = "many"
	zHat3 = "extra"
	zHat4 = "extra, extra"
	zExpectedResult = "A ZString with too many replacements."
	result = WFZString.fromZString( zKey .. zValue, zHat1, zHat2, zHat3, zHat4 )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

	zKey = "$".."$$/ZString/test/badHatSubstitution/tooManyReplacements="
	zValue = "A ZString with {one} {two} replacements."
	zHat1 = "too"
	zHat2 = "many"
	zHat3 = "extra"
	zHat4 = "extra, extra"
	zExpectedResult = "A ZString with too many replacements."
	result = WFZString.fromZString{ zKey .. zValue, one = zHat1, two = zHat2, three = zHat3, four = zHat4 }
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )


	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
		zValue = "A ZString with invalid {one} replacement."
		zHat1 = true
		zExpectedResult = "A ZString with invalid  replacements."
		result = WFZString.fromZString{ zKey .. zValue, one = zHat1 }
		checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	end )

	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
		zValue = "A ZString with invalid {one} replacement."
		zHat1 = 3.141592
		zExpectedResult = "A ZString with invalid  replacements."
		result = WFZString.fromZString{ zKey .. zValue, one = zHat1 }
		checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	end )

	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
		zValue = "A ZString with invalid {one} replacement."
		zHat1 = 42
		zExpectedResult = "A ZString with invalid  replacements."
		result = WFZString.fromZString{ zKey .. zValue, one = zHat1 }
		checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	end )
	
	zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
	zValue = "A ZString with hat (^1) replacement."
	zHat1 = true
	zExpectedResult = "A ZString with hat () replacement."
	result = WFZString.fromZString( zKey .. zValue, nil )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )

	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
		zValue = "A ZString with hat (^1) replacement."
		zHat1 = true
		zExpectedResult = "A ZString with hat () replacement."
		result = WFZString.fromZString( zKey .. zValue, zHat1 )
		checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	end )

	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
		zValue = "A ZString with hat (^1) replacement."
		zHat1 = 3.141592
		zExpectedResult = "A ZString with hat () replacement."
		result = WFZString.fromZString( zKey .. zValue, zHat1 )
		checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	end )

	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
		zValue = "A ZString with hat (^1) replacement."
		zHat1 = 42
		zExpectedResult = "A ZString with hat () replacement."
		result = WFZString.fromZString( zKey .. zValue, zHat1 )
		checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	end )
	
	KSTestUtils.testFails( function()
		zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
		zValue = "A ZString with hat (^10) replacement."
		zHat1 = 42
		zExpectedResult = "A ZString with hat () replacement."
		result = WFZString.fromZString( zKey .. zValue, "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" )
		checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	end )
	
	-- Hat substitutions: Unrecognized predefined hat sequences.
	
	zKey = "$".."$$/ZString/test/badHatSubstitution/unRecognizedSequence="
	zValue = "A ZString with an unrecognized sequence ^Z"
	zExpectedResult = "A ZString with an unrecognized sequence ^Z"
	result = WFZString.fromZString( zKey .. zValue )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
	
end

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

function WFZStringTest.testFromNativeCodeZString()

	local WFZString_DEBUG_LOCALIZATION = WFZString.DEBUG_LOCALIZATION

	local zPostFix = ""
	
	if WFZString_DEBUG_LOCALIZATION then
		zPostFix = "_ZZZ"
	end

    local zKey = "$".."$$/ZString/test/plainString="
    local zValue = "This is a plain old vanilla English string"
    local result = WFZString.fromNativeCodeZString( zKey .. zValue )
    checkEqualZStrings( zKey .. zValue, zValue .. zPostFix, result )


	zKey = "$".."$$/ZString/test/badCurlySubstitution/nonStringReplacements="
	zValue = "A ZString with hat (^1) replacement."
	local zHat1 = 42
	local zExpectedResult = "A ZString with hat (42) replacement."
	result = WFZString.fromZString( zKey .. zValue, zHat1 )
	checkEqualZStrings( zKey .. zValue, zExpectedResult .. zPostFix, result )
end

--------------------------------------------------------------------------------
--[[
	Test the "usesFileSyntax" code path in WFZString.parseZString function that
	exercises the use of translation map files.
]]

function WFZStringTest.testWithTranslationMap()

	local function testMakeTranslationMap( filename, mapStr )
	
		-- debug.print( 'WFZStringTest.testWithTranslationMap: file name is, filename )

		local file = io.open( filename, 'a' )
		
		if file then
			file:write( '"$' .. '$$/Foo/Bar=Baz"\n' )
			file:write( '"$' .. '$$/Foo/Baz=Bar"\n' )
			if mapStr ~= nil then
				file:write( mapStr .. '\n' )
			end
			file:close()
	
			local map = WFZString.makeTranslationMap( filename )
			
			-- debug.print( 'WFZStringTest.testWithTranslationMap: $$$/Foo/Bar in map is "'
			--				.. map[ "$" .. "$$/Foo/Bar" ] .. '"' )
	
			checkEqualZStrings( "$" .. "$$/Foo/Bar", "Baz", map[ "$" .. "$$/Foo/Bar" ] )
		else

			debug.print( 'WFZStringTest.testWithTranslationMap: could not open file "'
						 .. filename .. '"' )

		end
		
		os.remove( filename )
	
	end


	local KSPathUtils = require 'KSPathUtils'
	local tempPathName = KSPathUtils.getStandardFilePath( 'temp' )

	local filename = KSPathUtils.child( tempPathName, "ZStringTestMap" )

	os.remove( filename ) -- make sure we get rid of any test file first as we open in append

	testMakeTranslationMap( filename )

	-- write out a bom in front of the file using binary mode
	local file = io.open( filename, 'wb' )
	if file then
		file:write(string.char(239))
		file:write(string.char(187))
		file:write(string.char(191))
		file:close()
	end

	testMakeTranslationMap( filename )
	
	assert( not pcall( testMakeTranslationMap, filename, '"$' .. '$$/Foo/Bad=Bad' )) -- intentionally missing a " to cause a failure

	os.remove( filename ) -- if we fail during read we will leave the test file so delete it
	
end

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

return WFZStringTest
