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

WFCatIdleDownloaderTest.lua

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

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

------------------------------------------------------------------------------]]
	
	-- WF.core.os
local WFPlatformInfo = require 'WFPlatformInfo'

if not WFPlatformInfo.isDesktop then

	-- WFCatIdleDownloader is desktop only code
	return {}

end

	-- RxLua
local Rx = require 'Rx'
local Observable = Rx.Observable
local Subject = Rx.Subject
local WFRxScheduler = require 'WFRxScheduler'

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

	-- WF.core.utils
local KSDate = require 'KSDate'
local KSIdGenerator = require 'KSIdGenerator'
local KSPathUtils = require 'KSPathUtils'
local KSTableUtils = require 'KSTableUtils'
local WFFileUtils = require 'WFFileUtils'
local WFLogger = require 'WFLogger'
local WFOzTestUtils = require 'WFOzTestUtils'
local WFTableArchiving = require 'WFTableArchiving'

	-- WF.oz_client.managed_catalog
local WFCatAssetTestUtils = require 'WFCatAssetTestUtils'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFCatIdleDownloader = require 'WFCatIdleDownloader'
local WFCatSyncStatus = require 'WFCatSyncStatus'
local WFCatVersions = require 'WFCatVersions'

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

-- TODO [jandrew 2024-10-09]: This test suite needs to be rewritten. I am
-- ashamed to have written it, and the test cases are near inscrutable. Coverage
-- is very high both in terms of lines-hit and workflows, but it is very hard
-- update this file.

local WFCatIdleDownloaderTest = {}

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

local child = KSPathUtils.child

local derefOpt = assert( KSTableUtils.derefOpt )

local testDataPath = child( KSPathUtils.getStandardFilePath( 'testdata' ), 'wffileutils' )

local logger = WFLogger 'WFCatIdleDownloaderTest'

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

local counter = 1

local originalPath = child( testDataPath, 'original.txt' )
local originalRelativePath = WFFileUtils.removeVolumeFromPath( originalPath )
local originalVolumeGuid = WFFileUtils.getVolumeGuidForPath( originalPath )

local proxyPath = child( testDataPath, 'proxy.txt' )
local proxyRelativePath = WFFileUtils.removeVolumeFromPath( proxyPath )
local proxyVolumeGuid = WFFileUtils.getVolumeGuidForPath( proxyPath )

local xmpDevelopPath = child( testDataPath, 'xmpDevelop.txt' )

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

local kRunWithSubtypes = { 'image', 'deleted_image', 'video', 'deleted_video' }

local function isVideoSubtype( runWithSubtype )
	return runWithSubtype == 'video' or runWithSubtype == 'deleted_video'
end

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

local function modifyIdleDownloadLevers( docValue, hasMasterLink, hasProxyLink, hasLocalMaster, hasLocalProxy, 
						isBlocked, importTimestamp, isSubtype, isMarkedForOffline, waitingForProxy, waitExpired,
						corruptMaser, noRenditionsOnOz, hasExternalXmpLink )
				
	local localOnly = {
			files = {
				original = {},
				proxy = {}
			},
			deniedBy = {}
		}

	local smp = {}

	if isMarkedForOffline then
		localOnly.isMarkedForOfflineUse = true
	end

	if waitingForProxy and hasProxyLink then
		
		local startingTime = KSDate.timeInIso8601Format()
		
		if waitExpired then
			startingTime = KSDate.shiftIso8601DateTime( startingTime, -100000 )
		end
		
		smp.startedWaitingForProxyTimestamp = startingTime

	end
	
	if hasLocalMaster then
		localOnly.files.original.master = {
			relativePath = originalRelativePath,
			volumeGuid = originalVolumeGuid
		}
	else
		localOnly.files.original = { _delete = true }
	end
	
	local isVideo = isSubtype == 'video' or isSubtype == 'deleted_video'
	if hasLocalProxy then
		if isVideo then
			localOnly.files.proxy[ '720p' ] = {
				relativePath = proxyRelativePath,
				volumeGuid = proxyVolumeGuid
			}
		else
			localOnly.files.proxy[ '2560' ] = {
				relativePath = proxyRelativePath,
				volumeGuid = proxyVolumeGuid
			}
		end
	else
		localOnly.files.proxy = { _delete = true }
	end
	
	local links = {} 
	
	local importSource = {
		originalWidth = 640, -- avoid generating error in WFCatSearchByAssetType.lua bad argument max
		originalHeight = 480,
		sha256 = KSIdGenerator.uuidInLowercaseHex(),
		importTimestamp = importTimestamp or "2015-05-26T17:34:23-07:00"
	}
	
	if hasMasterLink then
		links[ '/rels/master' ] = { href = '/master/href/bogus/testing' }

		if corruptMaser then
			KSTableUtils.setNested( importSource, true, 'status', 'error', 'all', 'reason', 'sha256' )
		end

	end
	
	if hasProxyLink then

		if not waitingForProxy or waitExpired then

			if isVideo and not noRenditionsOnOz then
				links[ '/rels/rendition_type/720p' ] = { href = '/proxy/href/bogus/testing' } 
			elseif not isVideo then
				links[ '/rels/proxy_type/2560' ] = { href = '/proxy/href/bogus/testing' } 
			end

		end
		
	end

	if hasExternalXmpLink then

		links[ '/rels/xmp/develop' ] = { href = '/xmp_develop/href/bogus/testing' }

	end

	if not noRenditionsOnOz then
		links[ '/rels/rendition_type/thumbnail2x' ] = { href = '/proxy/href/bogus/testing' }
		links[ '/rels/rendition_type/640' ] = { href = '/rendition/hello/testing' }
	end

	if isBlocked then
		localOnly.deniedBy[ 'WFCatIdleDownloader' ] = true
	end

	smp.links = links
	
	docValue.importSource = importSource
	docValue._localOnly = localOnly
	docValue.subtype = isSubtype
	docValue._serverProvidedMetadata = smp
	docValue._id = string.format( '%032x', counter )
	
	docValue.develop = {
		processingModel = "lightroom",
		xmpCameraRaw = { sha256 = '0054ef228b1eaf3322c8caa31df6123e5851bfb3c851f81e0a09c270d51877dc' }
	}
	
	counter = counter + 1
	
	return docValue

end

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

local function createDoc( ... )

	local defaultId = KSIdGenerator.uuidInLowercaseHex()
		
	local docValue = WFOzTestUtils.v2.makeBaseValidAssetDocument( defaultId )

	docValue = modifyIdleDownloadLevers( docValue, ... )
	
	return docValue

end

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

