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

ADOBE CONFIDENTIAL
------------------
Copyright 2015 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.self_test
local WFAsyncTestCase = require 'WFAsyncTestCase'
local WFRxTestCase = require 'WFRxTestCase'
local KSTestUtils = require 'KSTestUtils'

	-- WF.sqlite.doc_store
local WFRxDocStore = require 'WFRxDocStore'

	-- WF.oz_client.doc_store
local OzDocStoreViaWFRxDocStore = require 'OzDocStoreViaWFRxDocStore'

	-- WF.core.utils
local KSIdGenerator = require 'KSIdGenerator'
local KSTableUtils = require 'KSTableUtils'

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

local rxDocStore, docStore

local OzDocStoreViaWFRxDocStoreTest = {}

local randomDocId = '9b572d0e423c4654b078893ddd41c230'

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

local function cleanDocument( docValue )

	-- The tests in this file don't expect `_localId`, `_revId` or `type`
	-- Since these *are* useful, just not in these tests, filter them out

	if type( docValue ) == 'table' then
	
		docValue._localId = nil
		docValue._revId = nil
		docValue.type = nil
	
	end

	return docValue

end

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

function OzDocStoreViaWFRxDocStoreTest.setUp()

	rxDocStore = WFRxDocStore( ':memory:' )
	docStore = OzDocStoreViaWFRxDocStore( rxDocStore )
	
end

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

function OzDocStoreViaWFRxDocStoreTest.tearDown()

	docStore:close()
	
end

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

function OzDocStoreViaWFRxDocStoreTest.rxTestAccessToRxDocStore( rxTest )

	rxTest:expectEqual( docStore:rxDocStore(), rxDocStore )
	
end

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

