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

PixelProviderCheckFullRenditionDownloadLinkStatusTaskTest.lua

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

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

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


if not require 'WFPlatformInfo'.hasACR then return {} end

	-- wf.core
local KSTableUtils = require 'KSTableUtils'
local KSPathUtils = require 'KSPathUtils'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFRxTestCase = require 'WFRxTestCase'
local WFFunctionUtils = require 'WFFunctionUtils'
local KSIdGenerator = require 'KSIdGenerator'
local WFFileUtils = require 'WFFileUtils'


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

	-- Rx
local Rx = require 'Rx'

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

local PixelPathProviderScheduler = require 'PixelPathProviderScheduler'
local PixelPathProviderRequestTypes = require 'PixelPathProviderRequestTypes'
local PixelPathProviderStateMachine = require 'PixelPathProviderStateMachine'
local PixelProviderCheckFullRenditionDownloadLinkStatusTask =
		require 'PixelProviderCheckFullRenditionDownloadLinkStatusTask'

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

local PixelPathProviderRequestTypeNames = PixelPathProviderRequestTypes.names

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

local WFFunctionUtils_reduce = 
		assert( WFFunctionUtils.reduce,
				"WFFunctionUtils.reduce does not exist" )

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

local function makeSchedulerForTest( rxTest )

	local catalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	local scheduler = PixelPathProviderScheduler( catalog )

	rxTest:finally( function() scheduler:close() end )

	return scheduler, catalog

end

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

local function digest( i )

	return string.format( "digest%s", i )

end

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

--[[
local function renderSize( i )

	return 10 + i

end
--]]

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

local function localAssetId( i )

	return i

end

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

local function makeOzAssetId( i )

	return string.format( "ozAssetIdFor%s", localAssetId( i ) )

end

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

local function pixStreamId( i, maybePrefix )

	return string.format( "pixStreamId%s%d", maybePrefix or "", i )

end

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

local function sortArray( arr, maybeSortFn )

	local sorted = KSTableUtils.deepCopy( arr )

	table.sort( sorted, maybeSortFn )

	return sorted

end

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

local function compareArrays( a1, a2 )

	if #a1 ~= #a2 then

		return #a1 > #a2

	end

	for i = 1, math.min( #a1, #a2 ) do

		if a1[ i ] ~= a2[ i ] then

			return a1[ i ] > a2 [i ]

		end

	end

	return false

end

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

local function sortTupleArray( tupleArray )

	return sortArray( tupleArray, compareArrays )

end

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

local function takeFirstN( n )

	return function( t )

		local ret = {}

		for i = 1, n do

			ret[ i ] = t[ i ]

		end

		return ret

	end

end

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

--[[
local testDataPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'testdata' ),
"import-samples" )

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

local testDataFolder1 = KSPathUtils.child( testDataPath, "folder-1" )

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

local _validDownloadPath = KSPathUtils.child( testDataFolder1, "IMG_7763.jpg" )
--]]

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