local function addMixedAssets( rxTest, catalog, wfCatIdleDownloader, isForSubtype, waitingForProxy, markedForOfflineDeniedInPriorSession, includeVersions, testXmpDevelopOnlyChange )

	local docStore = catalog:docStore()

	-- TODO [jandrew 2020-03-11]: This code is almost inscrutable. 
	-- This test suite needs to be rewritten.
	
	-- The following code creates 13 asset documents.
	-- Each document has a unique permutation of settings that changes
	-- the download logic inside of the idle downloader.

	-- If includeVersions is true, 2 version documents are also created.
	
	local assetLocalIdsWithVersions = { 4, 5 }

	local importTimestamp = KSDate.timeInIso8601Format()

	local docs = {}

	local proxyOverlays = {}

	local blockedId

	for i = 1, 13 do
	
		-- Assets 1-4, 7-8, 11-13 have masters on Oz
		-- Assets 2-6, 9-12 have proxies on Oz

		local hasMasterLink = i <= 4 or ( i > 6 and i <= 8 ) or i > 10
		local hasProxyLink = ( i > 2 and i <= 6 ) or i > 8 and i ~= 13
		
		-- Assets 4 and 5 have external xmp settings and a version.
		local hasExternalXmpLink = includeVersions and ( i == 4 or i == 5 )

		-- Local proxy/master
		
		local hasLocalMaster = i == 2 or i == 10
		local hasLocalProxy = i == 5
		
		-- Blocking from sync
		
		local isBlocked = i == 3
		if markedForOfflineDeniedInPriorSession then
			-- Make it so 4 which is markedForOffline also has the deniedBy flag
			-- set by a prior run of the app (don't call addToDeniedList).
			-- This will cause asset 1 which isn't desired to be before 4 but
			-- since the query for that test is limit 1 we will never be see
			-- asset 4 in order to call maybeResetDeniedListStatus on it and
			-- so asset 4 will never get downloaded.
			isBlocked = i == 4
		end

		-- Recent. Shouldn't have an affect on what's downoaded: only download order.

		local isRecent = i % 2 == 0 or i == 1
		
		-- Offline Use.
		
		local isMarkedForOffline = i == 4
		
		-- Expired Wait for Proxy
		
		local waitExpired = i == 11
		
		-- Corrupt master on Oz
		
		local corruptMaser = i == 13
		
		-- No renditions on Oz
		
		local noRenditionsOnOz = i == 12
			-- Asset 12 has no renditions on Oz. For video files, this mean there's
			-- no 720p rendition( proxy ), so we expect an original to be downloaded.
			-- For images, the proxy should be downloaded.
		
		-- Proxies that may need download ( mnd = no master, no proxy, oz has proxy ): 3, 4, 6, 9
		-- Proxies that need download in managed ( mnd, not blocked, not marked for offline ): 6, 9, 11, 12
		-- Proxies that need download in keep-all-originals ( mnd, not blocked, oz has no original, not marked for offline ): 6, 9
		
		-- Originals that may need download ( mnd = no original, oz has original ): 1, 3, 4, 7, 8
		-- Originals that need download in managed ( mnd, not blocked, no proxy, oz has no proxy, maybe marked for offline ): 1, 4, 7, 8
		-- Originals that need download in keep-all-originals mode ( mnd, not blocked ): 1, 4, 7, 8, 11, 12

		if testXmpDevelopOnlyChange and i == 10 then

			-- Asset 10 has a master and Proxy on Oz make it so the only thing
			-- that needs to be downloaded is the xmp_develop.

			hasExternalXmpLink = true

			hasLocalProxy = true
				-- Make it so we don't need to download the proxy.

			isMarkedForOffline = true
				-- Idle downloader only downloads assets marked for
				-- offline (albums marked keep local). When keepAllOriginalsLocal
				-- and keepAllProxiesLocal are not true.

		end

		local docValue = createDoc(
				hasMasterLink, 
				hasProxyLink, 
				hasLocalMaster, 
				hasLocalProxy, 
				isBlocked,
				isRecent and importTimestamp,
				isForSubtype,
				isMarkedForOffline,
				waitingForProxy,
				waitExpired,
				corruptMaser,
				noRenditionsOnOz,
				hasExternalXmpLink )
				
		if isBlocked then
			blockedId = docValue._id
		end
		
		if waitingForProxy and hasProxyLink and not waitExpired then
		
			local overlay = {}
		
			local isForVideo = isForSubtype == 'video' or isForSubtype == 'deleted_video'
			
			if isForVideo and not noRenditionsOnOz then
			
				KSTableUtils.setNested( overlay, '/proxy/href/bogus/testing', '_serverProvidedMetadata', 'links', '/rels/rendition_type/720p', 'href' )
				
			elseif not isForVideo then
			
				KSTableUtils.setNested( overlay, '/proxy/href/bogus/testing', '_serverProvidedMetadata', 'links', '/rels/proxy_type/2560', 'href' )
				
			end

			proxyOverlays[ #proxyOverlays + 1 ] = overlay

		end
		
		docs[ #docs + 1 ] = docValue
		
	end
	
	rxTest:waitFor( docStore:bulkSetDocValue( docs ) )
	
	if includeVersions then
	
		local versionOverlays = {}
		
		for _, localId in ipairs( assetLocalIdsWithVersions ) do
			
			-- Create the Version Document

			local versionId
			
			rxTest:waitFor( WFCatVersions.createVersionForAsset( catalog, localId, true, "foo" )
				:map( function( createdVersionId )
					versionId = createdVersionId
					return true
				end ) )
		
			-- Add an XMP download link
			
			local overlay = {
				_id = versionId,
				_serverProvidedMetadata = {}
			}
		
			local links = {}
			links[ '/rels/xmp/develop' ] = { href = '/xmp_develop/href/bogus/testing' }

			overlay._serverProvidedMetadata.links = links
			
			table.insert( versionOverlays, overlay )
		
		end
		
		rxTest:waitFor( docStore:bulkApplyOverlay( versionOverlays ) )
	
	end
	
	local addProxiesForWaitingAssetsFn = function()

		rxTest:waitFor( docStore:bulkApplyOverlay( proxyOverlays ) )

	end
	
	if wfCatIdleDownloader and blockedId and not markedForOfflineDeniedInPriorSession then
	
		rxTest:waitFor( docStore:docValue( blockedId )
			:flatMapLatest( function( docValue )
				return wfCatIdleDownloader._failedDownloadDeniedListHelper:addToDeniedList( docValue._localId )
			end ) )
			
	end
	
	return addProxiesForWaitingAssetsFn

end

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

local downloadStream = Subject( 1 )

local ids
local subscriptions

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

local function disposeOfDownloadSubscriptions()

	if subscriptions then
	
		for key, disposable in pairs( subscriptions ) do
		
			disposable:dispose()
			subscriptions[ key ] = nil
		
		end

	end

	subscriptions = {}

end

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

local fileSize = 100

local function createDownloader( rxTest, docStore, downloadCallback, reportRemainingSpace, slowDownload )

	ids = {}
	
	disposeOfDownloadSubscriptions()
	
	return function( localId, binaryType )

		local key = localId .. ':' .. binaryType

		if ids[ key ] then
			logger:warnf( "Already have downloaded %s for %d", key, ids[ key ] )
			rxTest:expectEqual( ids[ key ], nil )
		end

		ids[ key ] = localId

		local delay = slowDownload and 0.5 or 0.001

		logger:infof( "Downloading %s for %d", binaryType, localId )

		subscriptions[ key ] = Observable.timer( delay, WFRxScheduler.sharedScheduler() )
		
			:take( 1 )
		
			:flatMapLatest( function()

				local localOnly = {
					files = {
						original = {},
						proxy = {}
					}
				}

				if binaryType == 'original' then
					localOnly.files.original.master = {
					
						relativePath = originalRelativePath,
						volumeGuid = originalVolumeGuid,
						size = fileSize

					}
				end
				
				if binaryType == 'proxy' then
					localOnly.files.proxy[ '2560' ] = {
					
						relativePath = proxyRelativePath,
						volumeGuid = proxyVolumeGuid,
						size = fileSize
						
					}
					
					localOnly.files.proxy[ '720p' ] = {
					
						relativePath = proxyRelativePath,
						volumeGuid = proxyVolumeGuid,
						size = fileSize
						
					}
				end
		
				if binaryType == 'xmp_develop' then
					localOnly.files.xmp_develop = {
					
						path = xmpDevelopPath,
						sha256 = KSIdGenerator.uuidInLowercaseHex(),
						size = fileSize

					}
				end
				 
		
				downloadCallback()
		
				return docStore:applyOverlay {
					_id = localId,
					_localOnly = localOnly,
				}
				:tap( function()
				
					rxTest:logf( "DONE downloading %s for %d", binaryType, localId )
				
				end )

			end )
			
			:subscribe( function()
			
				if reportRemainingSpace then
					downloadStream:onNext( true, localId, true, binaryType, nil, fileSize )
				else
					downloadStream:onNext( true, localId, true, binaryType )
				end
				
				subscriptions[ key ] = nil
				
			end )

	end

end

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

function WFCatIdleDownloaderTest.rxTestWhatToDownloadBasic( rxTest )

	-- Aux should be downloaded first.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload(
		false, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload
		false, -- haveLocalPathForOriginal
		true, -- needsProxyDownload
		false, -- haveLocalPathForProxy
		true, -- needsDevelopXmpDownload
		true, -- needsAuxDownload
		false, -- isMarkedForOffline
		false, -- originalVolumeOfflineOrFull
		false, -- proxyVolumeOfflineOrFull
		true -- sufficientRenditionFoundOnOz
	), 'aux' )

	-- XMP Develop Settings should be downloaded next.

	rxTest:expectEqual( WFCatSyncStatus.whatToDownload(
		false, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload
		false, -- haveLocalPathForOriginal
		true, -- needsProxyDownload
		false, -- haveLocalPathForProxy
		true, -- needsDevelopXmpDownload
		false, -- needsAuxDownload
		false, -- isMarkedForOffline
		false, -- originalVolumeOfflineOrFull
		false, -- proxyVolumeOfflineOrFull
		true -- sufficientRenditionFoundOnOz
	), 'xmp_develop' )

	-- Proxy should be downloaded second.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'proxy' )
	
	-- If we can't download the proxy because the drive is offline, we're done.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		true, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), nil )

	-- If we can't download a proxy because it's not on Oz,
	-- download the original...
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- hasLocalOriginal,
		false, -- needsProxyDownload, 
		false, -- hasLocalProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'original' )
	
	-- ...unless the original volume is offline. Then we're done.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- hasLocalOriginal,
		false, -- needsProxyDownload, 
		false, -- hasLocalProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		true, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), nil )	

	-- After we have a proxy, we're done.

	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		false, -- needsProxyDownload, 
		true, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), nil )
	
	-- Import case: have local original, but no proxy.

	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		false, -- keepAllProxies
		false, -- needsOriginalDownload, 
		true, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'proxy' )

end

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

function WFCatIdleDownloaderTest.rxTestWhatToDownloadKeepAllOriginals( rxTest )

	-- Aux should be downloaded first.

	rxTest:expectEqual( WFCatSyncStatus.whatToDownload(
		true, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload
		false, -- haveLocalPathForOriginal
		true, -- needsProxyDownload
		false, -- haveLocalPathForProxy
		true, -- needsDevelopXmpDownload
		true, -- needsAuxDownload
		false, -- isMarkedForOffline
		false, -- originalVolumeOfflineOrFull
		false, -- proxyVolumeOfflineOrFull
		true -- sufficientRenditionFoundOnOz
	), 'aux' )

	-- XMP Develop Settings should be downloaded next.

	rxTest:expectEqual( WFCatSyncStatus.whatToDownload(
		true, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload
		false, -- haveLocalPathForOriginal
		true, -- needsProxyDownload
		false, -- haveLocalPathForProxy
		true, -- needsDevelopXmpDownload
		false, -- needsAuxDownload
		false, -- isMarkedForOffline
		false, -- originalVolumeOfflineOrFull
		false, -- proxyVolumeOfflineOrFull
		true -- sufficientRenditionFoundOnOz
	), 'xmp_develop' )

	-- Original should be downloaded second...
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		true, -- keepAllOriginals
		false, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'original' )

	-- ...Unless it's not on Oz...
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		true, -- keepAllOriginals
		false, -- keepAllProxies
		false, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'proxy' )
	
	-- ...OR the original volume is offline.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		true, -- keepAllOriginals
		false, -- keepAllProxies
		false, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'proxy' )
	
	-- But if we do download the original, we should download the
	-- proxy next...
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		true, -- keepAllOriginals
		false, -- keepAllProxies
		false, -- needsOriginalDownload, 
		true, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'proxy' )
	
	-- Once we have the original and proxy, we're done.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		true, -- keepAllOriginals
		false, -- keepAllProxies
		false, -- needsOriginalDownload, 
		true, -- haveLocalPathForOriginal,
		false, -- needsProxyDownload, 
		true, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), nil )

