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

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

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

	-- WF.core.lua
local KSData = require 'KSData'

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

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

	-- WF.core.utils
local WFCloseSupport = require 'WFCloseSupport'

	-- WF.oz_client.managed_catalog.pixel_provider
local WFCatPixelFileCacheSave = require 'WFCatPixelFileCacheSave'

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

local WFCatPixelFileCacheSaveTest = {}

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

local function makeCacheName( prefix, suffix )

	local cacheName = string.format( '%s_%s', prefix, suffix )

	return cacheName

end

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

function WFCatPixelFileCacheSaveTest.rxTestBasic( rxTest )

	rxTest:expectEqual( false, WFCatPixelFileCacheSave == nil )

	for _, cacheByteSizeLimit in ipairs( { -1, 0, 100 } ) do

		cacheByteSizeLimit = cacheByteSizeLimit >= 0 and cacheByteSizeLimit or nil

		local cacheName = makeCacheName( 'mockFileOps_rxTestBasic', cacheByteSizeLimit )

		rxTest:log( "make cache " .. cacheName )

		local cache = WFCatPixelFileCacheSave( cacheName, 2, cacheByteSizeLimit )

		rxTest:expectEqual( false, cache == nil )

		local fileOps = rxTest:observe( cache:test_getFileOps() )

		local dataOne = KSData.make( "first data" )
		local dataTwo = KSData.make( "second bits" )
		local dataThree = KSData.make( "data the third" )

		local first = cache:savePixels( '/basic-test-dir/1.txt', dataOne )
		local second = cache:savePixels( '/basic-test-dir/2.txt', dataTwo )
		local third = cache:savePixels( '/basic-test-dir/3.txt', dataThree )

		rxTest:expectOnlyCompleted( first )
		rxTest:expectOnlyCompleted( second )
		rxTest:expectOnlyError( third, "too many requests" )

		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataOne ) )
		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataTwo ) )
		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataThree ) )

		fileOps:expectData( 'write', '/basic-test-dir/1.txt', 10, '2b8532d4a19aea2b3ae887cd17382322' )
		fileOps:expectData( 'write', '/basic-test-dir/2.txt', 11, '89907089ecc5d85b9002db1820f550bd' )

		local writeSize =  cacheByteSizeLimit and cacheByteSizeLimit > 1 and cacheByteSizeLimit or 100

		local size1 = writeSize - 1
		local dataFour = KSData.make( string.rep( 'X', size1 ) )

		local size2 = writeSize - size1 + 1
		local dataFive = KSData.make( string.rep( 'X', size2 ) )

		local fourth = cache:savePixels( '/basic-test-dir/4.txt', dataFour )
		local fifth = cache:savePixels( '/basic-test-dir/5.txt', dataFive )

		rxTest:expectOnlyCompleted( fourth )

		if cacheByteSizeLimit and cacheByteSizeLimit > 0 then

			rxTest:expectOnlyError( fifth, "too much memory used by unsaved blobs" )
				-- Because more than specified 100 byte limit to in-flight requests.
				--
		else

			rxTest:expectOnlyCompleted( fifth )

		end

		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataFour ) )
		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataFive ) )

		cache:close()

	end

end

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

