Remove mongoFind and mostly remove adaptiveCollection (#1924)

* Use adapter.count

* use adapter.upsertOneObject

* Use adapter.deleteObjectsByQuery

* Use adapter.find

* use adapter.find

* Update tests to avoid mongoFind

* Fix a test to not use mongoFind

* Fix a test to not use mongoFind

* remove some mongoFind

* Remove some mongoFind

* Remove some mongoFind

* Remove more mongoFind

* remove more mongoFind

* remove more mongoFind

* remove more mongoFind

* remove more mongoFind

* remove more mongoFind

* remove more mongoFind

* remove more mongoFind

* remove more mongoFind

* Restore update ios device token with duplicate device token to original

* remove a mongoFind

* remove a mongoFind

* formatting

* formatting

* remove a mongoFind

* remove a mongoFind

* remove a mongoFind

* kill mongoFind

* Fix tests

* Fix tests

* fix syntax

* Fix test
This commit is contained in:
Drew
2016-05-28 09:25:09 -07:00
committed by Florent Vilmart
parent 17374eff8d
commit cd525802a6
7 changed files with 349 additions and 259 deletions

View File

@@ -2,8 +2,17 @@
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
const MongoClient = require('mongodb').MongoClient;
const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
// These tests are specific to the mongo storage adapter + mongo storage format
// and will eventually be moved into their own repo
describe('MongoStorageAdapter', () => {
beforeEach(done => {
new MongoStorageAdapter({ uri: databaseURI })
.deleteAllSchemas()
.then(done, fail);
});
it('auto-escapes symbols in auth information', () => {
spyOn(MongoClient, 'connect').and.returnValue(Promise.resolve(null));
new MongoStorageAdapter({
@@ -37,4 +46,110 @@ describe('MongoStorageAdapter', () => {
jasmine.any(Object)
);
});
it('stores objectId in _id', done => {
let adapter = new MongoStorageAdapter({ uri: databaseURI });
adapter.createObject('Foo', { objectId: 'abcde' }, { fields: { objectId: 'String' } })
.then(() => adapter._rawFind('Foo', {}))
.then(results => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(typeof obj._id).toEqual('string');
expect(obj.objectId).toBeUndefined();
done();
});
});
it('stores pointers with a _p_ prefix', (done) => {
let obj = {
objectId: 'bar',
aPointer: {
__type: 'Pointer',
className: 'JustThePointer',
objectId: 'qwerty'
}
};
let adapter = new MongoStorageAdapter({ uri: databaseURI });
adapter.createObject('APointerDarkly', obj, { fields: {
objectId: { type: 'String' },
aPointer: { type: 'Pointer', targetClass: 'JustThePointer' },
}})
.then(() => adapter._rawFind('APointerDarkly', {}))
.then(results => {
expect(results.length).toEqual(1);
let output = results[0];
expect(typeof output._id).toEqual('string');
expect(typeof output._p_aPointer).toEqual('string');
expect(output._p_aPointer).toEqual('JustThePointer$qwerty');
expect(output.aPointer).toBeUndefined();
done();
});
});
it('handles object and subdocument', done => {
let adapter = new MongoStorageAdapter({ uri: databaseURI });
let schema = { fields : { subdoc: { type: 'Object' } } };
let obj = { subdoc: {foo: 'bar', wu: 'tan'} };
adapter.createObject('MyClass', obj, schema)
.then(() => adapter._rawFind('MyClass', {}))
.then(results => {
expect(results.length).toEqual(1);
let mob = results[0];
expect(typeof mob.subdoc).toBe('object');
expect(mob.subdoc.foo).toBe('bar');
expect(mob.subdoc.wu).toBe('tan');
let obj = { 'subdoc.wu': 'clan' };
return adapter.findOneAndUpdate('MyClass', {}, schema, obj);
})
.then(() => adapter._rawFind('MyClass', {}))
.then(results => {
expect(results.length).toEqual(1);
let mob = results[0];
expect(typeof mob.subdoc).toBe('object');
expect(mob.subdoc.foo).toBe('bar');
expect(mob.subdoc.wu).toBe('clan');
done();
});
});
it('handles array, object, date', (done) => {
let adapter = new MongoStorageAdapter({ uri: databaseURI });
let obj = {
array: [1, 2, 3],
object: {foo: 'bar'},
date: {
__type: 'Date',
iso: '2016-05-26T20:55:01.154Z',
},
};
let schema = { fields: {
array: { type: 'Array' },
object: { type: 'Object' },
date: { type: 'Date' },
} };
adapter.createObject('MyClass', obj, schema)
.then(() => adapter._rawFind('MyClass', {}))
.then(results => {
expect(results.length).toEqual(1);
let mob = results[0];
expect(mob.array instanceof Array).toBe(true);
expect(typeof mob.object).toBe('object');
expect(mob.date instanceof Date).toBe(true);
return adapter.find('MyClass', {}, schema, {});
})
.then(results => {
expect(results.length).toEqual(1);
let mob = results[0];
expect(mob.array instanceof Array).toBe(true);
expect(typeof mob.object).toBe('object');
expect(mob.date.__type).toBe('Date');
expect(mob.date.iso).toBe('2016-05-26T20:55:01.154Z');
done();
})
.catch(error => {
console.log(error);
fail();
done();
});
});
});

View File

@@ -1,6 +1,7 @@
var OAuth = require("../src/authDataManager/OAuth1Client");
var request = require('request');
var Config = require("../src/Config");
var defaultColumns = require('../src/Controllers/SchemaController').defaultColumns;
describe('OAuth', function() {
@@ -283,9 +284,10 @@ describe('OAuth', function() {
"Expiration should be cleared");
// make sure the auth data is properly deleted
var config = new Config(Parse.applicationId);
config.database.mongoFind('_User', {
_id: model.id
}).then((res) => {
config.database.adapter.find('_User', { objectId: model.id }, {
fields: Object.assign({}, defaultColumns._Default, defaultColumns._Installation),
}, {})
.then(res => {
expect(res.length).toBe(1);
expect(res[0]._auth_data_myoauth).toBeUndefined();
expect(res[0]._auth_data_myoauth).not.toBeNull();

View File

@@ -203,7 +203,7 @@ describe('miscellaneous', function() {
return obj.save();
}).then(() => {
var db = DatabaseAdapter.getDatabaseConnection(appId, 'test_');
return db.mongoFind('TestObject', {}, {});
return db.adapter.find('TestObject', {}, { fields: {} }, {});
}).then((results) => {
expect(results.length).toEqual(1);
expect(results[0]['foo']).toEqual('bar');

View File

@@ -11,9 +11,11 @@ var rest = require('../src/rest');
var config = new Config('test');
let database = DatabaseAdapter.getDatabaseConnection('test', 'test_');
let defaultColumns = require('../src/Controllers/SchemaController').defaultColumns;
const installationSchema = { fields: Object.assign({}, defaultColumns._Default, defaultColumns._Installation) };
describe('Installations', () => {
it('creates an android installation with ids', (done) => {
var installId = '12345678-abcd-abcd-abcd-123456789abc';
var device = 'android';
@@ -22,9 +24,8 @@ describe('Installations', () => {
'deviceType': device
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(obj.installationId).toEqual(installId);
@@ -41,9 +42,8 @@ describe('Installations', () => {
'deviceType': device
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(obj.deviceToken).toEqual(t);
@@ -60,9 +60,8 @@ describe('Installations', () => {
'deviceType': device
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(obj.installationId).toEqual(installId);
@@ -80,9 +79,8 @@ describe('Installations', () => {
'channels': ['foo', 'bar']
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(obj.installationId).toEqual(installId);
@@ -104,9 +102,8 @@ describe('Installations', () => {
'channels': ['foo', 'bar']
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(obj.deviceToken).toEqual(t);
@@ -203,9 +200,8 @@ describe('Installations', () => {
'custom': 'allowed'
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(obj.custom).toEqual('allowed');
@@ -228,18 +224,17 @@ describe('Installations', () => {
var firstObject;
var secondObject;
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
firstObject = results[0];
delete input.deviceToken;
delete input.channels;
input['foo'] = 'bar';
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
secondObject = results[0];
expect(firstObject._id).toEqual(secondObject._id);
@@ -268,15 +263,14 @@ describe('Installations', () => {
var firstObject;
var secondObject;
rest.create(config, auth.nobody(config), '_Installation', input1)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
firstObject = results[0];
return rest.create(config, auth.nobody(config), '_Installation', input2);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(2);
if (results[0]['_id'] == firstObject._id) {
secondObject = results[1];
@@ -284,9 +278,9 @@ describe('Installations', () => {
secondObject = results[0];
}
return rest.create(config, auth.nobody(config), '_Installation', input3);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0]['_id']).toEqual(secondObject._id);
done();
@@ -310,17 +304,14 @@ describe('Installations', () => {
}).then(() => {
input.installationId = installId3;
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation',
{installationId: installId1}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', {installationId: installId1}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
return database.mongoFind('_Installation',
{installationId: installId2}, {});
}).then((results) => {
return database.adapter.find('_Installation', {installationId: installId2}, installationSchema, {});
}).then(results => {
expect(results.length).toEqual(1);
return database.mongoFind('_Installation',
{installationId: installId3}, {});
return database.adapter.find('_Installation', {installationId: installId3}, installationSchema, {});
}).then((results) => {
expect(results.length).toEqual(1);
done();
@@ -329,29 +320,31 @@ describe('Installations', () => {
it('updating with new channels', (done) => {
var input = {
'installationId': '12345678-abcd-abcd-abcd-123456789abc',
'deviceType': 'android',
'channels': ['foo', 'bar']
installationId: '12345678-abcd-abcd-abcd-123456789abc',
deviceType: 'android',
channels: ['foo', 'bar']
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
var id = results[0]['_id'];
var id = results[0].objectId;
var update = {
'channels': ['baz']
};
return rest.update(config, auth.nobody(config),
'_Installation', id, update);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
return rest.update(config, auth.nobody(config), '_Installation', id, update);
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0].channels.length).toEqual(1);
expect(results[0].channels[0]).toEqual('baz');
done();
}).catch((error) => { console.log(error); });
}).catch(error => {
console.log(error);
fail();
done();
});
});
it('update android fails with new installation id', (done) => {
@@ -363,15 +356,11 @@ describe('Installations', () => {
'channels': ['foo', 'bar']
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'installationId': installId2
};
return rest.update(config, auth.nobody(config), '_Installation',
results[0]['_id'], input);
input = { 'installationId': installId2 };
return rest.update(config, auth.nobody(config), '_Installation', results[0].objectId, input);
}).then(() => {
fail('Updating the installation should have failed.');
done();
@@ -390,15 +379,11 @@ describe('Installations', () => {
'channels': ['foo', 'bar']
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'deviceToken': b
};
return rest.update(config, auth.nobody(config), '_Installation',
results[0]['_id'], input);
input = { 'deviceToken': b };
return rest.update(config, auth.nobody(config), '_Installation', results[0].objectId, input);
}).then(() => {
fail('Updating the installation should have failed.');
}).catch((error) => {
@@ -418,20 +403,18 @@ describe('Installations', () => {
'channels': ['foo', 'bar']
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'installationId': installId,
'deviceToken': u,
'deviceType': 'ios'
};
return rest.update(config, auth.nobody(config), '_Installation',
results[0]['_id'], input);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
return rest.update(config, auth.nobody(config), '_Installation', results[0].objectId, input);
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0].deviceToken).toEqual(u);
done();
@@ -446,15 +429,13 @@ describe('Installations', () => {
'channels': ['foo', 'bar']
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'deviceType': 'ios'
};
return rest.update(config, auth.nobody(config), '_Installation',
results[0]['_id'], input);
return rest.update(config, auth.nobody(config), '_Installation', results[0].objectId, input);
}).then(() => {
fail('Should not have been able to update Installation.');
done();
@@ -472,18 +453,16 @@ describe('Installations', () => {
'channels': ['foo', 'bar']
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'custom': 'allowed'
};
return rest.update(config, auth.nobody(config), '_Installation',
results[0]['_id'], input);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
return rest.update(config, auth.nobody(config), '_Installation', results[0].objectId, input);
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0]['custom']).toEqual('allowed');
done();
@@ -508,34 +487,30 @@ describe('Installations', () => {
'deviceType': 'android'
};
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation',
{installationId: installId1}, {});
}).then((results) => {
expect(results.length).toEqual(1);
})
.then(() => database.adapter.find('_Installation', {installationId: installId1}, installationSchema, {}))
.then(results => {
firstObject = results[0];
return database.mongoFind('_Installation',
{installationId: installId2}, {});
}).then((results) => {
expect(results.length).toEqual(1);
return database.adapter.find('_Installation', {installationId: installId2}, installationSchema, {});
}).then(results => {
expect(results.length).toEqual(1);
secondObject = results[0];
// Update second installation to conflict with first installation
input = {
'objectId': secondObject._id,
'objectId': secondObject.objectId,
'deviceToken': t
};
return rest.update(config, auth.nobody(config), '_Installation',
secondObject._id, input);
}).then(() => {
return rest.update(config, auth.nobody(config), '_Installation', secondObject.objectId, input);
})
.then(() => database.adapter.find('_Installation', {objectId: firstObject.objectId}, installationSchema, {}))
.then(results => {
// The first object should have been deleted
return database.mongoFind('_Installation', {_id: firstObject._id}, {});
}).then((results) => {
expect(results.length).toEqual(0);
done();
}).catch((error) => { console.log(error); });
});
it('update ios device token with duplicate device token', (done) => {
var installId1 = '11111111-abcd-abcd-abcd-123456789abc';
var installId2 = '22222222-abcd-abcd-abcd-123456789abc';
@@ -554,15 +529,14 @@ describe('Installations', () => {
'deviceType': 'ios'
};
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation',
{installationId: installId1}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', {installationId: installId1}, installationSchema, {}))
.then((results) => {
expect(results.length).toEqual(1);
firstObject = results[0];
return database.mongoFind('_Installation',
{installationId: installId2}, {});
}).then((results) => {
return database.adapter.find('_Installation', {installationId: installId2}, installationSchema, {});
})
.then(results => {
expect(results.length).toEqual(1);
secondObject = results[0];
// Update second installation to conflict with first installation id
@@ -570,12 +544,11 @@ describe('Installations', () => {
'installationId': installId2,
'deviceToken': t
};
return rest.update(config, auth.nobody(config), '_Installation',
secondObject._id, input);
}).then(() => {
return rest.update(config, auth.nobody(config), '_Installation', secondObject.objectId, input);
})
.then(() => database.adapter.find('_Installation', {objectId: firstObject.objectId}, installationSchema, {}))
.then(results => {
// The first object should have been deleted
return database.mongoFind('_Installation', {_id: firstObject._id}, {});
}).then((results) => {
expect(results.length).toEqual(0);
done();
}).catch((error) => { console.log(error); });
@@ -596,9 +569,9 @@ describe('Installations', () => {
input.installationId = installId2;
input.appIdentifier = 'bar';
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
// The first object should have been deleted during merge
expect(results.length).toEqual(1);
expect(results[0].installationId).toEqual(installId2);
@@ -614,19 +587,17 @@ describe('Installations', () => {
'deviceType': 'ios'
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'deviceToken': t,
'channels': []
};
return rest.update(config, auth.nobody(config), '_Installation',
results[0]['_id'], input);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
return rest.update(config, auth.nobody(config), '_Installation', results[0].objectId, input);
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0].installationId).toEqual(installId);
expect(results[0].deviceToken).toEqual(t);
@@ -649,21 +620,19 @@ describe('Installations', () => {
'deviceType': 'ios'
};
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation',
{deviceToken: t}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', { deviceToken: t }, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'deviceToken': t,
'installationId': installId,
'deviceType': 'ios'
};
return rest.update(config, auth.nobody(config), '_Installation',
results[0]['_id'], input);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
return rest.update(config, auth.nobody(config), '_Installation', results[0].objectId, input);
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0].installationId).toEqual(installId);
expect(results[0].deviceToken).toEqual(t);
@@ -686,10 +655,9 @@ describe('Installations', () => {
'deviceType': 'ios'
};
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation',
{deviceToken: t}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', { deviceToken: t }, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'deviceToken': t,
@@ -700,11 +668,10 @@ describe('Installations', () => {
'amount': 1
}
};
return rest.update(config, auth.nobody(config), '_Installation',
results[0]['_id'], input);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
return rest.update(config, auth.nobody(config), '_Installation', results[0].objectId, input);
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0].installationId).toEqual(installId);
expect(results[0].deviceToken).toEqual(t);
@@ -724,9 +691,8 @@ describe('Installations', () => {
var installObj;
var tokenObj;
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
installObj = results[0];
input = {
@@ -734,9 +700,9 @@ describe('Installations', () => {
'deviceType': 'ios'
};
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation', {deviceToken: t}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', { deviceToken: t }, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
tokenObj = results[0];
input = {
@@ -744,11 +710,10 @@ describe('Installations', () => {
'deviceToken': t,
'deviceType': 'ios'
};
return rest.update(config, auth.nobody(config), '_Installation',
installObj._id, input);
}).then(() => {
return database.mongoFind('_Installation', {_id: tokenObj._id}, {});
}).then((results) => {
return rest.update(config, auth.nobody(config), '_Installation', installObj.objectId, input);
})
.then(() => database.adapter.find('_Installation', { objectId: tokenObj.objectId }, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0].installationId).toEqual(installId);
expect(results[0].deviceToken).toEqual(t);
@@ -766,9 +731,8 @@ describe('Installations', () => {
var installObj;
var tokenObj;
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
installObj = results[0];
input = {
@@ -776,9 +740,9 @@ describe('Installations', () => {
'deviceType': 'ios'
};
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation', {deviceToken: t}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', { deviceToken: t }, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
tokenObj = results[0];
input = {
@@ -790,11 +754,10 @@ describe('Installations', () => {
'amount': 1
}
};
return rest.update(config, auth.nobody(config), '_Installation',
installObj._id, input);
}).then(() => {
return database.mongoFind('_Installation', {_id: tokenObj._id}, {});
}).then((results) => {
return rest.update(config, auth.nobody(config), '_Installation', installObj.objectId, input);
})
.then(() => database.adapter.find('_Installation', { objectId: tokenObj.objectId }, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0].installationId).toEqual(installId);
expect(results[0].deviceToken).toEqual(t);
@@ -821,9 +784,8 @@ describe('Installations', () => {
'deviceType': 'ios'
};
rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
input = {
'installationId': installId,
@@ -831,13 +793,18 @@ describe('Installations', () => {
'deviceType': 'ios'
};
return rest.create(config, auth.nobody(config), '_Installation', input);
}).then(() => {
return database.mongoFind('_Installation', {}, {});
}).then((results) => {
})
.then(() => database.adapter.find('_Installation', {}, installationSchema, {}))
.then(results => {
expect(results.length).toEqual(1);
expect(results[0].deviceToken).toEqual(t);
expect(results[0].installationId).toEqual(installId);
done();
})
.catch(error => {
console.log(error);
fail();
done();
});
});

View File

@@ -1,3 +1,4 @@
"use strict";
// These tests check the "create" / "update" functionality of the REST API.
var auth = require('../src/Auth');
var cache = require('../src/cache');
@@ -11,65 +12,69 @@ var config = new Config('test');
var database = DatabaseAdapter.getDatabaseConnection('test', 'test_');
describe('rest create', () => {
it('handles _id', (done) => {
rest.create(config, auth.nobody(config), 'Foo', {}).then(() => {
return database.mongoFind('Foo', {});
}).then((results) => {
it('handles _id', done => {
rest.create(config, auth.nobody(config), 'Foo', {})
.then(() => database.adapter.find('Foo', {}, { fields: {} }, {}))
.then(results => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(typeof obj._id).toEqual('string');
expect(obj.objectId).toBeUndefined();
expect(typeof obj.objectId).toEqual('string');
expect(obj._id).toBeUndefined();
done();
});
});
it('handles array, object, date', (done) => {
let now = new Date();
var obj = {
array: [1, 2, 3],
object: {foo: 'bar'},
date: Parse._encode(new Date()),
date: Parse._encode(now),
};
rest.create(config, auth.nobody(config), 'MyClass', obj).then(() => {
return database.mongoFind('MyClass', {}, {});
}).then((results) => {
rest.create(config, auth.nobody(config), 'MyClass', obj)
.then(() => database.adapter.find('MyClass', {}, { fields: {
array: { type: 'Array' },
object: { type: 'Object' },
date: { type: 'Date' },
} }, {}))
.then(results => {
expect(results.length).toEqual(1);
var mob = results[0];
expect(mob.array instanceof Array).toBe(true);
expect(typeof mob.object).toBe('object');
expect(mob.date instanceof Date).toBe(true);
expect(mob.date.__type).toBe('Date');
expect(new Date(mob.date.iso).getTime()).toBe(now.getTime());
done();
});
});
it('handles object and subdocument', (done) => {
var obj = {
subdoc: {foo: 'bar', wu: 'tan'},
};
rest.create(config, auth.nobody(config), 'MyClass', obj).then(() => {
return database.mongoFind('MyClass', {}, {});
}).then((results) => {
it('handles object and subdocument', done => {
let obj = { subdoc: {foo: 'bar', wu: 'tan'} };
rest.create(config, auth.nobody(config), 'MyClass', obj)
.then(() => database.adapter.find('MyClass', {}, { fields: {} }, {}))
.then(results => {
expect(results.length).toEqual(1);
var mob = results[0];
let mob = results[0];
expect(typeof mob.subdoc).toBe('object');
expect(mob.subdoc.foo).toBe('bar');
expect(mob.subdoc.wu).toBe('tan');
expect(typeof mob._id).toEqual('string');
var obj = {
'subdoc.wu': 'clan',
};
rest.update(config, auth.nobody(config), 'MyClass', mob._id, obj).then(() => {
return database.mongoFind('MyClass', {}, {});
}).then((results) => {
expect(typeof mob.objectId).toEqual('string');
let obj = { 'subdoc.wu': 'clan' };
return rest.update(config, auth.nobody(config), 'MyClass', mob.objectId, obj)
})
.then(() => database.adapter.find('MyClass', {}, { fields: {} }, {}))
.then(results => {
expect(results.length).toEqual(1);
var mob = results[0];
let mob = results[0];
expect(typeof mob.subdoc).toBe('object');
expect(mob.subdoc.foo).toBe('bar');
expect(mob.subdoc.wu).toBe('clan');
done();
});
})
.catch(error => {
console.log(error);
fail();
done();
});
});
@@ -240,8 +245,8 @@ describe('rest create', () => {
});
});
it('stores pointers with a _p_ prefix', (done) => {
var obj = {
it('stores pointers', done => {
let obj = {
foo: 'bar',
aPointer: {
__type: 'Pointer',
@@ -250,15 +255,21 @@ describe('rest create', () => {
}
};
rest.create(config, auth.nobody(config), 'APointerDarkly', obj)
.then((r) => {
return database.mongoFind('APointerDarkly', {});
}).then((results) => {
.then(() => database.adapter.find('APointerDarkly', {}, { fields: {
foo: { type: 'String' },
aPointer: { type: 'Pointer', targetClass: 'JustThePointer' },
}}, {}))
.then(results => {
expect(results.length).toEqual(1);
var output = results[0];
expect(typeof output._id).toEqual('string');
expect(typeof output._p_aPointer).toEqual('string');
expect(output._p_aPointer).toEqual('JustThePointer$qwerty');
expect(output.aPointer).toBeUndefined();
let output = results[0];
expect(typeof output.foo).toEqual('string');
expect(typeof output._p_aPointer).toEqual('undefined');
expect(output._p_aPointer).toBeUndefined();
expect(output.aPointer).toEqual({
__type: 'Pointer',
className: 'JustThePointer',
objectId: 'qwerty'
});
done();
});
});

View File

@@ -236,6 +236,11 @@ export class MongoStorageAdapter {
.then(objects => objects.map(object => mongoObjectToParseObject(className, object, schema)));
}
// Used in tests
_rawFind(className, query) {
return this.adaptiveCollection(className).then(collection => collection.find(query));
}
// Executs a count.
count(className, query, schema) {
return this.adaptiveCollection(className)

View File

@@ -305,15 +305,13 @@ DatabaseController.prototype.handleRelationUpdates = function(className, objectI
// Adds a relation.
// Returns a promise that resolves successfully iff the add was successful.
const relationSchema = { fields: { relatedId: { type: 'String' }, owningId: { type: 'String' } } };
DatabaseController.prototype.addRelation = function(key, fromClassName, fromId, toId) {
let doc = {
relatedId: toId,
owningId : fromId
};
let className = `_Join:${key}:${fromClassName}`;
return this.adapter.adaptiveCollection(className).then((coll) => {
return coll.upsertOne(doc, doc);
});
return this.adapter.upsertOneObject(`_Join:${key}:${fromClassName}`, doc, relationSchema, doc);
};
// Removes a relation.
@@ -324,9 +322,13 @@ DatabaseController.prototype.removeRelation = function(key, fromClassName, fromI
relatedId: toId,
owningId: fromId
};
let className = `_Join:${key}:${fromClassName}`;
return this.adapter.adaptiveCollection(className).then(coll => {
return coll.deleteOne(doc);
return this.adapter.deleteObjectsByQuery(`_Join:${key}:${fromClassName}`, doc, relationSchema)
.catch(error => {
// We don't care if they try to delete a non-existent relation.
if (error.code == Parse.Error.OBJECT_NOT_FOUND) {
return;
}
throw error;
});
};
@@ -415,15 +417,6 @@ DatabaseController.prototype.canAddField = function(schema, className, object, a
return Promise.resolve();
}
// Runs a mongo query on the database.
// This should only be used for testing - use 'find' for normal code
// to avoid Mongo-format dependencies.
// Returns a promise that resolves to a list of items.
DatabaseController.prototype.mongoFind = function(className, query, options = {}) {
return this.adapter.adaptiveCollection(className)
.then(collection => collection.find(query, options));
};
// Deletes everything in the database matching the current collectionPrefix
// Won't delete collections in the system namespace
// Returns a promise.
@@ -449,17 +442,15 @@ function keysForQuery(query) {
// Returns a promise for a list of related ids given an owning id.
// className here is the owning className.
DatabaseController.prototype.relatedIds = function(className, key, owningId) {
return this.adapter.adaptiveCollection(joinTableName(className, key))
.then(coll => coll.find({owningId : owningId}))
.then(results => results.map(r => r.relatedId));
return this.adapter.find(joinTableName(className, key), { owningId }, relationSchema, {})
.then(results => results.map(result => result.relatedId));
};
// Returns a promise for a list of owning ids given some related ids.
// className here is the owning className.
DatabaseController.prototype.owningIds = function(className, key, relatedIds) {
return this.adapter.adaptiveCollection(joinTableName(className, key))
.then(coll => coll.find({ relatedId: { '$in': relatedIds } }))
.then(results => results.map(r => r.owningId));
return this.adapter.find(joinTableName(className, key), { relatedId: { '$in': relatedIds } }, relationSchema, {})
.then(results => results.map(result => result.owningId));
};
// Modifies query so that it no longer has $in on relation fields, or
@@ -702,8 +693,7 @@ DatabaseController.prototype.deleteSchema = function(className) {
if (!exist) {
return Promise.resolve();
}
return this.adapter.adaptiveCollection(className)
.then(collection => collection.count())
return this.adapter.count(className)
.then(count => {
if (count > 0) {
throw new Parse.Error(255, `Class ${className} is not empty, contains ${count} objects, cannot drop schema.`);