local function makeMockPutBinaryFunc()

	local urisSeen = {}

	local responseStream = Rx.Subject()

	local function mockPutBinaryFunc( _, uri )
	
		urisSeen[ #urisSeen + 1 ] = uri

		return responseStream

	end

	return mockPutBinaryFunc, urisSeen, responseStream

end

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

local function rxTestHasNoRenditions( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderCheckFullRenditionDownloadLinkStatusTask" )

	scheduler:addRequest( pixStreamId( 1 ), localAssetId( 1 ),
								PixelPathProviderRequestTypeNames.grid_visible, 1 )

	local mockPutBinaryFunc, urisSeen = makeMockPutBinaryFunc()

	scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask =
		PixelProviderCheckFullRenditionDownloadLinkStatusTask.privateUnitTestExport.injectMockPutBinaryFunc(
			scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask,
			mockPutBinaryFunc )

	local renditions = {}

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:pushCacheItem( 
							localAssetId( 1 ), 
						{ ozAssetId = makeOzAssetId( 1 ),
							changeCounter = 1, 
							revId = digest( 1 ),
							digest = digest( 1 ), 
							croppedLongSide = 1,
							renditions = renditions } )

	rxTest:logf( "Setting %s.%s request state to %s", 
					pixStreamId( 1 ), localAssetId( 1 ), 
					PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), 
								PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	rxTest:logf( "Checking that we are going to send %s",
				PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionDownloadNoLinks )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionDownloadNoLinks,
				takeFirstN( 2 ) ) ) )

	rxTest:log( "checking that no uri requests issued" )

	rxTest:expectEqual( #urisSeen, 0 )

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:destroyAll()

end

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

local function rxTestHasRenditionsButNotFull( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderCheckFullRenditionDownloadLinkStatusTask" )

	scheduler:addRequest( pixStreamId( 1 ), localAssetId( 1 ),
								PixelPathProviderRequestTypeNames.grid_visible, 1 )

	local mockPutBinaryFunc, urisSeen = makeMockPutBinaryFunc()

	scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask =
		PixelProviderCheckFullRenditionDownloadLinkStatusTask.privateUnitTestExport.injectMockPutBinaryFunc(
			scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask,
			mockPutBinaryFunc )

	local renditions = { 
		{
			size = 640,
			href = "not_used",
		}
	}

	for _, checkState in ipairs( {
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink,
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForCreateFullRenditionLink,
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForUpdatedFullRenditionLink } ) do

		scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:pushCacheItem( 
								localAssetId( 1 ), 
							{ ozAssetId = makeOzAssetId( 1 ),
								changeCounter = 1, 
								revId = digest( 1 ),
								digest = digest( 1 ), 
								croppedLongSide = 1,
								renditions = renditions } )

		rxTest:logf( "Setting %s.%s request state to %s", 
						pixStreamId( 1 ), localAssetId( 1 ), checkState )

		SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), checkState )

		SchedulerTestAPI.runScheduledRequests( scheduler )

		rxTest:logf( "Checking that we are going to send %s",
					PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionDownloadNoLinks )

		rxTest:expectEqual( 
			sortTupleArray( 
				{
					{ pixStreamId( 1 ), localAssetId( 1 ) }
				} ),
			sortTupleArray( 
				scheduler:_mapAllRequestsWithState( 
					PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionDownloadNoLinks,
					takeFirstN( 2 ) ) ) )

		rxTest:log( "checking that no uri requests issued" )

		rxTest:expectEqual( #urisSeen, 0 )

		scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:destroyAll()

	end

end

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

local function rxTestHasFullRendition( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderCheckFullRenditionDownloadLinkStatusTask" )

	scheduler:addRequest( pixStreamId( 1 ), localAssetId( 1 ),
								PixelPathProviderRequestTypeNames.grid_visible, 1 )

	for _, checkStateTuple in ipairs( {
			{
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink,
				PixelPathProviderStateMachine.DownloadStates.TryExistingFullSizeRenditionDownload,
				PixelPathProviderStateMachine.DownloadStates.TryExistingFullSizeRenditionDownload
			},
			{
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForCreateFullRenditionLink,
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation,
				PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionDownloadNoLinks,
			},
			{
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForUpdatedFullRenditionLink,
				PixelPathProviderStateMachine.DownloadStates.TryUpdatedFullSizeRenditionDownload,
				PixelPathProviderStateMachine.DownloadStates.TryUpdatedFullSizeRenditionDownload
			} } ) do

		local checkState, hasCreateState, hasNoCreateState = unpack( checkStateTuple )

		for _, hasCreateLink in ipairs( { true, false } ) do

			local renditions = { 
				{
					size = 640,
					href = "not_used",
				},
			}

			local mockPutBinaryFunc, urisSeen = makeMockPutBinaryFunc()

			scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask =
				PixelProviderCheckFullRenditionDownloadLinkStatusTask.privateUnitTestExport.injectMockPutBinaryFunc(
					scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask,
					mockPutBinaryFunc )

			scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:pushCacheItem( 
									localAssetId( 1 ), 
								{ ozAssetId = makeOzAssetId( 1 ),
									changeCounter = 1, 
									createFullRenditionURITemplate = hasCreateLink and "createPls",
									downloadFullRenditionURI = "not_used",
									revId = digest( 1 ),
									digest = digest( 1 ), 
									croppedLongSide = 1,
									renditions = renditions } )

			rxTest:logf( "Setting %s.%s request state to %s", 
							pixStreamId( 1 ), localAssetId( 1 ), checkState )

			SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), checkState )

			SchedulerTestAPI.runScheduledRequests( scheduler )

			local expectedState = hasCreateLink and hasCreateState or hasNoCreateState

			rxTest:logf( "Checking that we are going to send %s when we do%s have a create uri",
						expectedState,
						hasCreateLink and "" or " NOT" )

			rxTest:expectEqual( 
				sortTupleArray( 
					{
						{ pixStreamId( 1 ), localAssetId( 1 ) }
					} ),
				sortTupleArray( 
					scheduler:_mapAllRequestsWithState( 
						expectedState,
						takeFirstN( 2 ) ) ) )

			local expectedURIRequestCount =
					hasCreateLink and
						checkState == PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForCreateFullRenditionLink and
							1 or 0

			rxTest:logf( "checking that %s uri requests issued", expectedURIRequestCount )

			rxTest:expectEqual( #urisSeen, expectedURIRequestCount )

			scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:destroyAll()

		end

	end

end

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

local function getFullSizeRenditionInfo( fullSizeRenditionInfo, renditionInfo )

	if fullSizeRenditionInfo then

		return fullSizeRenditionInfo

	end

	return type( renditionInfo ) == "table" and 
			renditionInfo.size == "fullsize" and
			renditionInfo

end

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

local function rxTestCreateFullRenditionSuccess( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderCheckFullRenditionDownloadLinkStatusTask" )

	scheduler:addRequest( pixStreamId( 1 ), localAssetId( 1 ),
								PixelPathProviderRequestTypeNames.grid_visible, 1 )

	local mockPutBinaryFunc, urisSeen, responseStream = makeMockPutBinaryFunc()

	scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask =
		PixelProviderCheckFullRenditionDownloadLinkStatusTask.privateUnitTestExport.injectMockPutBinaryFunc(
			scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask,
			mockPutBinaryFunc )

	local renditions = { 
		{
			size = 640,
			href = "not_used",
		}
	}

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:pushCacheItem( 
							localAssetId( 1 ), 
						{ ozAssetId = makeOzAssetId( 1 ),
							changeCounter = 1, 
							createFullRenditionURITemplate = "createPls",
							revId = digest( 1 ),
							digest = digest( 1 ), 
							croppedLongSide = 1,
							renditions = renditions } )

	rxTest:logf( "Setting %s.%s request state to %s", 
					pixStreamId( 1 ), localAssetId( 1 ), 
					PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), 
								PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	rxTest:logf( "Checking that we are in state %s",
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation,
				takeFirstN( 2 ) ) ) )

	rxTest:log( "checking that uri request made" )

	rxTest:expectEqual( #urisSeen, 1 )

	rxTest:expectEqual( urisSeen[ 1 ], "createPls" )

	rxTest:log( "sending success response" )

	responseStream:onNext( "not used", { Location = "fullSizeHere" } )

	rxTest:log( "checking that we have expected full size rendition download link" )

	local baseRenderInfo =
		scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:peekCacheItem( 
								localAssetId( 1 ) ) or {}

	rxTest:logf( "Checking that we have updated baseRenderInfoCache with new full size uri" )

	rxTest:expectEqual( baseRenderInfo.downloadFullRenditionURI, "fullSizeHere" )
	
	rxTest:logf( "Checking that we are going to send %s",
				PixelPathProviderStateMachine.DownloadStates.TryExistingFullSizeRenditionDownload )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.DownloadStates.TryJustCreatedFullSizeRenditionDownload,
				takeFirstN( 2 ) ) ) )

	rxTest:log( "checking subscription is cleared" )

	rxTest:expectEqual(
		not not scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask.activeGenerateFullRenditionInfo,
		false )

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:destroyAll()