end

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

function WFCatIdleDownloaderTest.rxTestWhatToDownloadKeepAllProxies( rxTest )

	-- Aux should be downloaded first.

	rxTest:expectEqual( WFCatSyncStatus.whatToDownload(
		false, -- keepAllOriginals
		true, -- keepAllProxies
		true, -- needsOriginalDownload
		false, -- haveLocalPathForOriginal
		true, -- needsProxyDownload
		false, -- haveLocalPathForProxy
		true, -- needsDevelopXmpDownload
		true, -- needsAuxDownload
		false, -- isMarkedForOffline
		false, -- originalVolumeOfflineOrFull
		false, -- proxyVolumeOfflineOrFull
		true -- sufficientRenditionFoundOnOz
	), 'aux' )

	-- XMP Develop Settings should be downloaded first.

	rxTest:expectEqual( WFCatSyncStatus.whatToDownload(
		false, -- keepAllOriginals
		true, -- keepAllProxies
		true, -- needsOriginalDownload
		false, -- haveLocalPathForOriginal
		true, -- needsProxyDownload
		false, -- haveLocalPathForProxy
		true, -- needsDevelopXmpDownload
		false, -- needsAuxDownload
		false, -- isMarkedForOffline
		false, -- originalVolumeOfflineOrFull
		false, -- proxyVolumeOfflineOrFull
		true -- sufficientRenditionFoundOnOz
	), 'xmp_develop' )

	-- Proxy should be downloaded second...
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		true, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'proxy' )

	-- ...Unless it's not on Oz...
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		true, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		false, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'original' )
	
	-- ... if the proxy olume isn't online, download nothing.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		true, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		true, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), nil )
	
	-- Even if we have the original, download the proxy.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		true, -- keepAllProxies
		false, -- needsOriginalDownload, 
		true, -- haveLocalPathForOriginal,
		true, -- needsProxyDownload, 
		false, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), 'proxy' )
	
	-- Once we have the proxy, we're done.
	
	rxTest:expectEqual( WFCatSyncStatus.whatToDownload( 
		false, -- keepAllOriginals
		true, -- keepAllProxies
		true, -- needsOriginalDownload, 
		false, -- haveLocalPathForOriginal,
		false, -- needsProxyDownload, 
		true, -- haveLocalPathForProxy, 
		false, -- needsDevelopXmpDownload,
		false, -- needsAuxDownload,
		false, -- isMarkedForOffline,
		false, -- originalVolumeOfflineOrFull,
		false, -- proxyVolumeOfflineOrFull,
		true -- sufficientRenditionFoundOnOz 
	), nil )

end

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

local function setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs, maybeDownloader )

	optArgs = optArgs or {}

	rxTest:setTimeLimit( optArgs.timeLimit or 30 )
	
	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	
	local downloader = maybeDownloader
	
	if not downloader then
	
		downloader = {}
	
		local downloadCount = 0
		
		local revDownloadCount = function()
			downloadCount = downloadCount + 1
		end
		
		local reportRemainingSpace = optArgs.reportRemainingSpace
		
		downloader.func = createDownloader( rxTest, wfCatalog:docStore(), revDownloadCount, reportRemainingSpace, optArgs.slowDownload )
		
		downloader.resetCount = function()
		
			downloadCount = 0
		
		end
		
		downloader.getCount = function()
			return downloadCount
		end
		
	end
	
	downloader.cancelFunc = function( binaryType, localIds ) 
		
		for _, localId in ipairs( localIds ) do
		
			local key = localId .. ':' .. binaryType
			
			local maybeSubscription = subscriptions[ key ]
			subscriptions[ key ] = nil
			
			if maybeSubscription then
				maybeSubscription:dispose()
				maybeSubscription = nil
			end		
		
		end
	
	end
	
	keepAllOriginals = not not keepAllOriginals
	keepAllProxies = not not keepAllProxies
	
	local wfCatIdleDownloader = WFCatIdleDownloader( wfCatalog, downloader.func, downloadStream, downloader.cancelFunc, keepAllOriginals, keepAllProxies, optArgs )

	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

	return wfCatalog, wfCatIdleDownloader, downloader

end

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

function WFCatIdleDownloaderTest.rxTestProxyDelay_testNightly( rxTest )
	
	rxTest:setRetryLimit( 3 )
	
	rxTest:setTimeLimit( 30 )
	
	local optArgs = {
		debugQueryLimit = 1
	}
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, nil, nil, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	local dls = rxTest:observe( downloadStream )
	
	downloader.resetCount()

	addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image', true )

	wfCatIdleDownloader:start()

	rxTest:log( "Checking we should first download the assets that are required" )
	
	dls:expectData( true, 4, true, 'original' )
	
	dls:expectData( true, 12, true, 'original' )
		
	rxTest:expectEqual( 2, downloader.getCount() )
		
	wfCatIdleDownloader:stop()

end

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

function WFCatIdleDownloaderTest.rxTestRemainingSpace_testNightly( rxTest )
	
	local optArgs = {
		reportRemainingSpace = true,
		timeLimit = 60,
		downloadBlackoutWindowInSeconds = 0.1,
		debugQueryLimit = 1
	}
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, nil, nil, optArgs )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {
			[ volumeGuid ] = fileSize,
		}
	} )
	
	-- There's a limited amount of free space left, so the downloader should eventually
	-- run out of space and stop downloading without an outOfSpace trigger
	-- via reportStatusOfVolumes.
	
	downloader.resetCount()

	addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image' )

	wfCatIdleDownloader:start()

	rxTest:sleep( 3 )
		
	rxTest:expectEqual( downloader.getCount() < 10, true )

	wfCatIdleDownloader:stop()

end

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

function WFCatIdleDownloaderTest.rxTestAbandonDownloads( rxTest )

	local optArgs = {
		slowDownload = true
	}

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, nil, nil, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	downloader.resetCount()

	addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image' )

	wfCatIdleDownloader:start()

	rxTest:sleep( 0.1 )
	
	wfCatIdleDownloader:stop()

	rxTest:sleep( 1 )
	
	rxTest:expectEqual( 0, downloader.getCount() )
	
end

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

function WFCatIdleDownloaderTest.rxTestAbandonDownloads_OutOfSpace( rxTest )

	local optArgs = {
		slowDownload = true
	}

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, nil, nil, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	downloader.resetCount()

	addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image' )

	wfCatIdleDownloader:start()

	rxTest:sleep( 0.1 )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )

	rxTest:sleep( 1 )
	
	rxTest:expectEqual( 0, downloader.getCount() )
	
end

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

function WFCatIdleDownloaderTest.rxTestAbandonDownloads_Offline( rxTest )

	local optArgs = {
		slowDownload = true
	}

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, nil, nil, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	downloader.resetCount()

	addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image' )

	wfCatIdleDownloader:start()

	rxTest:sleep( 0.1 )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	rxTest:sleep( 1 )
	
	rxTest:expectEqual( 0, downloader.getCount() )
	
end

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

function WFCatIdleDownloaderTest.rxTestAbandonDownloads_OverIdleSpaceThreshold( rxTest )

	local optArgs = {
		slowDownload = true,
		debugQueryLimit = 1
	}

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, nil, nil, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	downloader.resetCount()

	addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image' )

	local dls = rxTest:observe( downloadStream )

	wfCatIdleDownloader:start()

	rxTest:sleep( 0.1 )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	dls:expectData( true, 4, true, 'original' ) 
	dls:expectData( true, 4, true, 'proxy' ) 
	dls:expectData( true, 12, true, 'proxy' )

	rxTest:expectEqual( 3, downloader.getCount() )
	
end

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

local function expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

	for _, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		downloader.resetCount()
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		rxTest:sleep( 0.1 )

		rxTest:expectEqual( 0, downloader.getCount() )
		
		wfCatIdleDownloader:stop()
		
	end
	
end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_VerifyDownloadOrder( rxTest )

	rxTest:makeVerbose()

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local optArgs = {
		debugQueryLimit = 1
	}
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	local dls = rxTest:observe( downloadStream )
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		downloader.resetCount()
		
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, true )
		
		wfCatIdleDownloader:start()
		
		local localIdOffset = ( i - 1 ) * 15
		
		rxTest:logf( "Doing tests with %s subtype", runWithSubtype )

		rxTest:log( "Checking downloads marked for offline assets first" )
	
		dls:expectData( true, 4 + localIdOffset, true, 'xmp_develop' )
		dls:expectData( true, 4 + localIdOffset, true, 'original' ) 
		dls:expectData( true, 4 + localIdOffset, true, 'proxy' )
		
		rxTest:log( "Checking downloads the important assets" )
		
		dls:expectData( true, 12 + localIdOffset, true, 'original' )
		dls:expectData( true, 1 + localIdOffset, true, 'original' )
		dls:expectData( true, 6 + localIdOffset, true, 'proxy' )
		dls:expectData( true, 8 + localIdOffset, true, 'original' )
		
		rxTest:log( "Checking standard downloads" )

		dls:expectData( true, 5 + localIdOffset, true, 'xmp_develop' )
		dls:expectData( true, 7 + localIdOffset, true, 'original' ) 
		dls:expectData( true, 9 + localIdOffset, true, 'proxy' )
		dls:expectData( true, 11 + localIdOffset, true, 'original' ) 
		
		local runWithVideos = isVideoSubtype( runWithSubtype )
		if runWithSubtype == 'image' then
		
			rxTest:expectEqual( runWithVideos and 10 or 11, downloader.getCount() )
		
		else
		
			rxTest:expectEqual( 11, downloader.getCount() )
		
		end
		wfCatIdleDownloader:stop()

	end