function OzDocStoreViaWFRxDocStoreTest.testToString( test )

	WFAsyncTestCase( test )

		-- GRUNGE [pkamin 2015-10-11]: Make sure the worker thread for this
		-- doc store spins up fully. This is done solely to prevent getting the
		-- GC close warning. IMHO this is temporary shim code and not a likely
		-- real-world scenario, so punting on a "real" fix here.
	
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', nil )
		
		:waitFor( function()

			local docStoreAsString = tostring( docStore )
			
			assert( type( docStoreAsString ) == 'string' )
			assert( #docStoreAsString > 0 )
		
			return docStoreAsString
		
		end )

end

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

-- @mark localState

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

function OzDocStoreViaWFRxDocStoreTest.testLocalState_boolean( test )

	WFAsyncTestCase( test )
	
		:waitFor( function()
			
			return docStore:setLocalStateP( 'foo', false )
			
		end )
		
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', false )
		
		:waitFor( function()
			
			return docStore:setLocalStateP( 'foo', true )
			
		end )
		
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', true )
		
end

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

function OzDocStoreViaWFRxDocStoreTest.testLocalState_nilByDefault( test )

	WFAsyncTestCase( test )
	
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', nil )
		
end

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

function OzDocStoreViaWFRxDocStoreTest.testLocalState_noCrossPollution( test )

	WFAsyncTestCase( test )
	
		:waitFor( function()
			
			return docStore:setLocalStateP( 'foo', 'bar' )
			
		end )
		
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', 'bar' )
		
		:waitFor( function()
			
			return docStore:setLocalStateP( 'bar', 'foo' )
			
		end )
		
		:waitFor( function()

			return docStore:localStateP( 'bar' )
		
		end )
		:continueWhenValueMatches( 'data', 'foo' )
		
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', 'bar' )
		
end

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

function OzDocStoreViaWFRxDocStoreTest.testLocalState_stringThenNil( test )

	WFAsyncTestCase( test )
	
		:waitFor( function()
			
			return docStore:setLocalStateP( 'foo', 'bar' )
			
		end )
		
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', 'bar' )
		
		:waitFor( function()
			
			return docStore:setLocalStateP( 'foo', nil )
			
		end )
		
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', nil )
		
end

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

function OzDocStoreViaWFRxDocStoreTest.testLocalStateB( test )

       WFAsyncTestCase( test )
	   
	   	:waitFor( function() 
                
			return docStore:localStateB( 'foo' )
               
        end )
               
        :continueWhenValueMatches( {} )
		
end

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

function OzDocStoreViaWFRxDocStoreTest.testLocalState_table( test )

	WFAsyncTestCase( test )
	
		:waitFor( function()
			
			return docStore:setLocalStateP( 'foo', {} )
			
		end )
		
		:waitFor( function()

			return docStore:localStateP( 'foo' )
		
		end )
		:continueWhenValueMatches( 'data', {} )
		
end

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

-- @mark :docValueOnceP

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

function OzDocStoreViaWFRxDocStoreTest.testDocValueOnceP_empty( test )

	local resultFromFirstDocValueCall

	WFAsyncTestCase( test )

		:waitFor( function()	-- step 1
		
			return docStore:docValueOnceP( 'asset', randomDocId )
				:mapDataP( function( _, doc )
				
					resultFromFirstDocValueCall = doc
						-- save this so we can hack on it in a moment
				
				end )
				:mapDataP_new( cleanDocument )
			
		end )
		:continueWhenValueMatches(
			'data',
			{
				_docType = 'asset',
				_docId = randomDocId,
				_deleted = true
			}
		)
		
		:waitFor( .1 )			-- step 2
		
		:waitFor( function()	-- step 3
		
			-- Make some changes to doc. Make sure doc store doesn't
			-- pick them up for next caller.
			
			resultFromFirstDocValueCall.favorite = true
			resultFromFirstDocValueCall.title = "My Nifty Photo"
		
			return docStore:docValueOnceP( 'asset', randomDocId )
		
		end )
		:continueWhenValueMatches(
			'data',
			{
				_docType = 'asset',
				_docId = randomDocId,
				_deleted = true,
				type = 'asset'
			}
		)

end

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

function OzDocStoreViaWFRxDocStoreTest.testDocValueOnceP_separateValuesFails( test )

	KSTestUtils.assertFails( function()

		return docStore:docValueOnceP( 'asset', randomDocId,
										{ separateValues = true } )
		
	end )

end

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

-- @mark :applyOverlayToDocumentP

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

function OzDocStoreViaWFRxDocStoreTest.testApplyOverlayToDocumentP( test )

	WFAsyncTestCase( test )

		:waitFor( function()	-- step 1
			
			return docStore:applyOverlayToDocumentP {
								docType = 'asset',
								docId = randomDocId,
								overlay = {
									favorite = true,
									subtype = 'image',
									title = "My Nifty Photo",
								},
							}
			
		end )
		
		:waitFor( function()	-- step 2
		
			return docStore:docValueOnceP( 'asset', randomDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			 {
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 1,
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image'
			}
		)
	
end

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

-- FIXME [jandrew 3/27/2018]: This test case is unstable.

function OzDocStoreViaWFRxDocStoreTest.DISABLE_testDocValueAfterTwoOverlays( test )

	local nDocIds = 5

	local docIds = {}
	for i = 1, nDocIds do
		docIds[ i ] = KSIdGenerator.uuidInLowercaseHex()
	end
	
	local victimDocId = docIds[ 4 ] -- just choose one at random
	local nonVictimDocId = docIds[ 5 ] -- any other doc

	WFAsyncTestCase( test )
	
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
					docType = 'asset',
					docIds = docIds,
					overlay = {
						favorite = true,
						subtype = 'image',
						title = "My Nifty Photo",
					},
				}
			
		end )
		
		:waitFor( function()

			return docStore:applyOverlayToDocumentP {
					docType = 'asset',
					docIds = victimDocId,
					overlay = {
						bar = 94,
					},
				}
		
		end )
		
		-- Spot check: Make sure we didn't affect any other documents.
		-- (Been there, done that!)
		
		:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', nonVictimDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = nonVictimDocId,
				_changeCounter = 5,
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image'
			}
		)

		-- And, of course, make sure we did affect the desired doc.
		
		:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', victimDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = victimDocId,
				_changeCounter = nDocIds + 1,
				bar = 94,
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image'
			}
		)

end

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

function OzDocStoreViaWFRxDocStoreTest.DISABLED_testDocValueAfterReplace( test )

	-- TODO [scouten 2013-05-21]: Consider implementing top-level _replace
	-- by using WFDocStore:setDocValueP instead of :applyOverlayP?

	WFAsyncTestCase( test )

		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
					docType = 'asset',
					docIds = randomDocId,
					overlay = {
						favorite = true,
						title = "My Nifty Photo",
					},
				}
			
		end )
		
		:waitFor( function()

			return docStore:applyOverlayToDocumentP {
					docType = 'asset',
					docIds = randomDocId,
					overlay = {
						_replace = true,
						bar = 94,
					},
				}
		
		end )
		
		:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', randomDocId )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 2,
				_replace = true,
				bar = 94,
				subtype = 'image',
			}
		)

end

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

