text: dojo.provide("tests.data.ItemFileWriteStore");
  dojo.require("tests.data.readOnlyItemFileTestTemplates");
  
  dojo.require("dojo.data.ItemFileWriteStore");
  dojo.require("dojo.data.api.Read");
  dojo.require("dojo.data.api.Identity");
  dojo.require("dojo.data.api.Write");
  dojo.require("dojo.data.api.Notification");
  
  
  // First, make sure ItemFileWriteStore can still pass all the same unit tests 
  // that we use for its superclass, ItemFileReadStore:
  tests.data.readOnlyItemFileTestTemplates.registerTestsForDatastore("dojo.data.ItemFileWriteStore");
  
  tests.data.ItemFileWriteStore.getTestData = function(name){
  	var data = {};
  	if(name === "reference_integrity"){
  		if(dojo.isBrowser){
  			data = {url: dojo.moduleUrl("tests", "data/reference_integrity.json").toString() };
  		}else{
  			data = 
  				{ data: { 
  					"identifier": "id",
  					"label": "name",
  					"items": [
  						{"id": 1, "name": "Item 1"},
  						{"id": 2, "name": "Item 2"},
  						{"id": 3, "name": "Item 3"},
  						{"id": 4, "name": "Item 4"},
  						{"id": 5, "name": "Item 5"},
  						{"id": 6, "name": "Item 6"},
  						{"id": 7, "name": "Item 7"},
  						{"id": 8, "name": "Item 8"},
  						{"id": 9, "name": "Item 9"},
  						{"id": 10, "name": "Item 10", "friends": [{"_reference": 1},{"_reference": 3},{"_reference": 5}]},
  						{"id": 11, "name": "Item 11", "friends": [{"_reference": 10}], "siblings": [{"_reference": 10}]},
  						{"id": 12, "name": "Item 12", "friends": [{"_reference": 3},{"_reference": 7}], "enemies": [{"_reference": 10}]},
  						{"id": 13, "name": "Item 13", "friends": [{"_reference": 10}]},
  						{"id": 14, "name": "Item 14", "friends": [{"_reference": 11}]},
  						{"id": 15, "name": "item 15", "friends": [{"id": 16, "name": "Item 16"}]}
  					]
  				}
  			};
  		}
  	}
  	return data;
  };
  
  
  // Now run some tests that are specific to the write-access features:
  doh.register("tests.data.ItemFileWriteStore", 
  	[
  		function test_getFeatures(){
  			//	summary: 
  			//		Simple test of the getFeatures function of the store
  			//	description:
  			//		Simple test of the getFeatures function of the store
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var features = store.getFeatures(); 
  
  			// make sure we have the expected features:
  			doh.assertTrue(features["dojo.data.api.Read"] !== null);
  			doh.assertTrue(features["dojo.data.api.Identity"] !== null);
  			doh.assertTrue(features["dojo.data.api.Write"] !== null);
  			doh.assertTrue(features["dojo.data.api.Notification"] !== null);
  			doh.assertFalse(features["iggy"]);
  			
  			// and only the expected features:
  			var count = 0;
  			for(var i in features){
  				doh.assertTrue((i === "dojo.data.api.Read" || 
  					i === "dojo.data.api.Identity" || 
  					i === "dojo.data.api.Write" || 
  					i === "dojo.data.api.Notification"));
  				count++;
  			}
  			doh.assertEqual(count, 4);
  		},
  		function testWriteAPI_setValue(){
  			//	summary: 
  			//		Simple test of the setValue API
  			//	description:
  			//		Simple test of the setValue API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			var onComplete = function(items, request){
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "capital", "Cairo"));
  				
  				// FIXME:  
  				//    Okay, so this seems very odd.  Maybe I'm just being dense.
  				//    These tests works:
  				doh.assertEqual(store.isDirty(item), false);
  				doh.assertTrue(store.isDirty(item) === false);
  				//    But these seemingly equivalent tests will not work:
  				// doh.assertFalse(store.isDirty(item));
  				// doh.assertTrue(!(store.isDirty(item)));
  				//   
  				//    All of which seems especially weird, given that this *does* work:
  				doh.assertFalse(store.isDirty());
  				
  				doh.assertTrue(store.isDirty(item) === false);
  				doh.assertTrue(!store.isDirty());
  				store.setValue(item, "capital", "New Cairo");
  				doh.assertTrue(store.isDirty(item));
  				doh.assertTrue(store.isDirty());
  				doh.assertEqual(store.getValue(item, "capital").toString(), "New Cairo");
  				deferred.callback(true);
  			};
  			var onError = function(error, request){
  				deferred.errback(error);
  			};
  			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_setValues(){
  			//	summary: 
  			//		Simple test of the setValues API
  			//	description:
  			//		Simple test of the setValues API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			function onComplete(items, request){
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
  				doh.assertTrue(store.isDirty(item) === false);
  				doh.assertTrue(!store.isDirty());
  				store.setValues(item, "name", ["Egypt 1", "Egypt 2"]);
  				doh.assertTrue(store.isDirty(item));
  				doh.assertTrue(store.isDirty());
  				var values = store.getValues(item, "name");
  				doh.assertTrue(values[0] == "Egypt 1");
  				doh.assertTrue(values[1] == "Egypt 2");
  				deferred.callback(true);
  			}
  			function onError(error, request){
  				deferred.errback(error);
  			}
  			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_unsetAttribute(){
  			//	summary: 
  			//		Simple test of the unsetAttribute API
  			//	description:
  			//		Simple test of the unsetAttribute API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			function onComplete(items, request) {
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
  				doh.assertTrue(store.isDirty(item) === false);
  				doh.assertTrue(!store.isDirty());
  				store.unsetAttribute(item, "name");
  				doh.assertTrue(store.isDirty(item));
  				doh.assertTrue(store.isDirty());
  				doh.assertTrue(!store.hasAttribute(item, "name"));
  				deferred.callback(true);
  			}
  			function onError(error, request) {
  				deferred.errback(error);
  			}
  			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_newItem(){
  			//	summary: 
  			//		Simple test of the newItem API
  			//	description:
  			//		Simple test of the newItem API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			doh.assertTrue(!store.isDirty());
  
  			var onNewInvoked = false;
  			store.onNew = function(newItem, parentInfo){
  
  				doh.assertTrue(newItem !== null);
  				doh.assertTrue(parentInfo === null);
  				doh.assertTrue(store.isItem(newItem));
  				onNewInvoked = true;
  			};
  			var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
  			doh.assertTrue(onNewInvoked);
  			
  			doh.assertTrue(store.isDirty(canada));
  			doh.assertTrue(store.isDirty());
  			doh.assertTrue(store.getValues(canada, "name") == "Canada");
  			function onComplete(items, request){
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "name", "Canada"));
  				deferred.callback(true);
  			}
  			function onError(error, request){
  				deferred.errback(error);
  			}
  			store.fetch({query:{name:"Canada"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_newItem_withParent(){
  			//	summary: 
  			//		Simple test of the newItem API with a parent assignment
  			//	description:
  			//		Simple test of the newItem API with a parent assignment
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			doh.assertTrue(!store.isDirty());
  
  			var onError = function(error, request){
  				deferred.errback(error);
  			};
  
  			var onComplete = function(items, request){
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
  
  				//Attach an onNew to validate we get expected values.
  				var onNewInvoked = false;
  				store.onNew = function(newItem, parentInfo){
  					doh.assertEqual(item, parentInfo.item);
  					doh.assertEqual("cities", parentInfo.attribute);
  					doh.assertTrue(parentInfo.oldValue === undefined);
  					doh.assertTrue(parentInfo.newValue === newItem);
  					onNewInvoked = true;
  				};
  
  				//Attach an onSet and verify onSet is NOT called in this case.
  				store.onSet = function(item, attribute, oldValue, newValue){
  					doh.assertTrue(false);
  				};
  
  
  
  				//See if we can add in a new item representing the city of Cairo.
  				//This should also call the onNew set above....
  				var newItem = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
  				doh.assertTrue(onNewInvoked);
  
  				function onCompleteNewItemShallow(items, request){
  					doh.assertEqual(0, items.length);
  					function onCompleteNewItemDeep(items, request){
  						doh.assertEqual(1, items.length);
  						var item = items[0];
  						doh.assertEqual("Cairo", store.getValue(item, "name"));
  						deferred.callback(true);
  					}
  					//Do a deep search now, should find the new item of the city with name attribute Cairo.
  					store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemDeep, onError: onError, queryOptions: {deep:true}});
  				}
  				//Do a shallow search first, should find nothing.
  				store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemShallow, onError: onError});
  			};
  			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  		
  		function testWriteAPI_newItem_multiple_withParent(){
  			//	summary: 
  			//		Simple test of the newItem API with a parent assignment multiple times.
  			//	description:
  			//		Simple test of the newItem API with a parent assignment multiple times.
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			
  			doh.assertTrue(!store.isDirty());
  			
  			function onComplete(items, request){
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
  
  				//Attach an onNew to validate we get expected values.
  				store.onNew = function(newItem, parentInfo){
  					doh.assertEqual(item, parentInfo.item);
  					doh.assertEqual("cities", parentInfo.attribute);
  					
  					doh.assertTrue(parentInfo.oldValue === undefined);
  					
  					doh.assertTrue(parentInfo.newValue === newItem);
  				};
  
  				//See if we can add in a new item representing the city of Cairo.
  				//This should also call the onNew set above....
  				var newItem1 = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
  				
  				//Attach a new onNew to validate we get expected values.
  				store.onNew = function(newItem, parentInfo){
  					doh.assertEqual(item, parentInfo.item);
  					doh.assertEqual("cities", parentInfo.attribute);
  					
  					console.log(parentInfo.oldValue);
  					doh.assertTrue(parentInfo.oldValue == newItem1);
  					
  					doh.assertTrue(parentInfo.newValue[0] == newItem1);
  					doh.assertTrue(parentInfo.newValue[1] == newItem);
  				};
  				var newItem2 = store.newItem({name: "Banha", abbr: "Banha"}, {parent: item, attribute: "cities"});
  				
  				//Attach a new onNew to validate we get expected values.
  				store.onNew = function(newItem, parentInfo){
  					doh.assertEqual(item, parentInfo.item);
  					doh.assertEqual("cities", parentInfo.attribute);
  					
  					doh.assertTrue(parentInfo.oldValue[0] == newItem1);
  					doh.assertTrue(parentInfo.oldValue[1] == newItem2);
  					
  					doh.assertTrue(parentInfo.newValue[0] == newItem1);
  					doh.assertTrue(parentInfo.newValue[1] == newItem2);
  					doh.assertTrue(parentInfo.newValue[2] == newItem);
  				};
  				var newItem3 = store.newItem({name: "Damanhur", abbr: "Damanhur"}, {parent: item, attribute: "cities"});
  				deferred.callback(true);
  			}
  			function onError(error, request){
  				deferred.errback(error);
  			}
  			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  
  		function testWriteAPI_deleteItem(){
  			//	summary: 
  			//		Simple test of the deleteItem API
  			//	description:
  			//		Simple test of the deleteItem API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  
  			var onError = function(error, request){
  				deferred.errback(error);
  			};
  
  			var onComplete = function(items, request){
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
  				doh.assertTrue(store.isDirty(item) === false);
  				doh.assertTrue(!store.isDirty());
  				store.deleteItem(item);
  				doh.assertTrue(store.isDirty(item));
  				doh.assertTrue(store.isDirty());
  				var onCompleteToo = function(itemsToo, requestToo) {
  					doh.assertEqual(0, itemsToo.length);
  					deferred.callback(true);
  				};
  				store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
  			};
  			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_isDirty(){
  			//	summary: 
  			//		Simple test of the isDirty API
  			//	description:
  			//		Simple test of the isDirty API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			function onComplete(items, request) {
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
  				store.setValue(item, "name", "Egypt 2");
  				doh.assertTrue(store.getValue(item, "name") == "Egypt 2");
  				doh.assertTrue(store.isDirty(item));
  				deferred.callback(true);
  			}
  			function onError(error, request) {
  				deferred.errback(error);
  			}
  			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_revert(){
  			//	summary: 
  			//		Simple test of the revert API
  			//	description:
  			//		Simple test of the revert API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  
  			var onError = function(error, request){
  				deferred.errback(error);
  			};
  
  			var onComplete = function(items, request) {
  				doh.assertEqual(1, items.length);
  				var item = items[0];
  				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
  				doh.assertTrue(store.isDirty(item) === false);
  				doh.assertTrue(!store.isDirty());
  				store.setValue(item, "name", "Egypt 2");
  				doh.assertTrue(store.getValue(item, "name") == "Egypt 2");
  				doh.assertTrue(store.isDirty(item));
  				doh.assertTrue(store.isDirty());
  				store.revert();
  				
  				//Fetch again to see if it reset the state.
  				var onCompleteToo = function(itemsToo, requestToo){
  					doh.assertEqual(1, itemsToo.length);
  					var itemToo = itemsToo[0];
  					doh.assertTrue(store.containsValue(itemToo, "name", "Egypt"));
  					deferred.callback(true);
  				};
  				store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
  			};
  			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_save(){
  			//	summary: 
  			//		Simple test of the save API
  			//	description:
  			//		Simple test of the save API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			function onError(error){
  				deferred.errback(error);
  			}
  			function onItem(item){
  				store.setValue(item, "capital", "New Cairo");
  				function onComplete() {
  					deferred.callback(true);
  				}
  				store.save({onComplete:onComplete, onError:onError});
  			}
  			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_saveVerifyState(){
  			//	summary: 
  			//		Simple test of the save API
  			//	description:
  			//		Simple test of the save API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			function onError(error){
  				deferred.errback(error);
  			}
  			function onItem(item){
  				store.setValue(item, "capital", "New Cairo");
  				function onComplete() {
  					//Check internal state.  Note:  Users should NOT do this, this is a UT verification
  					//of internals in this case.  Ref tracker: #4394
  					doh.assertTrue(!store._saveInProgress);
  					deferred.callback(true);
  				}
  				store.save({onComplete:onComplete, onError:onError});
  			}
  			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_saveEverything(){
  			//	summary: 
  			//		Simple test of the save API
  			//	description:
  			//		Simple test of the save API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  			var egypt;
  
  			var deferred = new doh.Deferred();
  			var onError = function(error){
  				deferred.errback(error);
  			};
  
  			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
  				var struct = dojo.fromJson(newFileContentString);
  				doh.assertEqual(struct.identifier, store.getIdentityAttributes(egypt)[0]);
  				doh.assertEqual(struct.label, store.getLabelAttributes(egypt)[0]);
  				doh.assertEqual(struct.items.length, 7);
  				
  				var cloneStore = new dojo.data.ItemFileWriteStore({data:struct});
  				var onItemClone = function(itemClone){
  					var egyptClone = itemClone;
  					doh.assertEqual(store.getIdentityAttributes(egypt)[0], cloneStore.getIdentityAttributes(egyptClone)[0]);
  					doh.assertEqual(store.getLabelAttributes(egypt)[0], cloneStore.getLabelAttributes(egyptClone)[0]);
  					doh.assertEqual(store.getValue(egypt, "name"), cloneStore.getValue(egyptClone, "name"));
  				};
  				cloneStore.fetchItemByIdentity({identity:"eg", onItem:onItemClone, onError:onError});
  				saveCompleteCallback();
  			};
  			var onItem = function(item){
  				egypt = item;
  				var onComplete = function() {
  					deferred.callback(true);
  				};
  				store.setValue(egypt, "capital", "New Cairo");
  				store.save({onComplete:onComplete, onError:onError});
  			};
  			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_saveEverything_withDateType(){
  			//	summary: 
  			//		Simple test of the save API	with a non-atomic type (Date) that has a type mapping.
  			//	description:
  			//		Simple test of the save API	with a non-atomic type (Date) that has a type mapping.
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  			
  			var deferred = new doh.Deferred();
  			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
  
  				//Now load the new data into a datastore and validate that it stored the date right.
  				var dataset = dojo.fromJson(newFileContentString);
  				var newStore = new dojo.data.ItemFileWriteStore({data: dataset});
  
  				function gotItem(item){
  					var independenceDate = newStore.getValue(item,"independence"); 
  					doh.assertTrue(independenceDate instanceof Date);
  					doh.assertTrue(dojo.date.compare(new Date(1993,4,24), independenceDate, "date") === 0);
  					saveCompleteCallback();
  				}
  				function failed(error, request){
  					deferred.errback(error);
  					saveFailedCallback();
  				}
  				newStore.fetchItemByIdentity({identity:"eg", onItem:gotItem, onError:failed});
  			};
  
  			var onError = function(error){
  				deferred.errback(error);
  			};
  			var onItem = function(item){
  				var onComplete = function() {
  					deferred.callback(true);
  				};
  				store.setValue(item, "independence", new Date(1993,4,24));
  				store.save({onComplete:onComplete, onError:onError});
  			};
  			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_saveEverything_withCustomColorTypeSimple(){
  			//	summary: 
  			//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
  			//	description:
  			//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
  
  			//Set up the store basics:  What data it has, and what to do when save is called for saveEverything
  			//And how to map the 'Color' type in and out of the format.
  			//(Test of saving all to a some location...)
  			var dataset = {
  				identifier:'name',
  				items: [
  					{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
  					{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
  				]
  			};
  
  			var customTypeMap = {'Color': dojo.Color };
  
  			var store = new dojo.data.ItemFileWriteStore({
  					data:dataset,
  					typeMap: customTypeMap
  			});
  			
  			var deferred = new doh.Deferred();
  			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
  				//Now load the new data into a datastore and validate that it stored the Color right.
  				var dataset = dojo.fromJson(newFileContentString);
  				var newStore = new dojo.data.ItemFileWriteStore({data: dataset, typeMap: customTypeMap});
  
  				var deferred = new doh.Deferred();
  				function gotItem(item){
  					var hairColor = newStore.getValue(item,"hairColor"); 
  					doh.assertTrue(hairColor instanceof dojo.Color);
  					doh.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
  					saveCompleteCallback();
  				}
  				function failed(error, request){
  					deferred.errback(error);
  					saveFailedCallback();
  				}
  				newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
  			};
  
  			//Add a new item with a color type, then save it.
              var onError = function(error){
  				deferred.errback(error);
  			};
  			var onComplete = function() {
  				deferred.callback(true);
  			};
  
  			var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
  			store.save({onComplete:onComplete, onError:onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_saveEverything_withCustomColorTypeGeneral(){
  			//	summary: 
  			//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
  			//	description:
  			//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
  
  			//Set up the store basics:  What data it has, and what to do when save is called for saveEverything
  			//And how to map the 'Color' type in and out of the format.
  			//(Test of saving all to a some location...)
  			var dataset = {
  				identifier:'name',
  				items: [
  					{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
  					{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
  				]
  			};
  
  			var customTypeMap = {'Color': 	{	
  												type: dojo.Color,
  												deserialize: function(value){
  													return new dojo.Color(value);
  												},
  												serialize: function(obj){
  													return obj.toString();
  												}
  											}
  								};
  			var store = new dojo.data.ItemFileWriteStore({
  					data:dataset,
  					typeMap: customTypeMap
  			});
  			
  			var deferred = new doh.Deferred();
  			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
  				//Now load the new data into a datastore and validate that it stored the Color right.
  				var dataset = dojo.fromJson(newFileContentString);
  				var newStore = new dojo.data.ItemFileWriteStore({data: dataset, typeMap: customTypeMap});
  
  				var gotItem = function(item){
  					var hairColor = newStore.getValue(item,"hairColor"); 
  					doh.assertTrue(hairColor instanceof dojo.Color);
  					doh.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
  					saveCompleteCallback();
  				};
  				var failed = function(error, request){
  					deferred.errback(error);
  					saveFailedCallback();
  				};
  				newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
  			};
  
  			//Add a new item with a color type, then save it.
              var onError = function(error){
  				deferred.errback(error);
  			};
  			var onComplete = function() {
  				deferred.callback(true);
  			};
  
  			var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
  			store.save({onComplete:onComplete, onError:onError});
  			return deferred; //Object
  		},
  		function testWriteAPI_newItem_revert(){
  			//	summary: 
  			//		Test for bug #5357.  Ensure that the revert properly nulls the identity position
  			//      for a new item after revert.
  			var args = {data: {
  				label:"name",
  				items:[
  					{name:'Ecuador', capital:'Quito'},
  					{name:'Egypt', capital:'Cairo'},
  					{name:'El Salvador', capital:'San Salvador'},
  					{name:'Equatorial Guinea', capital:'Malabo'},
  					{name:'Eritrea', capital:'Asmara'},
  					{name:'Estonia', capital:'Tallinn'},
  					{name:'Ethiopia', capital:'Addis Ababa'}
  				]
  			} }; 
  			var store = new dojo.data.ItemFileWriteStore(args);
  
  			var newCountry = store.newItem({name: "Utopia", capitol: "Perfect"});
  
  			//DO NOT ACCESS THIS WAY.  THESE ARE INTERNAL VARIABLES.  DOING THIS FOR TEST PURPOSES.
  			var itemEntryNum = newCountry[store._itemNumPropName];
  			doh.assertTrue(store._arrayOfAllItems[itemEntryNum] === newCountry);
  			store.revert();
  			doh.assertTrue(store._arrayOfAllItems[itemEntryNum] === null);
  		},
  		function testNotificationAPI_onSet(){
  			//	summary: 
  			//		Simple test of the onSet API
  			//	description:
  			//		Simple test of the onSet API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			function onError(error){
  				deferred.errback(error);
  			}
  			function onItem(fetchedItem){
  				var egypt = fetchedItem;
  				var connectHandle = null;
  				function setValueHandler(item, attribute, oldValue, newValue){
  					doh.assertTrue(store.isItem(item));
  					doh.assertTrue(item == egypt);
  					doh.assertTrue(attribute == "capital");
  					doh.assertTrue(oldValue == "Cairo");
  					doh.assertTrue(newValue == "New Cairo");
  					deferred.callback(true);
  					dojo.disconnect(connectHandle);
  				}
  				connectHandle = dojo.connect(store, "onSet", setValueHandler);
  				store.setValue(egypt, "capital", "New Cairo");
  			}
  			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
  		},
  		function testNotificationAPI_onNew(){
  			//	summary: 
  			//		Simple test of the onNew API
  			//	description:
  			//		Simple test of the onNew API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			var connectHandle = null;
  			function newItemHandler(item){
  				doh.assertTrue(store.isItem(item));
  				doh.assertTrue(store.getValue(item, "name") == "Canada");
  				deferred.callback(true);
  				dojo.disconnect(connectHandle);
  			}
  			connectHandle = dojo.connect(store, "onNew", newItemHandler);
  			var canada = store.newItem({name:"Canada", abbr:"ca", capital:"Ottawa"});
  		},
  		function testNotificationAPI_onDelete(){
  			//	summary: 
  			//		Simple test of the onDelete API
  			//	description:
  			//		Simple test of the onDelete API
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  
  			var deferred = new doh.Deferred();
  			function onError(error){
  				deferred.errback(error);
  			}
  			function onItem(fetchedItem){
  				var egypt = fetchedItem;
  				var connectHandle = null;
  				function deleteItemHandler(item){
  					doh.assertTrue(store.isItem(item) === false);
  					doh.assertTrue(item == egypt);
  					deferred.callback(true);
  					dojo.disconnect(connectHandle);
  				}
  				connectHandle = dojo.connect(store, "onDelete", deleteItemHandler);
  				store.deleteItem(egypt);
  			}
  			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
  		},
  		function testReadAPI_functionConformanceToo(){
  			//	summary: 
  			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
  			//	description:
  			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
  			var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  			var readApi = new dojo.data.api.Read();
  			var passed = true;
  
  			for(var functionName in readApi){
  				var member = readApi[functionName];
  				//Check that all the 'Read' defined functions exist on the test store.
  				if(typeof member === "function"){
  					var testStoreMember = testStore[functionName];
  					if(!(typeof testStoreMember === "function")){
  						passed = false;
  						break;
  					}
  				}
  			}
  			doh.assertTrue(passed);
  		},
  		function testWriteAPI_functionConformance(){
  			//	summary: 
  			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
  			//	description:
  			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
  			var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  			var writeApi = new dojo.data.api.Write();
  			var passed = true;
  
  			for(var functionName in writeApi){
  				var member = writeApi[functionName];
  				//Check that all the 'Write' defined functions exist on the test store.
  				if(typeof member === "function"){
  					var testStoreMember = testStore[functionName];
  					if(!(typeof testStoreMember === "function")){
  						passed = false;
  						break;
  					}
  				}
  			}
  			doh.assertTrue(passed);
  		},
  		function testNotificationAPI_functionConformance(){
  			//	summary: 
  			//		Simple test Notification API conformance.  Checks to see all declared functions are actual functions on the instances.
  			//	description:
  			//		Simple test Notification API conformance.  Checks to see all declared functions are actual functions on the instances.
  			var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
  			var api = new dojo.data.api.Notification();
  			var passed = true;
  
  			for(var functionName in api){
  				var member = api[functionName];
  				//Check that all the 'Write' defined functions exist on the test store.
  				if(typeof member === "function"){
  					var testStoreMember = testStore[functionName];
  					if(!(typeof testStoreMember === "function")){
  						passed = false;
  						break;
  					}
  				}
  			}
  			doh.assertTrue(passed);
  		},
  		function testIdentityAPI_noIdentifierSpecified(){
  			//	summary: 
  			//		Test for bug #3873. Given a datafile that does not specify an
  			//		identifier, make sure ItemFileWriteStore auto-creates identities 
  			//		that are unique even after calls to deleteItem() and newItem()
  			var args = {data: {
  				label:"name",
  				items:[
  					{name:'Ecuador', capital:'Quito'},
  					{name:'Egypt', capital:'Cairo'},
  					{name:'El Salvador', capital:'San Salvador'},
  					{name:'Equatorial Guinea', capital:'Malabo'},
  					{name:'Eritrea', capital:'Asmara'},
  					{name:'Estonia', capital:'Tallinn'},
  					{name:'Ethiopia', capital:'Addis Ababa'}
  				]
  			} }; 
  			var store = new dojo.data.ItemFileWriteStore(args);
  			var deferred = new doh.Deferred();
  			
  			var onError = function(error, request){
  				deferred.errback(error);
  			};
  			var onComplete = function(items, request){
  				doh.assertEqual(7, items.length);
  				
  				var lastItem = items[(items.length - 1)];
  				var idOfLastItem = store.getIdentity(lastItem);
  				store.deleteItem(lastItem);
  				store.newItem({name:'Canada', capital:'Ottawa'});
  				
  				var onCompleteAgain = function(itemsAgain, requestAgain){
  					doh.assertEqual(7, itemsAgain.length);
  					var identitiesInUse = {};
  					for(var i = 0; i < itemsAgain.length; ++i){
  						var item = itemsAgain[i];
  						var id = store.getIdentity(item);
  						if(identitiesInUse.hasOwnProperty(id)){
  							// there should not already be an entry for this id
  							doh.assertTrue(false);
  						}else{
  							// we want to add the entry now
  							identitiesInUse[id] = item;
  						}
  					}
  					deferred.callback(true);
  				};
  				store.fetch({onComplete:onCompleteAgain, onError:onError});
  			};
  			
  			store.fetch({onComplete:onComplete, onError:onError});
  			return deferred;
  		},
  		function testIdentityAPI_noIdentifierSpecified_revert(){
  			//	summary: 
  			//		Test for bug #4691  Given a datafile that does not specify an
  			//		identifier, make sure ItemFileWriteStore auto-creates identities 
  			//		that are unique even after calls to deleteItem() and newItem()
  			var args = {data: {
  				label:"name",
  				items:[
  					{name:'Ecuador', capital:'Quito'},
  					{name:'Egypt', capital:'Cairo'},
  					{name:'El Salvador', capital:'San Salvador'},
  					{name:'Equatorial Guinea', capital:'Malabo'},
  					{name:'Eritrea', capital:'Asmara'},
  					{name:'Estonia', capital:'Tallinn'},
  					{name:'Ethiopia', capital:'Addis Ababa'}
  				]
  			} }; 
  			var store = new dojo.data.ItemFileWriteStore(args);
  			var deferred = new doh.Deferred();
  			
  			var onError = function(error, request){
  				deferred.errback(error);
  			};
  			var onComplete = function(items, request){
  				doh.assertEqual(7, items.length);
  				
  				var lastItem = items[(items.length - 1)];
  				var idOfLastItem = store.getIdentity(lastItem);
  				store.deleteItem(lastItem);
  				store.newItem({name:'Canada', capital:'Ottawa'});
  				
  				var onCompleteAgain = function(itemsAgain, requestAgain){
  					doh.assertEqual(7, itemsAgain.length);
  					var identitiesInUse = {};
  					for(var i = 0; i < itemsAgain.length; ++i){
  						var item = itemsAgain[i];
  						var id = store.getIdentity(item);
  						if(identitiesInUse.hasOwnProperty(id)){
  							// there should not already be an entry for this id
  							doh.assertTrue(false);
  						}else{
  							// we want to add the entry now
  							identitiesInUse[id] = item;
  						}
  					}
  					//Last test, revert everything and check item sizes.
  					store.revert();
  
  					//Now call fetch again and verify store state.
  					var revertComplete = function(itemsReverted, request){
  						doh.assertEqual(7, itemsReverted.length);
  						deferred.callback(true);
  					};
  					store.fetch({onComplete:revertComplete, onError:onError});
  				};
  				store.fetch({onComplete:onCompleteAgain, onError:onError});
  			};
  			store.fetch({onComplete:onComplete, onError:onError});
  			return deferred;
  		},
  		function testReferenceIntegrity_checkReferences(){
  			//	summary: 
  			//		Simple test to verify the references were properly resolved.
  			//	description:
  			//		Simple test to verify the references were properly resolved.
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
  
  			var deferred = new doh.Deferred();
  			var onError = function(error, request){
  				deferred.errback(error);
  			};
  			var onComplete = function(items, request){
  
  				var item10 = null;
  				var item1  = null;
  				var item3  = null;
  				var item5  = null;
  
  				var i;
  				for (i = 0; i < items.length; i++) {
  					var ident = store.getIdentity(items[i]);
  					if (ident === 10) {
  						item10 = items[i];
  					}else if (ident === 1) {
  						item1 = items[i];
  					}else if (ident === 3) {
  						item3 = items[i];
  					}else if (ident === 5) {
  						item5 = items[i];
  					}
  				}
  				var friends = store.getValues(item10, "friends");
  				doh.assertTrue(friends !== null);
  				doh.assertTrue(friends !== undefined);
  
  				doh.assertTrue(store.isItem(item10));
  				doh.assertTrue(store.isItem(item1));
  				doh.assertTrue(store.isItem(item3));
  				doh.assertTrue(store.isItem(item5));
  				var found = 0;
  				try{
  					for (i = 0; i < friends.length; i++) {
  						if (i === 0) {
  							doh.assertTrue(store.isItem(friends[i]));
  							doh.assertEqual(friends[i], item1);
  							doh.assertEqual(store.getIdentity(friends[i]), 1);
  							found++;
  						}else if (i === 1) {
  							doh.assertTrue(store.isItem(friends[i]));
  							doh.assertEqual(friends[i], item3);
  							doh.assertEqual(store.getIdentity(friends[i]), 3);
  							found++;
  						}else if (i === 2) {
  							doh.assertTrue(store.isItem(friends[i]));
  							doh.assertEqual(friends[i], item5);
  							doh.assertEqual(store.getIdentity(friends[i]), 5);
  							found++;
  						}
  					}
  				}catch(e){
  					doh.errback(e);
  				}
  				doh.assertEqual(3, found);
  				deferred.callback(true);
  			};
  			store.fetch({onError: onError, onComplete: onComplete});
  			return deferred;
  		},
  		function testReferenceIntegrity_deleteReferencedItem(){
  			//	summary: 
  			//		Simple test to verify the references were properly deleted.
  			//	description:
  			//		Simple test to verify the references were properly deleted.
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
  
  			var deferred = new doh.Deferred();
  			var passed = true;
  			function onError(error, request){
  				deferred.errback(error);
  			}
  			function onItem(item, request){
  				try{
  					console.log("Before delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
  					store.deleteItem(item);
  					console.log("After delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
  					function verifyRefDelete(items, request){
  						var passed = true;
  						for(var i = 0; i < items.length; i++){
  							var curItem = items[i];
  							var attributes = store.getAttributes(curItem);
  							for(var j = 0; j < attributes.length; j++){
  								var values = store.getValues(curItem, attributes[j]);
  								var badRef = false;
  								for(var k = 0; k < values.length; k++){
  									var value = values[k];
  									try{
  										var id = store.getIdentity(value);
  										if(id == 10){
  											badRef = true;
  											break;
  										}
  									}catch(e){/*Not an item, even a dead one, just eat it.*/}
  								}
  								if(badRef){
  									deferred.errback(new Error("Found a reference remaining to a deleted item.  Failure."));
  									passed = false;
  									break;
  								}
  							}
  						}
  						if(passed){
  							deferred.callback(true);
  						}
  					}
  					store.fetch({onComplete: verifyRefDelete, onError: onError});
  				}catch(error){
  					deferred.errback(error);
  				}
  			}
  			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
  			return deferred;
  		},
  		function testReferenceIntegrity_deleteReferencedItemThenRevert(){
  			//	summary: 
  			//		Simple test to verify the references were properly deleted.
  			//	description:
  			//		Simple test to verify the references were properly deleted.
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
  
  			var deferred = new doh.Deferred();
  			var passed = true;
  			function onError(error, request){
  				deferred.errback(error);
  			}
  			function onItem(item, request){
  				try{
  					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
  					//THIS IS FOR TESTING INTERNAL STATE!
  					console.log("Map before delete:");
  					store._dumpReferenceMap();
  					var beforeDelete = dojo.toJson(item[store._reverseRefMap]);
  					store.deleteItem(item);
  					console.log("Map after delete:");
  					store._dumpReferenceMap();
  					var afterDelete = dojo.toJson(item[store._reverseRefMap]);
  					store.revert();
  					console.log("Map after revert:");
  					store._dumpReferenceMap();
  					var afterRevert = dojo.toJson(item[store._reverseRefMap]);
  					doh.assertTrue(afterRevert === beforeDelete);
  				}catch(e){
  					deferred.errback(e);
  					passed = false;
  				}
  				if(passed){
  					deferred.callback(true);
  				}
  			}
  			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
  			return deferred;
  		},
  		function testReferenceIntegrity_deleteMultipleItemsWithReferencesAndRevert(){
  			//	summary: 
  			//		Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
  			//		Created for tracker bug: #5743
  			//	description:
  			//		Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
  			//		Created for tracker bug: #5743
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_references"));
  
  			var deferred = new doh.Deferred();
  			var passed = true;
  			function onError(error, request){
  				deferred.errback(error);
  				doh.assertTrue(false);
  			}
  			function onItem(item, request){
  				//Save off the located item, then locate another one (peer to Egypt)
  				doh.assertTrue(store.isItem(item));
  				var egypt = item;
  
  				function onItem2(item, request){
  					doh.assertTrue(store.isItem(item));
  					var nairobi = item;
  
  					//Delete them
  					store.deleteItem(egypt);
  					store.deleteItem(nairobi);
  					try{
  						//Revert, then do a fetch.  If the internals have been damaged, this will generally
  						//cause onError to fire instead of onComplete.
  						store.revert();
  						function onComplete(items, request){
  							deferred.callback(true);
  						}
  						store.fetch({query: {name: "*"}, start: 0, count: 20, onComplete: onComplete, onError: onError});
  					}catch(e){
  						deferred.errback(e);
  					}
  				}
  				store.fetchItemByIdentity({identity: "Nairobi", onError: onError, onItem: onItem2});
  			}
  			store.fetchItemByIdentity({identity: "Egypt", onError: onError, onItem: onItem});
  			return deferred;
  		},
  		function testReferenceIntegrity_removeReferenceFromAttribute(){
  			//	summary: 
  			//		Simple test to verify the reference removal updates the internal map.
  			//	description:
  			//		Simple test to verify the reference removal updates the internal map.
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
  
  			var deferred = new doh.Deferred();
  			var passed = true;
  			function onError(error, request){
  				deferred.errback(error);
  				doh.assertTrue(false);
  			}
  			function onItem(item, request){
  				try{
  					store.setValues(item, "friends", [null]);
  
  					function onItem2(item10, request){
  						//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
  						//THIS IS FOR TESTING INTERNAL STATE!
  						var refMap = item10[store._reverseRefMap];
  						store._dumpReferenceMap();
  
  						console.log("MAP for Item 10 is: " + dojo.toJson(refMap));
  
  						//Assert there is no reference to item 10 in item 11's attribute 'friends'.
  						doh.assertTrue(!refMap["11"]["friends"]);
  						store.setValues(item, "siblings", [0, 1, 2]);
  						//Assert there are no more references to 10 in 11.  Ergo, "11"  should be a 'undefined' attribute for the map of items referencing '10'..
  						doh.assertTrue(!refMap["11"]);
  						deferred.callback(true);
  					}
  					store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem2});
  
  				}catch(e){
  					console.debug(e);
  					deferred.errback(e);
  					doh.assertTrue(false);
  				}
  			}
  			store.fetchItemByIdentity({identity: 11, onError: onError, onItem: onItem});
  			return deferred;
  		},
  		function testReferenceIntegrity_deleteReferencedItemNonParent(){
  			//	summary: 
  			//		Simple test to verify the references to a non-parent item was properly deleted.
  			//	description:
  			//		Simple test to verify the references to a non-parent item was properly deleted.
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
  
  			var deferred = new doh.Deferred();
  			var passed = true;
  			function onError(error, request){
  				deferred.errback(error);
  			}
  			function onItem(item, request){
  				try{
  					console.log("Reference state for item 16 is: " + dojo.toJson(item[store._reverseRefMap]));
  					store.deleteItem(item);
  					function verifyRefDelete(items, request){
  						var passed = true;
  						for(var i = 0; i < items.length; i++){
  							var curItem = items[i];
  							var attributes = store.getAttributes(curItem);
  							for(var j = 0; j < attributes.length; j++){
  								var values = store.getValues(curItem, attributes[j]);
  								var badRef = false;
  								for(var k = 0; k < values.length; k++){
  									var value = values[k];
  									try{
  										var id = store.getIdentity(value);
  										if(id == 16){
  											badRef = true;
  											break;
  										}
  									}catch(e){/*Not an item, even a dead one, just eat it.*/}
  								}
  								if(badRef){
  									deferred.errback(new Error("Found a reference remaining to a deleted item.  Failure."));
  									passed = false;
  									break;
  								}
  							}
  						}
  						if(passed){
  							deferred.callback(true);
  						}
  					}
  					store.fetch({onComplete: verifyRefDelete, onError: onError});
  				}catch(error){
  					deferred.errback(error);
  				}
  			}
  			store.fetchItemByIdentity({identity: 16, onError: onError, onItem: onItem});
  			return deferred;
  		},
  		function testReferenceIntegrity_addReferenceToAttribute(){
  			//	summary: 
  			//		Simple test to verify the reference additions can happen.
  			//	description:
  			//		Simple test to verify the reference additions can happen.
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
  
  			var deferred = new doh.Deferred();
  			var passed = true;
  			function onError(error, request){
  				deferred.errback(error);
  				doh.assertTrue(false);
  			}
  			function onComplete(items, request){
  
  				doh.assertTrue(items.length > 2);
  
  				var item1 = items[0];
  				var item2 = items[1];
  
  				//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
  				//THIS IS FOR TESTING INTERNAL STATE!
  				console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
  				console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
  
  				store.setValue(item1, "siblings", item2);
  
  				//Emit the current map state for inspection.
  				console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
  				console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
  
  				doh.assertTrue(item2[store._reverseRefMap] !== null);
  
  				//Assert there is a recorded reference to item 2 in item 1's attribute 'sibling'.
  				doh.assertTrue(item2[store._reverseRefMap][store.getIdentity(item1)]["siblings"]);
  
  				deferred.callback(true);
  			}
  			store.fetch({onError: onError, onComplete: onComplete});
  			return deferred;
  		},
  		function testReferenceIntegrity_newItemWithParentReference(){
  			//	summary: 
  			//		Simple test to verify that newItems with a parent properly record the parent's reference in the map.
  			//	description:
  			//		Simple test to verify that newItems with a parent properly record the parent's reference in the map.
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
  
  			var deferred = new doh.Deferred();
  			var passed = true;
  			function onError(error, request){
  				deferred.errback(error);
  				doh.assertTrue(false);
  			}
  			function onItem(item, request){
  				try{
  					//Create a new item and set its parent to item 10's uncle attribute.
  					var newItem = store.newItem({id: 17, name: "Item 17"}, {parent: item, attribute: "uncles"}); 
  					
  					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
  					//THIS IS FOR TESTING INTERNAL STATE!
  					//Look up the references to 17, as item 10 has one now on attribute 'uncles'
  					var refs = newItem[store._reverseRefMap];
  
  					//Assert there is a reference from 10 to item 17, on attribute uncle
  					doh.assertTrue(refs["10"]["uncles"]);
  
  					console.log("State of map of item 17 after newItem: " + dojo.toJson(refs));
  				}catch(e){
  					console.debug(e);
  					deferred.errback(e);
  					doh.assertTrue(false);
  					passed = false;
  				}
  				if(passed){
  					deferred.callback(true);
  				}
  			}
  			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
  			return deferred;
  		},
  		function testReferenceIntegrity_newItemWithReferenceToExistingItem(){
  			//	summary: 
  			//		Simple test to verify that a new item with references to existing items properly record the references in the map.
  			//	description:
  			//		Simple test to verify that a new item with references to existing items properly record the references in the map.
  		
  			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
  
  			var deferred = new doh.Deferred();
  			var passed = true;
  			function onError(error, request){
  				deferred.errback(error);
  				doh.assertTrue(false);
  			}
  			function onItem(item, request){
  				try{
  					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
  					//THIS IS FOR TESTING INTERNAL STATE!
  					console.log("State of reference map to item 10 before newItem: " + dojo.toJson(item[store._reverseRefMap]));
  					
  					//Create a new item and set its parent to item 10's uncle attribute.
  					var newItem = store.newItem({id: 17, name: "Item 17", friends: [item]});
  					
  					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
  					//THIS IS FOR TESTING INTERNAL STATE!
  					//Look up the references to 10, as item 17 has one on friends now.
  					var refs = item[store._reverseRefMap];
  					
  					//Assert there is a reference from 15 to item 10, on attribute friends
  					doh.assertTrue(refs["17"]["friends"]);
  
  					console.log("State of reference map to item 10 after newItem: " + dojo.toJson(refs));
  				}catch(e){
  					console.debug(e);
  					deferred.errback(e);
  					doh.assertTrue(false);
  					passed = false;
  				}
  				if(passed){
  					deferred.callback(true);
  				}
  			}
  			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
  			return deferred;
  		},
  		function testReferenceIntegrity_disableReferenceIntegrity(){
  			//	summary: 
  			//		Simple test to verify reference integrity can be disabled.
  			//	description:
  			//		Simple test to verify reference integrity can be disabled.
  		
  			var params = tests.data.ItemFileWriteStore.getTestData("reference_integrity");
  			params.referenceIntegrity = false;
  			var store = new dojo.data.ItemFileWriteStore(params);
  
  			var deferred = new doh.Deferred();
  			function onError(error, request){
  				deferred.errback(error);
  				doh.assertTrue(false);
  			}
  			function onItem(item, request){
  				//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
  				//THIS IS FOR TESTING INTERNAL STATE!
  				if(item[store._reverseRefMap] === undefined){
  					deferred.callback(true);
  				}else{
  					deferred.errback(new Error("Disabling of reference integrity failed."));
  				}
  			}
  			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
  			return deferred;
  		}, 
  		function testReadAPI_close_dirty_failure(){
  			//	summary: 
  			//		Function to test the close api properly clears the store for reload when clearOnClose is set.
  			if (dojo.isBrowser) {
  				var params = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
  				params.clearOnClose = true;
  				params.urlPreventCache = true;
  				var store = new dojo.data.ItemFileWriteStore(params);
  
  				var d = new doh.Deferred();
  				var onItem = function(item){
  					var error = null;
  					try {
  						doh.assertTrue(item !== null);
  						var ec = item;
  						var val = store.getValue(ec, "name");
  						doh.assertEqual("Ecuador", val);
  						var newItem = store.newItem({abbr: "foo", name: "bar"});
  						
  						//Should throw an error...
  						store.close();
  					}catch (e){
  						error = e;
  					}
  					if (error === null) {
  						d.errback(new Error("Store was dirty, should have thrown an error on close!"));
  					}else{
  						d.callback(true);
  					}
  				};
  				var onError = function(errData){
  					d.errback(errData);
  				};
  				store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
  				return d; // Deferred
  			}
  		}
  	]
  );
  
  
  