end

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

local function watchDownloadStream( rxTest, downloadStream )

	local downloads = {}
	local downloadCount = 0

	local verifyDownloadFn = function( downloads, ... )
	
		local args = { ... }
	
		local strKey = WFTableArchiving.tableToString( args )

		rxTest:expectEqual( strKey, downloads[ strKey ] and strKey )
	
	end

	local verifyDownload = function( ... )
		return verifyDownloadFn( downloads, ... )
	end

	local downloadStreamObserver = rxTest:observe( downloadStream

		:map( function( ... )

			local args = { ... }

			local strKey = WFTableArchiving.tableToString( args )
		
			downloads[ strKey ] = true

			downloadCount = downloadCount + 1
		
			return downloadCount
		
		end ) )
			
	return downloadStreamObserver, verifyDownload
			
end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, true )
		
		wfCatIdleDownloader:start()
		
		if runWithSubtype == 'image' then
			dls:expectDataWithinTime( 10, 13 )
		else
			dls:expectDataWithinTime( 10, 11 )
		end
		
		dls:dispose()
		
		local localIdOffset = ( i - 1 ) * 15
		
		rxTest:logf( "Doing tests with %s subtype", runWithSubtype )

		rxTest:log( "Checking downloads marked for offline assets first" )
	
		verifyDownload( true, 4 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		rxTest:log( "Checking downloads the important assets" )
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		rxTest:log( "Checking standard downloads" )

		verifyDownload( true, 5 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'original' )
		
		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_NoDiskSpace( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )
	
	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_OverIdleSpaceThreshold( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	-- We should only download "required" assets.
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 9 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		-- Then downloads the important assets
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' ) -- no master on Oz
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' ) -- no master on Oz
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_Offline( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 9 )

		local localIdOffset = ( i - 1 ) * 13

		rxTest:log( "Checking downloads marked for offline assets first" )
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		
		rxTest:log( "Checking downloads the important assets" )

		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		rxTest:log( "Checking standard downloads" )

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true
		},
		remainingSpace = {},
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()
	
		local runWithVideos = isVideoSubtype( runWithSubtype )
	
		if runWithVideos then
			dls:expectDataWithinTime( 10, 3 )
		else
			dls:expectDataWithinTime( 10, 4 )
		end

		local localIdOffset = ( i - 1 ) * 13

		rxTest:log( "Checking downloads marked for offline assets first" )
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 

		
		if not runWithVideos then
			rxTest:log( "Checking for more info, search this file for `noRenditionsOnOz`" )
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		rxTest:log( "Checking downloads the important assets" )
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		rxTest:log( "Checking standard priority downloads." )

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )
		
		if runWithVideos then
			dls:expectDataWithinTime( 10, 3 )
		else
			dls:expectDataWithinTime( 10, 4 )
		end

		local localIdOffset = ( i - 1 ) * 13

		rxTest:log( "Checking downloads marked for offline assets first" )
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 
		
		
		if not runWithVideos then
			rxTest:log( "Checking for more info, search this file for `noRenditionsOnOz`" )
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		rxTest:log( "Checking downloads the important assets" )
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
	
		rxTest:log( "Checking standard priority downloads." )

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_NoDiskSpace_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true
		},
		remainingSpace = {},
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()
		
		dls:expectDataWithinTime( 10, 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 

		-- Then downloads the important assets
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_NoDiskSpace_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {},
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_NoDiskSpace_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_Offline_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 

		-- Then downloads the important assets

		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_Offline_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_Offline_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_OverIdleSpaceThreshold_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 9 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		-- Then downloads the important assets
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' ) -- no master on Oz
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' ) -- no master on Oz
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_OverIdleSpaceThreshold_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )
		dls:expectDataWithinTime( 10, runWithVideos and 3 or 4 )

		local localIdOffset = ( i - 1 ) * 13

		-- Then the proxies when we already have the originals
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if not runWithVideos then
			-- Downloaded because there's no suitable rendition on Oz.
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		-- Then downloads the important assets
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' ) -- no master on Oz	

		-- Then the standard downloads
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' ) -- no master on Oz
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_OverIdleSpaceThreshold_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )
		dls:expectDataWithinTime( 10, runWithVideos and 3 or 4 )

		local localIdOffset = ( i - 1 ) * 13

		-- Then the proxies when we already have the originals
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if not runWithVideos then
			-- Downloaded because there's no suitable rendition on Oz.
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		-- Then downloads the important assets
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' ) -- no master on Oz	
		
		-- Then the standard downloads
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' ) -- no master on Oz

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllOriginals_XmpDevelopOnlyChange( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		local includeVersions = true
		local testXmpDevelopOnlyChange = true
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, includeVersions, testXmpDevelopOnlyChange )

		wfCatIdleDownloader:start()

		rxTest:logf( "Now checking %s", runWithSubtype )

		if runWithSubtype == 'image' then
			dls:expectDataWithinTime( 10, 14 )
		elseif runWithSubtype == 'deleted_image' then
			dls:expectDataWithinTime( 10, 12 )
		else -- video, deleted_video
			dls:expectDataWithinTime( 10, 12 )
		end

		local localIdOffset = ( i - 1 ) * 15

		verifyDownload( true, 4 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 5 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 10 + localIdOffset, true, 'xmp_develop' )
		if runWithSubtype == 'image' then
			verifyDownload( true, 14 + localIdOffset, true, 'xmp_develop' )
			verifyDownload( true, 15 + localIdOffset, true, 'xmp_develop' )
		end

		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		-- 2 already
		-- 3 blocked
		verifyDownload( true, 4 + localIdOffset, true, 'original' )
		-- 5 no master on oz
		-- 6 no master on oz
		verifyDownload( true, 7 + localIdOffset, true, 'original' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		-- 9 no master on oz
		-- 10 no master on oz
		verifyDownload( true, 11 + localIdOffset, true, 'original' )
		verifyDownload( true, 12 + localIdOffset, true, 'original' )

		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) -- marked for offline
		-- 5 proxy already local
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_VerifyDownloadOrder( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local optArgs = {
		debugQueryLimit = 1
	}
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	local dls = rxTest:observe( downloadStream )
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		downloader.resetCount()

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, true )
		
		wfCatIdleDownloader:start()
		
		local localIdOffset = ( i - 1 ) * 15

		-- downloads marked for offline assets first
		
		dls:expectData( true, 4 + localIdOffset, true, 'xmp_develop' )
		dls:expectData( true, 4 + localIdOffset, true, 'original' ) 
		dls:expectData( true, 4 + localIdOffset, true, 'proxy' )
		
		local runWithVideos = isVideoSubtype( runWithSubtype )
		if runWithVideos then
			dls:expectData( true, 12 + localIdOffset, true, 'original' )
		else
			dls:expectData( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		dls:expectData( true, 1 + localIdOffset, true, 'original' )
		dls:expectData( true, 6 + localIdOffset, true, 'proxy' )
		dls:expectData( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard priority downloads.

		dls:expectData( true, 5 + localIdOffset, true, 'xmp_develop' )
		dls:expectData( true, 7 + localIdOffset, true, 'original' )
		dls:expectData( true, 9 + localIdOffset, true, 'proxy' )
		dls:expectData( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		dls:expectData( true, 10 + localIdOffset, true, 'proxy' )
		
		if runWithSubtype == 'image' then
		
			-- The the external XMP from the version documents whose associated
			-- assets are marked for offline use.
			
			dls:expectData( true, 15 + localIdOffset, true, 'xmp_develop' )
			
			dls:expectData( true, 14 + localIdOffset, true, 'xmp_develop' )
		
		end

		rxTest:expectEqual( runWithSubtype == 'image' and 14 or 12, downloader.getCount() )

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
		
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, true )
		
		wfCatIdleDownloader:start()
		
		dls:expectDataWithinTime( 10, runWithSubtype == 'image' and 14 or 12 )
		
		local localIdOffset = ( i - 1 ) * 15

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		local runWithVideos = isVideoSubtype( runWithSubtype )
		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 5 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 7 + localIdOffset, true, 'original' )
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )
		
		if runWithSubtype == 'image' then
		
			-- The the external XMP from the version documents whose associated
			-- assets are marked for offline use.
			
			verifyDownload( true, 15 + localIdOffset, true, 'xmp_develop' )
			
			verifyDownload( true, 14 + localIdOffset, true, 'xmp_develop' )
		
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_NoDiskSpace( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )
	
	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_OverIdleSpaceThreshold( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	-- We should only download "required" assets.
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 10 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 
		
		local runWithVideos = isVideoSubtype( runWithSubtype )
		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )

		-- Then the standard priority downloads.

		verifyDownload( true, 7 + localIdOffset, true, 'original' )
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_Offline( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 10 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		local runWithVideos = isVideoSubtype( runWithSubtype )
		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 7 + localIdOffset, true, 'original' )
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true
		},
		remainingSpace = {},
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 

		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 
		
		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_NoDiskSpace_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true
		},
		remainingSpace = {},
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 5 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		
		-- Then downloads the important assets
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 7 + localIdOffset, true, 'original' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_NoDiskSpace_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {},
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_NoDiskSpace_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_Offline_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 5)

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		
		-- Then downloads the important assets
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 7 + localIdOffset, true, 'original' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_Offline_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_Offline_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_OverIdleSpaceThreshold_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 10 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 

		local runWithVideos = isVideoSubtype( runWithSubtype )
		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 7 + localIdOffset, true, 'original' )
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_OverIdleSpaceThreshold_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 
		
		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_OverIdleSpaceThreshold_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 
		
		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_XmpDevelopOnlyChange( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = true

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		local includeVersions = true
		local testXmpDevelopOnlyChange = true
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, includeVersions, testXmpDevelopOnlyChange )

		wfCatIdleDownloader:start()

		rxTest:logf( "Now checking %s", runWithSubtype )

		if runWithSubtype == 'image' then
			dls:expectDataWithinTime( 10, 14 )
		elseif runWithSubtype == 'deleted_image' then
			dls:expectDataWithinTime( 10, 12 )
		else -- video, deleted_video
			dls:expectDataWithinTime( 10, 12 )
		end

		local localIdOffset = ( i - 1 ) * 15

		verifyDownload( true, 4 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 5 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 10 + localIdOffset, true, 'xmp_develop' )
		if runWithSubtype == 'image' then
			verifyDownload( true, 14 + localIdOffset, true, 'xmp_develop' )
			verifyDownload( true, 15 + localIdOffset, true, 'xmp_develop' )
		end

		verifyDownload( true, 1 + localIdOffset, true, 'original' ) -- no proxy on oz, download original instead
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) -- marked for offline
		verifyDownload( true, 7 + localIdOffset, true, 'original' ) -- no proxy on oz, download original instead
		verifyDownload( true, 8 + localIdOffset, true, 'original' ) -- no proxy on oz, download original instead

		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) -- marked for offline
		-- 5 proxy already local
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		-- 10 proxy already local because testXmpDevelopOnlyChange
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		local runWithVideos = isVideoSubtype( runWithSubtype )
		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_VerifyDownloadOrder( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local optArgs = {
		debugQueryLimit = 1
	}
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	local dls = rxTest:observe( downloadStream )
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		downloader.resetCount()
		
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, true )
		
		wfCatIdleDownloader:start()
		
		local localIdOffset = ( i - 1 ) * 15

		-- Downloads marked for offline assets first
	
		dls:expectData( true, 4 + localIdOffset, true, 'xmp_develop' )
		dls:expectData( true, 4 + localIdOffset, true, 'original' ) 
		dls:expectData( true, 4 + localIdOffset, true, 'proxy' )
		
		dls:expectData( true, 12 + localIdOffset, true, 'original' )
		
		-- Then downloads the important assets

		dls:expectData( true, 1 + localIdOffset, true, 'original' )
		dls:expectData( true, 6 + localIdOffset, true, 'proxy' )
		dls:expectData( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		dls:expectData( true, 5 + localIdOffset, true, 'xmp_develop' )
		dls:expectData( true, 7 + localIdOffset, true, 'original' ) 
		dls:expectData( true, 9 + localIdOffset, true, 'proxy' )
		dls:expectData( true, 11 + localIdOffset, true, 'original' ) 
		
		-- Then the proxies when we already have the originals
		
		local runWithVideos = isVideoSubtype( runWithSubtype )
		if not runWithVideos then
			dls:expectData( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		dls:expectData( true, 10 + localIdOffset, true, 'proxy' ) 
		
		dls:expectData( true, 11 + localIdOffset, true, 'proxy' ) 
		
		if runWithSubtype == 'image' then
		
			-- The the external XMP from the version documents whose associated
			-- assets are marked for offline use.
			
			dls:expectData( true, 15 + localIdOffset, true, 'xmp_develop' )
			
			dls:expectData( true, 14 + localIdOffset, true, 'xmp_develop' )
		
			rxTest:expectEqual( runWithVideos and 15 or 16, downloader.getCount() )
		
		else
		
			rxTest:expectEqual( runWithVideos and 13 or 14, downloader.getCount() )
		
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
		
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, true )
		
		wfCatIdleDownloader:start()
		
		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )
		
		if runWithSubtype == 'image' then
			dls:expectDataWithinTime( 10, runWithVideos and 15 or 16 )
		else
			dls:expectDataWithinTime( 10, runWithVideos and 13 or 14 )
		end
		
		local localIdOffset = ( i - 1 ) * 15

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		
		-- Then downloads the important assets

		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 5 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 
		
		-- Then the proxies when we already have the originals
		
		if not runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' ) 
		
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' ) 
		
		if runWithSubtype == 'image' then
		
			-- The the external XMP from the version documents whose associated
			-- assets are marked for offline use.
			
			verifyDownload( true, 15 + localIdOffset, true, 'xmp_develop' )
			
			verifyDownload( true, 14 + localIdOffset, true, 'xmp_develop' )
		
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_NoDiskSpace( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )
	
	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_OverIdleSpaceThreshold( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	-- We should only download "required" assets.
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 11 or 12 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		
		-- Then downloads the important assets

		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 
		
		-- Then the proxies when we already have the originals
		
		
		if not runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' ) 
		
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' ) 
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_Offline( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )
	
	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 11 or 12 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		
		-- Then downloads the important assets

		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 
		
		-- Then the proxies when we already have the originals
		
		if not runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' ) 
		
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' ) 

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true
		},
		remainingSpace = {},
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 

		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		-- Then downloads the important assets
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 
		
		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_NoDiskSpace_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true
		},
		remainingSpace = {},
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 

		-- Then downloads the important assets
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_NoDiskSpace_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {},
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_NoDiskSpace_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_Offline_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 

		-- Then downloads the important assets

		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_Offline_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_Offline_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_OverIdleSpaceThreshold_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 11 or 12 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
	
		verifyDownload( true, 4 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )
		
		verifyDownload( true, 12 + localIdOffset, true, 'original' )
		
		-- Then downloads the important assets

		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		
		-- Then the standard downloads

		verifyDownload( true, 7 + localIdOffset, true, 'original' ) 
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'original' ) 
		
		-- Then the proxies when we already have the originals

		if not runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )
		
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_OverIdleSpaceThreshold_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 
		
		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )

		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_OverIdleSpaceThreshold_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()
	
	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}
	
	local keepAllOriginals = true
	local keepAllProxies = true
	
	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do
	
		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )
	
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 5 or 6 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first
		
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) 
		
		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end
		
		-- Then downloads the important assets
		
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		
		-- Then the standard priority downloads.

		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )
		
		-- Then the proxies when we already have the originals
		
		verifyDownload( true, 10 + localIdOffset, true, 'proxy' )
		
		wfCatIdleDownloader:stop()
		
	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepBothProxiesAndOriginals_XmpDevelopOnlyChange( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = true

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		local includeVersions = true
		local testXmpDevelopOnlyChange = true
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, includeVersions, testXmpDevelopOnlyChange )

		wfCatIdleDownloader:start()

		rxTest:logf( "Now checking %s", runWithSubtype )

		if runWithSubtype == 'image' then
			dls:expectDataWithinTime( 10, 16 )
		elseif runWithSubtype == 'deleted_image' then
			dls:expectDataWithinTime( 10, 14 )
		else -- video, deleted_video
			dls:expectDataWithinTime( 10, 13 )
		end

		local localIdOffset = ( i - 1 ) * 15

		verifyDownload( true, 4 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 5 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 10 + localIdOffset, true, 'xmp_develop' )
		if runWithSubtype == 'image' then
			verifyDownload( true, 14 + localIdOffset, true, 'xmp_develop' )
			verifyDownload( true, 15 + localIdOffset, true, 'xmp_develop' )
		end

		verifyDownload( true, 1 + localIdOffset, true, 'original' )
		-- 2 already
		-- 3 blocked
		verifyDownload( true, 4 + localIdOffset, true, 'original' )
		-- 5 no master on oz
		-- 6 no master on oz
		verifyDownload( true, 7 + localIdOffset, true, 'original' )
		verifyDownload( true, 8 + localIdOffset, true, 'original' )
		-- 9 no master on oz
		-- 10 no master on oz
		verifyDownload( true, 11 + localIdOffset, true, 'original' )
		verifyDownload( true, 12 + localIdOffset, true, 'original' )

		verifyDownload( true, 4 + localIdOffset, true, 'proxy' ) -- marked for offline
		-- 5 proxy already local
		verifyDownload( true, 6 + localIdOffset, true, 'proxy' )
		verifyDownload( true, 9 + localIdOffset, true, 'proxy' )
		-- 10 proxy already local because testXmpDevelopOnlyChange
		verifyDownload( true, 11 + localIdOffset, true, 'proxy' )

		local runWithVideos = isVideoSubtype( runWithSubtype )
		if not runWithVideos then
			-- Downloaded because there's no suitable rendition on Oz.
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_VerifyDownloadOrder( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = false

	local optArgs = {
		debugQueryLimit = 1
	}

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	local dls = rxTest:observe( downloadStream )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		downloader.resetCount()

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, true )

		wfCatIdleDownloader:start()

		local localIdOffset = ( i - 1 ) * 15

		-- Downloads marked for offline assets first

		dls:expectData( true, 4 + localIdOffset, true, 'xmp_develop' )
		dls:expectData( true, 4 + localIdOffset, true, 'original' )
		dls:expectData( true, 4 + localIdOffset, true, 'proxy' )

		local runWithVideos = isVideoSubtype( runWithSubtype )
		if runWithVideos then
			dls:expectData( true, 12 + localIdOffset, true, 'original' )
		else
			dls:expectData( true, 12 + localIdOffset, true, 'proxy' )
		end

		if runWithSubtype == 'image' then

			-- The the external XMP from the version documents whose associated
			-- assets are marked for offline use.

			dls:expectData( true, 14 + localIdOffset, true, 'xmp_develop' )

			rxTest:expectEqual( 5, downloader.getCount() )

		else

			rxTest:expectEqual( 4, downloader.getCount() )

		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		local includeVersions = true
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, includeVersions )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		if runWithSubtype == 'image' then
			dls:expectDataWithinTime( 10, 5 )
		elseif runWithSubtype == 'deleted_image' then
			dls:expectDataWithinTime( 10, 4 )
		else -- video, deleted_video
			dls:expectDataWithinTime( 10, 4 )
		end

		local localIdOffset = ( i - 1 ) * 15

		-- Downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'xmp_develop' )

		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		verifyDownload( true, 4 + localIdOffset, true, 'original' )
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		-- Then the proxies when we already have the originals

		if runWithSubtype == 'image' then

			-- The the external XMP from the version documents whose associated
			-- assets are marked for offline use.
	
			verifyDownload( true, 14 + localIdOffset, true, 'xmp_develop' )

		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_NoDiskSpace( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_OverIdleSpaceThreshold( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	-- We should only download "required" assets.

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, 3 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'original' )
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end


		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_Offline( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	local volumeGuid = WFFileUtils.getVolumeGuidForPath( wfCatalog:fileSpec():catalogPath() )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

	rxTest:finally( function()

		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, 3 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'original' )
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true
		},
		remainingSpace = {},
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 1 or 2 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		originalsVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 1 or 2 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_NoDiskSpace_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true
		},
		remainingSpace = {},
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 1 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first
		verifyDownload( true, 4 + localIdOffset, true, 'original' )

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_NoDiskSpace_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {},
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_NoDiskSpace_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ volumeGuid ] = true,
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_Offline_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		dls:expectDataWithinTime( 10, 2 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'original' )
		verifyDownload( true, 12 + localIdOffset, true, 'original' )

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_Offline_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_Offline_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ volumeGuid ] = true,
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	expectToDownloadNothing( rxTest, wfCatalog, wfCatIdleDownloader, downloader )

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_OverIdleSpaceThreshold_ExternalOriginals( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, 3 )

		local localIdOffset = ( i - 1 ) * 13

		-- Downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'original' )
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_OverIdleSpaceThreshold_ExternalOriginals_NoDiskSpace( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {
			[ externalVolumeGuid ] = true
		},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 1 or 2 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_OverIdleSpaceThreshold_ExternalOriginals_Offline( rxTest )

	local volumeGuid = KSIdGenerator.uuidInLowercaseHex()
	local externalVolumeGuid = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		catalogVolumeGuid = volumeGuid,
		originalsVolumeGuid = externalVolumeGuid,
		proxiesVolumeGuid = volumeGuid
	}

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {
			[ externalVolumeGuid ] = true
		},
		volumesOverIdleSpaceThreshold = {
			[ volumeGuid ] = true,
		},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		dls:expectDataWithinTime( 10, runWithVideos and 1 or 2 )

		local localIdOffset = ( i - 1 ) * 13

		-- downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		if not runWithVideos then
			-- For more info, search this file for `noRenditionsOnOz`
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