function WFCatPixelFileCacheSaveTest.rxTestLimitsOnImp( rxTest )


	for _, cacheByteSizeLimit in ipairs( { -1, 0, 100 } ) do

		cacheByteSizeLimit = cacheByteSizeLimit >= 0 and cacheByteSizeLimit or nil

		rxTest:expectEqual( false, WFCatPixelFileCacheSave == nil )

		local cacheName = makeCacheName( 'mockFileOps_rxTestLimitsOnImp', cacheByteSizeLimit )

		rxTest:log( "make cache " .. cacheName )

		local cache1 = WFCatPixelFileCacheSave( cacheName, 2, cacheByteSizeLimit )
		local cache2 = WFCatPixelFileCacheSave( cacheName, 2, cacheByteSizeLimit )

		rxTest:expectEqual( false, cache1 == nil )
		rxTest:expectEqual( false, cache2 == nil )
		rxTest:expectEqual( false, cache1 == cache2 )

		local fileOps = rxTest:observe( cache1:test_getFileOps() )

		local dataOne = KSData.make( "first data" )
		local dataTwo = KSData.make( "second bits" )
		local dataThree = KSData.make( "data the third" )

		rxTest:expectOnlyCompleted( cache1:test_startBacklog() )

		local first = cache1:savePixels( '/test-dir/1.txt', dataOne )
		local second = cache1:savePixels( '/test-dir/2.txt', dataTwo )
		local third = cache2:savePixels( '/test-dir/3.txt', dataThree )

		rxTest:expectOnlyCompleted( cache1:test_endBacklog() )

		rxTest:expectOnlyCompleted( first )
		rxTest:expectOnlyCompleted( second )
		rxTest:expectOnlyError( third, "too many requests" )

		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataOne ) )
		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataTwo ) )
		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataThree ) )

		fileOps:expectData( 'write', '/test-dir/1.txt', 10, '2b8532d4a19aea2b3ae887cd17382322' )
		fileOps:expectData( 'write', '/test-dir/2.txt', 11, '89907089ecc5d85b9002db1820f550bd' )

		local writeSize = cacheByteSizeLimit and cacheByteSizeLimit > 1 and cacheByteSizeLimit or 100

		local size1 = writeSize - 1
		local dataFour = KSData.make( string.rep( 'X', size1 ) )

		local size2 = writeSize - size1 + 1
		local dataFive = KSData.make( string.rep( 'X', size2 ) )

		rxTest:expectOnlyCompleted( cache1:test_startBacklog() )

		local fourth = cache1:savePixels( '/basic-test-dir/4.txt', dataFour )
		local fifth = cache2:savePixels( '/basic-test-dir/5.txt', dataFive )

		rxTest:expectOnlyCompleted( cache1:test_endBacklog() )

		rxTest:expectOnlyCompleted( fourth )

		if cacheByteSizeLimit and cacheByteSizeLimit > 0 then

			rxTest:log( "expecting  memory error" )

			rxTest:expectOnlyError( fifth, "too much memory used by unsaved blobs" )
				-- Because more than specified 100 byte limit to in-flight requests.
				--
		else

			rxTest:log( "expect ok" )

			rxTest:expectOnlyCompleted( fifth )

		end

		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataFour ) )
		rxTest:expectEqual( true, WFCloseSupport.hasBeenOrWillBeClosed( dataFive ) )

		cache1:close()
		cache2:close()

	end

end

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

function WFCatPixelFileCacheSaveTest.rxTestWithRealFile( rxTest )

	local realFileDir = KSPathUtils.getStandardFilePath( "temp" )
	local tempFilePath = KSPathUtils.child( realFileDir, "WFCatPixelFileCacheSaveTest.txt" )
	local filePath = WFFileUtils.ensureFileNameIsUnique( tempFilePath )

	rxTest:finally( function()
		WFFileUtils.delete( filePath )
		if tempFilePath ~= filePath then
			WFFileUtils.delete( tempFilePath )
		end
	end )

	rxTest:expectEqual( false, WFCatPixelFileCacheSave == nil )

	for _, cacheByteSizeLimit in ipairs( { -1, 0, 100 } ) do

		cacheByteSizeLimit = cacheByteSizeLimit >= 0 and cacheByteSizeLimit or nil

		local cacheName = makeCacheName( 'rxTestWithRealFile', cacheByteSizeLimit )

		rxTest:log( "make cache " .. cacheName )

		local cache = WFCatPixelFileCacheSave( cacheName, 2, cacheByteSizeLimit )

		rxTest:expectEqual( false, cache == nil )

		local testString = "WFCatPixelFileCacheSaveTest test data."
		local data = KSData.make( testString )

		local saveResult = cache:savePixels( filePath, data )

		rxTest:expectOnlyCompleted( saveResult )

		rxTest:expectEqual( "file", WFFileUtils.exists( filePath ) )
		local f = io.open( filePath, 'r' )
		local contents = f:read( "*all" )
		f:close()
		rxTest:expectEqual( testString, contents )

		cache:close()

	end

end

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

return WFRxTestCase.wrapSuite( WFCatPixelFileCacheSaveTest )
