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

KSDataLuaTest.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.

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

local KSData = require 'KSData'

	-- WF.core.os
local KSPathUtils = require 'KSPathUtils'
local WFFileUtils = require 'WFFileUtils'
local WFPlatformInfo = require 'WFPlatformInfo'

local KSDataLuaTest = {}

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

function KSDataLuaTest.testKSDataNamespace()

	local data = assert( KSData.make( "123abc" ) )

	assert( KSData.isData( data ) == true, "isData returned false for data" )
	assert( KSData.isData( "xyz" ) == false, "isData returned true for string" )
	assert( KSData.isData( 19 ) == false, "isData returned true for number" )
	assert( KSData.isData( nil ) == false, "isData returned true for nil" )

	assert( tostring( data ) == "123abc", "tostring not overloaded" )

	assert( KSData.length( data ) == 6, "length returned incorrect result" )
	assert( KSData.length( "xyz" ) == 0, "isData returned non-zero for string" )
	assert( KSData.length( 19 ) == 0, "isData returned non-zero for number" )
	assert( KSData.length( nil ) == 0, "isData returned non-zero for nil" )

	data:close()

end

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

function KSDataLuaTest.testMakeFromData()

	local stringData = assert( KSData.make( "123abc" ) )

	local data = assert( KSData.make( stringData ) )

	assert( KSData.isData( data ) == true, "isData returned false for data" )
	assert( KSData.isData( "xyz" ) == false, "isData returned true for string" )
	assert( KSData.isData( 19 ) == false, "isData returned true for number" )
	assert( KSData.isData( nil ) == false, "isData returned true for nil" )

	assert( tostring( data ) == "123abc", "tostring not overloaded" )

	assert( KSData.length( data ) == 6, "length returned incorrect result" )
	assert( KSData.length( "xyz" ) == 0, "isData returned non-zero for string" )
	assert( KSData.length( 19 ) == 0, "isData returned non-zero for number" )
	assert( KSData.length( nil ) == 0, "isData returned non-zero for nil" )

	stringData:close()
	data:close()

end

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

function KSDataLuaTest.testMakeFromString()

	local emptyStringData = assert( KSData.make( "" ) )

	assert( KSData.isData( emptyStringData ) == true, "isData returned false for empty string data" )
	assert( KSData.length( emptyStringData ) == 0, "isData returned non-zero length for empty string data" )

	emptyStringData:close()

	local stringData = assert( KSData.make( "123abc" ) )

	assert( KSData.isData( stringData ) == true, "isData returned false for string data" )
	assert( KSData.length( stringData ) == 6, "isData returned incorrect length for string data" )

	stringData:close()
end

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

function KSDataLuaTest.testDigest( test )

	-- digest values tested against mac os command line tool md5 and shasum

	local stringData = assert( KSData.make( "123abc" ) )

	local digests = {
		MD5 = { "a906449d5769fa7361d7ecc6aa3f6d28", "422a1740794ba84190fe6e4d178f5c0d" },
		SHA1 = { "4be30d9814c6d4e9800e0d2ea9ec9fb00efa887b", "a6e6f03a0c8a4e6c8096dda7c7ab199b7edcc850" },
		SHA256 = {
			"dd130a849d7b29e5541b05d2f7f86a4acd4f1ec598c1c9438783f56bc4f0ff80",
			"ebc83f059131be564238b82207818f5d843a812155d9b85efb640a445a8ba1ce" },
		SHA384 = {
			"40889bd7aee5be35f9d713c4f51ff00fe2099fd901d094284d6edc9aa39ec096cebe9547d3cbaf1f35101a6489f033c3",
			"c86ee2fac94384f2225ffc3b399fa2771ad67c0af3c0901a290d626c0e16b06e3143c9f9bf521252ac174340b1d8353a" },
		SHA512 = {
			"7b6ad79b346fb6951275343948e13c1b4ebca82a5452a6c5d15684377f096ca927506a23a847e6e046061399631b16fc2820c8b0e02d0ea87aa5a203a77c2a7e",
			"976ce700d2b79bf089e40305e965426505434d62c4f2bf8d6c53a04bfe002df76e53274a0b84747b79693cdc3c045aa2999b901c1ae0a8aaebe3bae35d10c1c0" },
	}

	local shortData = assert( KSData.make( stringData ), "Fail to make KSData" )
	local longString = string.rep( "smile!! ", 256 )
	local longData = assert( KSData.make( longString ), "Fail to make KSData" )

	for alg, expected in pairs( digests ) do

		local digest = shortData:digest( alg )
		test:log( digest )
		assert( digest == expected[ 1 ], alg .. " returned bad value for short string" )

		digest = longData:digest( alg )
		test:log( digest )
		assert( digest == expected[ 2 ], alg .. " returned bad value for long string" )

	end

	stringData:close()
	shortData:close()
	longData:close()

end

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