function WFCatIdleDownloaderTest.rxTestKeepNeither_XmpDevelopOnlyChange( rxTest )

	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local dls, verifyDownload = watchDownloadStream( rxTest, downloadStream )

		local includeVersions = true
		local testXmpDevelopOnlyChange = true
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype, nil, nil, includeVersions, testXmpDevelopOnlyChange )

		wfCatIdleDownloader:start()

		local runWithVideos = isVideoSubtype( runWithSubtype )

		if runWithSubtype == 'image' then
			dls:expectDataWithinTime( 10, 6 )
		elseif runWithSubtype == 'deleted_image' then
			dls:expectDataWithinTime( 10, 5 )
		else -- video, deleted_video
			dls:expectDataWithinTime( 10, 5 )
		end

		local localIdOffset = ( i - 1 ) * 15

		-- Downloads marked for offline assets first

		verifyDownload( true, 4 + localIdOffset, true, 'xmp_develop' )
		verifyDownload( true, 10 + localIdOffset, true, 'xmp_develop' )

		if runWithVideos then
			verifyDownload( true, 12 + localIdOffset, true, 'original' )
		else
			verifyDownload( true, 12 + localIdOffset, true, 'proxy' )
		end

		verifyDownload( true, 4 + localIdOffset, true, 'original' )
		verifyDownload( true, 4 + localIdOffset, true, 'proxy' )

		-- Then the proxies when we already have the originals

		if runWithSubtype == 'image' then
			verifyDownload( true, 14 + localIdOffset, true, 'xmp_develop' )
		end

		wfCatIdleDownloader:stop()

	end