-- OzDocStoreViaWFRxDocStoreTest.DISABLED_testDocTypeInvariant_read( test )
-- Disabled because we're not explicitly preserving doc type.

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

-- OzDocStoreViaWFRxDocStoreTest.DISABLED_testDocTypeInvariant_write( test )
-- Disabled because we're not explicitly preserving doc type.

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

-- OzDocStoreViaWFRxDocStoreTest.DISABLED_testDocTypeNotAllowedWhenWriting( test )
-- Disabled because we're not explicitly preserving doc type.

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

function OzDocStoreViaWFRxDocStoreTest.DISABLED_testDeletingDocLeavesLocalState( test )

	-- TODO [scouten 2013-05-20]: _deleted is supported but does not support
	-- the "leave-behind" semantics tested here. Hmmm.

	WFAsyncTestCase( test )

		:waitFor( function()	-- step 1
			
			return docStore:applyOverlayToDocumentP {
								docType = 'asset',
								docId = randomDocId,
								overlay = {
									_localOnly = {
										foo = 'bar',
									},
									favorite = true,
									title = "My Nifty Photo",
								},
							}
			
		end )
		
		:waitFor( function()	-- step 2
		
			return docStore:docValueOnceP( 'asset', randomDocId )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 1,
				_localOnly = {
					foo = 'bar',
				},
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image'
			},
			{
				_localOnly = {
					foo = 'bar',
				},
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image',
			}
		)
	
		:waitFor( function()	-- step 3
			
			return docStore:applyOverlayToDocumentP {
								docType = 'asset',
								docId = randomDocId,
								overlay = {
									_deleted = true,
								},
							}
			
		end )
		
		:waitFor( function()	-- step 4
		
			return docStore:docValueOnceP( 'asset', randomDocId )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 2,
				_localOnly = {
					foo = 'bar',
				},
				_deleted = true,
			},
			{
				_localOnly = {
					foo = 'bar',
				},
				_deleted = true,
			}
		)
	
end

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

function OzDocStoreViaWFRxDocStoreTest.testEmbeddedNullSafety( test )

	-- BLONDE encoding uses a zero byte to encode the number 0. This test
	-- validates that SQLite bridge code doesn't mishandle the Lua string data
	-- containing embedded nulls. (It did at one point ...)

	WFAsyncTestCase( test )

		:waitFor( function()
		
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						subtype = 'image',
						rating = 0,
						title = "My Nifty Photo",
					},
				}
		
		end )
		
		:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', randomDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 1,
				title = "My Nifty Photo",
				rating = 0,
				subtype = 'image',
			} )

end

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

-- FIXME [jandrew 2018-03-28]: This test is unstable on Android ( timeout ).

local WFPlatformInfo = require 'WFPlatformInfo'

if not WFPlatformInfo.isAndroid then

function OzDocStoreViaWFRxDocStoreTest.testDeleteValueFromTable( test )

	WFAsyncTestCase( test )
	
		:waitFor( function()
		
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						favorite = true,
						subtype = 'image',
						title = "My Nifty Photo"
					}
				}
		
		end )
		
		:waitFor( function()
	
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						favorite = { _delete = true },
						rating = 0,
					}
				}
			
		end )
		
		:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', randomDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 2,
				title = "My Nifty Photo",
				rating = 0,
				subtype = 'image',
			} )

end

end

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

function OzDocStoreViaWFRxDocStoreTest.testOverlaySubtable( test )

	WFAsyncTestCase( test )
	
		:waitFor( function()
		
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						stuff = {
							foo = 42,
						},
						title = "My Nifty Photo",
						subtype = 'image'
					},
				}
		end )
			
		:waitFor( function()
		
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						stuff = { bar = 94 },
					},
				}
			
		end )
		
		:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', randomDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 2,
				stuff = {
					foo = 42,
					bar = 94,
				},
				title = "My Nifty Photo",
				subtype = 'image',
			} )

end

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

function OzDocStoreViaWFRxDocStoreTest.testReplaceSubtable( test )

	WFAsyncTestCase( test )

		:waitFor( function()		-- step 1

			return docStore:applyOverlayToDocumentP {
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						stuff = {
							foo = 42,
						},
						title = "My Nifty Photo",
						subtype = 'image'
					}
				}
			
		end )
		
		:waitFor( function()		-- step 2
			
			return docStore:docValueOnceP( 'asset', randomDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_changeCounter = 1,
				_docType = 'asset',
				_docId = randomDocId,
				stuff = {
					foo = 42,
				},
				title = "My Nifty Photo",
				subtype = 'image',
			}
		)
		
		:waitFor( function()		-- step 3

			return docStore:applyOverlayToDocumentP {
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						stuff = { _replace = true, bar = 94 },
					},
				}
			
		end )
		
		:waitFor( function()		-- step 4
			
			return docStore:docValueOnceP( 'asset', randomDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_changeCounter = 2,
				_docType = 'asset',
				_docId = randomDocId,
				stuff = {
					-- _replace = true,
						-- OzDocStore bridge doesn't preserve _replace.
					bar = 94,
				},
				title = "My Nifty Photo",
				subtype = 'image',
			}
		)

