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

PixelProviderExternalXmpDevelopPathCheckTaskTest.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2022 Adobe
All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
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.
------------------------------------------------------------------------------]]

	-- If ACR is not supported, disable test before we attempt to
	-- require WFAcr. (That will fail.)
if not require 'WFPlatformInfo'.hasACR then return {} end

local Rx = require 'Rx'

	-- wf.core
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFRxTestCase = require 'WFRxTestCase'
local KSIdGenerator = require 'KSIdGenerator'
local KSTableUtils = require 'KSTableUtils'
local WFTableMerge = require 'WFTableMerge'

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

local PixelPathProviderScheduler = require "PixelPathProviderScheduler"
local PixelPathProviderRequestTypes = require "PixelPathProviderRequestTypes"
local PixelPathProviderStateMachine = require "PixelPathProviderStateMachine"
local PixelProviderExternalXmpDevelopPathCheckTask = require "PixelProviderExternalXmpDevelopPathCheckTask"
local PixelProviderSharedTaskUtils = require 'PixelProviderSharedTaskUtils'

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

local PixelPathProviderRequestTypeNames = PixelPathProviderRequestTypes.names

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

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 rxTestCheckMissingRenderInfo( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

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

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	local expectedMissingBaseRenderInfoStates = {

		[ PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal ] =
			PixelPathProviderStateMachine.DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore,

		[ PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal ] =
			PixelPathProviderStateMachine.PixelCacheCheckStates.ChooseRenditionStrategy,
	}

	local expectedMissingExternalDevelopFilesStates = {

		[ PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal ] =
			PixelPathProviderStateMachine.SendDataStates.SendPermanentError,

		[ PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal ] =
			PixelPathProviderStateMachine.SendDataStates.SendPermanentError,

	}

	for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalXmpDevelopIsLocalStates ) do
		for _, hasBaseRenderInfo in pairs( { false, true } ) do

			baseRenderInfoCache:popCacheItem( localAssetId )

			if hasBaseRenderInfo then

				-- add an entry that is missing what we need
				baseRenderInfoCache:pushCacheItem( localAssetId, {} )

			end

			SchedulerTestAPI.setState( 
				scheduler, pixStreamId, localAssetId, initialState )

			SchedulerTestAPI.runScheduledRequests( scheduler )

			local expectedStateAfterMissing = 
					not hasBaseRenderInfo and 
						expectedMissingBaseRenderInfoStates[ initialState ] or
						expectedMissingExternalDevelopFilesStates[ initialState ]

			if not expectedStateAfterMissing then

				-- run a failing test
				rxTest
					:expectEqual(
						string.format( "Must provide a %s entry for initial state: %s", 
										not hasBaseRenderInfo and
											"expectedMissingBaseRenderInfoStates" or
											"expectedMissingExternalDevelopFilesStates",
										initialState ),
						"" )

			end

			local localAssetIdRequests = 
					SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
					
			rxTest:expectEqual( #localAssetIdRequests, 1 )

			local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
					unpack( localAssetIdRequests[ 1 ] or {} )

			rxTest:expectEqual( pixStreamId, actualPixStreamId )

			rxTest:expectEqual( localAssetId, actualLocalAssetId )

			rxTest:logf( "Checking if actual state %s is same as expected: %s",
							actualState, expectedStateAfterMissing )

			rxTest:expectEqual( expectedStateAfterMissing, actualState )

		end

	end

end

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

local function makeMockFileChecker() -- rxTest )

	local mockFileCheckCount

	local mockFileCheckResultStreams = {}

	local mockFileChecker = {

		checkPath = function() -- _, path )

			mockFileCheckCount = ( mockFileCheckCount or 0 ) + 1 

			--rxTest:logf( "setting up mock file check %s for path %s", mockFileCheckCount, path )
	
			local mockFileCheckResultStream = Rx.Subject()

			mockFileCheckResultStreams[ #mockFileCheckResultStreams + 1 ] = 
				mockFileCheckResultStream

			return mockFileCheckResultStream

		end

	}

	return mockFileChecker, mockFileCheckResultStreams

end

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