end

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

local function rxTestCreateFullRenditionDeleteRequestCancels( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderCheckFullRenditionDownloadLinkStatusTask" )

	scheduler:addRequest( pixStreamId( 1 ), localAssetId( 1 ),
								PixelPathProviderRequestTypeNames.grid_visible, 1 )

	local mockPutBinaryFunc, urisSeen = makeMockPutBinaryFunc()

	scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask =
		PixelProviderCheckFullRenditionDownloadLinkStatusTask.privateUnitTestExport.injectMockPutBinaryFunc(
			scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask,
			mockPutBinaryFunc )

	local renditions = { 
		{
			size = 640,
			href = "not_used",
		}
	}

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:pushCacheItem( 
							localAssetId( 1 ), 
						{ ozAssetId = makeOzAssetId( 1 ),
							changeCounter = 1, 
							createFullRenditionURITemplate = "createPls",
							revId = digest( 1 ),
							digest = digest( 1 ), 
							croppedLongSide = 1,
							renditions = renditions } )

	rxTest:logf( "Setting %s.%s request state to %s", 
					pixStreamId( 1 ), localAssetId( 1 ), 
					PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), 
								PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	rxTest:logf( "Checking that we are in state %s",
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation,
				takeFirstN( 2 ) ) ) )

	rxTest:log( "checking that uri request made" )

	rxTest:expectEqual( #urisSeen, 1 )

	rxTest:expectEqual( urisSeen[ 1 ], "createPls" )

	rxTest:log( "checking before remove request that we have subscription" )

	rxTest:expectEqual(
		not not scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask.activeGenerateFullRenditionInfo,
		true )

	scheduler:removeRequest( pixStreamId( 1 ) , localAssetId( 1 ) )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	rxTest:log( "checking after remove request that we have NO subscription" )

	rxTest:expectEqual(
		not not scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask.activeGenerateFullRenditionInfo,
		false )

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:destroyAll()

end

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

local function rxTestCreateFullRenditionFailWithError( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderCheckFullRenditionDownloadLinkStatusTask" )

	scheduler:addRequest( pixStreamId( 1 ), localAssetId( 1 ),
								PixelPathProviderRequestTypeNames.grid_visible, 1 )

	local mockPutBinaryFunc, urisSeen, responseStream = makeMockPutBinaryFunc()

	scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask =
		PixelProviderCheckFullRenditionDownloadLinkStatusTask.privateUnitTestExport.injectMockPutBinaryFunc(
			scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask,
			mockPutBinaryFunc )

	local renditions = { 
		{
			size = 640,
			href = "not_used",
		}
	}

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:pushCacheItem( 
							localAssetId( 1 ), 
						{ ozAssetId = makeOzAssetId( 1 ),
							changeCounter = 1, 
							createFullRenditionURITemplate = "createPls",
							revId = digest( 1 ),
							digest = digest( 1 ), 
							croppedLongSide = 1,
							renditions = renditions } )

	rxTest:logf( "Setting %s.%s request state to %s", 
					pixStreamId( 1 ), localAssetId( 1 ), 
					PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), 
								PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	rxTest:logf( "Checking that we are in state %s",
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation,
				takeFirstN( 2 ) ) ) )

	rxTest:log( "checking that uri request made" )

	rxTest:expectEqual( #urisSeen, 1 )

	rxTest:expectEqual( urisSeen[ 1 ], "createPls" )

	rxTest:log( "sending fail response" )

	responseStream:onError( "fale wail" )

	rxTest:log( "checking that we do not have expected full size rendition download link" )

	local baseRenderInfo =
		scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:peekCacheItem( 
								localAssetId( 1 ) ) or {}

	local fullSizeRenditonInfo =
			WFFunctionUtils_reduce( false, 
					getFullSizeRenditionInfo, 
						baseRenderInfo.renditions or {} ) or {}

	rxTest:expectEqual( fullSizeRenditonInfo.href, nil )
	
	rxTest:logf( "Checking that we are going to send %s",
				PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionCreateFail )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionCreateFail,
				takeFirstN( 2 ) ) ) )

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:destroyAll()

	rxTest:log( "checking subscription is cleared" )

	rxTest:expectEqual(
		not not scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask.activeGenerateFullRenditionInfo,
		false )