end

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

-- OzDocStoreViaWFRxDocStoreTest.DISABLED_testNopChangeDoesntCreateNewRev( test )
-- This test was never implemented in OzDocStore.

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

function OzDocStoreViaWFRxDocStoreTest.testBulkInsert( test )

	local docIds = {}
	for i = 1, 1000 do
		docIds[ i ] = KSIdGenerator.uuidInLowercaseHex()
	end
	
	local victimDocId = docIds[ 4 ] -- just choose one at random

	WFAsyncTestCase( test, 18 )
		-- Yes, this got slower with the bridge.
	
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
					docType = 'asset',
					docIds = docIds,
					overlay = {
						subtype = 'image',
						favorite = true,
						title = "My Nifty Photo",
					}
				}
			
		end )
		
		:waitFor( function()

			return docStore:applyOverlayToDocumentP {
					docType = 'asset',
					docId = victimDocId,
					overlay = {
						bar = 94,
					},
				}
		
		end )
		
		:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', victimDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = victimDocId,
				_changeCounter = #docIds + 1,
				bar = 94,
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image'
			}
		)

end

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

function OzDocStoreViaWFRxDocStoreTest.testBulkInsertOverlays( test )

	local docIds = {}
	local overlays = {}
	
	for i = 1, 3 do
		docIds[ i ] = KSIdGenerator.uuidInLowercaseHex()
	end

	for i = 1, 3 do
		overlays[ i ] = {
			index = i,
			favorite = true,
			subtype = 'image',
			title = "My Nifty Photo",
		}
	end
	
	local case = WFAsyncTestCase( test )
	
		:waitFor( function()
		
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docIds = docIds,
					overlays = overlays,
				}
		
		end )
		
	for i = 1, 3 do
		case:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', docIds[ i ] )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = docIds[ i ],
				_changeCounter = i,
				index = i,
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image'
			} )
	end

end

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

function OzDocStoreViaWFRxDocStoreTest.testBulkInsertAndUpdate( test )

	local docIds = {}
	
	for i = 1, 1000 do
		docIds[ i ] = KSIdGenerator.uuidInLowercaseHex()
	end
	
	local victimDocId = docIds[ 4 ] -- just choose one at random

	WFAsyncTestCase( test, 30 )
	
		:waitFor( function()
		
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docIds = docIds,
					overlay = {
						favorite = true,
						subtype = 'image',
						title = "My Nifty Photo",
					},
				}
		
		end )
		
		:waitFor( function()
		
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docIds = docIds,
					overlay = {
						bar = 94,
					},
				}
			
		end )

		:waitFor( function()
		
			return docStore:docValueOnceP( 'asset', victimDocId )
				:mapDataP_new( cleanDocument )
		
		end )
		:continueWhenValueMatches( 'data',
			{
				_docType = 'asset',
				_docId = victimDocId,
				_changeCounter = 1004,
				bar = 94,
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image'
			} )

end

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

function OzDocStoreViaWFRxDocStoreTest.rxTestDocChangeCounterB( rxTest )

	rxTest:expectError( function()
	
		docStore:docChangeCounterB()
		
	end )
	
end

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

function OzDocStoreViaWFRxDocStoreTest.rxTestChangedDocsP( rxTest )

	rxTest:expectError( function()
	
		docStore:changedDocsP()
		
	end )

end

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

-- OzDocStoreViaWFRxDocStoreTest.DISABLED_testDocValueIdsOnly( test )
-- This test was never written for OzDocStore.

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