local function makeExternalDevelopFilesWithXmpSha256( hasMasks, hrefStatus, xmpSha256 )

	local xmpDevelopHref = hrefStatus ~= "none" and "fakeHref" or nil

	local externalDevelopFiles =
		{ { 'develop', xmpSha256, xmpDevelopHref } }

	if hasMasks then

		local mask1Href = hrefStatus ~= "none" and "fakeHref" or nil

		externalDevelopFiles[ #externalDevelopFiles + 1 ] =
			{ 'aux', KSIdGenerator.uuidInLowercaseHex(), mask1Href }

		local mask2Href = hrefStatus == "all" and "fakeHref" or nil

		externalDevelopFiles[ #externalDevelopFiles + 1 ] =
			{ 'aux', KSIdGenerator.uuidInLowercaseHex(), mask2Href }

	end

	return externalDevelopFiles

end

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

local function makeExternalDevelopFiles( hasMasks, hrefStatus )

	return makeExternalDevelopFilesWithXmpSha256( 
				hasMasks, hrefStatus, KSIdGenerator.uuidInLowercaseHex() )

end

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

local function makeMockDocstoreForTest() -- rxTest

	local docValuesPerId = {}

	local mockDocStore = {

		applyOverlay = 
			function( _, overlay ) 

				local assetId = 
					assert( 
						KSTableUtils.derefOpt( overlay, '_localId' ) or
							KSTableUtils.derefOpt( overlay, '_id' ), 
						"missing _id" )

				overlay._id = nil

				overlay._localId = nil

				docValuesPerId[ assetId ] = 
					WFTableMerge.applyOverlay( 
						docValuesPerId[ assetId ] or {}, overlay )

				return Rx.Observable.just( assetId )

			end,

		docValue =
			function( _, assetId )

				local docValue = docValuesPerId[ assetId ]

				if not docValue then

					return Rx.Observable.throw( string.format( "no docValue for %s", assetId ) )

				end

				return Rx.Observable.just( docValue )

			end,
	}

	return mockDocStore, docValuesPerId

end

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

local function makeMockFileSpec() -- rxTest

	return {

		pathForSettingsXmp = 
			function( _, sha256 )

				return string.format( "fakeXmpDevelopPathForSha256_%s", sha256 )

			end,
	}

end

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

local function justReturn( v ) 

	return function() 

		return v 

	end 

end

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

local function rxTestHaveAllLocalDevelopFiles( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

	local mockFileChecker, mockFileCheckResultStreams = makeMockFileChecker( rxTest )

	local currMockFileCheckResult

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"fileChecker", mockFileChecker )
	
	local mockDocStore, docValuesPerId = makeMockDocstoreForTest()

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"docStore", mockDocStore )

	local mockFileSpec = makeMockFileSpec()

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"fileSpec", mockFileSpec )

	local fakeXmpDevelopPathFileSize = 1234

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"makeAsyncFileSizeStream", 
		justReturn( Rx.Observable.just( fakeXmpDevelopPathFileSize ) ) )

	local sha256 = "sha256"

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"makeAsyncFileDigestStream", 
		justReturn( Rx.Observable.just( sha256 ) ) )

	rxTest:log( "making expected local only docValue" )

	local fakeXmpDevelopPath = mockFileSpec:pathForSettingsXmp( sha256 )

	rxTest
		:expectOnlyCompleted(
			PixelProviderSharedTaskUtils.updateDocStoreXmpDevelopInfoStream(
					mockDocStore, localAssetId, fakeXmpDevelopPath,
					fakeXmpDevelopPathFileSize, sha256 )
				:takeLast( 0 ) )

	local expectedDocValue = docValuesPerId[ localAssetId ]

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

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalXmpDevelopIsLocalStates ) do
		for _, hasMasks in pairs( { false, true } ) do
		for _, hasLocalOnlyXmpDevelopPath in pairs( { "none", "different", "matches" } ) do

			local localXmpDevelopPathFromDocstore, localXmpDevelopFilesize,
					localXmpDevelopSha256

			if hasLocalOnlyXmpDevelopPath == "none" then

				docValuesPerId[ localAssetId ] = nil

			elseif hasLocalOnlyXmpDevelopPath == "different" then

				localXmpDevelopPathFromDocstore = fakeXmpDevelopPath .. "different"

				localXmpDevelopFilesize = fakeXmpDevelopPathFileSize + 15

				localXmpDevelopSha256 = sha256 .. "different"

			else

				localXmpDevelopPathFromDocstore = fakeXmpDevelopPath

				localXmpDevelopFilesize = fakeXmpDevelopPathFileSize

				localXmpDevelopSha256 = sha256

			end

			if hasLocalOnlyXmpDevelopPath == "none" then

				rxTest
					:expectOnlyCompleted(
						PixelProviderSharedTaskUtils.updateDocStoreXmpDevelopInfoStream(
								mockDocStore, localAssetId, localXmpDevelopPathFromDocstore,
								localXmpDevelopFilesize, localXmpDevelopSha256 ) 
							:takeLast( 0 ) )

			end

			baseRenderInfoCache:popCacheItem( localAssetId )

			local externalDevelopFiles = makeExternalDevelopFilesWithXmpSha256( hasMasks, "all", sha256 )

			baseRenderInfoCache:pushCacheItem( 
				localAssetId, 
				{ 
					localXmpDevelopPathFromDocstore = localXmpDevelopPathFromDocstore,
					externalDevelopFiles = externalDevelopFiles 
				} )

			SchedulerTestAPI.setState( 
				scheduler, pixStreamId, localAssetId, initialState )

			SchedulerTestAPI.runScheduledRequests( scheduler )

			local expectedStateStartingCheck = 
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.CheckingIfExternalXmpDevelopIsLocal ) or
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalXmpDevelopIsLocal )

			if not expectedStateStartingCheck then

				-- run a failing test
				rxTest
					:expectEqual(
						string.format( "Must provide an entry for initial state: %s", 
										initialState ),
						"" )

			end

			local localAssetIdRequests = 
					SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
					
			rxTest:expectEqual( #localAssetIdRequests, 1 )

			local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
					unpack( localAssetIdRequests[ 1 ] or {} )

			rxTest:expectEqual( pixStreamId, actualPixStreamId )

			rxTest:expectEqual( localAssetId, actualLocalAssetId )

			rxTest:expectEqual( expectedStateStartingCheck, actualState )

			for _ = 1, #externalDevelopFiles do

				currMockFileCheckResult = ( currMockFileCheckResult or 0 ) + 1

				local mockFileCheckResultStream = 
						mockFileCheckResultStreams[ currMockFileCheckResult ]

				mockFileCheckResultStream:onNext( true )
				mockFileCheckResultStream:onCompleted()

			end

			SchedulerTestAPI.runScheduledRequests( scheduler )

			local expectedStateAfterCheck = 
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.SendDataStates.HaveLocalXmpDevelopPath ) or
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop )

			if not expectedStateAfterCheck then

				-- run a failing test
				rxTest
					:expectEqual(
						string.format( "Must provide an entry for initial state: %s", 
										initialState ),
						"" )

			end
				
			rxTest:logf( "Checking for %s transitions to have path state %s when there are%s masks",
							initialState, expectedStateAfterCheck,
							hasMasks and "" or " NOT" )

			localAssetIdRequests = 
				SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
					
			rxTest:expectEqual( #localAssetIdRequests, 1 )

			actualPixStreamId, actualLocalAssetId, _, _, actualState = 
					unpack( localAssetIdRequests[ 1 ] or {} )

			rxTest:expectEqual( pixStreamId, actualPixStreamId )

			rxTest:expectEqual( localAssetId, actualLocalAssetId )

			rxTest:logf( "Checking if actual state after completing check %s is same as expected: %s",
							initialState, expectedStateAfterCheck )

			rxTest:expectEqual( expectedStateAfterCheck, actualState )

			rxTest:logf( "Checking docValue after initialState %s hasMasks %s hasLocalOnlyXmpDevelopPath %s",
			 				initialState, hasMasks, hasLocalOnlyXmpDevelopPath )

			rxTest
				:expectEqual(
					expectedDocValue,
					docValuesPerId[ localAssetId] )

		end
		end

	end

end

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

local function rxTestMissingDownloadableLocalDevelopFiles( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

	local mockFileChecker, mockFileCheckResultStreams = makeMockFileChecker( rxTest )

	local currMockFileCheckResult

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"fileChecker", mockFileChecker )

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

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalXmpDevelopIsLocalStates ) do

		for _, missingAll in pairs( { false, true } ) do

			for _, hasMasks in pairs( { false, true } ) do

				baseRenderInfoCache:popCacheItem( localAssetId )

				local externalDevelopFiles = makeExternalDevelopFiles( hasMasks, "all" )

				baseRenderInfoCache:pushCacheItem( 
					localAssetId, 
					{ externalDevelopFiles = externalDevelopFiles } )

				SchedulerTestAPI.setState( 
					scheduler, pixStreamId, localAssetId, initialState )

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateStartingCheck = 
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.CheckingIfExternalXmpDevelopIsLocal ) or
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalXmpDevelopIsLocal )

				if not expectedStateStartingCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end

				local localAssetIdRequests = 
						SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:expectEqual( expectedStateStartingCheck, actualState )

				for i = 1, #externalDevelopFiles do

					local exists = not missingAll and i ~= 1 or false

					currMockFileCheckResult = ( currMockFileCheckResult or 0 ) + 1

					local mockFileCheckResultStream = 
							mockFileCheckResultStreams[ currMockFileCheckResult ]

					mockFileCheckResultStream:onNext( exists )
					mockFileCheckResultStream:onCompleted()

				end

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateAfterCheck = 
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.DownloadStates.NeedXmpDevelopDownload ) or
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.DownloadStates.RenderNeedXmpDevelopDownload )

				if not expectedStateAfterCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end
					
				rxTest:logf( "Checking for %s transitions to expected download state %s when there are%s masks",
								initialState, expectedStateAfterCheck,
								hasMasks and "" or " NOT" )

				localAssetIdRequests = 
					SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:logf( "Checking if actual state after completing check %s is same as expected: %s",
								initialState, expectedStateAfterCheck )

				rxTest:expectEqual( expectedStateAfterCheck, actualState )

			end

		end

	end