end

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

local function checkDownload( rxTest, docStore, localId, binaryType )

	local hasExpectedDownload = docStore:docValue( localId )

		:pluck( '_localOnly', 'files' )
	
		:map( function( files )
		
			if binaryType == 'original' then
				return derefOpt( files, 'original', 'master' ) and true or false	
			elseif binaryType == 'proxy' then
				return derefOpt( files, 'proxy', '2560' ) and true or false
			end
		
			return false
		
		end )

	rxTest:expectSingleValue( hasExpectedDownload, true )

end

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

function WFCatIdleDownloaderTest.rxTestManaged_Large_testNightly( rxTest )

	rxTest:setTimeLimit( 120 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	
	local docStore = wfCatalog:docStore()
	
	local downloadCount = 0
	
	local downloadCountSubject = Rx.BehaviorSubject()

	local revDownloadCount = function()
		downloadCount = downloadCount + 1
		downloadCountSubject:onNext( downloadCount )
	end
	
	local downloader = createDownloader( rxTest, wfCatalog:docStore(), revDownloadCount )
	
	local cancelFunc = function() --[[noop]] end
	
	local keepAllOriginals = false
	local keepAllProxies = false

	local wfCatIdleDownloader = WFCatIdleDownloader( wfCatalog, downloader, downloadStream, cancelFunc, keepAllOriginals, keepAllProxies )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for _ = 1, 100 do
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image', false, true )
	end
	
	downloadCount = 0
	
	local dls = rxTest:observe( downloadStream )
	
	wfCatIdleDownloader:start()

	-- Wait for everything to download
	-- Expecting to see proxy for 12 (which doesn't have any renditions)
	-- and both original and proxy for 4 (which is marked for offline)
	for i = 1, 300 do
		rxTest:logf( "Waiting for data %s", i )
		dls:expectData( true, ':ignore:', true, ':ignore:' )
	end

	-- cross check the download count
	rxTest:observe( downloadCountSubject )
	:expectData( 300 )
	:dispose()

	-- Verify we downloaded the proper things

	for i = 1, 100 do
	
		local offset = ( ( i - 1 ) * 13 )
		
		checkDownload( rxTest, docStore, 4 + offset, 'original' )
		checkDownload( rxTest, docStore, 4 + offset, 'proxy' )
		checkDownload( rxTest, docStore, 12 + offset, 'proxy' )
		
	end
	
	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()
		
	end )

end

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

-- FIXME [jandrew 2025-03-11]: Disabled due to instability.

function WFCatIdleDownloaderTest.DISABLED_rxTestKeepAllOriginals_Large_testNightly( rxTest )

	rxTest:setTimeLimit( 120 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	
	local docStore = wfCatalog:docStore()
	
	local downloadCount = 0
	
	local revDownloadCount = function()
		downloadCount = downloadCount + 1
	end
	
	local downloader = createDownloader( rxTest, wfCatalog:docStore(), revDownloadCount )
	
	local cancelFunc = function() --[[noop]] end
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatIdleDownloader = WFCatIdleDownloader( wfCatalog, downloader, downloadStream, cancelFunc, keepAllOriginals, keepAllProxies )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for _ = 1, 100 do
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image', false, true )
	end
	
	downloadCount = 0
	
	local dls = rxTest:observe( 
					downloadStream
						:tap( 
							function( _, id, _, binaryType )

								rxTest:logf( "Saw download of %s of type %s", id, binaryType )

							end ) )
	
	wfCatIdleDownloader:start()

	-- Wait for everything to download
	
	for i = 1, 1000 do
		rxTest:logf( "waiting for download item %s", i )
		dls:expectData( true, ':ignore:', true, ':ignore:' )
	end

	rxTest:sleep( 0.1 )
	rxTest:expectEqual( 1000, downloadCount )
		-- Sleep to make sure there are no additional, unexpected downloads.
		
	-- Verify we downloaded the proper things
	
	for i = 1, 100 do
		local offset = ( ( i - 1 ) * 13 )
		
		checkDownload( rxTest, docStore, 1 + offset, 'original' )
		checkDownload( rxTest, docStore, 3 + offset, 'original' ) 
		checkDownload( rxTest, docStore, 4 + offset, 'original' ) 
		checkDownload( rxTest, docStore, 4 + offset, 'proxy' )
		checkDownload( rxTest, docStore, 6 + offset, 'proxy' )
		checkDownload( rxTest, docStore, 7 + offset, 'original' ) 
		checkDownload( rxTest, docStore, 8 + offset, 'original' )
		checkDownload( rxTest, docStore, 9 + offset, 'proxy' )
		checkDownload( rxTest, docStore, 11 + offset, 'original' )
		checkDownload( rxTest, docStore, 12 + offset, 'original' )
	end

	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

function WFCatIdleDownloaderTest.rxTestKeepAllProxies_Large_testNightly( rxTest )

	rxTest:setTimeLimit( 120 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	
	local docStore = wfCatalog:docStore()
	
	local downloadCount = 0
	
	local revDownloadCount = function()
		downloadCount = downloadCount + 1
	end
	
	local downloader = createDownloader( rxTest, wfCatalog:docStore(), revDownloadCount )
	
	local cancelFunc = function() --[[noop]] end
	
	local keepAllOriginals = false
	local keepAllProxies = true
	
	local wfCatIdleDownloader = WFCatIdleDownloader( wfCatalog, downloader, downloadStream, cancelFunc, keepAllOriginals, keepAllProxies )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for _ = 1, 100 do
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image', false, true )
	end
	
	downloadCount = 0
	
	local dls = rxTest:observe( 
					downloadStream
						:tap( 
							function( _, id, _, binaryType )

								rxTest:logf( "Saw download of %s of type %s", id, binaryType )

							end ) )
	
	wfCatIdleDownloader:start()

	-- Wait for everything to download
	
	for i = 1, 1100 do
		rxTest:logf( "expectData for %s", i )
		dls:expectData( true, ':ignore:', true, ':ignore:' )
	end

	rxTest:sleep( 0.1 )
	rxTest:expectEqual( 1100, downloadCount )
		-- Sleep to make sure there are no additional, unexpected downloads.

	-- Verify we downloaded the proper things
	
	for i = 1, 100 do
	
		local offset = ( ( i - 1 ) * 13 )
		
		checkDownload( rxTest, docStore, 4 + offset, 'original' )
		checkDownload( rxTest, docStore, 4 + offset, 'proxy' )
		
		checkDownload( rxTest, docStore, 12 + offset, 'proxy' )
		
		checkDownload( rxTest, docStore, 1 + offset, 'original' )
		checkDownload( rxTest, docStore, 6 + offset, 'proxy' )
		checkDownload( rxTest, docStore, 8 + offset, 'original' )
		checkDownload( rxTest, docStore, 3 + offset, 'proxy' )
		
		checkDownload( rxTest, docStore, 7 + offset, 'original' ) 
		checkDownload( rxTest, docStore, 9 + offset, 'proxy' )
		checkDownload( rxTest, docStore, 11 + offset, 'proxy' )
		checkDownload( rxTest, docStore, 10 + offset, 'proxy' )

	end

	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

-- FIXME [jandrew 2025-03-11]: Disabled due to instability.

function WFCatIdleDownloaderTest.DISABLED_rxTestDenyAssetFromSync_testNightly( rxTest )

	rxTest:setTimeLimit( 30 )

	local kIdleDownloaderId = "streamId"
	local kAnyOtherError = "any-other-error"
	local kSendPermanentError = "SendPermanentError"

	local downloadFailCount = 0
	local downloadFailError = kAnyOtherError

	local function setBadDownloaderError( errorType )
		downloadFailError = errorType
		downloadFailCount = 0
	end
	
	local function createBadDownloader()

		return function( localId, binaryType )

			local delay = 0.1
			local disposable

			local disposeFn = function()
				disposable:dispose()
				disposable = nil
			end

			disposable = Observable.timer( delay, WFRxScheduler.sharedScheduler() )
				:take( 1 )
				:flatMapLatest( function()
					return Observable.just( true )
				end )
				:subscribe( function()
						-- print( "downloaded", downloadFailError, localId, binaryType )
						if downloadFailError then
							downloadFailCount = downloadFailCount + 1
							downloadStream:onNext( kIdleDownloaderId, localId, false, downloadFailError )
						else
							downloadStream:onNext( kIdleDownloaderId, localId, true, 'binaryPath', binaryType )
						end
					end,
					disposeFn,
					disposeFn )
		end

	end



	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	
	local badDownloader = createBadDownloader()
	
	local cancelFunc = function() --[[noop]] end
	
	local keepAllOriginals = false
	local keepAllProxies = false
	
	local dls = rxTest:observe( downloadStream )
	-- Expected tuples:
		-- streamId, localId, status(true), binaryPath, binaryType
		-- streamId, localId, status(false), errorType
	
	local optArgs = {
		failedDownloadBlackoutWindowInSeconds = 2
	}

	local wfCatIdleDownloader = WFCatIdleDownloader( wfCatalog, badDownloader, downloadStream, cancelFunc, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	for i, runWithSubtype in pairs( kRunWithSubtypes ) do

		local runWithVideos = isVideoSubtype( runWithSubtype )

		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, runWithSubtype )

		wfCatIdleDownloader:start()

		local localIdOffset = ( i - 1 ) * 13


		-- First try with an error to cause the asset to be marked with deniedBy

		setBadDownloaderError( kAnyOtherError )

		-- original for id 4
		dls:expectData( kIdleDownloaderId, 4 + localIdOffset, false, kAnyOtherError )
		rxTest:expectSingleValue( wfCatalog:docStore():docValue( 4 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ),
		nil )

		-- proxy id 12
		dls:expectData( kIdleDownloaderId, 12 + localIdOffset, false, kAnyOtherError )
		rxTest:expectSingleValue( wfCatalog:docStore():docValue( 12 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ),
		nil )

		-- retry original id 4
		dls:expectData( kIdleDownloaderId, 4 + localIdOffset, false, kAnyOtherError )

		rxTest:observe( wfCatalog:docStore():ongoingDocValue( 4 + localIdOffset )
		:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ) )
		:expectDataWithinTime( .5, true )
		:dispose()

		-- retry proxy id 12
		dls:expectData( kIdleDownloaderId, 12 + localIdOffset, false, kAnyOtherError )
		rxTest:observe( wfCatalog:docStore():ongoingDocValue( 12 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ) )
		:expectDataWithinTime( .5, true )
		:dispose()

		rxTest:expectEqual( 4, downloadFailCount )


		-- Now try again, but this time make the error permanent

		setBadDownloaderError( kSendPermanentError )

		-- The 2 second failedDownloadBlackoutWindowInSeconds will expire
		-- and deniedBy should be removed so the upload will be tried again below.
		rxTest:observe( wfCatalog:docStore():ongoingDocValue( 4 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ) )
		:expectDataWithinTime( 5, nil )
		:dispose()

		-- Make sure we can try again right away.
		wfCatIdleDownloader:clearRecentlyDownloadedStatus( 4 + localIdOffset, 'original' )
		wfCatIdleDownloader:clearRecentlyDownloadedStatus( 12 + localIdOffset, 'proxy' )

		-- original for id 4
		dls:expectData( kIdleDownloaderId, 4 + localIdOffset, false, kSendPermanentError )
		rxTest:expectSingleValue( wfCatalog:docStore():docValue( 4 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ),
		nil )

		if not runWithVideos then
			-- proxy id 12
			dls:expectData( kIdleDownloaderId, 12 + localIdOffset, false, kSendPermanentError )
			rxTest:expectSingleValue( wfCatalog:docStore():docValue( 12 + localIdOffset )
				:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ),
			nil )
        end

		-- retry original id 4
		dls:expectData( kIdleDownloaderId, 4 + localIdOffset, false, kSendPermanentError )

		rxTest:observe( wfCatalog:docStore():ongoingDocValue( 4 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ) )
		:expectDataWithinTime( .5, true )
		:dispose()

		-- It should now have a permanent download error marked in _localOnly.binaryDownloadErrors.
		rxTest:observe( wfCatalog:docStore():ongoingDocValue( 4 + localIdOffset )
			:pluck( '_localOnly', 'binaryDownloadErrors', '/rels/master', '/master/href/bogus/testing' ) )
		:expectDataWithinTime( .5, true )
		:dispose()

		if runWithVideos then
			rxTest:expectEqual( 2, downloadFailCount )
		else
			-- retry proxy id 12
			dls:expectData( kIdleDownloaderId, 12 + localIdOffset, false, kSendPermanentError )
			rxTest:observe( wfCatalog:docStore():ongoingDocValue( 12 + localIdOffset ):pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ) )
			:expectDataWithinTime( .5, true )
			:dispose()

			rxTest:expectEqual( 4, downloadFailCount )
		end


		-- Now try again, but only with the proxy and let it succeed as the original
		-- has been marked with a permanent binaryDownloadErrors.

		setBadDownloaderError( nil )

		-- The 2 second failedDownloadBlackoutWindowInSeconds will expire
		-- and deniedBy should be removed so the upload will be tried again below.

		rxTest:observe( wfCatalog:docStore():ongoingDocValue( 4 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ) )
		:expectDataWithinTime( 5, nil )
		:dispose()

		rxTest:observe( wfCatalog:docStore():ongoingDocValue( 12 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ) )
		:expectDataWithinTime( 5, nil )
		:dispose()

		-- Make sure we can try again right away.
		wfCatIdleDownloader:clearRecentlyDownloadedStatus( 4 + localIdOffset, 'original' )
		wfCatIdleDownloader:clearRecentlyDownloadedStatus( 12 + localIdOffset, 'proxy' )

		-- Idle downloader no longer sees there is a /rels/master link so it will attempt to
		-- download the proxy instead.

		-- proxy id 4
		dls:expectData( kIdleDownloaderId, 4 + localIdOffset, true, 'binaryPath', 'proxy' )
		rxTest:expectSingleValue( wfCatalog:docStore():docValue( 4 + localIdOffset )
			:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ),
		nil )

		if not runWithVideos then
			-- proxy id 12
			dls:expectData( kIdleDownloaderId, 12 + localIdOffset, true, 'binaryPath', 'proxy' )
			rxTest:expectSingleValue( wfCatalog:docStore():docValue( 12 + localIdOffset )
				:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ),
			nil )
		end

		rxTest:expectEqual( 0, downloadFailCount )

		wfCatIdleDownloader:stop()

	end

	rxTest:finally( function()
	
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

function WFCatIdleDownloaderTest.rxTestUndenyAssetFromSync_testNightly( rxTest )

	-- This happens when there are more than 100 assets that aren't required
	-- for download but an asset that has deniedBy on it from a prior session
	-- (caused by crash or force quit) has an album that contains it changed
	-- to be stored locally.

	rxTest:setTimeLimit( 30 )

	local keepAllOriginals = false
	local keepAllProxies = false

	local dls = rxTest:observe( downloadStream )

	local optArgs = {
		failedDownloadBlackoutWindowInSeconds = 2,
		debugQueryLimit = 1,
	}

	local wfCatalog, wfCatIdleDownloader, downloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies, optArgs )

	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )

	local markedForOfflineDeniedInPriorSession = true
	addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, 'image', nil, markedForOfflineDeniedInPriorSession )

	wfCatIdleDownloader:start()

	-- proxy id 12
	dls:expectData( true, 12, true, 'proxy' )

	rxTest:expectSingleValue( wfCatalog:docStore():docValue( 12 )
		:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ),
	nil )

	-- original id 4
	dls:expectData( true, 4, true, 'original' )

	-- proxy id 4
	dls:expectData( true, 4, true, 'proxy' )

	rxTest:expectSingleValue( wfCatalog:docStore():docValue( 4 )
		:pluck( '_localOnly', 'deniedBy', 'WFCatIdleDownloader' ),
	nil )


	rxTest:expectEqual( 3, downloader.getCount() )

	wfCatIdleDownloader:stop()

	rxTest:finally( function()

		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

function WFCatIdleDownloaderTest.rxTestIgnoreAssetsFromInaccessibleSpaces( rxTest )

	local keepAllOriginals = true
	local keepAllProxies = false

	local wfCatalog, wfCatIdleDownloader = setupDownloader( rxTest, keepAllOriginals, keepAllProxies )

	local volumeStatuses = {
		original = {},
		proxy = {},
		xmp_develop = {}
	}

	-- Make sure the query fires with nothing to download.

	rxTest:expectSingleValue( 
			wfCatIdleDownloader:_DEBUG_buildDownloadQuery( volumeStatuses ):take( 1 ),
			{} )

	-- Add an asset that needs a download.

	local assetId = KSIdGenerator.uuidInLowercaseHex()

	local optArgs = {
		noLocalOriginal = true
	}

	local spaceId = KSIdGenerator.uuidInLowercaseHex()

	local assetDocValue = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, assetId, optArgs )
	assetDocValue._spaceId = spaceId

	rxTest:waitFor( wfCatalog:docStore():setDocValue( assetDocValue ) )

	-- Create a space whose owner has a valid subscription

	local spaceDocValue = {
		type = 'space',
		_id = spaceId,
		subtype = 'shared',
		private = false,
		download = false,
		updated = '2012-08-15T15:22:29',
		created = '2012-08-15T15:22:29',
	}

	rxTest:waitFor( wfCatalog:docStore():setDocValue( spaceDocValue ) )

	-- There should be one binary to download.

	rxTest:expectSingleValue(
			wfCatIdleDownloader:_DEBUG_buildDownloadQuery( volumeStatuses )
				:take( 1 )
				:map( function( candidates )
					return #candidates
				end ),
			1 )

	-- Now, make the space inaccessible.

	local spaceOverlay = {
		_id = spaceId,
	}

	KSTableUtils.setNested( spaceOverlay, true, '_serverProvidedMetadata', 'owner', 'entitlementExpired' )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay( spaceOverlay ) )

	-- Make sure the query fires with nothing to download.

	rxTest:expectSingleValue(
			wfCatIdleDownloader:_DEBUG_buildDownloadQuery( volumeStatuses ):take( 1 ),
			{} )

