Skip to content

Commit

Permalink
Merge pull request #234 from Kinvey/feature/MLIBZ-1549-id_required_bu…
Browse files Browse the repository at this point in the history
…t_kmd_acl_not

MLIBZ-1549: _id required, but not _kmd and _acl
  • Loading branch information
tejasranade committed Sep 8, 2017
2 parents 2ba5e0c + e23e053 commit bd2cbe3
Show file tree
Hide file tree
Showing 6 changed files with 374 additions and 7 deletions.
20 changes: 18 additions & 2 deletions Kinvey/Kinvey/FindOperation.swift
Expand Up @@ -66,6 +66,7 @@ internal class FindOperation<T: Persistable>: ReadOperation<T, AnyRandomAccessCo

@discardableResult
func executeNetwork(_ completionHandler: CompletionHandler? = nil) -> Request {
let multiRequest = MultiRequest()
let deltaSet = self.deltaSet && (cache != nil ? !cache!.isEmpty() : false)
let fields: Set<String>? = deltaSet ? [Entity.Key.entityId, "\(Entity.Key.metadata).\(Metadata.Key.lastModifiedTime)"] : nil
let request = client.networkRequestFactory.buildAppDataFindByQuery(
Expand All @@ -80,6 +81,18 @@ internal class FindOperation<T: Persistable>: ReadOperation<T, AnyRandomAccessCo
self.resultsHandler?(jsonArray)
if let cache = self.cache, deltaSet {
let refObjs = self.reduceToIdsLmts(jsonArray)
guard jsonArray.count == refObjs.count else {
let operation = FindOperation(
query: self.query,
deltaSet: false,
readPolicy: self.readPolicy,
cache: cache,
options: self.options
)
let request = operation.executeNetwork(completionHandler)
multiRequest += request
return
}
let deltaSet = self.computeDeltaSet(self.query, refObjs: refObjs)
var allIds = Set<String>(minimumCapacity: deltaSet.created.count + deltaSet.updated.count + deltaSet.deleted.count)
allIds.formUnion(deltaSet.created)
Expand Down Expand Up @@ -166,7 +179,9 @@ internal class FindOperation<T: Persistable>: ReadOperation<T, AnyRandomAccessCo
} else {
func convert(_ jsonArray: [JsonDictionary]) -> AnyRandomAccessCollection<T> {
let startTime = CFAbsoluteTimeGetCurrent()
let entities = AnyRandomAccessCollection(jsonArray.lazy.map {
let entities = AnyRandomAccessCollection(jsonArray.lazy.filter {
($0[Entity.Key.entityId] as? String) != nil
}.map {
T(JSON: $0)!
})
log.debug("Time elapsed: \(CFAbsoluteTimeGetCurrent() - startTime) s")
Expand Down Expand Up @@ -198,7 +213,8 @@ internal class FindOperation<T: Persistable>: ReadOperation<T, AnyRandomAccessCo
completionHandler?(.failure(buildError(data, response, error, self.client)))
}
}
return request
multiRequest += request
return multiRequest
}

fileprivate func removeCachedRecords<S : Sequence>(_ cache: AnyCache<T>, keys: S, deleted: Set<String>) where S.Iterator.Element == String {
Expand Down
1 change: 1 addition & 0 deletions Kinvey/Kinvey/GetOperation.swift
Expand Up @@ -48,6 +48,7 @@ internal class GetOperation<T: Persistable>: ReadOperation<T, T, Swift.Error>, R
if let response = response,
response.isOK,
let json = self.client.responseParser.parse(data),
json[Entity.Key.entityId] != nil,
let obj = T(JSON: json)
{
self.cache?.save(entity: obj)
Expand Down
6 changes: 6 additions & 0 deletions Kinvey/Kinvey/Kinvey.swift
Expand Up @@ -195,6 +195,12 @@ func buildError(
let description = json["description"]
{
return Error.appNotFound(description: description)
} else if let response = response,
response.isOK,
let json = client.responseParser.parse(data),
json[Entity.Key.entityId] == nil
{
return Error.objectIdMissing
} else if let response = response,
let json = client.responseParser.parse(data)
{
Expand Down
3 changes: 2 additions & 1 deletion Kinvey/KinveyTests/DataTypeTestCase.swift
Expand Up @@ -52,7 +52,7 @@ class DataTypeTestCase: StoreTestCase {

mockResponse(json: [
[
"_id" : Foundation.UUID().uuidString,
"_id" : UUID().uuidString,
"fullName2" : [
"lastName" : "Barros",
"fontDescriptor" : [
Expand All @@ -63,6 +63,7 @@ class DataTypeTestCase: StoreTestCase {
],
"boolValue" : true,
"fullName" : [
"_id" : UUID().uuidString,
"lastName" : "Barros",
"firstName" : "Victor"
],
Expand Down
251 changes: 247 additions & 4 deletions Kinvey/KinveyTests/DeltaSetCacheTestCase.swift
Expand Up @@ -1335,7 +1335,7 @@ class DeltaSetCacheTestCase: KinveyTestCase {
}
}

func testFindOneRecordDeltaSet() {
func testFindOneRecordDeltaSetNoChange() {
signUp()

let store = DataStore<Person>.collection(.sync, deltaSet: true)
Expand Down Expand Up @@ -1399,10 +1399,10 @@ class DeltaSetCacheTestCase: KinveyTestCase {

let query = Query(format: "\(Person.aclProperty() ?? PersistableAclKey).creator == %@", client.activeUser!.userId)

var urlProtocolCalled = false
var mockCount = 0
if useMockData {
mockResponse { request in
urlProtocolCalled = true
mockCount += 1
return HttpResponse(json: [
[
"_id" : mockObjectId!,
Expand All @@ -1422,7 +1422,250 @@ class DeltaSetCacheTestCase: KinveyTestCase {
defer {
if useMockData {
setURLProtocol(nil)
XCTAssertTrue(urlProtocolCalled)
XCTAssertEqual(mockCount, 1)
}
}

weak var expectationFind = expectation(description: "Find")

store.find(query, readPolicy: .forceNetwork) { results, error in
XCTAssertNotNil(results)
XCTAssertNil(error)

if let results = results {
XCTAssertEqual(results.count, 1)

if let person = results.first {
XCTAssertEqual(person.name, "Victor")
}
}

expectationFind?.fulfill()
}

waitForExpectations(timeout: defaultTimeout) { (error) in
expectationFind = nil
}
}

func testFindOneRecordDeltaSetChanged() {
signUp()

let store = DataStore<Person>.collection(.sync, deltaSet: true)

let person = Person()
person.name = "Victor"

weak var expectationSave = expectation(description: "Save")

store.save(person) { (person, error) in
XCTAssertTrue(Thread.isMainThread)
XCTAssertNotNil(person)
XCTAssertNil(error)

expectationSave?.fulfill()
}

waitForExpectations(timeout: defaultTimeout) { (error) in
expectationSave = nil
}

var mockObjectId: String? = nil
var mockDate: Date? = nil
do {
if useMockData {
mockObjectId = UUID().uuidString
mockDate = Date()
mockResponse(statusCode: 201, json: [
"_id" : mockObjectId!,
"name" : "Victor",
"age" : 0,
"_acl" : [
"creator" : client.activeUser?.userId
],
"_kmd" : [
"lmt" : mockDate?.toString(),
"ect" : mockDate?.toString()
]
])
}
defer {
if useMockData {
setURLProtocol(nil)
}
}

weak var expectationPush = expectation(description: "Push")

store.push() { (count, error) in
XCTAssertTrue(Thread.isMainThread)
XCTAssertNotNil(count)
XCTAssertNil(error)

expectationPush?.fulfill()
}

waitForExpectations(timeout: defaultTimeout) { (error) in
expectationPush = nil
}
}

let query = Query(format: "\(Person.aclProperty() ?? PersistableAclKey).creator == %@", client.activeUser!.userId)

var mockCount = 0
if useMockData {
mockResponse { request in
mockCount += 1
return HttpResponse(json: [
[
"_id" : mockObjectId!,
"name" : "Victor",
"age" : 0,
"_acl" : [
"creator" : self.client.activeUser?.userId
],
"_kmd" : [
"lmt" : Date(timeInterval: 1, since: mockDate!).toString(),
"ect" : mockDate?.toString()
]
]
])
}
}
defer {
if useMockData {
setURLProtocol(nil)
XCTAssertEqual(mockCount, 2)
}
}

weak var expectationFind = expectation(description: "Find")

store.find(query, readPolicy: .forceNetwork) { results, error in
XCTAssertNotNil(results)
XCTAssertNil(error)

if let results = results {
XCTAssertEqual(results.count, 1)

if let person = results.first {
XCTAssertEqual(person.name, "Victor")
}
}

expectationFind?.fulfill()
}

waitForExpectations(timeout: defaultTimeout) { (error) in
expectationFind = nil
}
}

func testFindOneRecordDeltaSetNoKmd() {
signUp()

let store = DataStore<Person>.collection(.sync, deltaSet: true)

let person = Person()
person.name = "Victor"

weak var expectationSave = expectation(description: "Save")

store.save(person) { (person, error) in
XCTAssertTrue(Thread.isMainThread)
XCTAssertNotNil(person)
XCTAssertNil(error)

expectationSave?.fulfill()
}

waitForExpectations(timeout: defaultTimeout) { (error) in
expectationSave = nil
}

var mockObjectId: String? = nil
var mockDate: Date? = nil
do {
if useMockData {
mockObjectId = UUID().uuidString
mockDate = Date()
mockResponse(statusCode: 201, json: [
"_id" : mockObjectId!,
"name" : "Victor",
"age" : 0,
"_acl" : [
"creator" : client.activeUser?.userId
]
])
}
defer {
if useMockData {
setURLProtocol(nil)
}
}

weak var expectationPush = expectation(description: "Push")

store.push() { (count, error) in
XCTAssertTrue(Thread.isMainThread)
XCTAssertNotNil(count)
XCTAssertNil(error)

expectationPush?.fulfill()
}

waitForExpectations(timeout: defaultTimeout) { (error) in
expectationPush = nil
}
}

let query = Query(format: "\(Person.aclProperty() ?? PersistableAclKey).creator == %@", client.activeUser!.userId)

var mockCount = 0
if useMockData {
mockResponse { request in
defer {
mockCount += 1
}
switch mockCount {
case 0:
let urlComponents = URLComponents(url: request.url!, resolvingAgainstBaseURL: false)
let fields = urlComponents?.queryItems?.filter({ $0.name == "fields" }).first
XCTAssertNotNil(fields)
if let fields = fields {
XCTAssertNotNil(fields.value)
if let fieldsValue = fields.value {
let fields = fieldsValue.components(separatedBy: ",")
XCTAssertEqual(fields.count, 2)
XCTAssertTrue(fields.contains("_id"))
XCTAssertTrue(fields.contains("_kmd.lmt"))
}
}
return HttpResponse(json: [
[
"_id" : mockObjectId!
]
])
case 1:
return HttpResponse(json: [
[
"_id" : mockObjectId!,
"name" : "Victor",
"age" : 0,
"_acl" : [
"creator" : self.client.activeUser?.userId
]
]
])
default:
Swift.fatalError()
}
}
}
defer {
if useMockData {
setURLProtocol(nil)
XCTAssertEqual(mockCount, 2)
}
}

Expand Down

0 comments on commit bd2cbe3

Please sign in to comment.