end

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

local function rxTestMissingLocalDevelopFilesCannotDownload( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

	local mockFileChecker, mockFileCheckResultStreams = makeMockFileChecker( rxTest )

	local currMockFileCheckResult

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"fileChecker", mockFileChecker )

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

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalXmpDevelopIsLocalStates ) do

		for _, availableHrefStatus in pairs( { "none", "all", "some" } ) do

			for _, hasMasks in pairs( { false, true } ) do

				baseRenderInfoCache:popCacheItem( localAssetId )
				
				local externalDevelopFiles = 
						makeExternalDevelopFiles( hasMasks, availableHrefStatus )

				baseRenderInfoCache:pushCacheItem( 
					localAssetId, 
					{ externalDevelopFiles = externalDevelopFiles } )

				SchedulerTestAPI.setState( 
					scheduler, pixStreamId, localAssetId, initialState )

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateStartingCheck = 
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.CheckingIfExternalXmpDevelopIsLocal ) or
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalXmpDevelopIsLocal )

				if not expectedStateStartingCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end

				local localAssetIdRequests = 
						SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:expectEqual( expectedStateStartingCheck, actualState )

				for _ = 1, #externalDevelopFiles do

					currMockFileCheckResult = ( currMockFileCheckResult or 0 ) + 1

					local mockFileCheckResultStream = 
							mockFileCheckResultStreams[ currMockFileCheckResult ]

					mockFileCheckResultStream:onNext( false )
					mockFileCheckResultStream:onCompleted()

				end

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateAfterCheck = 
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							( availableHrefStatus ~= "none" and
								PixelPathProviderStateMachine.DownloadStates.NeedXmpDevelopDownload or 
								PixelPathProviderStateMachine.SendDataStates.SendMissingExpectedXmpDevelopUrl ) ) or
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
							( availableHrefStatus ~= "none" and
								PixelPathProviderStateMachine.DownloadStates.RenderNeedXmpDevelopDownload or 
								PixelPathProviderStateMachine.SendDataStates.SendMissingExpectedXmpDevelopUrlForRender ) ) 

				if not expectedStateAfterCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end
					
				rxTest:logf( "Checking for %s transitions to expected download state %s when there are%s masks",
								initialState, expectedStateAfterCheck,
								hasMasks and "" or " NOT" )

				localAssetIdRequests = 
					SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:logf( "Checking if actual state after completing check %s is same as expected: %s",
								initialState, expectedStateAfterCheck )

				rxTest:expectEqual( expectedStateAfterCheck, actualState )

			end

		end

	end