end

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

local function rxTestCreateFullRenditionFailMissingURLInSuccess( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderCheckFullRenditionDownloadLinkStatusTask" )

	scheduler:addRequest( pixStreamId( 1 ), localAssetId( 1 ),
								PixelPathProviderRequestTypeNames.grid_visible, 1 )

	local mockPutBinaryFunc, urisSeen, responseStream = makeMockPutBinaryFunc()

	scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask =
		PixelProviderCheckFullRenditionDownloadLinkStatusTask.privateUnitTestExport.injectMockPutBinaryFunc(
			scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask,
			mockPutBinaryFunc )

	local renditions = { 
		{
			size = 640,
			href = "not_used",
		}
	}

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:pushCacheItem( 
							localAssetId( 1 ), 
						{ ozAssetId = makeOzAssetId( 1 ),
							changeCounter = 1, 
							createFullRenditionURITemplate = "createPls",
							revId = digest( 1 ),
							digest = digest( 1 ), 
							croppedLongSide = 1,
							renditions = renditions } )

	rxTest:logf( "Setting %s.%s request state to %s", 
					pixStreamId( 1 ), localAssetId( 1 ), 
					PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), 
								PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.CheckForAnyFullRenditionLink )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	rxTest:logf( "Checking that we are in state %s",
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.CheckFullRenditionDownloadLinkStatusStates.WaitingForFullRenditionLinkCreation,
				takeFirstN( 2 ) ) ) )

	rxTest:log( "checking that uri request made" )

	rxTest:expectEqual( #urisSeen, 1 )

	rxTest:expectEqual( urisSeen[ 1 ], "createPls" )

	rxTest:log( "sending fail response" )

	responseStream:onNext( "not used", {} )

	rxTest:log( "checking that we do not have expected full size rendition download link" )

	local baseRenderInfo =
		scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:peekCacheItem( 
								localAssetId( 1 ) ) or {}

	local fullSizeRenditonInfo =
			WFFunctionUtils_reduce( false, 
					getFullSizeRenditionInfo, 
						baseRenderInfo.renditions or {} ) or {}

	rxTest:expectEqual( fullSizeRenditonInfo.href, nil )
	
	rxTest:logf( "Checking that we are going to send %s",
				PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionCreateFail )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.SendDataStates.SendPermanentErrorForExportFullRenditionCreateFail,
				takeFirstN( 2 ) ) ) )

	scheduler._testData.runLoopCaches.sharedCaches.baseRenderInfoCache:destroyAll()

	rxTest:log( "checking subscription is cleared" )

	rxTest:expectEqual(
		not not scheduler._testData.runLoopTaskStates.PixelProviderCheckFullRenditionDownloadLinkStatusTask.activeGenerateFullRenditionInfo,
		false )