function KSDataLuaTest.testKSDataTransit( test )
	local WFWorkerThread = require 'WFWorkerThread'
	local WFAsyncTestCase = require 'WFAsyncTestCase'

	local requestTestHandler = WFWorkerThread( 'WFRequestTestHandler.lua' )

	WFAsyncTestCase( test )

		:waitFor( function()

			local srcData = KSData.make( "Transit Data" )
			local p = requestTestHandler:requestP( 'echo', srcData )
			:waitForP( requestTestHandler:requestP( 'collectgarbage' ) )
			:observeP( function()
				srcData:close()
			end )

			return p:mapDataP_new( function( n, resultData )
				local s = tostring( resultData )
				resultData:close()
				requestTestHandler:close()
				return s
			end )

		end )
		:continueWhenValueMatches( 'data', "Transit Data" )

end

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

function KSDataLuaTest.testMakeRejectsOtherDataTypes()

	local function assertFails( dataType, func )

		local pcallResults = pcall( func )
		assert( pcallResults == false, string.format( "make didn't reject %s", dataType ) )

	end

	assertFails( "number", function() KSData.make( 4 ) end )
	assertFails( "nil", function() KSData.make( nil ) end )
	assertFails( "table", function() KSData.make( {} ) end )

end

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

function KSDataLuaTest.testClosedIsClosed()
	local WFCloseSupport = require 'WFCloseSupport'

	local data = KSData.make( "hello" )
	assert( WFCloseSupport.hasBeenOrWillBeClosed( data ) == false, 'Should not yet be closed' )
	data:close()
	assert( WFCloseSupport.hasBeenOrWillBeClosed( data ) == true, 'Should be closed' )

end

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

if not WFPlatformInfo.isWindows then

	function KSDataLuaTest.testSaveToFile()

		local child = KSPathUtils.child
		local getStandardFilePath = KSPathUtils.getStandardFilePath

		local testDataPath = child( getStandardFilePath( 'carouselDocuments' ), 'ksdataluatest' )

		local testString = "123"
		local updateString = "abc"

		local testData = assert( KSData.make( testString ), "Fail to make KSData" )
		local updateData = assert( KSData.make( updateString ), "Fail to make KSData" )

		KSData.saveToFile( testData, testDataPath )
		KSData.saveToFile( updateData, testDataPath )

		testData:close()
		updateData:close()

		local fileData = assert(
			KSData.memoryMappedContentsOfFile( testDataPath ), "Fail to read KSData" )

		assert( tostring( fileData ) == "abc", "File content doesn't match" )

		fileData:close()
		WFFileUtils.delete( testDataPath )

	end

end

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

function KSDataLuaTest.testCompressAndDecompress()

	local stringData = assert( KSData.make( "Hello world." ) )

	assert( KSData.isData( stringData ) == true, "isData returned false for string data" )
	assert( KSData.length( stringData ) == 12, "isData returned incorrect length for string data" )

	local compressedData = assert( KSData.compress( stringData ) )

	assert( KSData.isData( compressedData ) == true, "isData returned false for compressed data" )
	assert( KSData.length( compressedData ) ~= 12, "compress data length is equal to original data" )

	local decompressedData = assert( KSData.decompress( compressedData ) )

	assert( KSData.isData( decompressedData ) == true, "isData returned false for decompressed data" )
	assert( KSData.length( decompressedData ) == 12, "decompressed data length is not equal to original data" )

	assert( tostring( decompressedData ) == "Hello world.", "compress and decompress breaks the string data" )

	assert( tostring( KSData.decompress( KSData.compress( stringData ) ) )  == "Hello world.",
			"compress and decompress breaks the string data" )

	stringData:close()
	compressedData:close()
	decompressedData:close()

end

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

if WFPlatformInfo.isAndroid then

	function KSDataLuaTest.testSaveToFileUsingFileDescriptor()
	
		local child = KSPathUtils.child
		local getStandardFilePath = KSPathUtils.getStandardFilePath
	
		local testDataPath = child( getStandardFilePath( 'carouselDocuments' ), 'ksdataluatest' )
		local testDataPathFD = WFFileUtils.getWritableFileDescriptor( testDataPath )
	
		local testString = "123"
		local updateString = "abc"
	
		local testData = assert( KSData.make( testString ), "Fail to make KSData" )
		local updateData = assert( KSData.make( updateString ), "Fail to make KSData" )
	
		KSData.saveToFileUsingFileDescriptor( testData, testDataPathFD )
	
		-- Create another FD, since the older one cannot be reused.
		testDataPathFD = WFFileUtils.getWritableFileDescriptor( testDataPath )
		KSData.saveToFileUsingFileDescriptor( updateData, testDataPathFD )
	
		testData:close()
		updateData:close()
	
		local fileData = assert(
			KSData.memoryMappedContentsOfFile( testDataPath ), "Fail to read KSData" )
	
		assert( tostring( fileData ) == "abc", "File content doesn't match" )
	
		fileData:close()
		WFFileUtils.delete( testDataPath )
	
	end

end

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

return KSDataLuaTest