end

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

local function rxTestJoinXmpDownload( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamIdDownloading = "pixStreamIdDownloading"

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

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

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

	for _, downloadState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.externalXmpDevelopIsDownloadingStates ) do

		for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalXmpDevelopIsLocalStates ) do

			SchedulerTestAPI.setState( 
				scheduler, pixStreamId, localAssetId, initialState )

			SchedulerTestAPI.setState( 
				scheduler, pixStreamIdDownloading, localAssetId, downloadState )

			SchedulerTestAPI.runScheduledRequests( scheduler )

			local expectedStateAfterCheck = 
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
						PixelPathProviderStateMachine.DownloadStates.NeedXmpDevelopDownload ) or
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
						PixelPathProviderStateMachine.DownloadStates.RenderNeedXmpDevelopDownload )

				if not expectedStateAfterCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end

				local localAssetIdRequests = 
					scheduler:_mapAllRequestsWithPixStreamId( pixStreamId,
						function( request ) return request end )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:logf( "Checking if actual state after starting in %s is same as expected: %s",
								initialState, expectedStateAfterCheck )

				rxTest:expectEqual( expectedStateAfterCheck, actualState )

		end

	end

end

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

local function rxTestJoinXmpSave( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamIdSaving = "pixStreamIdSaving"

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

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

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

	for _, saveState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.externalXmpDevelopIsSavingStates ) do

		for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalXmpDevelopIsLocalStates ) do

			SchedulerTestAPI.setState( 
				scheduler, pixStreamId, localAssetId, initialState )

			SchedulerTestAPI.setState( 
				scheduler, pixStreamIdSaving, localAssetId, saveState )

			SchedulerTestAPI.runScheduledRequests( scheduler )

			local expectedStateAfterCheck = 
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
						PixelPathProviderStateMachine.SaveDownloadStates.NeedToSaveXmpDevelop ) or
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
						PixelPathProviderStateMachine.SaveDownloadStates.RenderNeedToSaveXmpDevelop )

				if not expectedStateAfterCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end

				local localAssetIdRequests = 
					scheduler:_mapAllRequestsWithPixStreamId( pixStreamId,
						function( request ) return request end )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:logf( "Checking if actual state after starting in %s and have other in %s is same as expected: %s",
								initialState, saveState, expectedStateAfterCheck )

				rxTest:expectEqual( expectedStateAfterCheck, actualState )

		end

	end