end

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

local function makeDocStoreRecordOriginalAndRenditionsImp( assetId, theLocalAssetId, harmony, fullSizeURI )

	local testDataPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'testdata' ),
											"import-samples" )

	local testDataFolder1 = KSPathUtils.child( testDataPath, "folder-1" )

	local originalPath = KSPathUtils.child( testDataFolder1, "IMG_7763.jpg" )

	local revId = digest( 1 )

	return {

		_id = assetId,
		_localId = theLocalAssetId,
		_revIds = { revId },
		type = "asset",
		subtype = "image",
		develop = {
			processingModel = "lightroom",
			croppedHeight = 12,
			croppedWidth = 345,
			userOrientation = 1,
			crsVersion = "11.3.1",
			xmpCameraRaw = "<xmp />",
		},
		userUpdated = "2019-08-08T21:19:53.434Z",
		copy = {
			copy_id = "4bce0aa638584d51b46f5fd6401f78db",
		},
		captureDate = "2016-12-26T15:34:13.318",
		aesthetics = {
			harmony = harmony,
			score = 61,
			lighting = -28,
			rot = 0,
			repetition = 3,
			symmetry = 2,
			balancing = 6,
			emphasis = -35,
			version = 1,
			application = "ias",
			created = "2019-08-08T21:20:06Z",
			dof = -7,
			content = 4,
			vivid = -41,
		},
		importSource = {
			originalHeight = 12,
			importedOnDevice = "bkruse-macbookpro2014",
			importTimestamp = "2019-08-08T21:19:52Z",
			contentType = "image/jpeg",
			fileName = "IMG_2261.JPG",
			fileSize = 1215097,
			originalWidth = 345,
			sha256 = "f9b430859b70d4d2673051172ac9bf8861ea398cbe7ee413d5a47fa49b7855c1",
			importedBy = "55fe3558cff715f3e3138579b5bcb1d9",
		},
		xmp = {
			tiff = {
				Orientation = "top left",
				Make = "Apple",
				Model = "iPhone 5",
			},
			exif = {
				ApertureValue = {
					2526069,
					1000000,
				},
				FNumber = {
					24,
					10,
				},
				FocalLength = {
					103,
					25,
				},
				DateTimeOriginal = "2016-12-26T15:34:13.318",
				FlashRedEyeMode = false,
				ExposureTime = {
					1,
					6800,
				},
				FlashFired = true,
				MeteringMode = "pattern",
				FocalLengthIn35mmFilm = 33,
				ExposureProgram = "normal program",
				FlashReturn = "no strobe return detection",
				ISOSpeedRatings = 64,
				ShutterSpeedValue = {
					12731319,
					1000000,
				},
				FlashMode = "compulsory flash firing",
				BrightnessValue = {
					9696,
					857,
				},
				FlashFunction = false,
				ExposureBiasValue = {
					0,
					1,
				},
			},
			aux = {
				Lens = "iPhone 5 back camera 4.12mm f/2.4",
			},
			xmp = {
				CreatorTool = "10.2",
				CreateDate = "2016-12-26T15:34:13.318",
				ModifyDate = "2016-12-26T15:34:13",
			},
			photoshop = {
				DateCreated = "2016-12-26T15:34:13.318",
			},
		},
		userCreated = "2019-08-08T21:19:53.434Z",
		_localOnly = {
			files = {
				proxy = {
					["2560"] = {
						relativePath = "Users/bkruse/Pictures/Lightroom Library.lrlibrary/ac1f6bf23e384320a753fb6e5934ee2f/proxies/2560/f7f/0cfb46e6a46368fb01407460a1430",
						volumeGuid = "DC5268AF-16FA-30B1-A355-111D5A326FF7",
						sha256 = "f9b430859b70d4d2673051172ac9bf8861ea398cbe7ee413d5a47fa49b7855c1",
						shouldExist = true,
						size = 396102,
					},
				},
				original = {
					master = {
						relativePath = 
							WFFileUtils.removeVolumeFromPath( originalPath ) or
							originalPath,
						volumeGuid = 
							WFFileUtils.getVolumeGuidForPath( originalPath ) or
							KSIdGenerator.uuidInLowercaseHex(),
						sha256 = "f9b430859b70d4d2673051172ac9bf8861ea398cbe7ee413d5a47fa49b7855c1",
						size = 1215097,
					},
				},
			},
			xmpSidecarExists = false,
			cameraProfileInfo = {
				profileDigest = "NA",
				isStandard = false,
				xmpCameraRawProfileDigest = "27ed687384abf82580f4fcee402a66f8",
			},
		},
		_serverProvidedMetadata = {
			updated = "2019-08-08T22:18:13.677478Z",
			revision_ids = { revId },
			created = "2019-08-08T21:19:55.788502Z",
			base = "https://photos.adobe.io/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/",
			links = {
				["self"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430",
				},
				["/rels/master_create"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/{revision_id}/master",
					templated = true,
				},
				["/rels/rendition_type/fullsize"] = {
					href = fullSizeURI,
				},
				["/rels/rendition_type/8192"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/7519d7b3f7af4ae38ba5a296d36373eb/renditions/261bde29b42782f6242b2f900747875f",
				},
				["/rels/rendition_type/2048"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/7519d7b3f7af4ae38ba5a296d36373eb/renditions/261bde29b42782f6242b2f900747875f",
				},
				["/rels/rendition_type/thumbnail2x"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/7519d7b3f7af4ae38ba5a296d36373eb/renditions/01f3248a7212ca863bee8d16ea4bcadd",
				},
				["/rels/xmp_develop_create"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/{revision_id}/xmp/develop",
					templated = true,
				},
				["/rels/rendition_create"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/{revision_id}/renditions/{rendition_id}",
					templated = true,
				},
				["/rels/proxy_type/2560"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/7519d7b3f7af4ae38ba5a296d36373eb/proxies/7a48cfcc02608ddcc48a87d067b96b32",
				},
				["/rels/rendition_type/640"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/7519d7b3f7af4ae38ba5a296d36373eb/renditions/721d33ad21b31c7c3103f7d7f70747db",
				},
				["/rels/proxy_create"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/{revision_id}/proxies/{proxy_id}",
					templated = true,
				},
				["/rels/rendition_type/1280"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/7519d7b3f7af4ae38ba5a296d36373eb/renditions/03e26909aca892195981d4e1513adeb1",
				},
				["/rels/master"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/7519d7b3f7af4ae38ba5a296d36373eb/master",
					content_type = "image/jpeg",
				},
				["/rels/xmp"] = {
					href = "/v2/catalogs/ac1f6bf23e384320a753fb6e5934ee2f/assets/f7f0cfb46e6a46368fb01407460a1430/revisions/7519d7b3f7af4ae38ba5a296d36373eb/xmp",
				},
			},
		},
	}