end

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

function WFCatIdleDownloaderTest.DISABLED_rxTestManaged_testPerformance( rxTest )

	rxTest:setTimeLimit( 1000 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	local downloadCount = 0
	
	local revDownloadCount = function()
		downloadCount = downloadCount + 1
	end
	
	local downloader = createDownloader( rxTest, wfCatalog:docStore(), revDownloadCount )
	
	local cancelFunc = function() --[[noop]] end
	
	local keepAllOriginals = false
	local keepAllProxies = false
	
	local wfCatIdleDownloader = WFCatIdleDownloader( wfCatalog, downloader, downloadStream, cancelFunc, keepAllOriginals, keepAllProxies )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for _ = 1, 1000 do
		logger:infof( "Adding assets..." )
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, false, false, true )
	end
	
	local dls = rxTest:observe( downloadStream )
	
	wfCatIdleDownloader:start()

	-- Verify we downloaded the proper things

	for i = 1, 1000 do
		local offset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 4 + offset, true, 'original' ) 
	end
	
	for i = 1, 1000 do
		local offset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 4 + offset, true, 'proxy' ) 
	end
	
	for i = 1, 1000 do
		local offset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 12 + offset, true, 'proxy' )
	end
	
	for i = 1, 1000 do
		local offset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 1 + offset, true, 'original' )
		dls:expectData( true, 6 + offset, true, 'proxy' )
		dls:expectData( true, 8 + offset, true, 'original' )
	end
	
	for i = 1, 1000 do
		local offset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 3 + offset, true, 'proxy' )
		dls:expectData( true, 7 + offset, true, 'original' )
		dls:expectData( true, 9 + offset, true, 'proxy' )
		dls:expectData( true, 11 + offset, true, 'proxy' )
	end
	
	for i = 1, 1000 do
		local offset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 10 + offset, true, 'proxy' )
	end
	
	rxTest:sleep( 0.1 )
	rxTest:expectEqual( 11000, downloadCount )
		-- Sleep to make sure there are no additional, unexpected downloads.
	
	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