end

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

local function rxTestJoinMaskDownload( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamIdDownloading = "pixStreamIdDownloading"

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

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

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

	for _, downloadState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.externalDevelopAuxFilesAreDownloadingStates ) do

		for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalAuxFilesLocalStates ) do

			SchedulerTestAPI.setState( 
				scheduler, pixStreamId, localAssetId, initialState )

			SchedulerTestAPI.setState( 
				scheduler, pixStreamIdDownloading, localAssetId, downloadState )

			SchedulerTestAPI.runScheduledRequests( scheduler )

			local expectedStateAfterCheck = 
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalDevelopAuxFilesAreLocal and
						PixelPathProviderStateMachine.DownloadStates.NeedExternalDevelopAuxFilesDownload ) or
				( initialState == 
					PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalDevelopAuxFilesAreLocal and
						PixelPathProviderStateMachine.DownloadStates.RenderNeedExternalDevelopAuxFilesDownload )

				if not expectedStateAfterCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end

				local localAssetIdRequests = 
					scheduler:_mapAllRequestsWithPixStreamId( pixStreamId,
						function( request ) return request end )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:logf( "Checking if actual state after starting in %s is same as expected: %s",
								initialState, expectedStateAfterCheck )

				rxTest:expectEqual( expectedStateAfterCheck, actualState )

		end

	end

end

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