end

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

local function logRequest( request, rxTest )

	rxTest:logf( "request: " .. "%s" .. string.rep( ", %s", #request ),
					unpack( request ) )

end

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

local function makeDocStoreRecordOriginalAndRenditions( 
				rxTest, catalog, assetId, theLocalAssetId, harmony, fullRenURI ) 

	rxTest
		:expectSingleValue(
			catalog
				:docStore()
				:setDocValue( 
					makeDocStoreRecordOriginalAndRenditionsImp(
						assetId, theLocalAssetId, harmony, fullRenURI ) ),
			':ignore:' )

end

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

local function updateDocStoreRecord( rxTest, catalog, assetId, harmony, fullRenURI ) 

	rxTest
		:expectSingleValue(
			catalog
				:docStore()
				:docValue( assetId )
				:take( 1 )
				:flatMapLatest(
					function( docValue )

						local revId = digest( 1 )

						docValue.aesthetics.harmony = harmony
						docValue._serverProvidedMetadata.links["/rels/rendition_type/fullsize"].href =
							fullRenURI
						docValue._serverProvidedMetadata.revision_ids = { revId }

						return catalog
								:docStore()
								:applyOverlay( 
									{
										_newRevId = revId,
										_id = assetId, 
										aesthetics = docValue.aesthetics,
										_serverProvidedMetadata = docValue._serverProvidedMetadata,
									} )

					end ),
			':ignore:' )

end

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

local function rxTestWaitForUpdatedFullRendition( rxTest )

	local scheduler, catalog = makeSchedulerForTest( rxTest )

	scheduler:setPreferRenderForNewRenditions( true )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderCheckFullRenditionDownloadLinkStatusTask" )

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderDocstoreInfoTask" )

	local assetId = KSIdGenerator.uuidInLowercaseHex()

	scheduler:addRequest( pixStreamId( 1 ), localAssetId( 1 ),
								PixelPathProviderRequestTypeNames.grid_visible, 1 )

	rxTest:log( "verify that we checked the docstore record so that we now we'll watch for changes" )

	SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), 
								PixelPathProviderStateMachine.DocstoreInfoStates.NeedAssetInfoForExportFullRendition )

	-- first make a docstore record without a full size link
	local harmony1, harmony2 = "r1", "r2"
	local uri1, uri2 = "yuuuge", "yuuuge2"

	makeDocStoreRecordOriginalAndRenditions(
		rxTest, catalog, assetId, localAssetId( 1 ), harmony1, uri1 )

	rxTest:log( "Checking that full uri is what we expect" )

	rxTest
		:expectSingleValue(
			catalog
				:docStore()
				:docValue( assetId )
				:take( 1 )
				:map( 
					function( docValue )

						return {
									docValue._serverProvidedMetadata.links["/rels/rendition_type/fullsize"].href,
									docValue.aesthetics.harmony,
									docValue._revId == docValue._serverProvidedMetadata.revision_ids[ 1 ]
								}

					end ),
					{ uri1, harmony1, true } )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	rxTest:log( "Wait for an async docstore request so scheduler sees the record" )

	rxTest:logf( "Checking that we saw the docstore info and we are at %s",
					PixelPathProviderStateMachine.PixelCacheCheckStates.NeedCheckForExportFullRenditionInCache )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.PixelCacheCheckStates.NeedCheckForExportFullRenditionInCache,
				takeFirstN( 2 ) ) ) )

	rxTest:log( "Checking that full uri is what we expect" )

	rxTest
		:expectSingleValue(
			catalog
				:docStore()
				:docValue( assetId )
				:take( 1 )
				:map( 
					function( docValue )

						return {
									docValue._serverProvidedMetadata.links["/rels/rendition_type/fullsize"].href,
									docValue.aesthetics.harmony,
									docValue._revId == docValue._serverProvidedMetadata.revision_ids[ 1 ]
								}

					end ),
					{ uri1, harmony1, true } )

	rxTest:logf( "Checking that request at state %s",
					PixelPathProviderStateMachine.EndStates.WaitForFullRenditionLinkUpdate )

	SchedulerTestAPI.setState( scheduler, pixStreamId( 1 ), localAssetId( 1 ), 
								PixelPathProviderStateMachine.EndStates.WaitForFullRenditionLinkUpdate )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.EndStates.WaitForFullRenditionLinkUpdate,
				takeFirstN( 2 ) ) ) )

	rxTest:logf( "Update docstore to different harmony same uri" )

	updateDocStoreRecord( rxTest, catalog, assetId, harmony2, uri1 )

	rxTest:log( "Checking that full uri is what we expect" )

	rxTest
		:expectSingleValue(
			catalog
				:docStore()
				:docValue( assetId )
				:take( 1 )
				:map( 
					function( docValue )

						return {
									docValue._serverProvidedMetadata.links["/rels/rendition_type/fullsize"].href,
									docValue.aesthetics.harmony,
									docValue._revId == docValue._serverProvidedMetadata.revision_ids[ 1 ]
								}

					end ),
					{ uri1, harmony2, true } )

	rxTest:sleep( 1 )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	scheduler
		:_mapAllRequestsWithPixStreamId( 
			pixStreamId( 1 ), logRequest, rxTest )

	rxTest:logf( "Checking that request at state %s",
					PixelPathProviderStateMachine.EndStates.WaitForFullRenditionLinkUpdate )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.EndStates.WaitForFullRenditionLinkUpdate,
				takeFirstN( 2 ) ) ) )

	rxTest:logf( "Update docstore to same harmony different uri" )

	updateDocStoreRecord( rxTest, catalog, assetId, harmony2, uri2 )

	scheduler
		:_mapAllRequestsWithPixStreamId( 
			pixStreamId( 1 ), logRequest, rxTest )

	rxTest:log( "Checking that full uri is what we expect" )

	rxTest
		:expectSingleValue(
			catalog
				:docStore()
				:docValue( assetId )
				:take( 1 )
				:tap( 
					function()

						rxTest:log( "in tap" )

						scheduler
							:_mapAllRequestsWithPixStreamId( 
								pixStreamId( 1 ), logRequest, rxTest )

					end )
				:map( 
					function( docValue )

						rxTest:log( "in map" )

						scheduler
							:_mapAllRequestsWithPixStreamId( 
								pixStreamId( 1 ), logRequest, rxTest )

						return {
									docValue._serverProvidedMetadata.links["/rels/rendition_type/fullsize"].href,
									docValue.aesthetics.harmony,
								}

					end ),
					{ uri2, harmony2 } )

	rxTest:sleep( 1 )

	scheduler
		:_mapAllRequestsWithPixStreamId( 
			pixStreamId( 1 ), logRequest, rxTest )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	rxTest:logf( "Checking that request at state %s",
					PixelPathProviderStateMachine.DownloadStates.TryUpdatedFullSizeRenditionDownload )

	scheduler
		:_mapAllRequestsWithPixStreamId( 
			pixStreamId( 1 ), logRequest, rxTest )

	rxTest:expectEqual( 
		sortTupleArray( 
			{
				{ pixStreamId( 1 ), localAssetId( 1 ) }
			} ),
		sortTupleArray( 
			scheduler:_mapAllRequestsWithState( 
				PixelPathProviderStateMachine.DownloadStates.TryUpdatedFullSizeRenditionDownload,
				takeFirstN( 2 ) ) ) )

end

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

local function bumpTimeLimit( f, n )

	return function( rxTest )

		rxTest:setTimeLimit( n )

		return f( rxTest )

	end

end

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

return WFRxTestCase.wrapSuite( 'PixelProviderCheckFullRenditionDownloadLinkStatusTaskTest', {

	rxTestHasNoRenditions = rxTestHasNoRenditions,

	rxTestHasRenditionsButNotFull = rxTestHasRenditionsButNotFull,

	rxTestHasFullRendition = rxTestHasFullRendition,

	rxTestCreateFullRenditionSuccess = rxTestCreateFullRenditionSuccess,

	rxTestCreateFullRenditionDeleteRequestCancels = 
		rxTestCreateFullRenditionDeleteRequestCancels,

	rxTestCreateFullRenditionFailWithError = 
		rxTestCreateFullRenditionFailWithError,

	rxTestCreateFullRenditionFailMissingURLInSuccess = 
		rxTestCreateFullRenditionFailMissingURLInSuccess,

	rxTestWaitForUpdatedFullRendition = 
		bumpTimeLimit( rxTestWaitForUpdatedFullRendition, 5 ),

} )
