12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2014 Realm Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- ////////////////////////////////////////////////////////////////////////////
- #import "RLMTestCase.h"
- @implementation DogArrayObject
- @end
- @interface ArrayPropertyTests : RLMTestCase
- @end
- @implementation ArrayPropertyTests
- -(void)testPopulateEmptyArray {
- RLMRealm *realm = [self realmWithTestPath];
- [realm beginWriteTransaction];
- ArrayPropertyObject *array = [ArrayPropertyObject createInRealm:realm withValue:@[@"arrayObject", @[], @[]]];
- XCTAssertNotNil(array.array, @"Should be able to get an empty array");
- XCTAssertEqual(array.array.count, 0U, @"Should start with no array elements");
- StringObject *obj = [[StringObject alloc] init];
- obj.stringCol = @"a";
- [array.array addObject:obj];
- [array.array addObject:[StringObject createInRealm:realm withValue:@[@"b"]]];
- [array.array addObject:obj];
- [realm commitWriteTransaction];
- XCTAssertEqual(array.array.count, 3U, @"Should have three elements in array");
- XCTAssertEqualObjects([array.array[0] stringCol], @"a", @"First element should have property value 'a'");
- XCTAssertEqualObjects([array.array[1] stringCol], @"b", @"Second element should have property value 'b'");
- XCTAssertEqualObjects([array.array[2] stringCol], @"a", @"Third element should have property value 'a'");
- RLMArray *arrayProp = array.array;
- RLMAssertThrowsWithReasonMatching([arrayProp addObject:obj], @"write transaction");
- // make sure we can fast enumerate
- for (RLMObject *obj in array.array) {
- XCTAssertTrue(obj.description.length, @"Object should have description");
- }
- }
- -(void)testModifyDetatchedArray {
- RLMRealm *realm = [self realmWithTestPath];
- [realm beginWriteTransaction];
- ArrayPropertyObject *arObj = [ArrayPropertyObject createInRealm:realm withValue:@[@"arrayObject", @[], @[]]];
- XCTAssertNotNil(arObj.array, @"Should be able to get an empty array");
- XCTAssertEqual(arObj.array.count, 0U, @"Should start with no array elements");
- StringObject *obj = [[StringObject alloc] init];
- obj.stringCol = @"a";
- RLMArray *array = arObj.array;
- [array addObject:obj];
- [array addObject:[StringObject createInRealm:realm withValue:@[@"b"]]];
- [realm commitWriteTransaction];
- XCTAssertEqual(array.count, 2U, @"Should have two elements in array");
- XCTAssertEqualObjects([array[0] stringCol], @"a", @"First element should have property value 'a'");
- XCTAssertEqualObjects([arObj.array[1] stringCol], @"b", @"Second element should have property value 'b'");
- RLMAssertThrowsWithReasonMatching([array addObject:obj], @"write transaction");
- }
- - (void)testDeleteUnmanagedObjectWithArrayProperty {
- ArrayPropertyObject *arObj = [[ArrayPropertyObject alloc] initWithValue:@[@"arrayObject", @[@[@"a"]], @[]]];
- RLMArray *stringArray = arObj.array;
- XCTAssertFalse(stringArray.isInvalidated, @"stringArray should be valid after creation.");
- arObj = nil;
- XCTAssertFalse(stringArray.isInvalidated, @"stringArray should still be valid after parent deletion.");
- }
- - (void)testDeleteObjectWithArrayProperty {
- RLMRealm *realm = [self realmWithTestPath];
- [realm beginWriteTransaction];
- ArrayPropertyObject *arObj = [ArrayPropertyObject createInRealm:realm withValue:@[@"arrayObject", @[@[@"a"]], @[]]];
- RLMArray *stringArray = arObj.array;
- XCTAssertFalse(stringArray.isInvalidated, @"stringArray should be valid after creation.");
- [realm deleteObject:arObj];
- XCTAssertTrue(stringArray.isInvalidated, @"stringArray should be invalid after parent deletion.");
- [realm commitWriteTransaction];
- }
- - (void)testDeleteObjectInArrayProperty {
- RLMRealm *realm = [self realmWithTestPath];
- [realm beginWriteTransaction];
- ArrayPropertyObject *arObj = [ArrayPropertyObject createInRealm:realm withValue:@[@"arrayObject", @[@[@"a"]], @[]]];
- RLMArray *stringArray = arObj.array;
- StringObject *firstObject = stringArray.firstObject;
- [realm deleteObjects:[StringObject allObjectsInRealm:realm]];
- XCTAssertFalse(stringArray.isInvalidated, @"stringArray should be valid after member object deletion.");
- XCTAssertTrue(firstObject.isInvalidated, @"firstObject should be invalid after deletion.");
- XCTAssertEqual(stringArray.count, 0U, @"stringArray.count should be zero after deleting its only member.");
- [realm commitWriteTransaction];
- }
- -(void)testInsertMultiple {
- RLMRealm *realm = [self realmWithTestPath];
- [realm beginWriteTransaction];
- ArrayPropertyObject *obj = [ArrayPropertyObject createInRealm:realm withValue:@[@"arrayObject", @[], @[]]];
- StringObject *child1 = [StringObject createInRealm:realm withValue:@[@"a"]];
- StringObject *child2 = [[StringObject alloc] init];
- child2.stringCol = @"b";
- [obj.array addObjects:@[child2, child1]];
- [realm commitWriteTransaction];
- RLMResults *children = [StringObject allObjectsInRealm:realm];
- XCTAssertEqualObjects([children[0] stringCol], @"a", @"First child should be 'a'");
- XCTAssertEqualObjects([children[1] stringCol], @"b", @"Second child should be 'b'");
- }
- -(void)testInsertAtIndex {
- RLMRealm *realm = [self realmWithTestPath];
- [realm beginWriteTransaction];
- ArrayPropertyObject *obj = [ArrayPropertyObject createInRealm:realm withValue:@[@"arrayObject", @[], @[]]];
- StringObject *child1 = [StringObject createInRealm:realm withValue:@[@"a"]];
- StringObject *child2 = [[StringObject alloc] init];
- child2.stringCol = @"b";
- [obj.array addObject:child2];
- RLMAssertThrowsWithReasonMatching([obj.array insertObject:child1 atIndex:2], @"must be less than 2");
- [realm commitWriteTransaction];
- RLMArray *children = obj.array;
- XCTAssertEqual(children.count, 1U);
- XCTAssertEqualObjects([children[0] stringCol], @"b", @"Only child should be 'b'");
- }
- - (void)testMove {
- RLMRealm *realm = [self realmWithTestPath];
- ArrayPropertyObject *obj = [[ArrayPropertyObject alloc] initWithValue:@[@"arrayObject", @[@[@"a"], @[@"b"]], @[]]];
- RLM_GENERIC_ARRAY(StringObject) *children = obj.array;
- [children moveObjectAtIndex:1 toIndex:0];
- XCTAssertEqualObjects([children[0] stringCol], @"b");
- XCTAssertEqualObjects([children[1] stringCol], @"a");
- [children moveObjectAtIndex:0 toIndex:1];
- XCTAssertEqualObjects([children[0] stringCol], @"a");
- XCTAssertEqualObjects([children[1] stringCol], @"b");
- [children moveObjectAtIndex:0 toIndex:0];
- XCTAssertEqualObjects([children[0] stringCol], @"a");
- XCTAssertEqualObjects([children[1] stringCol], @"b");
- RLMAssertThrowsWithReasonMatching([children moveObjectAtIndex:0 toIndex:2], @"must be less than 2");
- RLMAssertThrowsWithReasonMatching([children moveObjectAtIndex:2 toIndex:0], @"must be less than 2");
- [realm beginWriteTransaction];
- [realm addObject:obj];
- children = obj.array;
- [children moveObjectAtIndex:1 toIndex:0];
- XCTAssertEqualObjects([children[0] stringCol], @"b");
- XCTAssertEqualObjects([children[1] stringCol], @"a");
- [children moveObjectAtIndex:0 toIndex:1];
- XCTAssertEqualObjects([children[0] stringCol], @"a");
- XCTAssertEqualObjects([children[1] stringCol], @"b");
- [children moveObjectAtIndex:0 toIndex:0];
- XCTAssertEqualObjects([children[0] stringCol], @"a");
- XCTAssertEqualObjects([children[1] stringCol], @"b");
- RLMAssertThrowsWithReasonMatching([children moveObjectAtIndex:0 toIndex:2], @"must be less than 2");
- RLMAssertThrowsWithReasonMatching([children moveObjectAtIndex:2 toIndex:0], @"must be less than 2");
- [realm commitWriteTransaction];
- RLMAssertThrowsWithReasonMatching([children moveObjectAtIndex:1 toIndex:0], @"write transaction");
- }
- - (void)testAddInvalidated {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- CompanyObject *company = [CompanyObject createInDefaultRealmWithValue:@[@"company", @[]]];
- EmployeeObject *person = [[EmployeeObject alloc] init];
- person.name = @"Mary";
- [realm addObject:person];
- [realm deleteObjects:[EmployeeObject allObjects]];
- RLMAssertThrowsWithReasonMatching([company.employees addObject:person], @"invalidated");
- RLMAssertThrowsWithReasonMatching([company.employees insertObject:person atIndex:0], @"invalidated");
- [realm cancelWriteTransaction];
- }
- - (void)testAddNil {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- CompanyObject *company = [CompanyObject createInDefaultRealmWithValue:@[@"company", @[]]];
- RLMAssertThrowsWithReason([company.employees addObject:self.nonLiteralNil],
- @"Invalid nil value for array of 'EmployeeObject'.");
- [realm cancelWriteTransaction];
- }
- - (void)testUnmanaged {
- RLMRealm *realm = [self realmWithTestPath];
- ArrayPropertyObject *array = [[ArrayPropertyObject alloc] init];
- array.name = @"name";
- XCTAssertNotNil(array.array, @"RLMArray property should get created on access");
- XCTAssertNil(array.array.firstObject, @"No objects added yet");
- XCTAssertNil(array.array.lastObject, @"No objects added yet");
- StringObject *obj1 = [[StringObject alloc] init];
- obj1.stringCol = @"a";
- StringObject *obj2 = [[StringObject alloc] init];
- obj2.stringCol = @"b";
- StringObject *obj3 = [[StringObject alloc] init];
- obj3.stringCol = @"c";
- [array.array addObject:obj1];
- [array.array addObject:obj2];
- [array.array addObject:obj3];
- XCTAssertEqualObjects(array.array.firstObject, obj1, @"Objects should be equal");
- XCTAssertEqualObjects(array.array.lastObject, obj3, @"Objects should be equal");
- XCTAssertEqualObjects([array.array objectAtIndex:1], obj2, @"Objects should be equal");
- [realm beginWriteTransaction];
- [realm addObject:array];
- [realm commitWriteTransaction];
- XCTAssertEqual(array.array.count, 3U, @"Should have two elements in array");
- XCTAssertEqualObjects([array.array[0] stringCol], @"a", @"First element should have property value 'a'");
- XCTAssertEqualObjects([array.array[1] stringCol], @"b", @"Second element should have property value 'b'");
- [realm beginWriteTransaction];
- [array.array replaceObjectAtIndex:0 withObject:obj3];
- XCTAssertTrue([[array.array objectAtIndex:0] isEqualToObject:obj3], @"Objects should be replaced");
- array.array[0] = obj1;
- XCTAssertTrue([obj1 isEqualToObject:[array.array objectAtIndex:0]], @"Objects should be replaced");
- [array.array removeLastObject];
- XCTAssertEqual(array.array.count, 2U, @"2 objects left");
- [array.array addObject:obj1];
- [array.array removeAllObjects];
- XCTAssertEqual(array.array.count, 0U, @"All objects removed");
- [realm commitWriteTransaction];
- ArrayPropertyObject *intArray = [[ArrayPropertyObject alloc] init];
- IntObject *intObj = [[IntObject alloc] init];
- intObj.intCol = 1;
- RLMAssertThrowsWithReasonMatching([intArray.array addObject:(id)intObj], @"IntObject.*StringObject");
- [intArray.intArray addObject:intObj];
- XCTAssertThrows([intArray.intArray objectsWhere:@"intCol == 1"], @"Should throw on unmanaged RLMArray");
- XCTAssertThrows(([intArray.intArray objectsWithPredicate:[NSPredicate predicateWithFormat:@"intCol == %i", 1]]), @"Should throw on unmanaged RLMArray");
- XCTAssertThrows([intArray.intArray sortedResultsUsingKeyPath:@"intCol" ascending:YES], @"Should throw on unmanaged RLMArray");
- XCTAssertEqual(0U, [intArray.intArray indexOfObjectWhere:@"intCol == 1"]);
- XCTAssertEqual(0U, ([intArray.intArray indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:@"intCol == %i", 1]]));
- XCTAssertEqual([intArray.intArray indexOfObject:intObj], 0U, @"Should be first element");
- XCTAssertEqual([intArray.intArray indexOfObject:intObj], 0U, @"Should be first element");
- // test unmanaged with literals
- __unused ArrayPropertyObject *obj = [[ArrayPropertyObject alloc] initWithValue:@[@"n", @[], @[[[IntObject alloc] initWithValue:@[@1]]]]];
- }
- - (void)testUnmanagedPrimitive {
- AllPrimitiveArrays *obj = [[AllPrimitiveArrays alloc] init];
- XCTAssertTrue([obj.intObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.floatObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.doubleObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.boolObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.stringObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.dataObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.dateObj isKindOfClass:[RLMArray class]]);
- [obj.intObj addObject:@1];
- XCTAssertEqualObjects(obj.intObj[0], @1);
- XCTAssertThrows([obj.intObj addObject:@""]);
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- obj = [AllPrimitiveArrays createInRealm:realm withValue:@[@[],@[],@[],@[],@[],@[],@[]]];
- XCTAssertTrue([obj.intObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.floatObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.doubleObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.boolObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.stringObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.dataObj isKindOfClass:[RLMArray class]]);
- XCTAssertTrue([obj.dateObj isKindOfClass:[RLMArray class]]);
- [obj.intObj addObject:@5];
- XCTAssertEqualObjects(obj.intObj.firstObject, @5);
- }
- - (void)testReplaceObjectAtIndexInUnmanagedArray {
- ArrayPropertyObject *array = [[ArrayPropertyObject alloc] init];
- array.name = @"name";
- StringObject *stringObj1 = [[StringObject alloc] init];
- stringObj1.stringCol = @"a";
- StringObject *stringObj2 = [[StringObject alloc] init];
- stringObj2.stringCol = @"b";
- StringObject *stringObj3 = [[StringObject alloc] init];
- stringObj3.stringCol = @"c";
- [array.array addObject:stringObj1];
- [array.array addObject:stringObj2];
- [array.array addObject:stringObj3];
- IntObject *intObj1 = [[IntObject alloc] init];
- intObj1.intCol = 0;
- IntObject *intObj2 = [[IntObject alloc] init];
- intObj2.intCol = 1;
- IntObject *intObj3 = [[IntObject alloc] init];
- intObj3.intCol = 2;
- [array.intArray addObject:intObj1];
- [array.intArray addObject:intObj2];
- [array.intArray addObject:intObj3];
- XCTAssertEqualObjects(array.array[0], stringObj1, @"Objects should be equal");
- XCTAssertEqualObjects(array.array[1], stringObj2, @"Objects should be equal");
- XCTAssertEqualObjects(array.array[2], stringObj3, @"Objects should be equal");
- XCTAssertEqual(array.array.count, 3U, @"Should have 3 elements in string array");
- XCTAssertEqualObjects(array.intArray[0], intObj1, @"Objects should be equal");
- XCTAssertEqualObjects(array.intArray[1], intObj2, @"Objects should be equal");
- XCTAssertEqualObjects(array.intArray[2], intObj3, @"Objects should be equal");
- XCTAssertEqual(array.intArray.count, 3U, @"Should have 3 elements in int array");
- StringObject *stringObj4 = [[StringObject alloc] init];
- stringObj4.stringCol = @"d";
- [array.array replaceObjectAtIndex:0 withObject:stringObj4];
- XCTAssertTrue([[array.array objectAtIndex:0] isEqualToObject:stringObj4], @"Objects should be replaced");
- XCTAssertEqual(array.array.count, 3U, @"Should have 3 elements in int array");
- IntObject *intObj4 = [[IntObject alloc] init];
- intObj4.intCol = 3;
- [array.intArray replaceObjectAtIndex:1 withObject:intObj4];
- XCTAssertTrue([[array.intArray objectAtIndex:1] isEqualToObject:intObj4], @"Objects should be replaced");
- XCTAssertEqual(array.intArray.count, 3U, @"Should have 3 elements in int array");
- RLMAssertThrowsWithReasonMatching([array.array replaceObjectAtIndex:0 withObject:(id)intObj4],
- @"IntObject.*StringObject");
- RLMAssertThrowsWithReasonMatching([array.intArray replaceObjectAtIndex:1 withObject:(id)stringObj4],
- @"StringObject.*IntObject");
- }
- - (void)testDeleteObjectInUnmanagedArray {
- ArrayPropertyObject *array = [[ArrayPropertyObject alloc] init];
- array.name = @"name";
- StringObject *stringObj1 = [[StringObject alloc] init];
- stringObj1.stringCol = @"a";
- StringObject *stringObj2 = [[StringObject alloc] init];
- stringObj2.stringCol = @"b";
- StringObject *stringObj3 = [[StringObject alloc] init];
- stringObj3.stringCol = @"c";
- [array.array addObject:stringObj1];
- [array.array addObject:stringObj2];
- [array.array addObject:stringObj3];
- IntObject *intObj1 = [[IntObject alloc] init];
- intObj1.intCol = 0;
- IntObject *intObj2 = [[IntObject alloc] init];
- intObj2.intCol = 1;
- IntObject *intObj3 = [[IntObject alloc] init];
- intObj3.intCol = 2;
- [array.intArray addObject:intObj1];
- [array.intArray addObject:intObj2];
- [array.intArray addObject:intObj3];
- XCTAssertEqualObjects(array.array[0], stringObj1, @"Objects should be equal");
- XCTAssertEqualObjects(array.array[1], stringObj2, @"Objects should be equal");
- XCTAssertEqualObjects(array.array[2], stringObj3, @"Objects should be equal");
- XCTAssertEqual(array.array.count, 3U, @"Should have 3 elements in string array");
- XCTAssertEqualObjects(array.intArray[0], intObj1, @"Objects should be equal");
- XCTAssertEqualObjects(array.intArray[1], intObj2, @"Objects should be equal");
- XCTAssertEqualObjects(array.intArray[2], intObj3, @"Objects should be equal");
- XCTAssertEqual(array.intArray.count, 3U, @"Should have 3 elements in int array");
- [array.array removeLastObject];
- XCTAssertEqualObjects(array.array[0], stringObj1, @"Objects should be equal");
- XCTAssertEqualObjects(array.array[1], stringObj2, @"Objects should be equal");
- XCTAssertEqual(array.array.count, 2U, @"Should have 2 elements in string array");
- [array.array removeLastObject];
- XCTAssertEqualObjects(array.array[0], stringObj1, @"Objects should be equal");
- XCTAssertEqual(array.array.count, 1U, @"Should have 1 elements in string array");
- [array.array removeLastObject];
- XCTAssertEqual(array.array.count, 0U, @"Should have 0 elements in string array");
- [array.intArray removeAllObjects];
- XCTAssertEqual(array.intArray.count, 0U, @"Should have 0 elements in int array");
- }
- - (void)testExchangeObjectAtIndexWithObjectAtIndex {
- void (^test)(RLMArray *) = ^(RLMArray *array) {
- [array exchangeObjectAtIndex:0 withObjectAtIndex:1];
- XCTAssertEqual(2U, array.count);
- XCTAssertEqualObjects(@"b", [array[0] stringCol]);
- XCTAssertEqualObjects(@"a", [array[1] stringCol]);
- [array exchangeObjectAtIndex:1 withObjectAtIndex:1];
- XCTAssertEqual(2U, array.count);
- XCTAssertEqualObjects(@"b", [array[0] stringCol]);
- XCTAssertEqualObjects(@"a", [array[1] stringCol]);
- [array exchangeObjectAtIndex:1 withObjectAtIndex:0];
- XCTAssertEqual(2U, array.count);
- XCTAssertEqualObjects(@"a", [array[0] stringCol]);
- XCTAssertEqualObjects(@"b", [array[1] stringCol]);
- RLMAssertThrowsWithReasonMatching([array exchangeObjectAtIndex:1 withObjectAtIndex:20], @"less than 2");
- };
- ArrayPropertyObject *array = [[ArrayPropertyObject alloc] initWithValue:@[@"foo", @[@[@"a"], @[@"b"]], @[]]];
- test(array.array);
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- [realm addObject:array];
- test(array.array);
- [realm commitWriteTransaction];
- }
- - (void)testIndexOfObject
- {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- EmployeeObject *po1 = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Joe", @"age": @40, @"hired": @YES}];
- EmployeeObject *po2 = [EmployeeObject createInRealm:realm withValue:@{@"name": @"John", @"age": @30, @"hired": @NO}];
- EmployeeObject *po3 = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Jill", @"age": @25, @"hired": @YES}];
- EmployeeObject *deleted = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Jill", @"age": @25, @"hired": @YES}];
- EmployeeObject *indirectlyDeleted = [EmployeeObject allObjectsInRealm:realm].lastObject;
- [realm deleteObject:deleted];
- // create company
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- [company.employees addObjects:[EmployeeObject allObjects]];
- [company.employees removeObjectAtIndex:1];
- // test unmanaged
- XCTAssertEqual(0U, [company.employees indexOfObject:po1]);
- XCTAssertEqual(1U, [company.employees indexOfObject:po3]);
- XCTAssertEqual((NSUInteger)NSNotFound, [company.employees indexOfObject:po2]);
- // add to realm
- [realm addObject:company];
- [realm commitWriteTransaction];
- // test LinkView RLMArray
- XCTAssertEqual(0U, [company.employees indexOfObject:po1]);
- XCTAssertEqual(1U, [company.employees indexOfObject:po3]);
- XCTAssertEqual((NSUInteger)NSNotFound, [company.employees indexOfObject:po2]);
- // non realm employee
- EmployeeObject *notInRealm = [[EmployeeObject alloc] initWithValue:@[@"NoName", @1, @NO]];
- XCTAssertEqual((NSUInteger)NSNotFound, [company.employees indexOfObject:notInRealm]);
- // invalid object
- XCTAssertThrows([company.employees indexOfObject:(EmployeeObject *)company]);
- RLMAssertThrowsWithReasonMatching([company.employees indexOfObject:deleted], @"invalidated");
- RLMAssertThrowsWithReasonMatching([company.employees indexOfObject:indirectlyDeleted], @"invalidated");
- RLMResults *employees = [company.employees objectsWhere:@"age = %@", @40];
- XCTAssertEqual(0U, [employees indexOfObject:po1]);
- XCTAssertEqual((NSUInteger)NSNotFound, [employees indexOfObject:po3]);
- }
- - (void)testIndexOfObjectWhere
- {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- EmployeeObject *po1 = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Joe", @"age": @40, @"hired": @YES}];
- [EmployeeObject createInRealm:realm withValue:@{@"name": @"John", @"age": @30, @"hired": @NO}];
- EmployeeObject *po3 = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Jill", @"age": @25, @"hired": @YES}];
- EmployeeObject *po4 = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Bill", @"age": @55, @"hired": @YES}];
- // create company
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- [company.employees addObjects:@[po3, po1, po4]];
- // test unmanaged
- XCTAssertEqual(0U, [company.employees indexOfObjectWhere:@"name = 'Jill'"]);
- XCTAssertEqual(1U, [company.employees indexOfObjectWhere:@"name = 'Joe'"]);
- XCTAssertEqual((NSUInteger)NSNotFound, [company.employees indexOfObjectWhere:@"name = 'John'"]);
- // add to realm
- [realm addObject:company];
- [realm commitWriteTransaction];
- // test LinkView RLMArray
- XCTAssertEqual(0U, [company.employees indexOfObjectWhere:@"name = 'Jill'"]);
- XCTAssertEqual(1U, [company.employees indexOfObjectWhere:@"name = 'Joe'"]);
- XCTAssertEqual((NSUInteger)NSNotFound, [company.employees indexOfObjectWhere:@"name = 'John'"]);
- RLMResults *results = [company.employees objectsWhere:@"age > 30"];
- XCTAssertEqual(0U, [results indexOfObjectWhere:@"name = 'Joe'"]);
- XCTAssertEqual(1U, [results indexOfObjectWhere:@"name = 'Bill'"]);
- XCTAssertEqual((NSUInteger)NSNotFound, [results indexOfObjectWhere:@"name = 'John'"]);
- XCTAssertEqual((NSUInteger)NSNotFound, [results indexOfObjectWhere:@"name = 'Jill'"]);
- }
- - (void)testFastEnumeration
- {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- [realm addObject:company];
- [realm commitWriteTransaction];
- // enumerate empty array
- for (__unused id obj in company.employees) {
- XCTFail(@"Should be empty");
- }
- [realm beginWriteTransaction];
- for (int i = 0; i < 30; ++i) {
- EmployeeObject *eo = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Joe", @"age": @40, @"hired": @YES}];
- [company.employees addObject:eo];
- }
- [realm commitWriteTransaction];
- XCTAssertEqual(company.employees.count, 30U);
- __weak id objects[30];
- NSInteger count = 0;
- for (EmployeeObject *e in company.employees) {
- XCTAssertNotNil(e, @"Object is not nil and accessible");
- if (count > 16) {
- // 16 is the size of blocks fast enumeration happens to ask for at
- // the moment, but of course that's just an implementation detail
- // that may change
- XCTAssertNil(objects[count - 16]);
- }
- objects[count++] = e;
- }
- XCTAssertEqual(count, 30, @"should have enumerated 30 objects");
- for (int i = 0; i < count; i++) {
- XCTAssertNil(objects[i], @"Object should have been released");
- }
- @autoreleasepool {
- for (EmployeeObject *e in company.employees) {
- objects[0] = e;
- break;
- }
- }
- XCTAssertNil(objects[0], @"Object should have been released");
- }
- - (void)testModifyDuringEnumeration {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- [realm addObject:company];
- const size_t totalCount = 40;
- for (size_t i = 0; i < totalCount; ++i) {
- [company.employees addObject:[EmployeeObject createInRealm:realm withValue:@[@"name", @(i), @NO]]];
- }
- size_t count = 0;
- for (EmployeeObject *eo in company.employees) {
- ++count;
- [company.employees addObject:eo];
- }
- XCTAssertEqual(totalCount, count);
- XCTAssertEqual(totalCount * 2, company.employees.count);
- [realm cancelWriteTransaction];
- // Unmanaged array
- company = [[CompanyObject alloc] init];
- for (size_t i = 0; i < totalCount; ++i) {
- [company.employees addObject:[[EmployeeObject alloc] initWithValue:@[@"name", @(i), @NO]]];
- }
- count = 0;
- for (EmployeeObject *eo in company.employees) {
- ++count;
- [company.employees addObject:eo];
- }
- XCTAssertEqual(totalCount, count);
- XCTAssertEqual(totalCount * 2, company.employees.count);
- }
- - (void)testDeleteDuringEnumeration {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- [realm addObject:company];
- const size_t totalCount = 40;
- for (size_t i = 0; i < totalCount; ++i) {
- [company.employees addObject:[EmployeeObject createInRealm:realm withValue:@[@"name", @(i), @NO]]];
- }
- [realm commitWriteTransaction];
- [realm beginWriteTransaction];
- for (__unused EmployeeObject *eo in company.employees) {
- [realm deleteObjects:company.employees];
- }
- [realm commitWriteTransaction];
- }
- - (void)testValueForKey {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- XCTAssertEqualObjects([company.employees valueForKey:@"name"], @[]);
- [realm addObject:company];
- [realm commitWriteTransaction];
- XCTAssertEqualObjects([company.employees valueForKey:@"age"], @[]);
- // managed
- NSMutableArray *ages = [NSMutableArray array];
- [realm beginWriteTransaction];
- for (int i = 0; i < 30; ++i) {
- [ages addObject:@(i)];
- EmployeeObject *eo = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Joe", @"age": @(i), @"hired": @YES}];
- [company.employees addObject:eo];
- }
- [realm commitWriteTransaction];
- RLM_GENERIC_ARRAY(EmployeeObject) *employeeObjects = [company valueForKey:@"employees"];
- NSMutableArray *kvcAgeProperties = [NSMutableArray array];
- for (EmployeeObject *employee in employeeObjects) {
- [kvcAgeProperties addObject:@(employee.age)];
- }
- XCTAssertEqualObjects(kvcAgeProperties, ages);
- XCTAssertEqualObjects([company.employees valueForKey:@"age"], ages);
- XCTAssertTrue([[[company.employees valueForKey:@"self"] firstObject] isEqualToObject:company.employees.firstObject]);
- XCTAssertTrue([[[company.employees valueForKey:@"self"] lastObject] isEqualToObject:company.employees.lastObject]);
- XCTAssertEqual([[company.employees valueForKeyPath:@"@count"] integerValue], 30);
- XCTAssertEqual([[company.employees valueForKeyPath:@"@min.age"] integerValue], 0);
- XCTAssertEqual([[company.employees valueForKeyPath:@"@max.age"] integerValue], 29);
- XCTAssertEqualWithAccuracy([[company.employees valueForKeyPath:@"@avg.age"] doubleValue], 14.5, 0.1f);
- XCTAssertEqualObjects([company.employees valueForKeyPath:@"@unionOfObjects.age"],
- (@[@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22, @23, @24, @25, @26, @27, @28, @29]));
- XCTAssertEqualObjects([company.employees valueForKeyPath:@"@distinctUnionOfObjects.name"], (@[@"Joe"]));
- RLMAssertThrowsWithReasonMatching([company.employees valueForKeyPath:@"@sum.dogs.@sum.age"], @"Nested key paths.*not supported");
- // unmanaged object
- company = [[CompanyObject alloc] init];
- ages = [NSMutableArray array];
- for (int i = 0; i < 30; ++i) {
- [ages addObject:@(i)];
- EmployeeObject *eo = [[EmployeeObject alloc] initWithValue:@{@"name": @"Joe", @"age": @(i), @"hired": @YES}];
- [company.employees addObject:eo];
- }
- XCTAssertEqualObjects([company.employees valueForKey:@"age"], ages);
- XCTAssertTrue([[[company.employees valueForKey:@"self"] firstObject] isEqualToObject:company.employees.firstObject]);
- XCTAssertTrue([[[company.employees valueForKey:@"self"] lastObject] isEqualToObject:company.employees.lastObject]);
- XCTAssertEqual([[company.employees valueForKeyPath:@"@count"] integerValue], 30);
- XCTAssertEqual([[company.employees valueForKeyPath:@"@min.age"] integerValue], 0);
- XCTAssertEqual([[company.employees valueForKeyPath:@"@max.age"] integerValue], 29);
- XCTAssertEqualWithAccuracy([[company.employees valueForKeyPath:@"@avg.age"] doubleValue], 14.5, 0.1f);
- XCTAssertEqualObjects([company.employees valueForKeyPath:@"@unionOfObjects.age"],
- (@[@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22, @23, @24, @25, @26, @27, @28, @29]));
- XCTAssertEqualObjects([company.employees valueForKeyPath:@"@distinctUnionOfObjects.name"], (@[@"Joe"]));
- RLMAssertThrowsWithReasonMatching([company.employees valueForKeyPath:@"@sum.dogs.@sum.age"], @"Nested key paths.*not supported");
- }
- - (void)testSetValueForKey {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- [company.employees setValue:@"name" forKey:@"name"];
- XCTAssertEqualObjects([company.employees valueForKey:@"name"], @[]);
- [realm addObject:company];
- [realm commitWriteTransaction];
- XCTAssertThrows([company.employees setValue:@10 forKey:@"age"]);
- XCTAssertEqualObjects([company.employees valueForKey:@"age"], @[]);
- // managed
- NSMutableArray *ages = [NSMutableArray array];
- [realm beginWriteTransaction];
- for (int i = 0; i < 30; ++i) {
- [ages addObject:@(20)];
- EmployeeObject *eo = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Joe", @"age": @(i), @"hired": @YES}];
- [company.employees addObject:eo];
- }
- [company.employees setValue:@20 forKey:@"age"];
- [realm commitWriteTransaction];
- XCTAssertEqualObjects([company.employees valueForKey:@"age"], ages);
- // unmanaged object
- company = [[CompanyObject alloc] init];
- ages = [NSMutableArray array];
- for (int i = 0; i < 30; ++i) {
- [ages addObject:@(20)];
- EmployeeObject *eo = [[EmployeeObject alloc] initWithValue:@{@"name": @"Joe", @"age": @(i), @"hired": @YES}];
- [company.employees addObject:eo];
- }
- [company.employees setValue:@20 forKey:@"age"];
- XCTAssertEqualObjects([company.employees valueForKey:@"age"], ages);
- }
- - (void)testObjectAggregate {
- RLMRealm *realm = [RLMRealm defaultRealm];
- AggregateArrayObject *obj = [AggregateArrayObject new];
- XCTAssertEqual(0, [obj.array sumOfProperty:@"intCol"].intValue);
- XCTAssertNil([obj.array averageOfProperty:@"intCol"]);
- XCTAssertNil([obj.array minOfProperty:@"intCol"]);
- XCTAssertNil([obj.array maxOfProperty:@"intCol"]);
- NSDate *dateMinInput = [NSDate date];
- NSDate *dateMaxInput = [dateMinInput dateByAddingTimeInterval:1000];
- [realm transactionWithBlock:^{
- [AggregateObject createInRealm:realm withValue:@[@0, @1.2f, @0.0, @YES, dateMinInput]];
- [AggregateObject createInRealm:realm withValue:@[@1, @0.0f, @2.5, @NO, dateMaxInput]];
- [AggregateObject createInRealm:realm withValue:@[@0, @1.2f, @0.0, @YES, dateMinInput]];
- [AggregateObject createInRealm:realm withValue:@[@1, @0.0f, @2.5, @NO, dateMaxInput]];
- [AggregateObject createInRealm:realm withValue:@[@0, @1.2f, @0.0, @YES, dateMinInput]];
- [AggregateObject createInRealm:realm withValue:@[@1, @0.0f, @2.5, @NO, dateMaxInput]];
- [AggregateObject createInRealm:realm withValue:@[@0, @1.2f, @0.0, @YES, dateMinInput]];
- [AggregateObject createInRealm:realm withValue:@[@1, @0.0f, @2.5, @NO, dateMaxInput]];
- [AggregateObject createInRealm:realm withValue:@[@0, @1.2f, @0.0, @YES, dateMinInput]];
- [AggregateObject createInRealm:realm withValue:@[@0, @1.2f, @0.0, @YES, dateMinInput]];
- [obj.array addObjects:[AggregateObject allObjectsInRealm:realm]];
- }];
- void (^test)(void) = ^{
- RLMArray *array = obj.array;
- // SUM
- XCTAssertEqual([array sumOfProperty:@"intCol"].integerValue, 4);
- XCTAssertEqualWithAccuracy([array sumOfProperty:@"floatCol"].floatValue, 7.2f, 0.1f);
- XCTAssertEqualWithAccuracy([array sumOfProperty:@"doubleCol"].doubleValue, 10.0, 0.1f);
- RLMAssertThrowsWithReasonMatching([array sumOfProperty:@"foo"], @"foo.*AggregateObject");
- RLMAssertThrowsWithReasonMatching([array sumOfProperty:@"boolCol"], @"sum.*bool");
- RLMAssertThrowsWithReasonMatching([array sumOfProperty:@"dateCol"], @"sum.*date");
- // Average
- XCTAssertEqualWithAccuracy([array averageOfProperty:@"intCol"].doubleValue, 0.4, 0.1f);
- XCTAssertEqualWithAccuracy([array averageOfProperty:@"floatCol"].doubleValue, 0.72, 0.1f);
- XCTAssertEqualWithAccuracy([array averageOfProperty:@"doubleCol"].doubleValue, 1.0, 0.1f);
- RLMAssertThrowsWithReasonMatching([array averageOfProperty:@"foo"], @"foo.*AggregateObject");
- RLMAssertThrowsWithReasonMatching([array averageOfProperty:@"boolCol"], @"average.*bool");
- RLMAssertThrowsWithReasonMatching([array averageOfProperty:@"dateCol"], @"average.*date");
- // MIN
- XCTAssertEqual(0, [[array minOfProperty:@"intCol"] intValue]);
- XCTAssertEqual(0.0f, [[array minOfProperty:@"floatCol"] floatValue]);
- XCTAssertEqual(0.0, [[array minOfProperty:@"doubleCol"] doubleValue]);
- XCTAssertEqualObjects(dateMinInput, [array minOfProperty:@"dateCol"]);
- RLMAssertThrowsWithReasonMatching([array minOfProperty:@"foo"], @"foo.*AggregateObject");
- RLMAssertThrowsWithReasonMatching([array minOfProperty:@"boolCol"], @"min.*bool");
- // MAX
- XCTAssertEqual(1, [[array maxOfProperty:@"intCol"] intValue]);
- XCTAssertEqual(1.2f, [[array maxOfProperty:@"floatCol"] floatValue]);
- XCTAssertEqual(2.5, [[array maxOfProperty:@"doubleCol"] doubleValue]);
- XCTAssertEqualObjects(dateMaxInput, [array maxOfProperty:@"dateCol"]);
- RLMAssertThrowsWithReasonMatching([array maxOfProperty:@"foo"], @"foo.*AggregateObject");
- RLMAssertThrowsWithReasonMatching([array maxOfProperty:@"boolCol"], @"max.*bool");
- };
- test();
- [realm transactionWithBlock:^{ [realm addObject:obj]; }];
- test();
- }
- - (void)testRenamedPropertyAggregate {
- RLMRealm *realm = [RLMRealm defaultRealm];
- LinkToRenamedProperties1 *obj = [LinkToRenamedProperties1 new];
- XCTAssertEqual(0, [obj.array sumOfProperty:@"propA"].intValue);
- XCTAssertNil([obj.array averageOfProperty:@"propA"]);
- XCTAssertNil([obj.array minOfProperty:@"propA"]);
- XCTAssertNil([obj.array maxOfProperty:@"propA"]);
- XCTAssertThrows([obj.array sumOfProperty:@"prop 1"]);
- [realm transactionWithBlock:^{
- [RenamedProperties1 createInRealm:realm withValue:@[@1, @""]];
- [RenamedProperties1 createInRealm:realm withValue:@[@2, @""]];
- [RenamedProperties1 createInRealm:realm withValue:@[@3, @""]];
- [obj.array addObjects:[RenamedProperties1 allObjectsInRealm:realm]];
- }];
- XCTAssertEqual(6, [obj.array sumOfProperty:@"propA"].intValue);
- XCTAssertEqual(2.0, [obj.array averageOfProperty:@"propA"].doubleValue);
- XCTAssertEqual(1, [[obj.array minOfProperty:@"propA"] intValue]);
- XCTAssertEqual(3, [[obj.array maxOfProperty:@"propA"] intValue]);
- [realm transactionWithBlock:^{ [realm addObject:obj]; }];
- XCTAssertEqual(6, [obj.array sumOfProperty:@"propA"].intValue);
- XCTAssertEqual(2.0, [obj.array averageOfProperty:@"propA"].doubleValue);
- XCTAssertEqual(1, [[obj.array minOfProperty:@"propA"] intValue]);
- XCTAssertEqual(3, [[obj.array maxOfProperty:@"propA"] intValue]);
- }
- - (void)testValueForCollectionOperationKeyPath
- {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- EmployeeObject *e1 = [PrimaryEmployeeObject createInRealm:realm withValue:@{@"name": @"A", @"age": @20, @"hired": @YES}];
- EmployeeObject *e2 = [PrimaryEmployeeObject createInRealm:realm withValue:@{@"name": @"B", @"age": @30, @"hired": @NO}];
- EmployeeObject *e3 = [PrimaryEmployeeObject createInRealm:realm withValue:@{@"name": @"C", @"age": @40, @"hired": @YES}];
- EmployeeObject *e4 = [PrimaryEmployeeObject createInRealm:realm withValue:@{@"name": @"D", @"age": @50, @"hired": @YES}];
- PrimaryCompanyObject *c1 = [PrimaryCompanyObject createInRealm:realm withValue:@{@"name": @"ABC AG", @"employees": @[e1, e2, e3, e2]}];
- PrimaryCompanyObject *c2 = [PrimaryCompanyObject createInRealm:realm withValue:@{@"name": @"ABC AG 2", @"employees": @[e1, e4]}];
- ArrayOfPrimaryCompanies *companies = [ArrayOfPrimaryCompanies createInRealm:realm withValue:@[@[c1, c2]]];
- [realm commitWriteTransaction];
- // count operator
- XCTAssertEqual([[c1.employees valueForKeyPath:@"@count"] integerValue], 4);
- // numeric operators
- XCTAssertEqual([[c1.employees valueForKeyPath:@"@min.age"] intValue], 20);
- XCTAssertEqual([[c1.employees valueForKeyPath:@"@max.age"] intValue], 40);
- XCTAssertEqual([[c1.employees valueForKeyPath:@"@sum.age"] integerValue], 120);
- XCTAssertEqualWithAccuracy([[c1.employees valueForKeyPath:@"@avg.age"] doubleValue], 30, 0.1f);
- // collection
- XCTAssertEqualObjects([c1.employees valueForKeyPath:@"@unionOfObjects.name"],
- (@[@"A", @"B", @"C", @"B"]));
- XCTAssertEqualObjects([[c1.employees valueForKeyPath:@"@distinctUnionOfObjects.name"] sortedArrayUsingSelector:@selector(compare:)],
- (@[@"A", @"B", @"C"]));
- XCTAssertEqualObjects([companies.companies valueForKeyPath:@"@unionOfArrays.employees"],
- (@[e1, e2, e3, e2, e1, e4]));
- NSComparator cmp = ^NSComparisonResult(id obj1, id obj2) { return [[obj1 name] compare:[obj2 name]]; };
- XCTAssertEqualObjects([[companies.companies valueForKeyPath:@"@distinctUnionOfArrays.employees"] sortedArrayUsingComparator:cmp],
- (@[e1, e2, e3, e4]));
- // invalid key paths
- RLMAssertThrowsWithReasonMatching([c1.employees valueForKeyPath:@"@invalid.name"],
- @"Unsupported KVC collection operator found in key path '@invalid.name'");
- RLMAssertThrowsWithReasonMatching([c1.employees valueForKeyPath:@"@sum"],
- @"Missing key path for KVC collection operator sum in key path '@sum'");
- RLMAssertThrowsWithReasonMatching([c1.employees valueForKeyPath:@"@sum."],
- @"Missing key path for KVC collection operator sum in key path '@sum.'");
- RLMAssertThrowsWithReasonMatching([c1.employees valueForKeyPath:@"@sum.employees.@sum.age"],
- @"Nested key paths.*not supported");
- }
- - (void)testCrossThreadAccess
- {
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- EmployeeObject *eo = [[EmployeeObject alloc] init];
- eo.name = @"Joe";
- eo.age = 40;
- eo.hired = YES;
- [company.employees addObject:eo];
- RLMArray *employees = company.employees;
- // Unmanaged object can be accessed from other threads
- [self dispatchAsyncAndWait:^{
- XCTAssertNoThrow(company.employees);
- XCTAssertNoThrow([employees lastObject]);
- }];
- [RLMRealm.defaultRealm beginWriteTransaction];
- [RLMRealm.defaultRealm addObject:company];
- [RLMRealm.defaultRealm commitWriteTransaction];
- employees = company.employees;
- XCTAssertNoThrow(company.employees);
- XCTAssertNoThrow([employees lastObject]);
- [self dispatchAsyncAndWait:^{
- XCTAssertThrows(company.employees);
- XCTAssertThrows([employees lastObject]);
- }];
- }
- - (void)testSortByNoColumns {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- DogObject *a2 = [DogObject createInDefaultRealmWithValue:@[@"a", @2]];
- DogObject *b1 = [DogObject createInDefaultRealmWithValue:@[@"b", @1]];
- DogObject *a1 = [DogObject createInDefaultRealmWithValue:@[@"a", @1]];
- DogObject *b2 = [DogObject createInDefaultRealmWithValue:@[@"b", @2]];
- RLMArray<DogObject *> *array = [DogArrayObject createInDefaultRealmWithValue:@[@[a2, b1, a1, b2]]].dogs;
- [realm commitWriteTransaction];
- RLMResults *notActuallySorted = [array sortedResultsUsingDescriptors:@[]];
- XCTAssertTrue([array[0] isEqualToObject:notActuallySorted[0]]);
- XCTAssertTrue([array[1] isEqualToObject:notActuallySorted[1]]);
- XCTAssertTrue([array[2] isEqualToObject:notActuallySorted[2]]);
- XCTAssertTrue([array[3] isEqualToObject:notActuallySorted[3]]);
- }
- - (void)testSortByMultipleColumns {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- DogObject *a1 = [DogObject createInDefaultRealmWithValue:@[@"a", @1]];
- DogObject *a2 = [DogObject createInDefaultRealmWithValue:@[@"a", @2]];
- DogObject *b1 = [DogObject createInDefaultRealmWithValue:@[@"b", @1]];
- DogObject *b2 = [DogObject createInDefaultRealmWithValue:@[@"b", @2]];
- DogArrayObject *array = [DogArrayObject createInDefaultRealmWithValue:@[@[a1, a2, b1, b2]]];
- [realm commitWriteTransaction];
- bool (^checkOrder)(NSArray *, NSArray *, NSArray *) = ^bool(NSArray *properties, NSArray *ascending, NSArray *dogs) {
- NSArray *sort = @[[RLMSortDescriptor sortDescriptorWithKeyPath:properties[0] ascending:[ascending[0] boolValue]],
- [RLMSortDescriptor sortDescriptorWithKeyPath:properties[1] ascending:[ascending[1] boolValue]]];
- RLMResults *actual = [array.dogs sortedResultsUsingDescriptors:sort];
- return [actual[0] isEqualToObject:dogs[0]]
- && [actual[1] isEqualToObject:dogs[1]]
- && [actual[2] isEqualToObject:dogs[2]]
- && [actual[3] isEqualToObject:dogs[3]];
- };
- // Check each valid sort
- XCTAssertTrue(checkOrder(@[@"dogName", @"age"], @[@YES, @YES], @[a1, a2, b1, b2]));
- XCTAssertTrue(checkOrder(@[@"dogName", @"age"], @[@YES, @NO], @[a2, a1, b2, b1]));
- XCTAssertTrue(checkOrder(@[@"dogName", @"age"], @[@NO, @YES], @[b1, b2, a1, a2]));
- XCTAssertTrue(checkOrder(@[@"dogName", @"age"], @[@NO, @NO], @[b2, b1, a2, a1]));
- XCTAssertTrue(checkOrder(@[@"age", @"dogName"], @[@YES, @YES], @[a1, b1, a2, b2]));
- XCTAssertTrue(checkOrder(@[@"age", @"dogName"], @[@YES, @NO], @[b1, a1, b2, a2]));
- XCTAssertTrue(checkOrder(@[@"age", @"dogName"], @[@NO, @YES], @[a2, b2, a1, b1]));
- XCTAssertTrue(checkOrder(@[@"age", @"dogName"], @[@NO, @NO], @[b2, a2, b1, a1]));
- }
- - (void)testSortByRenamedColumns {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- id value = @{@"array": @[@[@1, @"c"], @[@2, @"b"], @[@3, @"a"]]};
- LinkToRenamedProperties1 *obj = [LinkToRenamedProperties1 createInRealm:realm withValue:value];
- // FIXME: sorting has to use the column names because the parsing is done by
- // the object store. This is not ideal.
- XCTAssertEqualObjects([[obj.array sortedResultsUsingKeyPath:@"prop 1" ascending:YES] valueForKeyPath:@"propA"],
- (@[@1, @2, @3]));
- XCTAssertEqualObjects([[obj.array sortedResultsUsingKeyPath:@"prop 2" ascending:YES] valueForKeyPath:@"propA"],
- (@[@3, @2, @1]));
- LinkToRenamedProperties2 *obj2 = [LinkToRenamedProperties2 allObjectsInRealm:realm].firstObject;
- XCTAssertEqualObjects([[obj2.array sortedResultsUsingKeyPath:@"prop 1" ascending:YES] valueForKeyPath:@"propC"],
- (@[@1, @2, @3]));
- XCTAssertEqualObjects([[obj2.array sortedResultsUsingKeyPath:@"prop 2" ascending:YES] valueForKeyPath:@"propC"],
- (@[@3, @2, @1]));
- [realm cancelWriteTransaction];
- }
- - (void)testDeleteLinksAndObjectsInArray
- {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- EmployeeObject *po1 = [EmployeeObject createInRealm:realm withValue:@[@"Joe", @40, @YES]];
- EmployeeObject *po2 = [EmployeeObject createInRealm:realm withValue:@[@"John", @30, @NO]];
- EmployeeObject *po3 = [EmployeeObject createInRealm:realm withValue:@[@"Jill", @25, @YES]];
- CompanyObject *company = [[CompanyObject alloc] init];
- company.name = @"name";
- [company.employees addObjects:[EmployeeObject allObjects]];
- [realm addObject:company];
- [realm commitWriteTransaction];
- RLMArray *peopleInCompany = company.employees;
- // Delete link to employee
- XCTAssertThrowsSpecificNamed([peopleInCompany removeObjectAtIndex:1], NSException, @"RLMException", @"Not allowed in read transaction");
- XCTAssertEqual(peopleInCompany.count, 3U, @"No links should have been deleted");
- [realm beginWriteTransaction];
- XCTAssertThrowsSpecificNamed([peopleInCompany removeObjectAtIndex:3], NSException, @"RLMException", @"Out of bounds");
- XCTAssertNoThrow([peopleInCompany removeObjectAtIndex:1], @"Should delete link to employee");
- [realm commitWriteTransaction];
- XCTAssertEqual(peopleInCompany.count, 2U, @"link deleted when accessing via links");
- EmployeeObject *test = peopleInCompany[0];
- XCTAssertEqual(test.age, po1.age, @"Should be equal");
- XCTAssertEqualObjects(test.name, po1.name, @"Should be equal");
- XCTAssertEqual(test.hired, po1.hired, @"Should be equal");
- XCTAssertTrue([test isEqualToObject:po1], @"Should be equal");
- test = peopleInCompany[1];
- XCTAssertEqual(test.age, po3.age, @"Should be equal");
- XCTAssertEqualObjects(test.name, po3.name, @"Should be equal");
- XCTAssertEqual(test.hired, po3.hired, @"Should be equal");
- XCTAssertTrue([test isEqualToObject:po3], @"Should be equal");
- XCTAssertThrowsSpecificNamed([peopleInCompany removeLastObject], NSException, @"RLMException", @"Not allowed in read transaction");
- XCTAssertThrowsSpecificNamed([peopleInCompany removeAllObjects], NSException, @"RLMException", @"Not allowed in read transaction");
- XCTAssertThrowsSpecificNamed([peopleInCompany replaceObjectAtIndex:0 withObject:po2], NSException, @"RLMException", @"Not allowed in read transaction");
- XCTAssertThrowsSpecificNamed([peopleInCompany insertObject:po2 atIndex:0], NSException, @"RLMException", @"Not allowed in read transaction");
- [realm beginWriteTransaction];
- XCTAssertNoThrow([peopleInCompany removeLastObject], @"Should delete last link");
- XCTAssertEqual(peopleInCompany.count, 1U, @"1 remaining link");
- [peopleInCompany replaceObjectAtIndex:0 withObject:po2];
- XCTAssertEqual(peopleInCompany.count, 1U, @"1 link replaced");
- [peopleInCompany insertObject:po1 atIndex:0];
- XCTAssertEqual(peopleInCompany.count, 2U, @"2 links");
- XCTAssertNoThrow([peopleInCompany removeAllObjects], @"Should delete all links");
- XCTAssertEqual(peopleInCompany.count, 0U, @"0 remaining links");
- [realm commitWriteTransaction];
- RLMResults *allPeople = [EmployeeObject allObjects];
- XCTAssertEqual(allPeople.count, 3U, @"Only links should have been deleted, not the employees");
- }
- - (void)testArrayDescription {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
- RLMArray<EmployeeObject *> *employees = [CompanyObject createInDefaultRealmWithValue:@[@"company"]].employees;
- RLMArray<NSNumber *> *ints = [AllPrimitiveArrays createInDefaultRealmWithValue:@[]].intObj;
- for (NSInteger i = 0; i < 1012; ++i) {
- EmployeeObject *person = [[EmployeeObject alloc] init];
- person.name = @"Mary";
- person.age = 24;
- person.hired = YES;
- [employees addObject:person];
- [ints addObject:@(i + 100)];
- }
- [realm commitWriteTransaction];
- RLMAssertMatches(employees.description,
- @"(?s)RLMArray\\<EmployeeObject\\> \\<0x[a-z0-9]+\\> \\(\n"
- @"\t\\[0\\] EmployeeObject \\{\n"
- @"\t\tname = Mary;\n"
- @"\t\tage = 24;\n"
- @"\t\thired = 1;\n"
- @"\t\\},\n"
- @".*\n"
- @"\t... 912 objects skipped.\n"
- @"\\)");
- RLMAssertMatches(ints.description,
- @"(?s)RLMArray\\<int\\> \\<0x[a-z0-9]+\\> \\(\n"
- @"\t\\[0\\] 100,\n"
- @"\t\\[1\\] 101,\n"
- @"\t\\[2\\] 102,\n"
- @".*\n"
- @"\t... 912 objects skipped.\n"
- @"\\)");
- }
- - (void)testUnmanagedAssignment {
- IntObject *io1 = [[IntObject alloc] init];
- IntObject *io2 = [[IntObject alloc] init];
- IntObject *io3 = [[IntObject alloc] init];
- ArrayPropertyObject *array1 = [[ArrayPropertyObject alloc] init];
- ArrayPropertyObject *array2 = [[ArrayPropertyObject alloc] init];
- // Assigning NSArray shallow copies
- array1.intArray = (id)@[io1, io2];
- XCTAssertEqualObjects([array1.intArray valueForKey:@"self"], (@[io1, io2]));
- [array1 setValue:@[io3, io1] forKey:@"intArray"];
- XCTAssertEqualObjects([array1.intArray valueForKey:@"self"], (@[io3, io1]));
- array1[@"intArray"] = @[io2, io3];
- XCTAssertEqualObjects([array1.intArray valueForKey:@"self"], (@[io2, io3]));
- // Assigning RLMArray shallow copies
- array2.intArray = array1.intArray;
- XCTAssertEqualObjects([array2.intArray valueForKey:@"self"], (@[io2, io3]));
- [array1.intArray removeAllObjects];
- XCTAssertEqualObjects([array2.intArray valueForKey:@"self"], (@[io2, io3]));
- // Self-assignment is a no-op
- array2.intArray = array2.intArray;
- XCTAssertEqualObjects([array2.intArray valueForKey:@"self"], (@[io2, io3]));
- array2[@"intArray"] = array2[@"intArray"];
- XCTAssertEqualObjects([array2[@"intArray"] valueForKey:@"self"], (@[io2, io3]));
- }
- - (void)testManagedAssignment {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- IntObject *io1 = [IntObject createInRealm:realm withValue:@[@1]];
- IntObject *io2 = [IntObject createInRealm:realm withValue:@[@2]];
- IntObject *io3 = [IntObject createInRealm:realm withValue:@[@3]];
- ArrayPropertyObject *array1 = [ArrayPropertyObject createInRealm:realm withValue:@[@""]];
- ArrayPropertyObject *array2 = [ArrayPropertyObject createInRealm:realm withValue:@[@""]];
- // Assigning NSArray shallow copies
- array1.intArray = (id)@[io1, io2];
- XCTAssertEqualObjects([array1.intArray valueForKey:@"intCol"], (@[@1, @2]));
- [array1 setValue:@[io3, io1] forKey:@"intArray"];
- XCTAssertEqualObjects([array1.intArray valueForKey:@"intCol"], (@[@3, @1]));
- array1[@"intArray"] = @[io2, io3];
- XCTAssertEqualObjects([array1.intArray valueForKey:@"intCol"], (@[@2, @3]));
- // Assigning RLMArray shallow copies
- array2.intArray = array1.intArray;
- XCTAssertEqualObjects([array2.intArray valueForKey:@"intCol"], (@[@2, @3]));
- [array1.intArray removeAllObjects];
- XCTAssertEqualObjects([array2.intArray valueForKey:@"intCol"], (@[@2, @3]));
- // Self-assignment is a no-op
- array2.intArray = array2.intArray;
- XCTAssertEqualObjects([array2.intArray valueForKey:@"intCol"], (@[@2, @3]));
- array2[@"intArray"] = array2[@"intArray"];
- XCTAssertEqualObjects([array2[@"intArray"] valueForKey:@"intCol"], (@[@2, @3]));
- [realm cancelWriteTransaction];
- }
- - (void)testAssignIncorrectType {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- ArrayPropertyObject *array = [ArrayPropertyObject createInRealm:realm
- withValue:@[@"", @[@[@"a"]], @[@[@0]]]];
- RLMAssertThrowsWithReason(array.intArray = (id)array.array,
- @"RLMArray<StringObject> does not match expected type 'IntObject' for property 'ArrayPropertyObject.intArray'.");
- RLMAssertThrowsWithReason(array[@"intArray"] = array[@"array"],
- @"RLMArray<StringObject> does not match expected type 'IntObject' for property 'ArrayPropertyObject.intArray'.");
- [realm cancelWriteTransaction];
- }
- - (void)testNotificationSentInitially {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- ArrayPropertyObject *array = [ArrayPropertyObject createInRealm:realm withValue:@[@"", @[], @[]]];
- [realm commitWriteTransaction];
- id expectation = [self expectationWithDescription:@""];
- id token = [array.array addNotificationBlock:^(RLMArray *array, RLMCollectionChange *change, NSError *error) {
- XCTAssertNotNil(array);
- XCTAssertNil(change);
- XCTAssertNil(error);
- [expectation fulfill];
- }];
- [self waitForExpectationsWithTimeout:2.0 handler:nil];
- [(RLMNotificationToken *)token invalidate];
- }
- - (void)testNotificationSentAfterCommit {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- ArrayPropertyObject *array = [ArrayPropertyObject createInRealm:realm withValue:@[@"", @[], @[]]];
- [realm commitWriteTransaction];
- __block bool first = true;
- __block id expectation = [self expectationWithDescription:@""];
- id token = [array.array addNotificationBlock:^(RLMArray *array, RLMCollectionChange *change, NSError *error) {
- XCTAssertNotNil(array);
- XCTAssert(first ? !change : !!change);
- XCTAssertNil(error);
- first = false;
- [expectation fulfill];
- }];
- [self waitForExpectationsWithTimeout:2.0 handler:nil];
- expectation = [self expectationWithDescription:@""];
- [self dispatchAsyncAndWait:^{
- RLMRealm *realm = self.realmWithTestPath;
- [realm transactionWithBlock:^{
- RLMArray *array = [(ArrayPropertyObject *)[ArrayPropertyObject allObjectsInRealm:realm].firstObject array];
- [array addObject:[[StringObject alloc] init]];
- }];
- }];
- [self waitForExpectationsWithTimeout:2.0 handler:nil];
- [(RLMNotificationToken *)token invalidate];
- }
- - (void)testNotificationNotSentForUnrelatedChange {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- ArrayPropertyObject *array = [ArrayPropertyObject createInRealm:realm withValue:@[@"", @[], @[]]];
- [realm commitWriteTransaction];
- id expectation = [self expectationWithDescription:@""];
- id token = [array.array addNotificationBlock:^(__unused RLMArray *array, __unused RLMCollectionChange *change, __unused NSError *error) {
- // will throw if it's incorrectly called a second time due to the
- // unrelated write transaction
- [expectation fulfill];
- }];
- [self waitForExpectationsWithTimeout:2.0 handler:nil];
- // All notification blocks are called as part of a single runloop event, so
- // waiting for this one also waits for the above one to get a chance to run
- [self waitForNotification:RLMRealmDidChangeNotification realm:realm block:^{
- [self dispatchAsyncAndWait:^{
- RLMRealm *realm = self.realmWithTestPath;
- [realm transactionWithBlock:^{
- [ArrayPropertyObject createInRealm:realm withValue:@[@"", @[], @[]]];
- }];
- }];
- }];
- [(RLMNotificationToken *)token invalidate];
- }
- - (void)testNotificationSentOnlyForActualRefresh {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- ArrayPropertyObject *array = [ArrayPropertyObject createInRealm:realm withValue:@[@"", @[], @[]]];
- [realm commitWriteTransaction];
- __block id expectation = [self expectationWithDescription:@""];
- id token = [array.array addNotificationBlock:^(RLMArray *array, __unused RLMCollectionChange *change, NSError *error) {
- XCTAssertNotNil(array);
- XCTAssertNil(error);
- // will throw if it's called a second time before we create the new
- // expectation object immediately before manually refreshing
- [expectation fulfill];
- }];
- [self waitForExpectationsWithTimeout:2.0 handler:nil];
- // Turn off autorefresh, so the background commit should not result in a notification
- realm.autorefresh = NO;
- // All notification blocks are called as part of a single runloop event, so
- // waiting for this one also waits for the above one to get a chance to run
- [self waitForNotification:RLMRealmRefreshRequiredNotification realm:realm block:^{
- [self dispatchAsyncAndWait:^{
- RLMRealm *realm = self.realmWithTestPath;
- [realm transactionWithBlock:^{
- RLMArray *array = [(ArrayPropertyObject *)[ArrayPropertyObject allObjectsInRealm:realm].firstObject array];
- [array addObject:[[StringObject alloc] init]];
- }];
- }];
- }];
- expectation = [self expectationWithDescription:@""];
- [realm refresh];
- [self waitForExpectationsWithTimeout:2.0 handler:nil];
- [(RLMNotificationToken *)token invalidate];
- }
- - (void)testDeletingObjectWithNotificationsRegistered {
- RLMRealm *realm = self.realmWithTestPath;
- [realm beginWriteTransaction];
- ArrayPropertyObject *array = [ArrayPropertyObject createInRealm:realm withValue:@[@"", @[], @[]]];
- [realm commitWriteTransaction];
- __block id expectation = [self expectationWithDescription:@""];
- id token = [array.array addNotificationBlock:^(RLMArray *array, __unused RLMCollectionChange *change, NSError *error) {
- XCTAssertNotNil(array);
- XCTAssertNil(error);
- [expectation fulfill];
- }];
- [self waitForExpectationsWithTimeout:2.0 handler:nil];
- [realm beginWriteTransaction];
- [realm deleteObject:array];
- [realm commitWriteTransaction];
- [(RLMNotificationToken *)token invalidate];
- }
- - (void)testAllMethodsCheckThread {
- RLMRealm *realm = [RLMRealm defaultRealm];
- __block IntObject *io;
- __block RLMArray *array;
- [realm transactionWithBlock:^{
- io = [IntObject createInDefaultRealmWithValue:@[@0]];
- ArrayPropertyObject *obj = [ArrayPropertyObject createInDefaultRealmWithValue:@[@"", @[], @[io]]];
- array = obj.intArray;
- }];
- [realm beginWriteTransaction];
- [self dispatchAsyncAndWait:^{
- RLMAssertThrowsWithReasonMatching([array count], @"thread");
- RLMAssertThrowsWithReasonMatching([array objectAtIndex:0], @"thread");
- RLMAssertThrowsWithReasonMatching([array firstObject], @"thread");
- RLMAssertThrowsWithReasonMatching([array lastObject], @"thread");
- RLMAssertThrowsWithReasonMatching([array addObject:io], @"thread");
- RLMAssertThrowsWithReasonMatching([array addObjects:@[io]], @"thread");
- RLMAssertThrowsWithReasonMatching([array insertObject:io atIndex:0], @"thread");
- RLMAssertThrowsWithReasonMatching([array removeObjectAtIndex:0], @"thread");
- RLMAssertThrowsWithReasonMatching([array removeLastObject], @"thread");
- RLMAssertThrowsWithReasonMatching([array removeAllObjects], @"thread");
- RLMAssertThrowsWithReasonMatching([array replaceObjectAtIndex:0 withObject:io], @"thread");
- RLMAssertThrowsWithReasonMatching([array moveObjectAtIndex:0 toIndex:1], @"thread");
- RLMAssertThrowsWithReasonMatching([array exchangeObjectAtIndex:0 withObjectAtIndex:1], @"thread");
- RLMAssertThrowsWithReasonMatching([array indexOfObject:[IntObject allObjects].firstObject], @"thread");
- RLMAssertThrowsWithReasonMatching([array indexOfObjectWhere:@"intCol = 0"], @"thread");
- RLMAssertThrowsWithReasonMatching([array indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:@"intCol = 0"]], @"thread");
- RLMAssertThrowsWithReasonMatching([array objectsWhere:@"intCol = 0"], @"thread");
- RLMAssertThrowsWithReasonMatching([array objectsWithPredicate:[NSPredicate predicateWithFormat:@"intCol = 0"]], @"thread");
- RLMAssertThrowsWithReasonMatching([array sortedResultsUsingKeyPath:@"intCol" ascending:YES], @"thread");
- RLMAssertThrowsWithReasonMatching([array sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithKeyPath:@"intCol" ascending:YES]]], @"thread");
- RLMAssertThrowsWithReasonMatching(array[0], @"thread");
- RLMAssertThrowsWithReasonMatching(array[0] = io, @"thread");
- RLMAssertThrowsWithReasonMatching([array valueForKey:@"intCol"], @"thread");
- RLMAssertThrowsWithReasonMatching([array setValue:@1 forKey:@"intCol"], @"thread");
- RLMAssertThrowsWithReasonMatching({for (__unused id obj in array);}, @"thread");
- }];
- [realm cancelWriteTransaction];
- }
- - (void)testAllMethodsCheckForInvalidation {
- RLMRealm *realm = [RLMRealm defaultRealm];
- __block IntObject *io;
- __block RLMArray *array;
- [realm transactionWithBlock:^{
- io = [IntObject createInDefaultRealmWithValue:@[@0]];
- ArrayPropertyObject *obj = [ArrayPropertyObject createInDefaultRealmWithValue:@[@"", @[], @[io]]];
- array = obj.intArray;
- }];
- [realm beginWriteTransaction];
- XCTAssertNoThrow([array objectClassName]);
- XCTAssertNoThrow([array realm]);
- XCTAssertNoThrow([array isInvalidated]);
- XCTAssertNoThrow([array count]);
- XCTAssertNoThrow([array objectAtIndex:0]);
- XCTAssertNoThrow([array firstObject]);
- XCTAssertNoThrow([array lastObject]);
- XCTAssertNoThrow([array addObject:io]);
- XCTAssertNoThrow([array addObjects:@[io]]);
- XCTAssertNoThrow([array insertObject:io atIndex:0]);
- XCTAssertNoThrow([array removeObjectAtIndex:0]);
- XCTAssertNoThrow([array removeLastObject]);
- XCTAssertNoThrow([array removeAllObjects]);
- [array addObjects:@[io, io, io]];
- XCTAssertNoThrow([array replaceObjectAtIndex:0 withObject:io]);
- XCTAssertNoThrow([array moveObjectAtIndex:0 toIndex:1]);
- XCTAssertNoThrow([array exchangeObjectAtIndex:0 withObjectAtIndex:1]);
- XCTAssertNoThrow([array indexOfObject:[IntObject allObjects].firstObject]);
- XCTAssertNoThrow([array indexOfObjectWhere:@"intCol = 0"]);
- XCTAssertNoThrow([array indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:@"intCol = 0"]]);
- XCTAssertNoThrow([array objectsWhere:@"intCol = 0"]);
- XCTAssertNoThrow([array objectsWithPredicate:[NSPredicate predicateWithFormat:@"intCol = 0"]]);
- XCTAssertNoThrow([array sortedResultsUsingKeyPath:@"intCol" ascending:YES]);
- XCTAssertNoThrow([array sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithKeyPath:@"intCol" ascending:YES]]]);
- XCTAssertNoThrow(array[0]);
- XCTAssertNoThrow(array[0] = io);
- XCTAssertNoThrow([array valueForKey:@"intCol"]);
- XCTAssertNoThrow([array setValue:@1 forKey:@"intCol"]);
- XCTAssertNoThrow({for (__unused id obj in array);});
- [realm cancelWriteTransaction];
- [realm invalidate];
- [realm beginWriteTransaction];
- io = [IntObject createInDefaultRealmWithValue:@[@0]];
- XCTAssertNoThrow([array objectClassName]);
- XCTAssertNoThrow([array realm]);
- XCTAssertNoThrow([array isInvalidated]);
- RLMAssertThrowsWithReasonMatching([array count], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array objectAtIndex:0], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array firstObject], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array lastObject], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array addObject:io], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array addObjects:@[io]], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array insertObject:io atIndex:0], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array removeObjectAtIndex:0], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array removeLastObject], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array removeAllObjects], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array replaceObjectAtIndex:0 withObject:io], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array moveObjectAtIndex:0 toIndex:1], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array exchangeObjectAtIndex:0 withObjectAtIndex:1], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array indexOfObject:[IntObject allObjects].firstObject], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array indexOfObjectWhere:@"intCol = 0"], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:@"intCol = 0"]], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array objectsWhere:@"intCol = 0"], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array objectsWithPredicate:[NSPredicate predicateWithFormat:@"intCol = 0"]], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array sortedResultsUsingKeyPath:@"intCol" ascending:YES], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithKeyPath:@"intCol" ascending:YES]]], @"invalidated");
- RLMAssertThrowsWithReasonMatching(array[0], @"invalidated");
- RLMAssertThrowsWithReasonMatching(array[0] = io, @"invalidated");
- RLMAssertThrowsWithReasonMatching([array valueForKey:@"intCol"], @"invalidated");
- RLMAssertThrowsWithReasonMatching([array setValue:@1 forKey:@"intCol"], @"invalidated");
- RLMAssertThrowsWithReasonMatching({for (__unused id obj in array);}, @"invalidated");
- [realm cancelWriteTransaction];
- }
- - (void)testMutatingMethodsCheckForWriteTransaction {
- RLMRealm *realm = [RLMRealm defaultRealm];
- __block IntObject *io;
- __block RLMArray *array;
- [realm transactionWithBlock:^{
- io = [IntObject createInDefaultRealmWithValue:@[@0]];
- ArrayPropertyObject *obj = [ArrayPropertyObject createInDefaultRealmWithValue:@[@"", @[], @[io]]];
- array = obj.intArray;
- }];
- XCTAssertNoThrow([array objectClassName]);
- XCTAssertNoThrow([array realm]);
- XCTAssertNoThrow([array isInvalidated]);
- XCTAssertNoThrow([array count]);
- XCTAssertNoThrow([array objectAtIndex:0]);
- XCTAssertNoThrow([array firstObject]);
- XCTAssertNoThrow([array lastObject]);
- XCTAssertNoThrow([array indexOfObject:[IntObject allObjects].firstObject]);
- XCTAssertNoThrow([array indexOfObjectWhere:@"intCol = 0"]);
- XCTAssertNoThrow([array indexOfObjectWithPredicate:[NSPredicate predicateWithFormat:@"intCol = 0"]]);
- XCTAssertNoThrow([array objectsWhere:@"intCol = 0"]);
- XCTAssertNoThrow([array objectsWithPredicate:[NSPredicate predicateWithFormat:@"intCol = 0"]]);
- XCTAssertNoThrow([array sortedResultsUsingKeyPath:@"intCol" ascending:YES]);
- XCTAssertNoThrow([array sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithKeyPath:@"intCol" ascending:YES]]]);
- XCTAssertNoThrow(array[0]);
- XCTAssertNoThrow([array valueForKey:@"intCol"]);
- XCTAssertNoThrow({for (__unused id obj in array);});
- RLMAssertThrowsWithReasonMatching([array addObject:io], @"write transaction");
- RLMAssertThrowsWithReasonMatching([array addObjects:@[io]], @"write transaction");
- RLMAssertThrowsWithReasonMatching([array insertObject:io atIndex:0], @"write transaction");
- RLMAssertThrowsWithReasonMatching([array removeObjectAtIndex:0], @"write transaction");
- RLMAssertThrowsWithReasonMatching([array removeLastObject], @"write transaction");
- RLMAssertThrowsWithReasonMatching([array removeAllObjects], @"write transaction");
- RLMAssertThrowsWithReasonMatching([array replaceObjectAtIndex:0 withObject:io], @"write transaction");
- RLMAssertThrowsWithReasonMatching([array moveObjectAtIndex:0 toIndex:1], @"write transaction");
- RLMAssertThrowsWithReasonMatching([array exchangeObjectAtIndex:0 withObjectAtIndex:1], @"write transaction");
- RLMAssertThrowsWithReasonMatching(array[0] = io, @"write transaction");
- RLMAssertThrowsWithReasonMatching([array setValue:@1 forKey:@"intCol"], @"write transaction");
- }
- @end
|