local function rxTestPrepareForMaskCheck( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

	local localBinaryPathCache = 
			SchedulerTestAPI.getSharedCache( scheduler, "localBinaryPathCache" )

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

	for _, baseRenderState in pairs( { 'missing', 'no_localBinaryPathCacheItem', 'localBinaryPathCacheItem' } ) do

		for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalAuxFilesLocalStates ) do

			for _, hasMasks in pairs( { true, false } ) do

				baseRenderInfoCache:popCacheItem( localAssetId )

				localBinaryPathCache:popCacheItem( pixStreamId, localAssetId )

				if baseRenderState ~= 'missing' then

					baseRenderInfoCache
						:pushCacheItem( 
							localAssetId, 
							{ 
								hasDevelopAuxFiles = hasMasks or nil,

								externalDevelopFiles = 
									hasMasks and 
										makeExternalDevelopFiles( true, "all" ) or nil
							} )

				end

				if baseRenderState ~= 'no_localBinaryPathCacheItem' then

					localBinaryPathCache
							:pushCacheItem( pixStreamId, localAssetId, { "FakeLocalXmpDevelopPath", "xmp_develop" } )

				end

				SchedulerTestAPI.setState( 
					scheduler, pixStreamId, localAssetId, initialState )

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateAfterCheck = 
					( ( baseRenderState == 'missing' or
							baseRenderState == "no_localBinaryPathCacheItem" ) and 
						PixelPathProviderStateMachine.SendDataStates.SendPermanentError ) or
					( not hasMasks and
						( ( initialState ==
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalDevelopAuxFilesAreLocal and
								PixelPathProviderStateMachine.SendDataStates.HaveLocalXmpDevelopPath ) or
						( initialState ==
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalDevelopAuxFilesAreLocal and
								PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop ) ) ) or
					( initialState ==
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalDevelopAuxFilesAreLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.CheckingIfExternalDevelopAuxFilesAreLocal ) or
					( initialState ==
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalDevelopAuxFilesAreLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalDevelopAuxFilesAreLocal )

					if not expectedStateAfterCheck then

						-- run a failing test
						rxTest
							:expectEqual(
								string.format( "Must provide an entry for initial state: %s", 
												initialState ),
								"" )

					end

					local localAssetIdRequests = 
						scheduler:_mapAllRequestsWithPixStreamId( pixStreamId,
							function( request ) return request end )
							
					rxTest:expectEqual( #localAssetIdRequests, 1 )

					local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
							unpack( localAssetIdRequests[ 1 ] or {} )

					rxTest:expectEqual( pixStreamId, actualPixStreamId )

					rxTest:expectEqual( localAssetId, actualLocalAssetId )

					rxTest:logf( "Checking if actual state after starting in %s %s %s is same as expected: %s",
									initialState, baseRenderState,
									hasMasks and "has masks" or "no masks", expectedStateAfterCheck )

					rxTest:expectEqual( expectedStateAfterCheck, actualState )

			end

		end

	end

end

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

local function rxTestDevSettingsMissing( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

	local mockFileChecker, mockFileCheckResultStreams = makeMockFileChecker( rxTest )

	local currMockFileCheckResult

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"fileChecker", mockFileChecker )

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

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalXmpDevelopIsLocalStates ) do

		for _, missingBaseRenderInfo in pairs( { false, true } ) do

			for _, hasMasks in pairs( { false, true } ) do

				baseRenderInfoCache:popCacheItem( localAssetId )
				
				local externalDevelopFiles = 
						makeExternalDevelopFiles( hasMasks, "all" )

				baseRenderInfoCache:pushCacheItem( 
					localAssetId, 
					{ externalDevelopFiles = externalDevelopFiles } )

				SchedulerTestAPI.setState( 
					scheduler, pixStreamId, localAssetId, initialState )

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateStartingCheck = 
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.CheckingIfExternalXmpDevelopIsLocal ) or
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalXmpDevelopIsLocal )

				if not expectedStateStartingCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end

				local localAssetIdRequests = 
						SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:expectEqual( expectedStateStartingCheck, actualState )

				if missingBaseRenderInfo then

					baseRenderInfoCache:popCacheItem( localAssetId )

				else

					baseRenderInfoCache:pushCacheItem( 
						localAssetId, 
						{ externalDevelopFiles = makeExternalDevelopFiles( hasMasks, "all" ) } )

				end

				for _ = 1, #externalDevelopFiles do

					currMockFileCheckResult = ( currMockFileCheckResult or 0 ) + 1

					local mockFileCheckResultStream = 
							mockFileCheckResultStreams[ currMockFileCheckResult ]

					mockFileCheckResultStream:onNext( false )
					mockFileCheckResultStream:onCompleted()

				end

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateAfterCheck = 
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore ) or
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.PixelCacheCheckStates.ChooseRenditionStrategy )

				if not expectedStateAfterCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end
					
				rxTest:logf( "Checking for %s transitions to expected download state %s when there are%s masks",
								initialState, expectedStateAfterCheck,
								hasMasks and "" or " NOT" )

				localAssetIdRequests = 
					SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:logf( "Checking if actual state after completing check %s is same as expected: %s",
								initialState, expectedStateAfterCheck )

				rxTest:expectEqual( expectedStateAfterCheck, actualState )

			end

		end

	end