function OzDocStoreViaWFRxDocStoreTest.testDocValueB( test )

	local expectedDocValue = {
		_docType = 'asset',
		_docId = randomDocId,
	}
	
	local docValueB = docStore:docValueB( 'asset', randomDocId )
		:closingMapB( function( docValue )
		
			docValue._deleted = nil
			docValue._revId = nil
			docValue._localId = nil
			
			return docValue
			
		end )
	
	WFAsyncTestCase( test )

		:waitFor( docValueB )
		:continueWhenValueMatches( expectedDocValue )
		
		:waitFor( function()
		
			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						favorite = true,
						subtype = 'image',
						title = "My Nifty Photo",
					},
				}
		
		end )
		
		:waitFor( docValueB )
		:continueWhenValueMatches(
			{
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 1,
				favorite = true,
				title = "My Nifty Photo",
				subtype = 'image',
				type = 'asset',
			} )
		
		:waitFor( function()

			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						rating = 0,
					},
				}

		end )
		
		:waitFor( docValueB )
		:continueWhenValueMatches(
			{
				_docType = 'asset',
				_docId = randomDocId,
				_changeCounter = 2,
				favorite = true,
				title = "My Nifty Photo",
				rating = 0,
				subtype = 'image',
				type = 'asset'
			} )
		
end

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

function OzDocStoreViaWFRxDocStoreTest.testDocValueBehaviorsAreWeaklyHeld( test )

	local WFCloseSupport = require 'WFCloseSupport'

	local docValueBehaviors = KSTableUtils.makeFullyWeak()
	local docValueB = docStore:docValueB( 'asset', randomDocId )
	
	docValueBehaviors[ 1 ] = docValueB


	WFAsyncTestCase( test )
	
		:waitFor( function()

			return docStore:applyOverlayToDocumentP
				{
					docType = 'asset',
					docId = randomDocId,
					overlay = {
						favorite = true,
						title = "My Nifty Photo"
					},
				}
			
		end )
		
		:waitFor( function()
			
			assert( docValueBehaviors[ 1 ] == docValueB,
					"docValueB disappeared already ?!?" )
			
			assert( not WFCloseSupport.hasBeenOrWillBeClosed( docValueB ),
					"docValueB has already been closed ?!?" )

			return true
			
		end )
		
		:waitFor( function()

			docValueB = nil
			collectgarbage()
			collectgarbage()
			collectgarbage()
			
			return true
		
		end )
		
		:waitFor( function()
		
			return tostring( docValueBehaviors[ 1 ] )
		
		end )
		:continueWhenValueMatches( 'data', 'nil' )

end

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

function OzDocStoreViaWFRxDocStoreTest.testFieldValueB( test )

	local fieldValueB = docStore:fieldValueB( 'asset', randomDocId, 'rating' )
	
	WFAsyncTestCase( test )
	
		:waitFor( fieldValueB )		-- step 1
		:continueWhenValueMatches( nil )
		
		:waitFor( function()		-- step 2
		
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = randomDocId,
				overlay = {
					rating = 2,
					title = "My Nifty Photo",
				},
			}

		end )
	
		:waitFor( fieldValueB )		-- step 3
		:continueWhenValueMatches( 2 )
		
		:waitFor( function()		-- step 4
		
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = randomDocId,
				overlay = {
					rating = 0,
				},
			}

		end )
	
		:waitFor( fieldValueB )		-- step 5
		:continueWhenValueMatches( 0 )
		
end

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

-- OzDocStoreViaWFRxDocStoreTest.DISABLED_testFieldValueBSilentWhenDifferentFieldChanges( test )
-- This test was never written for OzDocStore.

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

function OzDocStoreViaWFRxDocStoreTest.testNestedFieldValueB( test )

	local fieldValueB = docStore:fieldValueB( 'asset', randomDocId, 'foo/1/rating' )
	
	WFAsyncTestCase( test )
	
		:waitFor( fieldValueB )		-- step 1
		:continueWhenValueMatches( nil )
		
		:waitFor( function()		-- step 2
		
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = randomDocId,
				overlay = {
					foo = {
						{
							rating = 2
						}
					},
					title = "My Nifty Photo",
				},
			}
		
		end )
		
		:waitFor( fieldValueB )		-- step 3
		:continueWhenValueMatches( 2 )
		
		:waitFor( function()		-- step 4
		
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = randomDocId,
				overlay = {
					foo = { _delete = true },
				},
			}
			
		end )
		
		:waitFor( fieldValueB )		-- step 5
		:continueWhenValueMatches( nil )
		
		:waitFor( function()		-- step 6

			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = randomDocId,
				overlay = {
					foo = {
						{
							rating = 4
						}
					}
				},
			}
		
		end )

		:waitFor( fieldValueB )		-- step 7
		:continueWhenValueMatches( 4 )
		
end

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

return WFRxTestCase.wrapSuite( OzDocStoreViaWFRxDocStoreTest )