diff --git a/package.json b/package.json
index 42ea8fb0..517a022e 100644
--- a/package.json
+++ b/package.json
@@ -55,9 +55,9 @@
"xcode": "0.8.4"
},
"devDependencies": {
- "babel-eslint": "^6.0.0-beta.6",
- "eslint": "^2.4.0",
- "eslint-plugin-react": "^4.2.3",
+ "babel-eslint": "^6.0.4",
+ "eslint": "^2.10.2",
+ "eslint-plugin-react": "^5.1.1",
"jsdoc": "^3.4.0",
"semver": "^5.1.0"
},
diff --git a/src/rpc.cpp b/src/rpc.cpp
index dd1fe422..3fcb539c 100644
--- a/src/rpc.cpp
+++ b/src/rpc.cpp
@@ -182,15 +182,18 @@ RPCServer::RPCServer() {
return json::object();
};
m_requests["/clear_test_state"] = [this](const json dict) {
- for (auto object : m_objects) {
- // The session ID points to the Realm constructor object, which should remain.
- if (object.first != m_session_id) {
- m_objects.erase(object.first);
- }
+ // The session ID points to the Realm constructor object, which should remain.
+ auto realm_constructor = m_objects[m_session_id];
+ m_objects.clear();
+
+ if (realm_constructor) {
+ m_objects.emplace(m_session_id, realm_constructor);
}
+
m_callbacks.clear();
JSGarbageCollect(m_context);
js::delete_all_realms();
+
return json::object();
};
}
diff --git a/tests/js/.eslintrc.json b/tests/js/.eslintrc.json
index fd485029..acc84647 100644
--- a/tests/js/.eslintrc.json
+++ b/tests/js/.eslintrc.json
@@ -14,8 +14,5 @@
"Uint32Array": false,
"Uint8Array": false,
"Uint8ClampedArray": false
- },
- "rules": {
- "no-redeclare": 1
}
}
diff --git a/tests/js/base-test.js b/tests/js/base-test.js
deleted file mode 100644
index 24ca6fee..00000000
--- a/tests/js/base-test.js
+++ /dev/null
@@ -1,36 +0,0 @@
-////////////////////////////////////////////////////////////////////////////
-//
-// Copyright 2016 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.
-//
-////////////////////////////////////////////////////////////////////////////
-
-'use strict';
-
-var Realm = require('realm');
-
-var prototype = exports.prototype = {};
-
-exports.extend = function(object) {
- object.__proto__ = prototype;
- return object;
-};
-
-Object.defineProperties(prototype, {
- afterEach: {
- value: function() {
- Realm.clearTestState();
- }
- }
-});
diff --git a/tests/js/encryption-tests.js b/tests/js/encryption-tests.js
index 44b87749..df531a33 100644
--- a/tests/js/encryption-tests.js
+++ b/tests/js/encryption-tests.js
@@ -19,11 +19,10 @@
'use strict';
var Realm = require('realm');
-var BaseTest = require('./base-test');
var TestCase = require('./asserts');
var Schemas = require('./schemas');
-module.exports = BaseTest.extend({
+module.exports = {
testEncryptedInvalidKeys: function() {
// test failure with invalid keys
TestCase.assertThrows(function() {
@@ -54,7 +53,7 @@ module.exports = BaseTest.extend({
});
// test can reopen with original key
- var realm = new Realm({schema: [Schemas.TestObject], encryptionKey: key});
+ realm = new Realm({schema: [Schemas.TestObject], encryptionKey: key});
TestCase.assertEqual(realm.objects('TestObject').length, 1);
},
-});
+};
diff --git a/tests/js/index.js b/tests/js/index.js
index e53a4810..e240b801 100644
--- a/tests/js/index.js
+++ b/tests/js/index.js
@@ -18,6 +18,8 @@
'use strict';
+var Realm = require('realm');
+
var TESTS = {
ListTests: require('./list-tests'),
ObjectTests: require('./object-tests'),
@@ -58,7 +60,14 @@ exports.runTest = function(suiteName, testName) {
var testMethod = testSuite && testSuite[testName];
if (testMethod) {
- testMethod.call(testSuite);
+ // Start fresh in case of a crash in a previous run.
+ Realm.clearTestState();
+
+ try {
+ testMethod.call(testSuite);
+ } finally {
+ Realm.clearTestState();
+ }
} else if (!testSuite || !(testName in SPECIAL_METHODS)) {
throw new Error('Missing test: ' + suiteName + '.' + testName);
}
diff --git a/tests/js/list-tests.js b/tests/js/list-tests.js
index bbd92fe2..262fe412 100644
--- a/tests/js/list-tests.js
+++ b/tests/js/list-tests.js
@@ -19,11 +19,10 @@
'use strict';
var Realm = require('realm');
-var BaseTest = require('./base-test');
var TestCase = require('./asserts');
var schemas = require('./schemas');
-module.exports = BaseTest.extend({
+module.exports = {
testListConstructor: function() {
var realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});
@@ -527,7 +526,7 @@ module.exports = BaseTest.extend({
list = object.list;
});
- var names = function(results, prop) {
+ var names = function(results) {
return results.map(function(object) {
return object.name;
});
@@ -653,4 +652,4 @@ module.exports = BaseTest.extend({
list.length;
});
},
-});
+};
diff --git a/tests/js/migration-tests.js b/tests/js/migration-tests.js
index 58c65535..017ec45e 100644
--- a/tests/js/migration-tests.js
+++ b/tests/js/migration-tests.js
@@ -19,11 +19,10 @@
'use strict';
var Realm = require('realm');
-var BaseTest = require('./base-test');
var TestCase = require('./asserts');
var Schemas = require('./schemas');
-module.exports = BaseTest.extend({
+module.exports = {
testMigrationFunction: function() {
var count = 0;
function migrationFunction(oldRealm, newRealm) {
@@ -82,7 +81,7 @@ module.exports = BaseTest.extend({
});
realm.close();
- var realm = new Realm({
+ realm = new Realm({
schema: [{
name: 'TestObject',
properties: {
@@ -130,7 +129,7 @@ module.exports = BaseTest.extend({
}]});
realm.close();
- var realm = new Realm({
+ realm = new Realm({
schema: [{
name: 'TestObject',
properties: {
@@ -159,4 +158,4 @@ module.exports = BaseTest.extend({
}
});
},
-});
+};
diff --git a/tests/js/object-tests.js b/tests/js/object-tests.js
index cf1ca398..86cb626a 100644
--- a/tests/js/object-tests.js
+++ b/tests/js/object-tests.js
@@ -19,7 +19,6 @@
'use strict';
var Realm = require('realm');
-var BaseTest = require('./base-test');
var TestCase = require('./asserts');
var schemas = require('./schemas');
@@ -28,7 +27,7 @@ var RANDOM_DATA = new Uint8Array([
0x67, 0x1e, 0x40, 0xa7, 0x6d, 0x52, 0x83, 0xda, 0x07, 0x29, 0x9c, 0x70, 0x38, 0x48, 0x4e, 0xff,
]);
-module.exports = BaseTest.extend({
+module.exports = {
testBasicTypesPropertyGetters: function() {
var realm = new Realm({schema: [schemas.BasicTypes]});
var object;
@@ -506,4 +505,4 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(realm.objects('Date')[2].currentDate.getTime(), 1000000000000);
TestCase.assertEqual(realm.objects('Date')[3].currentDate.getTime(), -1000000000000);
}
-});
+};
diff --git a/tests/js/query-tests.js b/tests/js/query-tests.js
index 3f5f2ace..9dea5cea 100644
--- a/tests/js/query-tests.js
+++ b/tests/js/query-tests.js
@@ -20,9 +20,7 @@
'use strict';
var Realm = require('realm');
-var BaseTest = require('./base-test');
var TestCase = require('./asserts');
-var schemas = require('./schemas');
var testCases = require('./query-tests.json');
var typeConverters = {};
@@ -77,18 +75,24 @@ function runQuerySuite(suite) {
for (var index in suite.tests) {
var test = suite.tests[index];
+ var type;
+ var args;
+ var results;
+
if (test[0] == "QueryCount") {
- var type = test[2];
- var args = getArgs(3);
- var objects = realm.objects(type);
- var length = objects.filtered.apply(objects, args).length;
+ type = test[2];
+ args = getArgs(3);
+ results = realm.objects(type);
+
+ var length = results.filtered.apply(results, args).length;
TestCase.assertEqual(test[1], length, "Query '" + args[0] + "' on type '" + type + "' expected " + test[1] + " results, got " + length);
}
else if (test[0] == "ObjectSet") {
- var type = test[2];
- var args = getArgs(3);
- var objects = realm.objects(type);
- var results = objects.filtered.apply(objects, args);
+ type = test[2];
+ args = getArgs(3);
+ results = realm.objects(type);
+ results = results.filtered.apply(results, args);
+
TestCase.assertEqual(test[1].length, results.length, "Query '" + args[0] + "' on type '" + type+ "' expected " + test[1].length + " results, got " + results.length);
var objSchema = suite.schema.find(function(el) { return el.name == type });
@@ -102,11 +106,12 @@ function runQuerySuite(suite) {
}));
}
else if (test[0] == "QueryThrows") {
- var type = test[1];
- var args = getArgs(2);
- var objects = realm.objects(type);
+ type = test[1];
+ args = getArgs(2);
+ results = realm.objects(type);
+
TestCase.assertThrows(function() {
- objects.filtered.apply(objects, args);
+ results.filtered.apply(results, args);
}, "Expected exception not thrown for query: " + JSON.stringify(args));
}
else if (test[0] != "Disabled") {
@@ -116,7 +121,7 @@ function runQuerySuite(suite) {
}
-module.exports = BaseTest.extend({
+module.exports = {
testDateQueries: function() {
runQuerySuite(testCases.dateTests);
},
@@ -150,1685 +155,4 @@ module.exports = BaseTest.extend({
testOptionalQueries: function() {
runQuerySuite(testCases.optionalTests);
}
-});
-
-
-/*
--(void)testQueryBetween
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- NSDate *date1 = [NSDate date];
- NSDate *date2 = [date1 dateByAddingTimeInterval:1];
- NSDate *date3 = [date2 dateByAddingTimeInterval:1];
- NSDate *date33 = [date3 dateByAddingTimeInterval:1];
-
- StringObject *stringObj = [StringObject new];
- stringObj.stringCol = @"string";
-
- [realm beginWriteTransaction];
- [AllTypesObject createInRealm:realm withValue:@[@YES, @1, @1.0f, @1.0, @"a", [@"a" dataUsingEncoding:NSUTF8StringEncoding], date1, @YES, @((long)1), @1, stringObj]];
- [AllTypesObject createInRealm:realm withValue:@[@YES, @2, @2.0f, @2.0, @"b", [@"b" dataUsingEncoding:NSUTF8StringEncoding], date2, @YES, @((long)2), @"mixed", stringObj]];
- [AllTypesObject createInRealm:realm withValue:@[@NO, @3, @3.0f, @3.0, @"c", [@"c" dataUsingEncoding:NSUTF8StringEncoding], date3, @YES, @((long)3), @"mixed", stringObj]];
- [AllTypesObject createInRealm:realm withValue:@[@NO, @33, @3.3f, @3.3, @"cc", [@"cc" dataUsingEncoding:NSUTF8StringEncoding], date33, @NO, @((long)3.3), @"mixed", stringObj]];
- [realm commitWriteTransaction];
-
- RLMResults *betweenResults = [AllTypesObject objectsWithPredicate:[NSPredicate predicateWithFormat:@"intCol BETWEEN %@", @[@2, @3]]];
- XCTAssertEqual(betweenResults.count, 2U, @"Should equal 2");
- betweenResults = [AllTypesObject objectsWithPredicate:[NSPredicate predicateWithFormat:@"floatCol BETWEEN %@", @[@1.0f, @4.0f]]];
- XCTAssertEqual(betweenResults.count, 4U, @"Should equal 4");
- betweenResults = [AllTypesObject objectsWithPredicate:[NSPredicate predicateWithFormat:@"doubleCol BETWEEN %@", @[@3.0, @7.0f]]];
- XCTAssertEqual(betweenResults.count, 2U, @"Should equal 2");
- betweenResults = [AllTypesObject objectsWithPredicate:[NSPredicate predicateWithFormat:@"dateCol BETWEEN %@", @[date2,date3]]];
- XCTAssertEqual(betweenResults.count, 2U, @"Should equal 2");
-
- betweenResults = [AllTypesObject objectsWhere:@"intCol BETWEEN {2, 3}"];
- XCTAssertEqual(betweenResults.count, 2U, @"Should equal 2");
- betweenResults = [AllTypesObject objectsWhere:@"doubleCol BETWEEN {3.0, 7.0}"];
- XCTAssertEqual(betweenResults.count, 2U, @"Should equal 2");
-
- betweenResults = [AllTypesObject.allObjects objectsWhere:@"intCol BETWEEN {2, 3}"];
- XCTAssertEqual(betweenResults.count, 2U, @"Should equal 2");
- betweenResults = [AllTypesObject.allObjects objectsWhere:@"doubleCol BETWEEN {3.0, 7.0}"];
- XCTAssertEqual(betweenResults.count, 2U, @"Should equal 2");
-}
-
-
-- (void)testArrayQuery
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [PersonObject createInRealm:realm withValue:@[@"Fiel", @27]];
- [PersonObject createInRealm:realm withValue:@[@"Tim", @29]];
- [PersonObject createInRealm:realm withValue:@[@"Ari", @33]];
- [realm commitWriteTransaction];
-
- // query on class
- RLMResults *all = [PersonObject allObjects];
- XCTAssertEqual(all.count, 3U, @"Expecting 3 results");
-
- RLMResults *some = [[PersonObject objectsWhere:@"age > 28"] sortedResultsUsingProperty:@"age" ascending:YES];
-
- // query/order on array
- XCTAssertEqual([all objectsWhere:@"age == 27"].count, 1U, @"Expecting 1 result");
- XCTAssertEqual([all objectsWhere:@"age == 28"].count, 0U, @"Expecting 0 results");
- some = [some sortedResultsUsingProperty:@"age" ascending:NO];
- XCTAssertEqualObjects([some[0] name], @"Ari", @"Ari should be first results");
-}
-
-- (void)verifySort:(RLMRealm *)realm column:(NSString *)column ascending:(BOOL)ascending expected:(id)val {
- RLMResults *results = [[AllTypesObject allObjectsInRealm:realm] sortedResultsUsingProperty:column ascending:ascending];
- AllTypesObject *obj = results[0];
- XCTAssertEqualObjects(obj[column], val, @"Array not sorted as expected - %@ != %@", obj[column], val);
-
- RLMArray *ar = (RLMArray *)[[[ArrayOfAllTypesObject allObjectsInRealm:realm] firstObject] array];
- results = [ar sortedResultsUsingProperty:column ascending:ascending];
- obj = results[0];
- XCTAssertEqualObjects(obj[column], val, @"Array not sorted as expected - %@ != %@", obj[column], val);
-}
-
-- (void)verifySortWithAccuracy:(RLMRealm *)realm column:(NSString *)column ascending:(BOOL)ascending getter:(double(^)(id))getter expected:(double)val accuracy:(double)accuracy {
- // test TableView query
- RLMResults *results = [[AllTypesObject allObjectsInRealm:realm] sortedResultsUsingProperty:column ascending:ascending];
- XCTAssertEqualWithAccuracy(getter(results[0][column]), val, accuracy, @"Array not sorted as expected");
-
- // test LinkView query
- RLMArray *ar = (RLMArray *)[[[ArrayOfAllTypesObject allObjectsInRealm:realm] firstObject] array];
- results = [ar sortedResultsUsingProperty:column ascending:ascending];
- XCTAssertEqualWithAccuracy(getter(results[0][column]), val, accuracy, @"Array not sorted as expected");
-}
-
-- (void)testQuerySorting
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- NSDate *date1 = [NSDate date];
- NSDate *date2 = [date1 dateByAddingTimeInterval:1];
- NSDate *date3 = [date2 dateByAddingTimeInterval:1];
- NSDate *date33 = [date3 dateByAddingTimeInterval:1];
-
- [realm beginWriteTransaction];
- ArrayOfAllTypesObject *arrayOfAll = [ArrayOfAllTypesObject createInRealm:realm withValue:@{}];
-
- StringObject *stringObj = [StringObject new];
- stringObj.stringCol = @"string";
-
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@YES, @1, @1.0f, @1.0, @"a", [@"a" dataUsingEncoding:NSUTF8StringEncoding], date1, @YES, @1, @1, stringObj]]];
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@YES, @2, @2.0f, @2.0, @"b", [@"b" dataUsingEncoding:NSUTF8StringEncoding], date2, @YES, @2, @"mixed", stringObj]]];
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@NO, @3, @3.0f, @3.0, @"c", [@"c" dataUsingEncoding:NSUTF8StringEncoding], date3, @YES, @3, @"mixed", stringObj]]];
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@NO, @33, @3.3f, @3.3, @"cc", [@"cc" dataUsingEncoding:NSUTF8StringEncoding], date33, @NO, @3, @"mixed", stringObj]]];
-
- [realm commitWriteTransaction];
-
-
- //////////// sort by boolCol
- [self verifySort:realm column:@"boolCol" ascending:YES expected:@NO];
- [self verifySort:realm column:@"boolCol" ascending:NO expected:@YES];
-
- //////////// sort by intCol
- [self verifySort:realm column:@"intCol" ascending:YES expected:@1];
- [self verifySort:realm column:@"intCol" ascending:NO expected:@33];
-
- //////////// sort by dateCol
- double (^dateGetter)(id) = ^(NSDate *d) { return d.timeIntervalSince1970; };
- [self verifySortWithAccuracy:realm column:@"dateCol" ascending:YES getter:dateGetter expected:date1.timeIntervalSince1970 accuracy:1];
- [self verifySortWithAccuracy:realm column:@"dateCol" ascending:NO getter:dateGetter expected:date33.timeIntervalSince1970 accuracy:1];
-
- //////////// sort by doubleCol
- double (^doubleGetter)(id) = ^(NSNumber *n) { return n.doubleValue; };
- [self verifySortWithAccuracy:realm column:@"doubleCol" ascending:YES getter:doubleGetter expected:1.0 accuracy:0.0000001];
- [self verifySortWithAccuracy:realm column:@"doubleCol" ascending:NO getter:doubleGetter expected:3.3 accuracy:0.0000001];
-
- //////////// sort by floatCol
- [self verifySortWithAccuracy:realm column:@"floatCol" ascending:YES getter:doubleGetter expected:1.0 accuracy:0.0000001];
- [self verifySortWithAccuracy:realm column:@"floatCol" ascending:NO getter:doubleGetter expected:3.3 accuracy:0.0000001];
-
- //////////// sort by stringCol
- [self verifySort:realm column:@"stringCol" ascending:YES expected:@"a"];
- [self verifySort:realm column:@"stringCol" ascending:NO expected:@"cc"];
-
- // sort by mixed column
- RLMAssertThrowsWithReasonMatching([[AllTypesObject allObjects] sortedResultsUsingProperty:@"mixedCol" ascending:YES], @"'mixedCol' .* 'AllTypesObject': sorting is only supported .* type any");
- XCTAssertThrows([arrayOfAll.array sortedResultsUsingProperty:@"mixedCol" ascending:NO]);
-
- // sort invalid name
- RLMAssertThrowsWithReasonMatching([[AllTypesObject allObjects] sortedResultsUsingProperty:@"invalidCol" ascending:YES], @"'invalidCol'.* 'AllTypesObject'.* not found");
- XCTAssertThrows([arrayOfAll.array sortedResultsUsingProperty:@"invalidCol" ascending:NO]);
-
- // sort on key path
- RLMAssertThrowsWithReasonMatching([[AllTypesObject allObjects] sortedResultsUsingProperty:@"key.path" ascending:YES], @"key paths is not supported");
- XCTAssertThrows([arrayOfAll.array sortedResultsUsingProperty:@"key.path" ascending:NO]);
-}
-
-- (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]];
- [realm commitWriteTransaction];
-
- bool (^checkOrder)(NSArray *, NSArray *, NSArray *) = ^bool(NSArray *properties, NSArray *ascending, NSArray *dogs) {
- NSArray *sort = @[[RLMSortDescriptor sortDescriptorWithProperty:properties[0] ascending:[ascending[0] boolValue]],
- [RLMSortDescriptor sortDescriptorWithProperty:properties[1] ascending:[ascending[1] boolValue]]];
- RLMResults *actual = [DogObject.allObjects 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)testSortedLinkViewWithDeletion {
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- NSDate *date1 = [NSDate date];
- NSDate *date2 = [date1 dateByAddingTimeInterval:1];
- NSDate *date3 = [date2 dateByAddingTimeInterval:1];
- NSDate *date33 = [date3 dateByAddingTimeInterval:1];
-
- [realm beginWriteTransaction];
- ArrayOfAllTypesObject *arrayOfAll = [ArrayOfAllTypesObject createInRealm:realm withValue:@{}];
-
- StringObject *stringObj = [StringObject new];
- stringObj.stringCol = @"string";
-
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@YES, @1, @1.0f, @1.0, @"a", [@"a" dataUsingEncoding:NSUTF8StringEncoding], date1, @YES, @1, @1, stringObj]]];
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@YES, @2, @2.0f, @2.0, @"b", [@"b" dataUsingEncoding:NSUTF8StringEncoding], date2, @YES, @2, @"mixed", stringObj]]];
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@NO, @3, @3.0f, @3.0, @"c", [@"c" dataUsingEncoding:NSUTF8StringEncoding], date3, @YES, @3, @"mixed", stringObj]]];
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@NO, @33, @3.3f, @3.3, @"cc", [@"cc" dataUsingEncoding:NSUTF8StringEncoding], date33, @NO, @3, @"mixed", stringObj]]];
-
- [realm commitWriteTransaction];
-
- RLMResults *results = [arrayOfAll.array sortedResultsUsingProperty:@"stringCol" ascending:NO];
- XCTAssertEqualObjects([results[0] stringCol], @"cc");
-
- // delete cc, add d results should update
- [realm transactionWithBlock:^{
- [arrayOfAll.array removeObjectAtIndex:3];
-
- // create extra alltypesobject
- [arrayOfAll.array addObject:[AllTypesObject createInRealm:realm withValue:@[@YES, @1, @1.0f, @1.0, @"d", [@"d" dataUsingEncoding:NSUTF8StringEncoding], date1, @YES, @((long)1), @1, stringObj]]];
- }];
- XCTAssertEqualObjects([results[0] stringCol], @"d");
- XCTAssertEqualObjects([results[1] stringCol], @"c");
-
- // delete from realm should be removed from results
- [realm transactionWithBlock:^{
- [realm deleteObject:arrayOfAll.array.lastObject];
- }];
- XCTAssertEqualObjects([results[0] stringCol], @"c");
-}
-
-- (void)testQueryingSortedQueryPreservesOrder {
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- for (int i = 0; i < 5; ++i) {
- [IntObject createInRealm:realm withValue:@[@(i)]];
- }
-
- ArrayPropertyObject *array = [ArrayPropertyObject createInRealm:realm withValue:@[@"name", @[], [IntObject allObjects]]];
- [realm commitWriteTransaction];
-
- RLMResults *asc = [IntObject.allObjects sortedResultsUsingProperty:@"intCol" ascending:YES];
- RLMResults *desc = [IntObject.allObjects sortedResultsUsingProperty:@"intCol" ascending:NO];
-
- // sanity check; would work even without sort order being preserved
- XCTAssertEqual(2, [[[asc objectsWhere:@"intCol >= 2"] firstObject] intCol]);
-
- // check query on allObjects and query on query
- XCTAssertEqual(4, [[[desc objectsWhere:@"intCol >= 2"] firstObject] intCol]);
- XCTAssertEqual(3, [[[[desc objectsWhere:@"intCol >= 2"] objectsWhere:@"intCol < 4"] firstObject] intCol]);
-
- // same thing but on an linkview
- asc = [array.intArray sortedResultsUsingProperty:@"intCol" ascending:YES];
- desc = [array.intArray sortedResultsUsingProperty:@"intCol" ascending:NO];
-
- XCTAssertEqual(2, [[[asc objectsWhere:@"intCol >= 2"] firstObject] intCol]);
- XCTAssertEqual(4, [[[desc objectsWhere:@"intCol >= 2"] firstObject] intCol]);
- XCTAssertEqual(3, [[[[desc objectsWhere:@"intCol >= 2"] objectsWhere:@"intCol < 4"] firstObject] intCol]);
-}
-
-- (void)testPredicateNotSupported
-{
- // These are things which are valid predicates, but which we do not support
-
- // Aggregate operators on non-arrays
- XCTAssertThrows([PersonObject objectsWhere:@"ANY age > 5"]);
- XCTAssertThrows([PersonObject objectsWhere:@"ALL age > 5"]);
- XCTAssertThrows([PersonObject objectsWhere:@"SOME age > 5"]);
- XCTAssertThrows([PersonObject objectsWhere:@"NONE age > 5"]);
-
- // nil on LHS of comparison with nullable property
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"nil = boolObj"]);
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"nil = intObj"]);
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"nil = floatObj"]);
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"nil = doubleObj"]);
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"nil = string"]);
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"nil = data"]);
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"nil = date"]);
-
- // comparing two constants
- XCTAssertThrows([PersonObject objectsWhere:@"5 = 5"]);
- XCTAssertThrows([PersonObject objectsWhere:@"nil = nil"]);
-
- // substring operations with constant on LHS
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"'' CONTAINS string"]);
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"'' BEGINSWITH string"]);
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"'' ENDSWITH string"]);
- XCTAssertThrows(([AllOptionalTypes objectsWhere:@"%@ CONTAINS data", [NSData data]]));
-
- // data is missing stuff
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"data = data"]);
- XCTAssertThrows(([LinkToAllTypesObject objectsWhere:@"%@ = allTypesCol.binaryCol", [NSData data]]));
- XCTAssertThrows(([LinkToAllTypesObject objectsWhere:@"allTypesCol.binaryCol CONTAINS %@", [NSData data]]));
-
- // LinkList equality is unsupport since the semantics are unclear
- XCTAssertThrows(([ArrayOfAllTypesObject objectsWhere:@"ANY array = array"]));
-
- // subquery
- XCTAssertThrows(([ArrayOfAllTypesObject objectsWhere:@"SUBQUERY(array, $obj, $obj.intCol = 5).@count > 1"]));
-}
-
-- (void)testPredicateMisuse
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- NSString *className = PersonObject.className;
-
- // invalid column/property name
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"height > 72"], @"'height' not found in .* 'PersonObject'");
-
- // wrong/invalid data types
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age != xyz"], @"'xyz' not found in .* 'PersonObject'");
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"name == 3"], @"type string .* property 'name' .* 'PersonObject'.*: 3");
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age IN {'xyz'}"], @"type int .* property 'age' .* 'PersonObject'.*: xyz");
- XCTAssertThrows([realm objects:className where:@"name IN {3}"], @"invalid type");
-
- className = AllTypesObject.className;
-
- XCTAssertThrows([realm objects:className where:@"boolCol == Foo"], @"invalid type");
- XCTAssertThrows([realm objects:className where:@"boolCol == 2"], @"invalid type");
- XCTAssertThrows([realm objects:className where:@"dateCol == 7"], @"invalid type");
- XCTAssertThrows([realm objects:className where:@"doubleCol == The"], @"invalid type");
- XCTAssertThrows([realm objects:className where:@"floatCol == Bar"], @"invalid type");
- XCTAssertThrows([realm objects:className where:@"intCol == Baz"], @"invalid type");
-
- className = PersonObject.className;
-
- // compare two constants
- XCTAssertThrows([realm objects:className where:@"3 == 3"], @"comparing 2 constants");
-
- // invalid strings
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@""], @"Unable to parse");
- XCTAssertThrows([realm objects:className where:@"age"], @"column name only");
- XCTAssertThrows([realm objects:className where:@"sdlfjasdflj"], @"gibberish");
- XCTAssertThrows([realm objects:className where:@"age * 25"], @"invalid operator");
- XCTAssertThrows([realm objects:className where:@"age === 25"], @"invalid operator");
- XCTAssertThrows([realm objects:className where:@","], @"comma");
- XCTAssertThrows([realm objects:className where:@"()"], @"parens");
-
- // not a link column
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age.age == 25"], @"'age' is not a link .* 'PersonObject'");
- XCTAssertThrows([realm objects:className where:@"age.age.age == 25"]);
-
- // abuse of BETWEEN
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age BETWEEN 25"], @"type NSArray for BETWEEN");
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age BETWEEN Foo"], @"BETWEEN operator must compare a KeyPath with an aggregate");
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age BETWEEN {age, age}"], @"must be constant values");
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age BETWEEN {age, 0}"], @"must be constant values");
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age BETWEEN {0, age}"], @"must be constant values");
- RLMAssertThrowsWithReasonMatching([realm objects:className where:@"age BETWEEN {0, {1, 10}}"], @"must be constant values");
-
- NSPredicate *pred = [NSPredicate predicateWithFormat:@"age BETWEEN %@", @[@1]];
- RLMAssertThrowsWithReasonMatching([realm objects:className withPredicate:pred], @"exactly two objects");
-
- pred = [NSPredicate predicateWithFormat:@"age BETWEEN %@", @[@1, @2, @3]];
- RLMAssertThrowsWithReasonMatching([realm objects:className withPredicate:pred], @"exactly two objects");
-
- pred = [NSPredicate predicateWithFormat:@"age BETWEEN %@", @[@"Foo", @"Bar"]];
- RLMAssertThrowsWithReasonMatching([realm objects:className withPredicate:pred], @"type int for BETWEEN");
-
- pred = [NSPredicate predicateWithFormat:@"age BETWEEN %@", @[@1.5, @2.5]];
- RLMAssertThrowsWithReasonMatching([realm objects:className withPredicate:pred], @"type int for BETWEEN");
-
- pred = [NSPredicate predicateWithFormat:@"age BETWEEN %@", @[@1, @[@2, @3]]];
- RLMAssertThrowsWithReasonMatching([realm objects:className withPredicate:pred], @"type int for BETWEEN");
-
- pred = [NSPredicate predicateWithFormat:@"age BETWEEN %@", @{@25 : @35}];
- RLMAssertThrowsWithReasonMatching([realm objects:className withPredicate:pred], @"type NSArray for BETWEEN");
-
- pred = [NSPredicate predicateWithFormat:@"height BETWEEN %@", @[@25, @35]];
- RLMAssertThrowsWithReasonMatching([realm objects:className withPredicate:pred], @"'height' not found .* 'PersonObject'");
-
- // bad type in link IN
- XCTAssertThrows([PersonLinkObject objectsInRealm:realm where:@"person.age IN {'Tim'}"]);
-}
-
-- (void)testTwoColumnComparison
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
-
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @YES, @1, @2, @23.0f, @1.7f, @0.0, @5.55, @"a", @"a"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @NO, @1, @3, @-5.3f, @4.21f, @1.0, @4.44, @"a", @"A"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@NO, @NO, @2, @2, @1.0f, @3.55f, @99.9, @6.66, @"a", @"ab"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@NO, @YES, @3, @6, @4.21f, @1.0f, @1.0, @7.77, @"a", @"AB"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @YES, @4, @5, @23.0f, @23.0f, @7.4, @8.88, @"a", @"b"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @NO, @15, @8, @1.0f, @66.0f, @1.01, @9.99, @"a", @"ba"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@NO, @YES, @15, @15, @1.0f, @66.0f, @1.01, @9.99, @"a", @"BA"]];
-
- [realm commitWriteTransaction];
-
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"bool1 == bool1"].count);
- XCTAssertEqual(3U, [self.queryObjectClass objectsWhere:@"bool1 == bool2"].count);
- XCTAssertEqual(4U, [self.queryObjectClass objectsWhere:@"bool1 != bool2"].count);
-
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"int1 == int1"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"int1 == int2"].count);
- XCTAssertEqual(5U, [self.queryObjectClass objectsWhere:@"int1 != int2"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"int1 > int2"].count);
- XCTAssertEqual(4U, [self.queryObjectClass objectsWhere:@"int1 < int2"].count);
- XCTAssertEqual(3U, [self.queryObjectClass objectsWhere:@"int1 >= int2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"int1 <= int2"].count);
-
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"float1 == float1"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"float1 == float2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"float1 != float2"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"float1 > float2"].count);
- XCTAssertEqual(4U, [self.queryObjectClass objectsWhere:@"float1 < float2"].count);
- XCTAssertEqual(3U, [self.queryObjectClass objectsWhere:@"float1 >= float2"].count);
- XCTAssertEqual(5U, [self.queryObjectClass objectsWhere:@"float1 <= float2"].count);
-
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"double1 == double1"].count);
- XCTAssertEqual(0U, [self.queryObjectClass objectsWhere:@"double1 == double2"].count);
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"double1 != double2"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"double1 > double2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"double1 < double2"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"double1 >= double2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"double1 <= double2"].count);
-
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"string1 == string1"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"string1 == string2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"string1 != string2"].count);
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"string1 CONTAINS string1"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"string1 CONTAINS string2"].count);
- XCTAssertEqual(3U, [self.queryObjectClass objectsWhere:@"string2 CONTAINS string1"].count);
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"string1 BEGINSWITH string1"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"string1 BEGINSWITH string2"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"string2 BEGINSWITH string1"].count);
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"string1 ENDSWITH string1"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"string1 ENDSWITH string2"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"string2 ENDSWITH string1"].count);
-
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"string1 ==[c] string1"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"string1 ==[c] string2"].count);
- XCTAssertEqual(5U, [self.queryObjectClass objectsWhere:@"string1 !=[c] string2"].count);
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"string1 CONTAINS[c] string1"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"string1 CONTAINS[c] string2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"string2 CONTAINS[c] string1"].count);
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"string1 BEGINSWITH[c] string1"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"string1 BEGINSWITH[c] string2"].count);
- XCTAssertEqual(4U, [self.queryObjectClass objectsWhere:@"string2 BEGINSWITH[c] string1"].count);
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"string1 ENDSWITH[c] string1"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"string1 ENDSWITH[c] string2"].count);
- XCTAssertEqual(4U, [self.queryObjectClass objectsWhere:@"string2 ENDSWITH[c] string1"].count);
-
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"int1 == float1"],
- @"Property type mismatch between int and float");
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"float2 >= double1"],
- @"Property type mismatch between float and double");
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"double2 <= int2"],
- @"Property type mismatch between double and int");
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"int2 != string1"],
- @"Property type mismatch between int and string");
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"float1 > string1"],
- @"Property type mismatch between float and string");
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"double1 < string1"],
- @"Property type mismatch between double and string");
-}
-
-- (void)testKeyPathLocationInComparison
-{
- NSExpression *keyPath = [NSExpression expressionForKeyPath:@"intCol"];
- NSExpression *expr = [NSExpression expressionForConstantValue:@0];
- NSPredicate *predicate;
-
- predicate = [RLMPredicateUtil defaultPredicateGenerator](keyPath, expr);
- XCTAssert([RLMPredicateUtil isEmptyIntColWithPredicate:predicate],
- @"Key path to the left in an integer comparison.");
-
- predicate = [RLMPredicateUtil defaultPredicateGenerator](expr, keyPath);
- XCTAssert([RLMPredicateUtil isEmptyIntColWithPredicate:predicate],
- @"Key path to the right in an integer comparison.");
-
- predicate = [RLMPredicateUtil defaultPredicateGenerator](keyPath, keyPath);
- XCTAssert([RLMPredicateUtil isEmptyIntColWithPredicate:predicate],
- @"Key path in both locations in an integer comparison.");
-
- predicate = [RLMPredicateUtil defaultPredicateGenerator](expr, expr);
- XCTAssertThrowsSpecificNamed([RLMPredicateUtil isEmptyIntColWithPredicate:predicate],
- NSException, @"Invalid predicate expressions",
- @"Key path in absent in an integer comparison.");
-}
-
-- (void)testLiveQueriesInsideTransaction
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- {
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @YES, @1, @2, @23.0f, @1.7f, @0.0, @5.55, @"", @""]];
-
- RLMResults *resultsQuery = [self.queryObjectClass objectsWhere:@"bool1 = YES"];
- RLMResults *resultsTableView = [self.queryObjectClass objectsWhere:@"bool1 = YES"];
-
- // Force resultsTableView to form the TableView to verify that it syncs
- // correctly, and don't call anything but count on resultsQuery so that
- // it always reruns the query count method
- (void)[resultsTableView firstObject];
-
- XCTAssertEqual(resultsQuery.count, 1U);
- XCTAssertEqual(resultsTableView.count, 1U);
-
- // Delete the (only) object in result set
- [realm deleteObject:[resultsTableView lastObject]];
- XCTAssertEqual(resultsQuery.count, 0U);
- XCTAssertEqual(resultsTableView.count, 0U);
-
- // Add an object that does not match query
- QueryObject *q1 = [self.queryObjectClass createInRealm:realm withValue:@[@NO, @YES, @1, @2, @23.0f, @1.7f, @0.0, @5.55, @"", @""]];
- XCTAssertEqual(resultsQuery.count, 0U);
- XCTAssertEqual(resultsTableView.count, 0U);
-
- // Change object to match query
- q1[@"bool1"] = @YES;
- XCTAssertEqual(resultsQuery.count, 1U);
- XCTAssertEqual(resultsTableView.count, 1U);
-
- // Add another object that matches
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @NO, @1, @3, @-5.3f, @4.21f, @1.0, @4.44, @"", @""]];
- XCTAssertEqual(resultsQuery.count, 2U);
- XCTAssertEqual(resultsTableView.count, 2U);
- }
- [realm commitWriteTransaction];
-}
-
-- (void)testLiveQueriesBetweenTransactions
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @YES, @1, @2, @23.0f, @1.7f, @0.0, @5.55, @"", @""]];
- [realm commitWriteTransaction];
-
- RLMResults *resultsQuery = [self.queryObjectClass objectsWhere:@"bool1 = YES"];
- RLMResults *resultsTableView = [self.queryObjectClass objectsWhere:@"bool1 = YES"];
-
- // Force resultsTableView to form the TableView to verify that it syncs
- // correctly, and don't call anything but count on resultsQuery so that
- // it always reruns the query count method
- (void)[resultsTableView firstObject];
-
- XCTAssertEqual(resultsQuery.count, 1U);
- XCTAssertEqual(resultsTableView.count, 1U);
-
- // Delete the (only) object in result set
- [realm beginWriteTransaction];
- [realm deleteObject:[resultsTableView lastObject]];
- [realm commitWriteTransaction];
-
- XCTAssertEqual(resultsQuery.count, 0U);
- XCTAssertEqual(resultsTableView.count, 0U);
-
- // Add an object that does not match query
- [realm beginWriteTransaction];
- QueryObject *q1 = [self.queryObjectClass createInRealm:realm withValue:@[@NO, @YES, @1, @2, @23.0f, @1.7f, @0.0, @5.55, @"", @""]];
- [realm commitWriteTransaction];
-
- XCTAssertEqual(resultsQuery.count, 0U);
- XCTAssertEqual(resultsTableView.count, 0U);
-
- // Change object to match query
- [realm beginWriteTransaction];
- q1[@"bool1"] = @YES;
- [realm commitWriteTransaction];
-
- XCTAssertEqual(resultsQuery.count, 1U);
- XCTAssertEqual(resultsTableView.count, 1U);
-
- // Add another object that matches
- [realm beginWriteTransaction];
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @NO, @1, @3, @-5.3f, @4.21f, @1.0, @4.44, @"", @""]];
- [realm commitWriteTransaction];
-
- XCTAssertEqual(resultsQuery.count, 2U);
- XCTAssertEqual(resultsTableView.count, 2U);
-}
-
-- (void)makeDogWithName:(NSString *)name owner:(NSString *)ownerName {
- RLMRealm *realm = [self realmWithTestPath];
-
- OwnerObject *owner = [[OwnerObject alloc] init];
- owner.name = ownerName;
- owner.dog = [[DogObject alloc] init];
- owner.dog.dogName = name;
-
- [realm beginWriteTransaction];
- [realm addObject:owner];
- [realm commitWriteTransaction];
-}
-
-- (void)makeDogWithAge:(int)age owner:(NSString *)ownerName {
- RLMRealm *realm = [self realmWithTestPath];
-
- OwnerObject *owner = [[OwnerObject alloc] init];
- owner.name = ownerName;
- owner.dog = [[DogObject alloc] init];
- owner.dog.dogName = @"";
- owner.dog.age = age;
-
- [realm beginWriteTransaction];
- [realm addObject:owner];
- [realm commitWriteTransaction];
-}
-
-- (void)testLinkQueryString
-{
- RLMRealm *realm = [self realmWithTestPath];
-
- [self makeDogWithName:@"Harvie" owner:@"Tim"];
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'Harvie'"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName != 'Harvie'"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'eivraH'"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'Fido'"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName IN {'Fido', 'Harvie'}"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName IN {'Fido', 'eivraH'}"].count), 0U);
-
- [self makeDogWithName:@"Harvie" owner:@"Joe"];
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'Harvie'"].count), 2U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName != 'Harvie'"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'eivraH'"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'Fido'"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName IN {'Fido', 'Harvie'}"].count), 2U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName IN {'Fido', 'eivraH'}"].count), 0U);
-
- [self makeDogWithName:@"Fido" owner:@"Jim"];
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'Harvie'"].count), 2U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName != 'Harvie'"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'eivraH'"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'Fido'"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName IN {'Fido', 'Harvie'}"].count), 3U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName IN {'Fido', 'eivraH'}"].count), 1U);
-
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'Harvie' and name = 'Tim'"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.dogName = 'Harvie' and name = 'Jim'"].count), 0U);
-
- // test invalid operators
- XCTAssertThrows([realm objects:[OwnerObject className] where:@"dog.dogName > 'Harvie'"], @"Invalid operator should throw");
-}
-
-- (void)testLinkQueryInt
-{
- RLMRealm *realm = [self realmWithTestPath];
-
- [self makeDogWithAge:5 owner:@"Tim"];
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 5"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age != 5"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 10"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 8"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age IN {5, 8}"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age IN {8, 10}"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age BETWEEN {0, 10}"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age BETWEEN {0, 7}"].count), 1U);
-
- [self makeDogWithAge:5 owner:@"Joe"];
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 5"].count), 2U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age != 5"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 10"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 8"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age IN {5, 8}"].count), 2U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age IN {8, 10}"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age BETWEEN {0, 10}"].count), 2U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age BETWEEN {0, 7}"].count), 2U);
-
- [self makeDogWithAge:8 owner:@"Jim"];
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 5"].count), 2U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age != 5"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 10"].count), 0U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age = 8"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age IN {5, 8}"].count), 3U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age IN {8, 10}"].count), 1U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age BETWEEN {0, 10}"].count), 3U);
- XCTAssertEqual(([OwnerObject objectsInRealm:realm where:@"dog.age BETWEEN {0, 7}"].count), 2U);
-}
-
-- (void)testLinkQueryAllTypes
-{
- RLMRealm *realm = [self realmWithTestPath];
-
- NSDate *now = [NSDate dateWithTimeIntervalSince1970:100000];
-
- LinkToAllTypesObject *linkToAllTypes = [[LinkToAllTypesObject alloc] init];
- linkToAllTypes.allTypesCol = [[AllTypesObject alloc] init];
- linkToAllTypes.allTypesCol.boolCol = YES;
- linkToAllTypes.allTypesCol.intCol = 1;
- linkToAllTypes.allTypesCol.floatCol = 1.1f;
- linkToAllTypes.allTypesCol.doubleCol = 1.11;
- linkToAllTypes.allTypesCol.stringCol = @"string";
- linkToAllTypes.allTypesCol.binaryCol = [NSData dataWithBytes:"a" length:1];
- linkToAllTypes.allTypesCol.dateCol = now;
- linkToAllTypes.allTypesCol.cBoolCol = YES;
- linkToAllTypes.allTypesCol.longCol = 11;
- linkToAllTypes.allTypesCol.mixedCol = @0;
- StringObject *obj = [[StringObject alloc] initWithValue:@[@"string"]];
- linkToAllTypes.allTypesCol.objectCol = obj;
-
- [realm beginWriteTransaction];
- [realm addObject:linkToAllTypes];
- [realm commitWriteTransaction];
-
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.boolCol = YES"] count], 1U);
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.boolCol = NO"] count], 0U);
-
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.intCol = 1"] count], 1U);
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.intCol != 1"] count], 0U);
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.intCol > 0"] count], 1U);
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.intCol > 1"] count], 0U);
-
- NSPredicate *predEq = [NSPredicate predicateWithFormat:@"allTypesCol.floatCol = %f", 1.1];
- XCTAssertEqual([LinkToAllTypesObject objectsInRealm:realm withPredicate:predEq].count, 1U);
- NSPredicate *predLessEq = [NSPredicate predicateWithFormat:@"allTypesCol.floatCol <= %f", 1.1];
- XCTAssertEqual([LinkToAllTypesObject objectsInRealm:realm withPredicate:predLessEq].count, 1U);
- NSPredicate *predLess = [NSPredicate predicateWithFormat:@"allTypesCol.floatCol < %f", 1.1];
- XCTAssertEqual([LinkToAllTypesObject objectsInRealm:realm withPredicate:predLess].count, 0U);
-
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.doubleCol = 1.11"] count], 1U);
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.doubleCol >= 1.11"] count], 1U);
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.doubleCol > 1.11"] count], 0U);
-
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.longCol = 11"] count], 1U);
- XCTAssertEqual([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.longCol != 11"] count], 0U);
-
- XCTAssertEqual(([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.dateCol = %@", now] count]), 1U);
- XCTAssertEqual(([[realm objects:[LinkToAllTypesObject className] where:@"allTypesCol.dateCol != %@", now] count]), 0U);
-}
-
-- (void)testLinkQueryInvalid {
- XCTAssertThrows([LinkToAllTypesObject objectsWhere:@"allTypesCol.binaryCol = 'a'"], @"Binary data not supported");
- XCTAssertThrows([LinkToAllTypesObject objectsWhere:@"allTypesCol.mixedCol = 'a'"], @"Mixed data not supported");
- XCTAssertThrows([LinkToAllTypesObject objectsWhere:@"allTypesCol.invalidCol = 'a'"], @"Invalid column name should throw");
-
- XCTAssertThrows([LinkToAllTypesObject objectsWhere:@"allTypesCol.longCol = 'a'"], @"Wrong data type should throw");
-
- XCTAssertThrows([LinkToAllTypesObject objectsWhere:@"intArray.intCol > 5"], @"RLMArray query without ANY modifier should throw");
-}
-
-
-- (void)testLinkQueryMany
-{
- RLMRealm *realm = [self realmWithTestPath];
-
- ArrayPropertyObject *arrPropObj1 = [[ArrayPropertyObject alloc] init];
- arrPropObj1.name = @"Test";
- for(NSUInteger i=0; i<10; i++) {
- StringObject *sobj = [[StringObject alloc] init];
- sobj.stringCol = [NSString stringWithFormat:@"%lu", (unsigned long)i];
- [arrPropObj1.array addObject:sobj];
- IntObject *iobj = [[IntObject alloc] init];
- iobj.intCol = (int)i;
- [arrPropObj1.intArray addObject:iobj];
- }
- [realm beginWriteTransaction];
- [realm addObject:arrPropObj1];
- [realm commitWriteTransaction];
-
- XCTAssertEqual([[realm objects:[ArrayPropertyObject className] where:@"ANY intArray.intCol > 10"] count], 0U);
- XCTAssertEqual([[realm objects:[ArrayPropertyObject className] where:@"ANY intArray.intCol > 5"] count], 1U);
- XCTAssertEqual([[realm objects:[ArrayPropertyObject className] where:@"ANY array.stringCol = '1'"] count], 1U);
- XCTAssertEqual([realm objects:[ArrayPropertyObject className] where:@"NONE intArray.intCol == 5"].count, 0U);
- XCTAssertEqual([realm objects:[ArrayPropertyObject className] where:@"NONE intArray.intCol > 10"].count, 1U);
-
- ArrayPropertyObject *arrPropObj2 = [[ArrayPropertyObject alloc] init];
- arrPropObj2.name = @"Test";
- for(NSUInteger i=0; i<4; i++) {
- StringObject *sobj = [[StringObject alloc] init];
- sobj.stringCol = [NSString stringWithFormat:@"%lu", (unsigned long)i];
- [arrPropObj2.array addObject:sobj];
- IntObject *iobj = [[IntObject alloc] init];
- iobj.intCol = (int)i;
- [arrPropObj2.intArray addObject:iobj];
- }
- [realm beginWriteTransaction];
- [realm addObject:arrPropObj2];
- [realm commitWriteTransaction];
- XCTAssertEqual([[realm objects:[ArrayPropertyObject className] where:@"ANY intArray.intCol > 10"] count], 0U);
- XCTAssertEqual([[realm objects:[ArrayPropertyObject className] where:@"ANY intArray.intCol > 5"] count], 1U);
- XCTAssertEqual([[realm objects:[ArrayPropertyObject className] where:@"ANY intArray.intCol > 2"] count], 2U);
- XCTAssertEqual([realm objects:[ArrayPropertyObject className] where:@"NONE intArray.intCol == 5"].count, 1U);
- XCTAssertEqual([realm objects:[ArrayPropertyObject className] where:@"NONE intArray.intCol > 10"].count, 2U);
-}
-
-- (void)testMultiLevelLinkQuery
-{
- RLMRealm *realm = [self realmWithTestPath];
-
- [realm beginWriteTransaction];
- CircleObject *circle = nil;
- for (int i = 0; i < 5; ++i) {
- circle = [CircleObject createInRealm:realm withValue:@{@"data": [NSString stringWithFormat:@"%d", i],
- @"next": circle ?: NSNull.null}];
- }
- [realm commitWriteTransaction];
-
- XCTAssertTrue([circle isEqualToObject:[CircleObject objectsInRealm:realm where:@"data = '4'"].firstObject]);
- XCTAssertTrue([circle isEqualToObject:[CircleObject objectsInRealm:realm where:@"next.data = '3'"].firstObject]);
- XCTAssertTrue([circle isEqualToObject:[CircleObject objectsInRealm:realm where:@"next.next.data = '2'"].firstObject]);
- XCTAssertTrue([circle isEqualToObject:[CircleObject objectsInRealm:realm where:@"next.next.next.data = '1'"].firstObject]);
- XCTAssertTrue([circle isEqualToObject:[CircleObject objectsInRealm:realm where:@"next.next.next.next.data = '0'"].firstObject]);
- XCTAssertTrue([circle.next isEqualToObject:[CircleObject objectsInRealm:realm where:@"next.next.next.data = '0'"].firstObject]);
- XCTAssertTrue([circle.next.next isEqualToObject:[CircleObject objectsInRealm:realm where:@"next.next.data = '0'"].firstObject]);
-
- XCTAssertNoThrow(([CircleObject objectsInRealm:realm where:@"next = %@", circle]));
- XCTAssertThrows(([CircleObject objectsInRealm:realm where:@"next.next = %@", circle]));
- XCTAssertTrue([circle.next.next.next.next isEqualToObject:[CircleObject objectsInRealm:realm where:@"next = nil"].firstObject]);
-}
-
-- (void)testArrayMultiLevelLinkQuery
-{
- RLMRealm *realm = [self realmWithTestPath];
-
- [realm beginWriteTransaction];
- CircleObject *circle = nil;
- for (int i = 0; i < 5; ++i) {
- circle = [CircleObject createInRealm:realm withValue:@{@"data": [NSString stringWithFormat:@"%d", i],
- @"next": circle ?: NSNull.null}];
- }
- [CircleArrayObject createInRealm:realm withValue:@[[CircleObject allObjectsInRealm:realm]]];
- [realm commitWriteTransaction];
-
- XCTAssertEqual(1U, [CircleArrayObject objectsInRealm:realm where:@"ANY circles.data = '4'"].count);
- XCTAssertEqual(0U, [CircleArrayObject objectsInRealm:realm where:@"ANY circles.next.data = '4'"].count);
- XCTAssertEqual(1U, [CircleArrayObject objectsInRealm:realm where:@"ANY circles.next.data = '3'"].count);
- XCTAssertEqual(1U, [CircleArrayObject objectsInRealm:realm where:@"ANY circles.data = '3'"].count);
- XCTAssertEqual(1U, [CircleArrayObject objectsInRealm:realm where:@"NONE circles.next.data = '4'"].count);
-
- XCTAssertEqual(0U, [CircleArrayObject objectsInRealm:realm where:@"ANY circles.next.next.data = '3'"].count);
- XCTAssertEqual(1U, [CircleArrayObject objectsInRealm:realm where:@"ANY circles.next.next.data = '2'"].count);
- XCTAssertEqual(1U, [CircleArrayObject objectsInRealm:realm where:@"ANY circles.next.data = '2'"].count);
- XCTAssertEqual(1U, [CircleArrayObject objectsInRealm:realm where:@"ANY circles.data = '2'"].count);
- XCTAssertEqual(1U, [CircleArrayObject objectsInRealm:realm where:@"NONE circles.next.next.data = '3'"].count);
-
- XCTAssertThrows([CircleArrayObject objectsInRealm:realm where:@"ANY data = '2'"]);
- XCTAssertThrows([CircleArrayObject objectsInRealm:realm where:@"ANY circles.next = '2'"]);
- XCTAssertThrows([CircleArrayObject objectsInRealm:realm where:@"ANY data.circles = '2'"]);
- XCTAssertThrows([CircleArrayObject objectsInRealm:realm where:@"circles.data = '2'"]);
- XCTAssertThrows([CircleArrayObject objectsInRealm:realm where:@"NONE data.circles = '2'"]);
-}
-
-- (void)testClass:(Class)class
- withNormalCount:(NSUInteger)normalCount
- notCount:(NSUInteger)notCount
- where:(NSString *)predicateFormat, ...
-{
- va_list args;
- va_start(args, predicateFormat);
- va_end(args);
- XCTAssertEqual(normalCount, [[class objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]] count]);
- predicateFormat = [NSString stringWithFormat:@"NOT(%@)", predicateFormat];
- va_start(args, predicateFormat);
- va_end(args);
- XCTAssertEqual(notCount, [[class objectsWithPredicate:[NSPredicate predicateWithFormat:predicateFormat arguments:args]] count]);
-}
-
-- (void)testINPredicate
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- StringObject *so = [StringObject createInRealm:realm withValue:(@[@"abc"])];
- [AllTypesObject createInRealm:realm withValue:@[@YES, @1, @1.0f, @1.0, @"abc", [@"a" dataUsingEncoding:NSUTF8StringEncoding], [NSDate dateWithTimeIntervalSince1970:1], @YES, @1LL, @1, so]];
- [realm commitWriteTransaction];
-
- // Tests for each type always follow: none, some, more
-
- ////////////////////////
- // Literal Predicates
- ////////////////////////
-
- // BOOL
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"boolCol IN {NO}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"boolCol IN {YES}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"boolCol IN {NO, YES}"];
-
- // int
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"intCol IN {0, 2, 3}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"intCol IN {1}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"intCol IN {1, 2}"];
-
- // float
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"floatCol IN {0, 2, 3}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"floatCol IN {1}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"floatCol IN {1, 2}"];
-
- // double
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"doubleCol IN {0, 2, 3}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"doubleCol IN {1}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"doubleCol IN {1, 2}"];
-
- // NSString
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"stringCol IN {'abc'}"];
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"stringCol IN {'def'}"];
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"stringCol IN {'ABC'}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"stringCol IN[c] {'abc'}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"stringCol IN[c] {'ABC'}"];
-
- // NSData
- // Can't represent NSData with NSPredicate literal. See format predicates below
-
- // NSDate
- // Can't represent NSDate with NSPredicate literal. See format predicates below
-
- // bool
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"cBoolCol IN {NO}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"cBoolCol IN {YES}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"cBoolCol IN {NO, YES}"];
-
- // int64_t
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"longCol IN {0, 2, 3}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"longCol IN {1}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"longCol IN {1, 2}"];
-
- // mixed
- // FIXME: Support IN predicates with mixed properties
- XCTAssertThrows([AllTypesObject objectsWhere:@"mixedCol IN {0, 2, 3}"]);
- XCTAssertThrows([AllTypesObject objectsWhere:@"NOT(mixedCol IN {0, 2, 3})"]);
-
- // string subobject
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"objectCol.stringCol IN {'abc'}"];
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"objectCol.stringCol IN {'def'}"];
- [self testClass:[AllTypesObject class] withNormalCount:0 notCount:1 where:@"objectCol.stringCol IN {'ABC'}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"objectCol.stringCol IN[c] {'abc'}"];
- [self testClass:[AllTypesObject class] withNormalCount:1 notCount:0 where:@"objectCol.stringCol IN[c] {'ABC'}"];
-
- ////////////////////////
- // Format Predicates
- ////////////////////////
-
- // BOOL
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"boolCol IN %@", @[@NO]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"boolCol IN %@", @[@YES]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"boolCol IN %@", @[@NO, @YES]];
-
- // int
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"intCol IN %@", @[@0, @2, @3]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"intCol IN %@", @[@1]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"intCol IN %@", @[@1, @2]];
-
- // float
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"floatCol IN %@", @[@0, @2, @3]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"floatCol IN %@", @[@1]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"floatCol IN %@", @[@1, @2]];
-
- // double
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"doubleCol IN %@", @[@0, @2, @3]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"doubleCol IN %@", @[@1]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"doubleCol IN %@", @[@1, @2]];
-
- // NSString
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"stringCol IN %@", @[@"abc"]];
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"stringCol IN %@", @[@"def"]];
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"stringCol IN %@", @[@"ABC"]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"stringCol IN[c] %@", @[@"abc"]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"stringCol IN[c] %@", @[@"ABC"]];
-
- // NSData
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"binaryCol IN %@", @[[@"" dataUsingEncoding:NSUTF8StringEncoding]]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"binaryCol IN %@", @[[@"a" dataUsingEncoding:NSUTF8StringEncoding]]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"binaryCol IN %@", @[[@"a" dataUsingEncoding:NSUTF8StringEncoding], [@"b" dataUsingEncoding:NSUTF8StringEncoding]]];
-
- // NSDate
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"dateCol IN %@", @[[NSDate dateWithTimeIntervalSince1970:0]]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"dateCol IN %@", @[[NSDate dateWithTimeIntervalSince1970:1]]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"dateCol IN %@", @[[NSDate dateWithTimeIntervalSince1970:0], [NSDate dateWithTimeIntervalSince1970:1]]];
-
- // bool
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"cBoolCol IN %@", @[@NO]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"cBoolCol IN %@", @[@YES]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"cBoolCol IN %@", @[@NO, @YES]];
-
- // int64_t
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"longCol IN %@", @[@0, @2, @3]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"longCol IN %@", @[@1]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"longCol IN %@", @[@1, @2]];
-
- // mixed
- // FIXME: Support IN predicates with mixed properties
- XCTAssertThrows(([[AllTypesObject objectsWhere:@"mixedCol IN %@", @[@0, @2, @3]] count]));
- XCTAssertThrows(([[AllTypesObject objectsWhere:@"NOT(mixedCol IN %@)", @[@0, @2, @3]] count]));
-
- // string subobject
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"objectCol.stringCol IN %@", @[@"abc"]];
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"objectCol.stringCol IN %@", @[@"def"]];
- [self testClass:[AllTypesObject class] withNormalCount:0U notCount:1U where:@"objectCol.stringCol IN %@", @[@"ABC"]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"objectCol.stringCol IN[c] %@", @[@"abc"]];
- [self testClass:[AllTypesObject class] withNormalCount:1U notCount:0U where:@"objectCol.stringCol IN[c] %@", @[@"ABC"]];
-}
-
-- (void)testArrayIn
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
-
- ArrayPropertyObject *arr = [ArrayPropertyObject createInRealm:realm withValue:@[@"name", @[], @[]]];
- [arr.array addObject:[StringObject createInRealm:realm withValue:@[@"value"]]];
- [realm commitWriteTransaction];
-
-
- XCTAssertEqual(0U, ([[ArrayPropertyObject objectsWhere:@"ANY array.stringCol IN %@", @[@"missing"]] count]));
- XCTAssertEqual(1U, ([[ArrayPropertyObject objectsWhere:@"ANY array.stringCol IN %@", @[@"value"]] count]));
- XCTAssertEqual(1U, ([[ArrayPropertyObject objectsWhere:@"NONE array.stringCol IN %@", @[@"missing"]] count]));
- XCTAssertEqual(0U, ([[ArrayPropertyObject objectsWhere:@"NONE array.stringCol IN %@", @[@"value"]] count]));
-
- XCTAssertEqual(0U, ([[ArrayPropertyObject objectsWhere:@"ANY array IN %@", [StringObject objectsWhere:@"stringCol = 'missing'"]] count]));
- XCTAssertEqual(1U, ([[ArrayPropertyObject objectsWhere:@"ANY array IN %@", [StringObject objectsWhere:@"stringCol = 'value'"]] count]));
- XCTAssertEqual(1U, ([[ArrayPropertyObject objectsWhere:@"NONE array IN %@", [StringObject objectsWhere:@"stringCol = 'missing'"]] count]));
- XCTAssertEqual(0U, ([[ArrayPropertyObject objectsWhere:@"NONE array IN %@", [StringObject objectsWhere:@"stringCol = 'value'"]] count]));
-}
-
-- (void)testQueryChaining {
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [PersonObject createInRealm:realm withValue:@[@"Tim", @29]];
- [PersonObject createInRealm:realm withValue:@[@"Ari", @33]];
- [realm commitWriteTransaction];
-
- XCTAssertEqual(1U, [[PersonObject objectsWhere:@"name == 'Ari'"] count]);
- XCTAssertEqual(0U, [[PersonObject objectsWhere:@"name == 'Ari' and age == 29"] count]);
- XCTAssertEqual(0U, [[[PersonObject objectsWhere:@"name == 'Ari'"] objectsWhere:@"age == 29"] count]);
-}
-
-- (void)testLinkViewQuery {
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [CompanyObject createInRealm:realm
- withValue:@[@"company name", @[@{@"name": @"John", @"age": @30, @"hired": @NO},
- @{@"name": @"Joe", @"age": @40, @"hired": @YES},
- @{@"name": @"Jill", @"age": @50, @"hired": @YES}]]];
- [realm commitWriteTransaction];
-
- CompanyObject *co = [CompanyObject allObjects][0];
- XCTAssertEqual(1U, [co.employees objectsWhere:@"hired = NO"].count);
- XCTAssertEqual(2U, [co.employees objectsWhere:@"hired = YES"].count);
- XCTAssertEqual(1U, [co.employees objectsWhere:@"hired = YES AND age = 40"].count);
- XCTAssertEqual(0U, [co.employees objectsWhere:@"hired = YES AND age = 30"].count);
- XCTAssertEqual(3U, [co.employees objectsWhere:@"hired = YES OR age = 30"].count);
- XCTAssertEqual(1U, [[co.employees objectsWhere:@"hired = YES"] objectsWhere:@"name = 'Joe'"].count);
-}
-
-- (void)testLinkViewQueryLifetime {
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [CompanyObject createInRealm:realm
- withValue:@[@"company name", @[@{@"name": @"John", @"age": @30, @"hired": @NO},
- @{@"name": @"Jill", @"age": @50, @"hired": @YES}]]];
- [EmployeeObject createInRealm:realm withValue:@{@"name": @"Joe", @"age": @40, @"hired": @YES}];
- [realm commitWriteTransaction];
-
- RLMResults *subarray = nil;
- @autoreleasepool {
- __attribute((objc_precise_lifetime)) CompanyObject *co = [CompanyObject allObjects][0];
- subarray = [co.employees objectsWhere:@"age = 40"];
- XCTAssertEqual(0U, subarray.count);
- }
-
- [realm beginWriteTransaction];
- @autoreleasepool {
- __attribute((objc_precise_lifetime)) CompanyObject *co = [CompanyObject allObjects][0];
- [co.employees addObject:[EmployeeObject createInRealm:realm withValue:@{@"name": @"Joe", @"age": @40, @"hired": @YES}]];
- }
- [realm commitWriteTransaction];
-
- XCTAssertEqual(1U, subarray.count);
- XCTAssertEqualObjects(@"Joe", subarray[0][@"name"]);
-}
-
-- (void)testLinkViewQueryLiveUpdate {
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [CompanyObject createInRealm:realm
- withValue:@[@"company name", @[@{@"name": @"John", @"age": @30, @"hired": @NO},
- @{@"name": @"Jill", @"age": @40, @"hired": @YES}]]];
- EmployeeObject *eo = [EmployeeObject createInRealm:realm withValue:@{@"name": @"Joe", @"age": @40, @"hired": @YES}];
- [realm commitWriteTransaction];
-
- CompanyObject *co = CompanyObject.allObjects.firstObject;
- RLMResults *basic = [co.employees objectsWhere:@"age = 40"];
- RLMResults *sort = [co.employees sortedResultsUsingProperty:@"name" ascending:YES];
- RLMResults *sortQuery = [[co.employees sortedResultsUsingProperty:@"name" ascending:YES] objectsWhere:@"age = 40"];
- RLMResults *querySort = [[co.employees objectsWhere:@"age = 40"] sortedResultsUsingProperty:@"name" ascending:YES];
-
- XCTAssertEqual(1U, basic.count);
- XCTAssertEqual(2U, sort.count);
- XCTAssertEqual(1U, sortQuery.count);
- XCTAssertEqual(1U, querySort.count);
-
- XCTAssertEqualObjects(@"Jill", [[basic lastObject] name]);
- XCTAssertEqualObjects(@"Jill", [[sortQuery lastObject] name]);
- XCTAssertEqualObjects(@"Jill", [[querySort lastObject] name]);
-
- [realm beginWriteTransaction];
- [co.employees addObject:eo];
- [realm commitWriteTransaction];
-
- XCTAssertEqual(2U, basic.count);
- XCTAssertEqual(3U, sort.count);
- XCTAssertEqual(2U, sortQuery.count);
- XCTAssertEqual(2U, querySort.count);
-
- XCTAssertEqualObjects(@"Joe", [[basic lastObject] name]);
- XCTAssertEqualObjects(@"Joe", [[sortQuery lastObject] name]);
- XCTAssertEqualObjects(@"Joe", [[querySort lastObject] name]);
-}
-
-- (void)testConstantPredicates
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [PersonObject createInRealm:realm withValue:@[@"Fiel", @27]];
- [PersonObject createInRealm:realm withValue:@[@"Tim", @29]];
- [PersonObject createInRealm:realm withValue:@[@"Ari", @33]];
- [realm commitWriteTransaction];
-
- RLMResults *all = [PersonObject objectsWithPredicate:[NSPredicate predicateWithValue:YES]];
- XCTAssertEqual(all.count, 3U, @"Expecting 3 results");
-
- RLMResults *none = [PersonObject objectsWithPredicate:[NSPredicate predicateWithValue:NO]];
- XCTAssertEqual(none.count, 0U, @"Expecting 0 results");
-}
-
-- (void)testEmptyCompoundPredicates
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [PersonObject createInRealm:realm withValue:@[@"Fiel", @27]];
- [PersonObject createInRealm:realm withValue:@[@"Tim", @29]];
- [PersonObject createInRealm:realm withValue:@[@"Ari", @33]];
- [realm commitWriteTransaction];
-
- RLMResults *all = [PersonObject objectsWithPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:@[]]];
- XCTAssertEqual(all.count, 3U, @"Expecting 3 results");
-
- RLMResults *none = [PersonObject objectsWithPredicate:[NSCompoundPredicate orPredicateWithSubpredicates:@[]]];
- XCTAssertEqual(none.count, 0U, @"Expecting 0 results");
-}
-
-- (void)testComparisonsWithKeyPathOnRHS
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
-
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @YES, @1, @2, @23.0f, @1.7f, @0.0, @5.55, @"a", @"a"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @NO, @1, @3, @-5.3f, @4.21f, @1.0, @4.44, @"a", @"A"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@NO, @NO, @2, @2, @1.0f, @3.55f, @99.9, @6.66, @"a", @"ab"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@NO, @YES, @3, @6, @4.21f, @1.0f, @1.0, @7.77, @"a", @"AB"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @YES, @4, @5, @23.0f, @23.0f, @7.4, @8.88, @"a", @"b"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@YES, @NO, @15, @8, @1.0f, @66.0f, @1.01, @9.99, @"a", @"ba"]];
- [self.queryObjectClass createInRealm:realm withValue:@[@NO, @YES, @15, @15, @1.0f, @66.0f, @1.01, @9.99, @"a", @"BA"]];
-
- [realm commitWriteTransaction];
-
- XCTAssertEqual(4U, [self.queryObjectClass objectsWhere:@"TRUE == bool1"].count);
- XCTAssertEqual(3U, [self.queryObjectClass objectsWhere:@"TRUE != bool2"].count);
-
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"1 == int1"].count);
- XCTAssertEqual(5U, [self.queryObjectClass objectsWhere:@"2 != int2"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"2 > int1"].count);
- XCTAssertEqual(4U, [self.queryObjectClass objectsWhere:@"2 < int1"].count);
- XCTAssertEqual(3U, [self.queryObjectClass objectsWhere:@"2 >= int1"].count);
- XCTAssertEqual(5U, [self.queryObjectClass objectsWhere:@"2 <= int1"].count);
-
- XCTAssertEqual(3U, [self.queryObjectClass objectsWhere:@"1.0 == float1"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"1.0 != float2"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"1.0 > float1"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"1.0 < float2"].count);
- XCTAssertEqual(4U, [self.queryObjectClass objectsWhere:@"1.0 >= float1"].count);
- XCTAssertEqual(7U, [self.queryObjectClass objectsWhere:@"1.0 <= float2"].count);
-
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"1.0 == double1"].count);
- XCTAssertEqual(5U, [self.queryObjectClass objectsWhere:@"1.0 != double1"].count);
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"5.0 > double2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"5.0 < double2"].count);
- XCTAssertEqual(2U, [self.queryObjectClass objectsWhere:@"5.55 >= double2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"5.55 <= double2"].count);
-
- XCTAssertEqual(1U, [self.queryObjectClass objectsWhere:@"'a' == string2"].count);
- XCTAssertEqual(6U, [self.queryObjectClass objectsWhere:@"'a' != string2"].count);
-
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"'Realm' CONTAINS string1"].count,
- @"Operator 'CONTAINS' is not supported .* right side");
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"'Amazon' BEGINSWITH string2"].count,
- @"Operator 'BEGINSWITH' is not supported .* right side");
- RLMAssertThrowsWithReasonMatching([self.queryObjectClass objectsWhere:@"'Tuba' ENDSWITH string1"].count,
- @"Operator 'ENDSWITH' is not supported .* right side");
-}
-
-@end
-
-@interface NullQueryTests : QueryTests
-@end
-
-@implementation NullQueryTests
-- (Class)queryObjectClass {
- return [NullQueryObject class];
-}
-
-- (void)testQueryOnNullableStringColumn {
- void (^testWithStringClass)(Class) = ^(Class stringObjectClass) {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm transactionWithBlock:^{
- [stringObjectClass createInRealm:realm withValue:@[@"a"]];
- [stringObjectClass createInRealm:realm withValue:@[NSNull.null]];
- [stringObjectClass createInRealm:realm withValue:@[@"b"]];
- [stringObjectClass createInRealm:realm withValue:@[NSNull.null]];
- [stringObjectClass createInRealm:realm withValue:@[@""]];
- }];
-
- RLMResults *allObjects = [stringObjectClass allObjectsInRealm:realm];
- XCTAssertEqual(5U, allObjects.count);
-
- RLMResults *nilStrings = [stringObjectClass objectsInRealm:realm where:@"stringCol = NULL"];
- XCTAssertEqual(2U, nilStrings.count);
- XCTAssertEqualObjects((@[NSNull.null, NSNull.null]), [nilStrings valueForKey:@"stringCol"]);
-
- RLMResults *nonNilStrings = [stringObjectClass objectsInRealm:realm where:@"stringCol != NULL"];
- XCTAssertEqual(3U, nonNilStrings.count);
- XCTAssertEqualObjects((@[@"a", @"b", @""]), [nonNilStrings valueForKey:@"stringCol"]);
-
- XCTAssertEqual(3U, [stringObjectClass objectsInRealm:realm where:@"stringCol IN {NULL, 'a'}"].count);
-
- XCTAssertEqual(1U, [stringObjectClass objectsInRealm:realm where:@"stringCol CONTAINS 'a'"].count);
- XCTAssertEqual(1U, [stringObjectClass objectsInRealm:realm where:@"stringCol BEGINSWITH 'a'"].count);
- XCTAssertEqual(1U, [stringObjectClass objectsInRealm:realm where:@"stringCol ENDSWITH 'a'"].count);
-
- XCTAssertEqual(0U, [stringObjectClass objectsInRealm:realm where:@"stringCol CONTAINS 'z'"].count);
-
- XCTAssertEqual(1U, [stringObjectClass objectsInRealm:realm where:@"stringCol = ''"].count);
-
- RLMResults *sorted = [[stringObjectClass allObjectsInRealm:realm] sortedResultsUsingProperty:@"stringCol" ascending:YES];
- XCTAssertEqualObjects((@[NSNull.null, NSNull.null, @"", @"a", @"b"]), [sorted valueForKey:@"stringCol"]);
- XCTAssertEqualObjects((@[@"b", @"a", @"", NSNull.null, NSNull.null]), [[sorted sortedResultsUsingProperty:@"stringCol" ascending:NO] valueForKey:@"stringCol"]);
-
- [realm transactionWithBlock:^{
- [realm deleteObject:[stringObjectClass allObjectsInRealm:realm].firstObject];
- }];
-
- XCTAssertEqual(2U, nilStrings.count);
- XCTAssertEqual(2U, nonNilStrings.count);
-
- XCTAssertEqualObjects([nonNilStrings valueForKey:@"stringCol"], [[stringObjectClass objectsInRealm:realm where:@"stringCol CONTAINS ''"] valueForKey:@"stringCol"]);
- XCTAssertEqualObjects([nonNilStrings valueForKey:@"stringCol"], [[stringObjectClass objectsInRealm:realm where:@"stringCol BEGINSWITH ''"] valueForKey:@"stringCol"]);
- XCTAssertEqualObjects([nonNilStrings valueForKey:@"stringCol"], [[stringObjectClass objectsInRealm:realm where:@"stringCol ENDSWITH ''"] valueForKey:@"stringCol"]);
- XCTAssertEqualObjects([nonNilStrings valueForKey:@"stringCol"], [[stringObjectClass objectsInRealm:realm where:@"stringCol CONTAINS[c] ''"] valueForKey:@"stringCol"]);
- XCTAssertEqualObjects([nonNilStrings valueForKey:@"stringCol"], [[stringObjectClass objectsInRealm:realm where:@"stringCol BEGINSWITH[c] ''"] valueForKey:@"stringCol"]);
- XCTAssertEqualObjects([nonNilStrings valueForKey:@"stringCol"], [[stringObjectClass objectsInRealm:realm where:@"stringCol ENDSWITH[c] ''"] valueForKey:@"stringCol"]);
-
- XCTAssertEqualObjects(@[], ([[stringObjectClass objectsInRealm:realm where:@"stringCol CONTAINS %@", @"\0"] valueForKey:@"self"]));
- XCTAssertEqualObjects([[stringObjectClass allObjectsInRealm:realm] valueForKey:@"stringCol"], ([[StringObject objectsInRealm:realm where:@"stringCol CONTAINS NULL"] valueForKey:@"stringCol"]));
- };
- testWithStringClass([StringObject class]);
- testWithStringClass([IndexedStringObject class]);
-}
-
-- (void)testQueryingOnLinkToNullableStringColumn {
- void (^testWithStringClass)(Class, Class) = ^(Class stringLinkClass, Class stringObjectClass) {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm transactionWithBlock:^{
- [stringLinkClass createInRealm:realm withValue:@[[stringObjectClass createInRealm:realm withValue:@[@"a"]]]];
- [stringLinkClass createInRealm:realm withValue:@[[stringObjectClass createInRealm:realm withValue:@[NSNull.null]]]];
- [stringLinkClass createInRealm:realm withValue:@[[stringObjectClass createInRealm:realm withValue:@[@"b"]]]];
- [stringLinkClass createInRealm:realm withValue:@[[stringObjectClass createInRealm:realm withValue:@[NSNull.null]]]];
- [stringLinkClass createInRealm:realm withValue:@[[stringObjectClass createInRealm:realm withValue:@[@""]]]];
- }];
-
- RLMResults *nilStrings = [stringLinkClass objectsInRealm:realm where:@"objectCol.stringCol = NULL"];
- XCTAssertEqual(2U, nilStrings.count);
- XCTAssertEqualObjects((@[NSNull.null, NSNull.null]), [nilStrings valueForKeyPath:@"objectCol.stringCol"]);
-
- RLMResults *nonNilStrings = [stringLinkClass objectsInRealm:realm where:@"objectCol.stringCol != NULL"];
- XCTAssertEqual(3U, nonNilStrings.count);
- XCTAssertEqualObjects((@[@"a", @"b", @""]), [nonNilStrings valueForKeyPath:@"objectCol.stringCol"]);
-
- XCTAssertEqual(3U, [stringLinkClass objectsInRealm:realm where:@"objectCol.stringCol IN {NULL, 'a'}"].count);
-
- XCTAssertEqual(1U, [stringLinkClass objectsInRealm:realm where:@"objectCol.stringCol CONTAINS 'a'"].count);
- XCTAssertEqual(1U, [stringLinkClass objectsInRealm:realm where:@"objectCol.stringCol BEGINSWITH 'a'"].count);
- XCTAssertEqual(1U, [stringLinkClass objectsInRealm:realm where:@"objectCol.stringCol ENDSWITH 'a'"].count);
-
- XCTAssertEqual(0U, [stringLinkClass objectsInRealm:realm where:@"objectCol.stringCol CONTAINS 'z'"].count);
-
- XCTAssertEqual(1U, [stringLinkClass objectsInRealm:realm where:@"objectCol.stringCol = ''"].count);
- };
-
- testWithStringClass([LinkStringObject class], [StringObject class]);
- testWithStringClass([LinkIndexedStringObject class], [IndexedStringObject class]);
-}
-
-- (void)testSortingColumnsWithNull {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
-
- {
- NumberObject *no1 = [NumberObject createInRealm:realm withValue:@[@1, @1.1f, @1.1, @YES]];
- NumberObject *noNull = [NumberObject createInRealm:realm withValue:@[NSNull.null, NSNull.null, NSNull.null, NSNull.null]];
- NumberObject *no0 = [NumberObject createInRealm:realm withValue:@[@0, @0.0f, @0.0, @NO]];
- for (RLMProperty *property in [[NumberObject alloc] init].objectSchema.properties) {
- NSString *name = property.name;
- RLMResults *ascending = [[NumberObject allObjectsInRealm:realm] sortedResultsUsingProperty:name ascending:YES];
- XCTAssertEqualObjects([ascending valueForKey:name], ([@[noNull, no0, no1] valueForKey:name]));
-
- RLMResults *descending = [[NumberObject allObjectsInRealm:realm] sortedResultsUsingProperty:name ascending:NO];
- XCTAssertEqualObjects([descending valueForKey:name], ([@[no1, no0, noNull] valueForKey:name]));
- }
- }
-
- {
- DateObject *doPositive = [DateObject createInRealm:realm withValue:@[[NSDate dateWithTimeIntervalSince1970:100]]];
- DateObject *doNegative = [DateObject createInRealm:realm withValue:@[[NSDate dateWithTimeIntervalSince1970:-100]]];
- DateObject *doZero = [DateObject createInRealm:realm withValue:@[[NSDate dateWithTimeIntervalSince1970:0]]];
- DateObject *doNull = [DateObject createInRealm:realm withValue:@[NSNull.null]];
-
- RLMResults *ascending = [[DateObject allObjectsInRealm:realm] sortedResultsUsingProperty:@"dateCol" ascending:YES];
- XCTAssertEqualObjects([ascending valueForKey:@"dateCol"], ([@[doNull, doNegative, doZero, doPositive] valueForKey:@"dateCol"]));
-
- RLMResults *descending = [[DateObject allObjectsInRealm:realm] sortedResultsUsingProperty:@"dateCol" ascending:NO];
- XCTAssertEqualObjects([descending valueForKey:@"dateCol"], ([@[doPositive, doZero, doNegative, doNull] valueForKey:@"dateCol"]));
- }
-
- {
- StringObject *soA = [StringObject createInRealm:realm withValue:@[@"A"]];
- StringObject *soEmpty = [StringObject createInRealm:realm withValue:@[@""]];
- StringObject *soB = [StringObject createInRealm:realm withValue:@[@"B"]];
- StringObject *soNull = [StringObject createInRealm:realm withValue:@[NSNull.null]];
- StringObject *soAB = [StringObject createInRealm:realm withValue:@[@"AB"]];
-
- RLMResults *ascending = [[StringObject allObjectsInRealm:realm] sortedResultsUsingProperty:@"stringCol" ascending:YES];
- XCTAssertEqualObjects([ascending valueForKey:@"stringCol"], ([@[soNull, soEmpty, soA, soAB, soB] valueForKey:@"stringCol"]));
-
- RLMResults *descending = [[StringObject allObjectsInRealm:realm] sortedResultsUsingProperty:@"stringCol" ascending:NO];
- XCTAssertEqualObjects([descending valueForKey:@"stringCol"], ([@[soB, soAB, soA, soEmpty, soNull] valueForKey:@"stringCol"]));
- }
-
- [realm cancelWriteTransaction];
-}
-
-- (void)testCountOnCollection {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
-
- IntegerArrayPropertyObject *arr = [IntegerArrayPropertyObject createInRealm:realm withValue:@[ @1234, @[]]];
- [arr.array addObject:[IntObject createInRealm:realm withValue:@[ @456 ]]];
-
- arr = [IntegerArrayPropertyObject createInRealm:realm withValue:@[ @4567, @[]]];
- [arr.array addObject:[IntObject createInRealm:realm withValue:@[ @1 ]]];
- [arr.array addObject:[IntObject createInRealm:realm withValue:@[ @2 ]]];
- [arr.array addObject:[IntObject createInRealm:realm withValue:@[ @3 ]]];
-
- arr = [IntegerArrayPropertyObject createInRealm:realm withValue:@[ @4567, @[]]];
-
- [realm commitWriteTransaction];
-
- XCTAssertEqual(2U, ([IntegerArrayPropertyObject objectsWhere:@"array.@count > 0"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@count == 3"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@count < 1"].count));
- XCTAssertEqual(2U, ([IntegerArrayPropertyObject objectsWhere:@"0 < array.@count"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"3 == array.@count"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"1 > array.@count"].count));
-
- // We do not yet handle collection operations with a keypath on the other side of the comparison.
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@count != number"]), @"'array.@count' not found in object");
-
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@count.foo.bar != 0"]), @"single level key");
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@count.intCol > 0"]), @"@count does not have any properties");
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@count != 'Hello'"]), @"@count can only be compared with a numeric value");
-}
-
-- (void)testAggregateCollectionOperators {
- RLMRealm *realm = [RLMRealm defaultRealm];
- [realm beginWriteTransaction];
-
- IntegerArrayPropertyObject *arr = [IntegerArrayPropertyObject createInRealm:realm withValue:@[ @1111, @[] ]];
- [arr.array addObject:[IntObject createInRealm:realm withValue:@[ @1234 ]]];
- [arr.array addObject:[IntObject createInRealm:realm withValue:@[ @2 ]]];
- [arr.array addObject:[IntObject createInRealm:realm withValue:@[ @-12345 ]]];
-
- arr = [IntegerArrayPropertyObject createInRealm:realm withValue:@[ @2222, @[] ]];
- [arr.array addObject:[IntObject createInRealm:realm withValue:@[ @100 ]]];
-
- arr = [IntegerArrayPropertyObject createInRealm:realm withValue:@[ @3333, @[] ]];
-
- [realm commitWriteTransaction];
-
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@min.intCol == -12345"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@min.intCol == 100"].count));
- XCTAssertEqual(2U, ([IntegerArrayPropertyObject objectsWhere:@"array.@min.intCol < 1000"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@min.intCol > -1000"].count));
-
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@max.intCol == 1234"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@max.intCol == 100"].count));
- XCTAssertEqual(2U, ([IntegerArrayPropertyObject objectsWhere:@"array.@max.intCol > -1000"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@max.intCol > 1000"].count));
-
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@sum.intCol == 100"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@sum.intCol == -11109"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@sum.intCol == 0"].count));
- XCTAssertEqual(2U, ([IntegerArrayPropertyObject objectsWhere:@"array.@sum.intCol > -50"].count));
- XCTAssertEqual(2U, ([IntegerArrayPropertyObject objectsWhere:@"array.@sum.intCol < 50"].count));
-
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@avg.intCol == 100"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@avg.intCol == -3703.0"].count));
- XCTAssertEqual(0U, ([IntegerArrayPropertyObject objectsWhere:@"array.@avg.intCol == 0"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@avg.intCol < -50"].count));
- XCTAssertEqual(1U, ([IntegerArrayPropertyObject objectsWhere:@"array.@avg.intCol > 50"].count));
-
- // We do not yet handle collection operations with a keypath on the other side of the comparison.
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@min.intCol == number"]), @"'array.@min.intCol' not found in object");
-
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@min.intCol.foo.bar == 1.23"]), @"single level key");
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@max.intCol.foo.bar == 1.23"]), @"single level key");
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@sum.intCol.foo.bar == 1.23"]), @"single level key");
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@avg.intCol.foo.bar == 1.23"]), @"single level key");
-
- // Average is omitted from this test as its result is always a double.
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@min.intCol == 1.23"]), @"@min.*type int cannot be compared");
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@max.intCol == 1.23"]), @"@max.*type int cannot be compared");
- RLMAssertThrowsWithReasonMatching(([IntegerArrayPropertyObject objectsWhere:@"array.@sum.intCol == 1.23"]), @"@sum.*type int cannot be compared");
-}
-
-struct NullTestData {
- __unsafe_unretained NSString *propertyName;
- __unsafe_unretained NSString *nonMatchingStr;
- __unsafe_unretained NSString *matchingStr;
- __unsafe_unretained id nonMatchingValue;
- __unsafe_unretained id matchingValue;
- bool orderable;
- bool substringOperations;
};
-
-- (void)testPrimitiveOperatorsOnAllNullablePropertyTypes {
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- // nil on LHS is currently not supported by core
- XCTAssertThrows([AllOptionalTypes objectsWhere:@"nil = boolObj"]);
-
- // These need to be stored in variables because the struct does not retain them
- NSData *matchingData = [@"" dataUsingEncoding:NSUTF8StringEncoding];
- NSData *notMatchingData = [@"a" dataUsingEncoding:NSUTF8StringEncoding];
- NSDate *matchingDate = [NSDate dateWithTimeIntervalSince1970:1];
- NSDate *notMatchingDate = [NSDate dateWithTimeIntervalSince1970:2];
-
- struct NullTestData data[] = {
- {@"boolObj", @"YES", @"NO", @YES, @NO},
- {@"intObj", @"1", @"0", @1, @0, true},
- {@"floatObj", @"1", @"0", @1, @0, true},
- {@"doubleObj", @"1", @"0", @1, @0, true},
- {@"string", @"'a'", @"''", @"a", @"", false, true},
- {@"data", nil, nil, notMatchingData, matchingData},
- {@"date", nil, nil, notMatchingDate, matchingDate, true},
- };
-
- // Assert that the query "prop op value" gives expectedCount results when
- // assembled via string formatting
-#define RLMAssertCountWithString(expectedCount, op, prop, value) \
- do { \
- NSString *queryStr = [NSString stringWithFormat:@"%@ " #op " %@", prop, value]; \
- NSUInteger actual = [AllOptionalTypes objectsWhere:queryStr].count; \
- XCTAssertEqual(expectedCount, actual, @"%@: expected %@, got %@", queryStr, @(expectedCount), @(actual)); \
- } while (0)
-
- // Assert that the query "prop op value" gives expectedCount results when
- // assembled via predicateWithFormat
-#define RLMAssertCountWithPredicate(expectedCount, op, prop, value) \
- do { \
- NSPredicate *query = [NSPredicate predicateWithFormat:@"%K " #op " %@", prop, value]; \
- NSUInteger actual = [AllOptionalTypes objectsWithPredicate:query].count; \
- XCTAssertEqual(expectedCount, actual, @"%@ " #op " %@: expected %@, got %@", prop, value, @(expectedCount), @(actual)); \
- } while (0)
-
- // Assert that the given operator gives the expected count for each of the
- // stored value, a different value, and nil
-#define RLMAssertOperator(op, matchingCount, notMatchingCount, nilCount) \
- do { \
- if (d.matchingStr) { \
- RLMAssertCountWithString(matchingCount, op, d.propertyName, d.matchingStr); \
- RLMAssertCountWithString(notMatchingCount, op, d.propertyName, d.nonMatchingStr); \
- } \
- RLMAssertCountWithString(nilCount, op, d.propertyName, nil); \
- \
- RLMAssertCountWithPredicate(matchingCount, op, d.propertyName, d.matchingValue); \
- RLMAssertCountWithPredicate(notMatchingCount, op, d.propertyName, d.nonMatchingValue); \
- RLMAssertCountWithPredicate(nilCount, op, d.propertyName, nil); \
- } while (0)
-
- // First test with the `matchingValue` stored in each property
-
- [realm beginWriteTransaction];
- [AllOptionalTypes createInRealm:realm withValue:@[@NO, @0, @0, @0, @"", matchingData, matchingDate]];
- [realm commitWriteTransaction];
-
- for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i) {
- struct NullTestData d = data[i];
- RLMAssertOperator(=, 1U, 0U, 0U);
- RLMAssertOperator(!=, 0U, 1U, 1U);
-
- if (d.orderable) {
- RLMAssertOperator(<, 0U, 1U, 0U);
- RLMAssertOperator(<=, 1U, 1U, 0U);
- RLMAssertOperator(>, 0U, 0U, 0U);
- RLMAssertOperator(>=, 1U, 0U, 0U);
- }
- if (d.substringOperations) {
- RLMAssertOperator(BEGINSWITH, 1U, 0U, 1U);
- RLMAssertOperator(ENDSWITH, 1U, 0U, 1U);
- RLMAssertOperator(CONTAINS, 1U, 0U, 1U);
- }
- }
-
- // Retest with all properties nil
-
- [realm beginWriteTransaction];
- [realm deleteAllObjects];
- [AllOptionalTypes createInRealm:realm withValue:@[NSNull.null, NSNull.null,
- NSNull.null, NSNull.null,
- NSNull.null, NSNull.null,
- NSNull.null]];
- [realm commitWriteTransaction];
-
- for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i) {
- struct NullTestData d = data[i];
- RLMAssertOperator(=, 0U, 0U, 1U);
- RLMAssertOperator(!=, 1U, 1U, 0U);
-
- if (d.orderable) {
- RLMAssertOperator(<, 0U, 0U, 0U);
- RLMAssertOperator(<=, 0U, 0U, 1U);
- RLMAssertOperator(>, 0U, 0U, 0U);
- RLMAssertOperator(>=, 0U, 0U, 1U);
- }
- if (d.substringOperations) {
- RLMAssertOperator(BEGINSWITH, 0U, 0U, 1U);
- RLMAssertOperator(ENDSWITH, 0U, 0U, 1U);
- RLMAssertOperator(CONTAINS, 0U, 0U, 1U);
- }
- }
-}
-
-- (void)testINPredicateOnNullWithNonNullValues
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [AllOptionalTypes createInRealm:realm withValue:@[@YES, @1, @1, @1, @"abc",
- [@"a" dataUsingEncoding:NSUTF8StringEncoding],
- [NSDate dateWithTimeIntervalSince1970:1]]];
- [realm commitWriteTransaction];
-
- ////////////////////////
- // Literal Predicates
- ////////////////////////
-
- // BOOL
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"boolObj IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"boolObj IN {YES}"];
-
- // int
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"intObj IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"intObj IN {1}"];
-
- // float
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"floatObj IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"floatObj IN {1}"];
-
- // double
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"doubleObj IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"doubleObj IN {1}"];
-
- // NSString
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"string IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"string IN {'abc'}"];
-
- // NSData
- // Can't represent NSData with NSPredicate literal. See format predicates below
-
- // NSDate
- // Can't represent NSDate with NSPredicate literal. See format predicates below
-
- ////////////////////////
- // Format Predicates
- ////////////////////////
-
- // BOOL
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"boolObj IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"boolObj IN %@", @[@YES]];
-
- // int
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"intObj IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"intObj IN %@", @[@1]];
-
- // float
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"floatObj IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"floatObj IN %@", @[@1]];
-
- // double
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"doubleObj IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"doubleObj IN %@", @[@1]];
-
- // NSString
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"string IN %@", @[@"abc"]];
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"string IN %@", @[NSNull.null]];
-
- // NSData
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"data IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"data IN %@", @[[@"a" dataUsingEncoding:NSUTF8StringEncoding]]];
-
- // NSDate
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"date IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"date IN %@", @[[NSDate dateWithTimeIntervalSince1970:1]]];
-}
-
-- (void)testINPredicateOnNullWithNullValues
-{
- RLMRealm *realm = [RLMRealm defaultRealm];
-
- [realm beginWriteTransaction];
- [AllOptionalTypes createInRealm:realm withValue:@[NSNull.null, NSNull.null,
- NSNull.null, NSNull.null,
- NSNull.null, NSNull.null,
- NSNull.null]];
- [realm commitWriteTransaction];
-
- ////////////////////////
- // Literal Predicates
- ////////////////////////
-
- // BOOL
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"boolObj IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"boolObj IN {YES}"];
-
- // int
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"intObj IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"intObj IN {1}"];
-
- // float
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"floatObj IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"floatObj IN {1}"];
-
- // double
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"doubleObj IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"doubleObj IN {1}"];
-
- // NSString
- [self testClass:[AllOptionalTypes class] withNormalCount:1 notCount:0 where:@"string IN {NULL}"];
- [self testClass:[AllOptionalTypes class] withNormalCount:0 notCount:1 where:@"string IN {'abc'}"];
-
- // NSData
- // Can't represent NSData with NSPredicate literal. See format predicates below
-
- // NSDate
- // Can't represent NSDate with NSPredicate literal. See format predicates below
-
- ////////////////////////
- // Format Predicates
- ////////////////////////
-
- // BOOL
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"boolObj IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"boolObj IN %@", @[@YES]];
-
- // int
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"intObj IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"intObj IN %@", @[@1]];
-
- // float
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"floatObj IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"floatObj IN %@", @[@1]];
-
- // double
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"doubleObj IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"doubleObj IN %@", @[@1]];
-
- // NSString
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"string IN %@", @[@"abc"]];
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"string IN %@", @[NSNull.null]];
-
- // NSData
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"data IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"data IN %@", @[[@"a" dataUsingEncoding:NSUTF8StringEncoding]]];
-
- // NSDate
- [self testClass:[AllOptionalTypes class] withNormalCount:1U notCount:0U where:@"date IN %@", @[NSNull.null]];
- [self testClass:[AllOptionalTypes class] withNormalCount:0U notCount:1U where:@"date IN %@", @[[NSDate dateWithTimeIntervalSince1970:1]]];
-}
-*/
-
diff --git a/tests/js/realm-tests.js b/tests/js/realm-tests.js
index cc0e2bfc..628adfde 100644
--- a/tests/js/realm-tests.js
+++ b/tests/js/realm-tests.js
@@ -19,11 +19,10 @@
'use strict';
var Realm = require('realm');
-var BaseTest = require('./base-test');
var TestCase = require('./asserts');
var schemas = require('./schemas');
-module.exports = BaseTest.extend({
+module.exports = {
testRealmConstructor: function() {
var realm = new Realm({schema: []});
TestCase.assertTrue(realm instanceof Realm);
@@ -160,13 +159,16 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(Realm.schemaVersion(Realm.defaultPath), -1);
var realm = new Realm({schema: []});
+ TestCase.assertEqual(realm.schemaVersion, 0);
TestCase.assertEqual(Realm.schemaVersion(Realm.defaultPath), 0);
realm = new Realm({schema: [], schemaVersion: 2, path: 'another.realm'});
+ TestCase.assertEqual(realm.schemaVersion, 2);
TestCase.assertEqual(Realm.schemaVersion('another.realm'), 2);
var encryptionKey = new Int8Array(64);
realm = new Realm({schema: [], schemaVersion: 3, path: 'encrypted.realm', encryptionKey: encryptionKey});
+ TestCase.assertEqual(realm.schemaVersion, 3);
TestCase.assertEqual(Realm.schemaVersion('encrypted.realm', encryptionKey), 3);
TestCase.assertThrows(function() {
@@ -652,7 +654,7 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(notificationName, 'change');
var secondNotificationCount = 0;
- function secondNotification(realm, name) {
+ function secondNotification() {
secondNotificationCount++;
}
@@ -750,7 +752,7 @@ module.exports = BaseTest.extend({
// copy should not overwrite existing files
Realm.copyBundledRealmFiles();
- var realm = new Realm({path: 'dates-v5.realm', schema: [schemas.DateObject]});
+ realm = new Realm({path: 'dates-v5.realm', schema: [schemas.DateObject]});
TestCase.assertEqual(realm.objects('Date')[0].currentDate.getTime(), 1);
},
-});
+};
diff --git a/tests/js/results-tests.js b/tests/js/results-tests.js
index 09149967..24b3822f 100644
--- a/tests/js/results-tests.js
+++ b/tests/js/results-tests.js
@@ -19,11 +19,10 @@
'use strict';
var Realm = require('realm');
-var BaseTest = require('./base-test');
var TestCase = require('./asserts');
var schemas = require('./schemas');
-module.exports = BaseTest.extend({
+module.exports = {
testResultsConstructor: function() {
var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject');
@@ -100,15 +99,16 @@ module.exports = BaseTest.extend({
testResultsInvalidObjectType: function() {
var realm = new Realm({schema: [schemas.TestObject]});
TestCase.assertThrows(function() {
- var objects = realm.objects('NotTestObject');
+ realm.objects('NotTestObject');
});
},
testResultsEnumerate: function() {
var realm = new Realm({schema: [schemas.TestObject]});
var objects = realm.objects('TestObject');
+ var index;
- for (var index in objects) {
+ for (index in objects) {
TestCase.assertTrue(false, "No objects should have been enumerated");
}
@@ -119,7 +119,7 @@ module.exports = BaseTest.extend({
var count = 0;
var keys = Object.keys(objects);
- for (var index in objects) {
+ for (index in objects) {
TestCase.assertEqual(count++, +index);
TestCase.assertEqual(keys[index], index);
}
@@ -185,7 +185,7 @@ module.exports = BaseTest.extend({
realm.create('IntPrimaryObject', {primaryCol: 0, valueCol: 'c'});
});
- var primaries = function(results, prop) {
+ var primaries = function(results) {
return results.map(function(object) {
return object.primaryCol;
});
@@ -368,4 +368,4 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(snapshot.length, 0);
});
}
-});
+};
diff --git a/tests/react-test-app/.eslintrc.json b/tests/react-test-app/.eslintrc.json
index 37f901d5..2e15d198 100644
--- a/tests/react-test-app/.eslintrc.json
+++ b/tests/react-test-app/.eslintrc.json
@@ -18,7 +18,6 @@
"parser": "babel-eslint",
"parserOptions": {
"ecmaFeatures": {
- "forOf": false,
"jsx": true
}
},
diff --git a/tests/react-test-app/index.android.js b/tests/react-test-app/index.android.js
index 75bd0741..da211d31 100644
--- a/tests/react-test-app/index.android.js
+++ b/tests/react-test-app/index.android.js
@@ -17,60 +17,44 @@
////////////////////////////////////////////////////////////////////////////
'use strict';
-const React = require('react');
-const Realm = require('realm');
-const RealmTests = require('realm-tests');
-const builder = require('xmlbuilder');
-const RNFS = require('react-native-fs');
-
-const {
+import {
AppRegistry,
StyleSheet,
Image,
Text,
View,
- TouchableNativeFeedback,
-} = require('react-native');
+} from 'react-native';
-RealmTests.registerTests({
- ListViewTest: require('./tests/listview-test'),
-});
+import builder from 'xmlbuilder';
+import React from 'react';
+import RNFS from 'react-native-fs';
+import { getTestNames, runTest } from './tests';
-function runTests() {
+async function runTests() {
+ let testNames = getTestNames();
let rootXml = builder.create('testsuites');
- let testNames = RealmTests.getTestNames();
for (let suiteName in testNames) {
let itemTestsuite = rootXml.ele('testsuite');
let nbrTests = 0;
let nbrFailures = 0;
- console.log('Starting suite ' + suiteName);
+ console.log('Starting ' + suiteName);
- testNames[suiteName].forEach((testName) => {
+ for (let testName of testNames[suiteName]) {
nbrTests++;
let itemTest = itemTestsuite.ele('testcase');
itemTest.att('name', testName);
- console.log('Starting ' + testName);
- RealmTests.runTest(suiteName, 'beforeEach');
-
try {
- RealmTests.runTest(suiteName, testName);
- console.log('+ ' + testName);
+ runTest(suiteName, testName);
}
catch (e) {
- console.log('- ' + testName);
- console.warn(e.message);
-
itemTest.ele('error', {'message': ''}, e.message);
nbrFailures++;
}
- finally {
- RealmTests.runTest(suiteName, 'afterEach');
- }
- });
+ }
// update Junit XML report
itemTestsuite.att('name', suiteName);
@@ -80,55 +64,57 @@ function runTests() {
}
// export unit tests results
- var xmlString = rootXml.end({ pretty: true, indent: ' ', newline: '\n' });
- var path = '/sdcard/tests.xml';
+ let xmlString = rootXml.end({
+ pretty: true,
+ indent: ' ',
+ newline: '\n',
+ });
// write the unit tests reports
- RNFS.writeFile(path, xmlString , 'utf8')
- .then((success) => {
+ try {
+ await RNFS.writeFile('/sdcard/tests.xml', xmlString, 'utf8');
console.log('__REALM_REACT_ANDROID_TESTS_COMPLETED__');
- })
- .catch((err) => {
- console.log(err.message);
- });
-
+ }
+ catch (e) {
+ console.error(e);
+ }
}
class ReactTests extends React.Component {
- render() {
- return (
-
-
- Running Tests...
-
+ render() {
+ return (
+
+
+ Running Tests...
+
- runTests()}
- />
-
- );
- }
+ runTests()}
+ />
+
+ );
+ }
}
-var styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: '#F5FCFF',
- },
- welcome: {
- fontSize: 20,
- textAlign: 'center',
- margin: 10,
- },
- instructions: {
- textAlign: 'center',
- color: '#333333',
- marginBottom: 5,
- },
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#F5FCFF',
+ },
+ welcome: {
+ fontSize: 20,
+ textAlign: 'center',
+ margin: 10,
+ },
+ instructions: {
+ textAlign: 'center',
+ color: '#333333',
+ marginBottom: 5,
+ },
});
AppRegistry.registerComponent('ReactTests', () => ReactTests);
diff --git a/tests/react-test-app/index.ios.js b/tests/react-test-app/index.ios.js
index cce02e5e..d1aaaa7b 100644
--- a/tests/react-test-app/index.ios.js
+++ b/tests/react-test-app/index.ios.js
@@ -18,23 +18,21 @@
'use strict';
-const React = require('react');
-const Realm = require('realm');
-const tests = require('./tests');
-
-const {
+import {
AppRegistry,
StyleSheet,
Text,
- TouchableHighlight,
View,
-} = require('react-native');
+} from 'react-native';
+
+import React from 'react';
+import { runTests } from './tests';
class ReactTests extends React.Component {
render() {
return (
-
+
Tap to Run Tests
@@ -46,7 +44,7 @@ class ReactTests extends React.Component {
}
}
-var styles = StyleSheet.create({
+const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
diff --git a/tests/react-test-app/tests/index.js b/tests/react-test-app/tests/index.js
index 4e4e8aaa..2eff1504 100644
--- a/tests/react-test-app/tests/index.js
+++ b/tests/react-test-app/tests/index.js
@@ -18,22 +18,14 @@
'use strict';
-const React = require('react-native');
-const RealmTests = require('realm-tests');
+import { NativeAppEventEmitter, NativeModules } from 'react-native';
+import * as RealmTests from 'realm-tests';
+import ListViewTest from './listview-test';
RealmTests.registerTests({
- ListViewTest: require('./listview-test'),
+ ListViewTest,
});
-const {
- NativeAppEventEmitter,
- NativeModules,
-} = React;
-
-module.exports = {
- runTests,
-};
-
// Listen for event to run a particular test.
NativeAppEventEmitter.addListener('realm-run-test', (test) => {
let error;
@@ -48,29 +40,41 @@ NativeAppEventEmitter.addListener('realm-run-test', (test) => {
// Inform the native test harness about the test suite once it's ready.
setTimeout(() => {
- NativeModules.Realm.emit('realm-test-names', RealmTests.getTestNames());
+ // The emit() method only exists on iOS, for now.
+ if (NativeModules.Realm.emit) {
+ NativeModules.Realm.emit('realm-test-names', getTestNames());
+ }
}, 0);
-function runTests() {
- let testNames = RealmTests.getTestNames();
+export function getTestNames() {
+ return RealmTests.getTestNames();
+}
+
+export function runTests() {
+ let testNames = getTestNames();
for (let suiteName in testNames) {
console.log('Starting ' + suiteName);
for (let testName of testNames[suiteName]) {
- RealmTests.runTest(suiteName, 'beforeEach');
-
- try {
- RealmTests.runTest(suiteName, testName);
- console.log('+ ' + testName);
- }
- catch (e) {
- console.warn('- ' + testName);
- console.warn(e.message);
- }
- finally {
- RealmTests.runTest(suiteName, 'afterEach');
- }
+ runTest(suiteName, testName);
}
}
}
+
+export function runTest(suiteName, testName) {
+ RealmTests.runTest(suiteName, 'beforeEach');
+
+ try {
+ RealmTests.runTest(suiteName, testName);
+ console.log('+ ' + testName);
+ }
+ catch (e) {
+ console.warn('- ' + testName);
+ console.warn(e.message || e);
+ throw e;
+ }
+ finally {
+ RealmTests.runTest(suiteName, 'afterEach');
+ }
+}
diff --git a/tests/react-test-app/tests/listview-test.js b/tests/react-test-app/tests/listview-test.js
index d6d8827e..8e28975e 100644
--- a/tests/react-test-app/tests/listview-test.js
+++ b/tests/react-test-app/tests/listview-test.js
@@ -18,9 +18,9 @@
'use strict';
-const Realm = require('realm');
-const { ListView } = require('realm/react-native');
-const { assertEqual, assertTrue } = require('realm-tests/asserts');
+import Realm from 'realm';
+import { ListView } from 'realm/react-native';
+import { assertEqual, assertTrue } from 'realm-tests/asserts';
const OBJECT_SCHEMA = {
name: 'UniqueObject',
@@ -48,11 +48,7 @@ function createDataSource() {
});
}
-module.exports = {
- afterEach() {
- Realm.clearTestState();
- },
-
+export default {
testDataSource() {
let realm = createRealm();
let objects = realm.objects('UniqueObject').sorted('id');