end

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

local function rxTestErrorCheckingFiles( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

	local mockFileChecker, mockFileCheckResultStreams = makeMockFileChecker( rxTest )

	local currMockFileCheckResult

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderExternalXmpDevelopPathCheckTask",
		"fileChecker", mockFileChecker )

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

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderExternalXmpDevelopPathCheckTask" )

	for _, initialState in pairs( PixelProviderExternalXmpDevelopPathCheckTask.privateUnitTestExport.needCheckIfExternalXmpDevelopIsLocalStates ) do

		for _, missingAllHref in pairs( { false, true } ) do

			for _, hasMasks in pairs( { false, true } ) do

				baseRenderInfoCache:popCacheItem( localAssetId )

				local externalDevelopFiles = 
						makeExternalDevelopFiles( hasMasks, missingAllHref and "none" or "some" )

				baseRenderInfoCache:pushCacheItem( 
					localAssetId, 
					{ externalDevelopFiles = externalDevelopFiles } )

				SchedulerTestAPI.setState( 
					scheduler, pixStreamId, localAssetId, initialState )

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateStartingCheck = 
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.CheckingIfExternalXmpDevelopIsLocal ) or
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalXmpDevelopIsLocal )

				if not expectedStateStartingCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end

				local localAssetIdRequests = 
						SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:expectEqual( expectedStateStartingCheck, actualState )

				for i = 1, #externalDevelopFiles do

					currMockFileCheckResult = ( currMockFileCheckResult or 0 ) + 1


					if i == 1 then

						local mockFileCheckResultStream = 
								mockFileCheckResultStreams[ currMockFileCheckResult ]

						mockFileCheckResultStream:onError( "fale wail" )

					end

				end

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedStateAfterCheck = 
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.SendDataStates.SendPermanentError ) or
					( initialState == 
						PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal and
							PixelPathProviderStateMachine.SendDataStates.SendPermanentError )

				if not expectedStateAfterCheck then

					-- run a failing test
					rxTest
						:expectEqual(
							string.format( "Must provide an entry for initial state: %s", 
											initialState ),
							"" )

				end
					
				rxTest:logf( "Checking for %s transitions to expected download state %s when there are%s masks",
								initialState, expectedStateAfterCheck,
								hasMasks and "" or " NOT" )

				localAssetIdRequests = 
					SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:logf( "Checking if actual state after completing check %s is same as expected: %s",
								initialState, expectedStateAfterCheck )

				rxTest:expectEqual( expectedStateAfterCheck, actualState )

			end

		end

	end

end

	--[[
-- use this to debug tests
local function logRequest( request, rxTest, desc )

	local requestPlaceHolders = "%s" .. string.rep( ", %s", #request )

	rxTest:logf( "%s: { " .. requestPlaceHolders .. " } ",
					desc, unpack( request ) )

end
	scheduler
		:_mapAllRequestsWithPixStreamId( 
			pixStreamId, 
				logRequest, 
					rxTest, 
					string.format( "after runScheduledRequests with state %s", 
									initialState ) )
	--]]

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

return WFRxTestCase.wrapSuite( 'PixelProviderExternalXmpDevelopPathCheckTaskTest', {

	rxTestCheckMissingRenderInfo = rxTestCheckMissingRenderInfo,

	rxTestHaveAllLocalDevelopFiles = rxTestHaveAllLocalDevelopFiles,

	rxTestMissingDownloadableLocalDevelopFiles = 
		rxTestMissingDownloadableLocalDevelopFiles,

	rxTestMissingLocalDevelopFilesCannotDownload = 
		rxTestMissingLocalDevelopFilesCannotDownload,

	rxTestJoinXmpDownload = rxTestJoinXmpDownload,

	rxTestJoinXmpSave = rxTestJoinXmpSave,

	rxTestJoinMaskDownload = rxTestJoinMaskDownload,

	rxTestPrepareForMaskCheck = rxTestPrepareForMaskCheck,

	rxTestDevSettingsMissing = rxTestDevSettingsMissing,

	rxTestErrorCheckingFiles = rxTestErrorCheckingFiles,

} )