function WFCatIdleDownloaderTest.DISABLED_rxTestKeepAllOriginals_testPerformance( rxTest )

	rxTest:setTimeLimit( 1000 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	
	local downloadCount = 0
	
	local revDownloadCount = function()
		downloadCount = downloadCount + 1
	end
	
	local downloader = createDownloader( rxTest, wfCatalog:docStore(), revDownloadCount )
	
	local cancelFunc = function() --[[noop]] end
	
	local keepAllOriginals = true
	local keepAllProxies = false
	
	local wfCatIdleDownloader = WFCatIdleDownloader( wfCatalog, downloader, downloadStream, cancelFunc, keepAllOriginals, keepAllProxies )
	
	wfCatIdleDownloader:reportStatusOfVolumes( {
		offlineVolumes = {},
		volumesOverIdleSpaceThreshold = {},
		volumesOutOfSpace = {},
		remainingSpace = {}
	} )
	
	for _ = 1, 1000 do
		logger:infof( "Adding assets..." )
		addMixedAssets( rxTest, wfCatalog, wfCatIdleDownloader, false, false, true )
	end
	
	local dls = rxTest:observe( downloadStream )
	
	wfCatIdleDownloader:start()

	-- Wait for everything to download
	
	for i = 1, 1000 do
		local localIdOffset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 4 + localIdOffset, true, 'original' ) 
	end
	
	for i = 1, 1000 do
		local localIdOffset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 4 + localIdOffset, true, 'proxy' ) 
	end
	
	for i = 1, 1000 do
		local localIdOffset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 12 + localIdOffset, true, 'original' )
	end
	
	for i = 1, 1000 do
		local localIdOffset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 1 + localIdOffset, true, 'original' )
		dls:expectData( true, 6 + localIdOffset, true, 'proxy' )
		dls:expectData( true, 8 + localIdOffset, true, 'original' )
	end
	
	for i = 1, 1000 do
		local localIdOffset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 3 + localIdOffset, true, 'original' ) 
		dls:expectData( true, 7 + localIdOffset, true, 'original' ) 
		dls:expectData( true, 9 + localIdOffset, true, 'proxy' )
		dls:expectData( true, 11 + localIdOffset, true, 'original' ) 
	end
	
	for i = 1, 1000 do
		local localIdOffset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 12 + localIdOffset, true, 'proxy' )
	end
	
	for i = 1, 1000 do
		local localIdOffset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 10 + localIdOffset, true, 'proxy' ) 
	end
	
	for i = 1, 1000 do
		local localIdOffset = ( ( i - 1 ) * 13 )
		dls:expectData( true, 3 + localIdOffset, true, 'proxy' ) 
		dls:expectData( true, 11 + localIdOffset, true, 'proxy' ) 
	end

	rxTest:sleep( 0.1 )
	rxTest:expectEqual( 14000, downloadCount )
		-- Sleep to make sure there are no additional, unexpected downloads.

	rxTest:finally( function()
	
		disposeOfDownloadSubscriptions()
		wfCatIdleDownloader:stop()
		wfCatIdleDownloader:close()

	end )

end

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

return WFRxTestCase.wrapSuite( 'WFCatIdleDownloaderTest', WFCatIdleDownloaderTest )
