Skip to content

Commit

Permalink
add unit test cases for migration
Browse files Browse the repository at this point in the history
lint fixes
  • Loading branch information
zihejia committed Sep 7, 2021
1 parent 74bce0d commit 6ee1f2c
Show file tree
Hide file tree
Showing 21 changed files with 248 additions and 131 deletions.
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ disabled_rules:
- type_body_length
- variable_name
- trailing_whitespace
- unused_optional_binding
47 changes: 28 additions & 19 deletions MixpanelDemo/MixpanelDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
8654F3002671636B00ACEED5 /* MixpanelPeopleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8654F2FB2671636B00ACEED5 /* MixpanelPeopleTests.swift */; };
8654F3012671636B00ACEED5 /* MixpanelOptOutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8654F2FC2671636B00ACEED5 /* MixpanelOptOutTests.swift */; };
8654F3052671C4B000ACEED5 /* MixpanelGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8654F3032671C4B000ACEED5 /* MixpanelGroupTests.swift */; };
8675E9A126DF356B0096858F /* mixpanel-testToken-events in Resources */ = {isa = PBXBuildFile; fileRef = 8675E99C26DF356A0096858F /* mixpanel-testToken-events */; };
8675E9A226DF356B0096858F /* mixpanel-testToken-groups in Resources */ = {isa = PBXBuildFile; fileRef = 8675E99E26DF356A0096858F /* mixpanel-testToken-groups */; };
8675E9A326DF356B0096858F /* mixpanel-testToken-people in Resources */ = {isa = PBXBuildFile; fileRef = 8675E99F26DF356A0096858F /* mixpanel-testToken-people */; };
8675E9AB26E144FE0096858F /* mixpanel-testToken-optOutStatus in Resources */ = {isa = PBXBuildFile; fileRef = 8675E9AA26E144FE0096858F /* mixpanel-testToken-optOutStatus */; };
8675E9B426E171AE0096858F /* mixpanel-testToken-properties in Resources */ = {isa = PBXBuildFile; fileRef = 8675E9B326E171AE0096858F /* mixpanel-testToken-properties */; };
86F86E8F22440C5D00B69832 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 86F86E8D22440C5C00B69832 /* Interface.storyboard */; };
86F86E9122440C5F00B69832 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 86F86E9022440C5F00B69832 /* Assets.xcassets */; };
86F86E9822440C5F00B69832 /* MixpanelDemoWatch Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 86F86E9722440C5F00B69832 /* MixpanelDemoWatch Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -275,6 +280,11 @@
8654F2FB2671636B00ACEED5 /* MixpanelPeopleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MixpanelPeopleTests.swift; sourceTree = "<group>"; };
8654F2FC2671636B00ACEED5 /* MixpanelOptOutTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MixpanelOptOutTests.swift; sourceTree = "<group>"; };
8654F3032671C4B000ACEED5 /* MixpanelGroupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MixpanelGroupTests.swift; sourceTree = "<group>"; };
8675E99C26DF356A0096858F /* mixpanel-testToken-events */ = {isa = PBXFileReference; explicitFileType = text.pbxproject; path = "mixpanel-testToken-events"; sourceTree = "<group>"; };
8675E99E26DF356A0096858F /* mixpanel-testToken-groups */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = "mixpanel-testToken-groups"; sourceTree = "<group>"; };
8675E99F26DF356A0096858F /* mixpanel-testToken-people */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = "mixpanel-testToken-people"; sourceTree = "<group>"; };
8675E9AA26E144FE0096858F /* mixpanel-testToken-optOutStatus */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = "mixpanel-testToken-optOutStatus"; sourceTree = "<group>"; };
8675E9B326E171AE0096858F /* mixpanel-testToken-properties */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = "mixpanel-testToken-properties"; sourceTree = "<group>"; };
86F86E8B22440C5C00B69832 /* MixpanelDemoWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MixpanelDemoWatch.app; sourceTree = BUILT_PRODUCTS_DIR; };
86F86E8E22440C5C00B69832 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = "<group>"; };
86F86E9022440C5F00B69832 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -323,13 +333,6 @@
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
0AAB97762ADB463FE09D6381 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
8654F2C1266ED84F00ACEED5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -470,6 +473,18 @@
path = MixpanelDemoMacUITests;
sourceTree = "<group>";
};
8675E9A626DF37B20096858F /* Resources */ = {
isa = PBXGroup;
children = (
8675E99C26DF356A0096858F /* mixpanel-testToken-events */,
8675E9B326E171AE0096858F /* mixpanel-testToken-properties */,
8675E99E26DF356A0096858F /* mixpanel-testToken-groups */,
8675E99F26DF356A0096858F /* mixpanel-testToken-people */,
8675E9AA26E144FE0096858F /* mixpanel-testToken-optOutStatus */,
);
name = Resources;
sourceTree = "<group>";
};
86F86E8C22440C5C00B69832 /* MixpanelDemoWatch */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -524,6 +539,7 @@
E12BD03A1D8A14D6008989C9 /* Supporting Files */ = {
isa = PBXGroup;
children = (
8675E9A626DF37B20096858F /* Resources */,
E12BD03C1D8A14F3008989C9 /* Assets.xcassets */,
E15FF7ED1D0461130076CDE3 /* Info.plist */,
);
Expand Down Expand Up @@ -825,11 +841,6 @@
LastUpgradeCheck = 1200;
ORGANIZATIONNAME = Mixpanel;
TargetAttributes = {
60DDD14623D39620004F7CBB = {
CreatedOnToolsVersion = 11.2;
DevelopmentTeam = E8FVX7QLET;
ProvisioningStyle = Automatic;
};
8654F2C3266ED84F00ACEED5 = {
CreatedOnToolsVersion = 12.5;
};
Expand Down Expand Up @@ -960,13 +971,6 @@
/* End PBXReferenceProxy section */

/* Begin PBXResourcesBuildPhase section */
60DDD14523D39620004F7CBB /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
8654F2C2266ED84F00ACEED5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -1045,6 +1049,11 @@
buildActionMask = 2147483647;
files = (
E12BD03D1D8A14F3008989C9 /* Assets.xcassets in Resources */,
8675E9A226DF356B0096858F /* mixpanel-testToken-groups in Resources */,
8675E9B426E171AE0096858F /* mixpanel-testToken-properties in Resources */,
8675E9A126DF356B0096858F /* mixpanel-testToken-events in Resources */,
8675E9A326DF356B0096858F /* mixpanel-testToken-people in Resources */,
8675E9AB26E144FE0096858F /* mixpanel-testToken-optOutStatus in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
80 changes: 80 additions & 0 deletions MixpanelDemo/MixpanelDemoTests/MixpanelDemoTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -988,4 +988,84 @@ class MixpanelDemoTests: MixpanelBaseTests {
removeDBfile(testToken)
}

func testMigration() {
let token = "testToken"
// clean up
removeDBfile(token)
// copy the legacy archived file for the migration test
let legacyFiles = ["mixpanel-testToken-events", "mixpanel-testToken-properties", "mixpanel-testToken-groups", "mixpanel-testToken-people", "mixpanel-testToken-optOutStatus"]
prepareForMigrationFiles(legacyFiles)
// initialize mixpanel will do the migration automatically if found legacy archive files.
let testMixpanel = Mixpanel.initialize(token: token, flushInterval: 60)
let fileManager = FileManager.default
let libraryUrls = fileManager.urls(for: .libraryDirectory,
in: .userDomainMask)
XCTAssertFalse(fileManager.fileExists(atPath: (libraryUrls.first?.appendingPathComponent("mixpanel-testToken-events"))!.path), "after migration, the legacy archive files should be removed")
XCTAssertFalse(fileManager.fileExists(atPath: (libraryUrls.first?.appendingPathComponent("mixpanel-testToken-properties"))!.path), "after migration, the legacy archive files should be removed")
XCTAssertFalse(fileManager.fileExists(atPath: (libraryUrls.first?.appendingPathComponent("mixpanel-testToken-groups"))!.path), "after migration, the legacy archive files should be removed")
XCTAssertFalse(fileManager.fileExists(atPath: (libraryUrls.first?.appendingPathComponent("mixpanel-testToken-people"))!.path), "after migration, the legacy archive files should be removed")

let events = eventQueue(token: testMixpanel.apiToken)
XCTAssertEqual(events.count, 306)

XCTAssertEqual(events[0]["event"] as? String, "$identify")
XCTAssertEqual(events[1]["event"] as? String, "Logged in")
XCTAssertEqual(events[2]["event"] as? String, "$ae_first_open")
XCTAssertEqual(events[3]["event"] as? String, "Tracked event 1")
let properties = events.last?["properties"] as? InternalProperties
XCTAssertEqual(properties?["Cool Property"] as? [Int], [12345,301])
XCTAssertEqual(properties?["Super Property 2"] as? String, "p2")

let people = peopleQueue(token: testMixpanel.apiToken)
XCTAssertEqual(people.count, 6)
XCTAssertEqual(people[0]["$distinct_id"] as? String, "demo_user")
XCTAssertEqual(people[0]["$token"] as? String, "testToken")
let appendProperties = people[5]["$append"] as! InternalProperties
XCTAssertEqual(appendProperties["d"] as? String, "goodbye")

let group = groupQueue(token: testMixpanel.apiToken)
XCTAssertEqual(group.count, 2)
XCTAssertEqual(group[0]["$group_key"] as? String, "Cool Property")
let setProperties = group[0]["$set"] as! InternalProperties
XCTAssertEqual(setProperties["g"] as? String, "yo")
let setProperties2 = group[1]["$set"] as! InternalProperties
XCTAssertEqual(setProperties2["a"] as? Int, 1)
XCTAssertTrue(MixpanelPersistence.loadOptOutStatusFlag(apiToken: token)!)
XCTAssertTrue(MixpanelPersistence.loadAutomacticEventsEnabledFlag(apiToken: token))

//timedEvents
let testTimedEvents = MixpanelPersistence.loadTimedEvents(apiToken: token)
XCTAssertEqual(testTimedEvents.count, 3)
XCTAssertNotNil(testTimedEvents["Time Event A"])
XCTAssertNotNil(testTimedEvents["Time Event B"])
XCTAssertNotNil(testTimedEvents["Time Event C"])
let identity = MixpanelPersistence.loadIdentity(apiToken: token)
XCTAssertEqual(identity.distinctID, "demo_user")
XCTAssertEqual(identity.peopleDistinctID, "demo_user")
XCTAssertNotNil(identity.anonymousId)
XCTAssertEqual(identity.userId, "demo_user")
XCTAssertEqual(identity.alias, "New Alias")
XCTAssertEqual(identity.hadPersistedDistinctId, false)

let superProperties = MixpanelPersistence.loadSuperProperties(apiToken: token)
XCTAssertEqual(superProperties.count, 7)
XCTAssertEqual(superProperties["Super Property 1"] as? Int, 1)
XCTAssertEqual(superProperties["Super Property 7"] as? NSNull, NSNull())
removeDBfile("testToken")
}

func prepareForMigrationFiles(_ fileNames: [String]) {
for fileName in fileNames {
let fileManager = FileManager.default
let filepath = Bundle(for: type(of: self)).url(forResource: fileName, withExtension: nil)!
let libraryUrls = fileManager.urls(for: .libraryDirectory,
in: .userDomainMask)
let destURL = libraryUrls.first?.appendingPathComponent(fileName)
do {
try FileManager.default.copyItem(at: filepath, to: destURL!)
} catch let error {
print(error)
}
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8 changes: 4 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ let package = Package(
.iOS(.v9),
.tvOS(.v9),
.macOS(.v10_10),
.watchOS(.v3),
.watchOS(.v3)
],
products: [
.library(name: "Mixpanel", targets: ["Mixpanel"]),
.library(name: "Mixpanel", targets: ["Mixpanel"])
],
targets: [
.target(
Expand All @@ -21,8 +21,8 @@ let package = Package(
"Info.plist"
],
swiftSettings: [
.define("DECIDE", .when(platforms: [.iOS])),
.define("DECIDE", .when(platforms: [.iOS]))
]
),
)
]
)
18 changes: 8 additions & 10 deletions Sources/AutomaticEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// Copyright © 2017 Mixpanel. All rights reserved.
//

protocol AEDelegate {
protocol AEDelegate: AnyObject {
func track(event: String?, properties: Properties?)
func setOnce(properties: Properties)
func increment(property: String, by: Double)
Expand All @@ -21,26 +21,26 @@ class AutomaticEvents: NSObject, SKPaymentTransactionObserver, SKProductsRequest

var _minimumSessionDuration: UInt64 = 10000
var minimumSessionDuration: UInt64 {
set {
_minimumSessionDuration = newValue
}
get {
return _minimumSessionDuration
}
set {
_minimumSessionDuration = newValue
}
}
var _maximumSessionDuration: UInt64 = UINT64_MAX
var maximumSessionDuration: UInt64 {
set {
_maximumSessionDuration = newValue
}
get {
return _maximumSessionDuration
}
set {
_maximumSessionDuration = newValue
}
}

var awaitingTransactions = [String: SKPaymentTransaction]()
let defaults = UserDefaults(suiteName: "Mixpanel")
var delegate: AEDelegate?
weak var delegate: AEDelegate?
var sessionLength: TimeInterval = 0
var sessionStartTime: TimeInterval = Date().timeIntervalSince1970
var hasAddedObserver = false
Expand Down Expand Up @@ -121,7 +121,6 @@ class AutomaticEvents: NSObject, SKPaymentTransactionObserver, SKProductsRequest
case .purchased:
productIdentifiers.insert(trans.payment.productIdentifier)
awaitingTransactions[trans.payment.productIdentifier] = trans
break
case .failed: break
case .restored: break
default: break
Expand Down Expand Up @@ -172,4 +171,3 @@ class AutomaticEvents: NSObject, SKPaymentTransactionObserver, SKProductsRequest
}

#endif

1 change: 0 additions & 1 deletion Sources/Decide.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class Decide {
let lock: ReadWriteLock
var decideFetched = false
let mixpanelPersistence: MixpanelPersistence


required init(basePathIdentifier: String, lock: ReadWriteLock, mixpanelPersistence: MixpanelPersistence) {
self.decideRequest = DecideRequest(basePathIdentifier: basePathIdentifier)
Expand Down
20 changes: 10 additions & 10 deletions Sources/Flush.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Foundation

protocol FlushDelegate {
protocol FlushDelegate: AnyObject {
func flush(completion: (() -> Void)?)
func flushSuccess(type: FlushType, ids: [Int32])

Expand All @@ -19,14 +19,19 @@ protocol FlushDelegate {

class Flush: AppLifecycle {
var timer: Timer?
var delegate: FlushDelegate?
weak var delegate: FlushDelegate?
var useIPAddressForGeoLocation = true
var flushRequest: FlushRequest
var flushOnBackground = true
var _flushInterval = 0.0
private let flushIntervalReadWriteLock: DispatchQueue

var flushInterval: Double {
get {
flushIntervalReadWriteLock.sync {
return _flushInterval
}
}
set {
flushIntervalReadWriteLock.sync(flags: .barrier, execute: {
_flushInterval = newValue
Expand All @@ -35,19 +40,13 @@ class Flush: AppLifecycle {
delegate?.flush(completion: nil)
startFlushTimer()
}
get {
flushIntervalReadWriteLock.sync {
return _flushInterval
}
}
}

required init(basePathIdentifier: String) {
self.flushRequest = FlushRequest(basePathIdentifier: basePathIdentifier)
flushIntervalReadWriteLock = DispatchQueue(label: "com.mixpanel.flush_interval.lock", qos: .utility, attributes: .concurrent)
}


func flushQueue(type: FlushType, queue: Queue) {
if flushRequest.requestNotAllowed() {
return
Expand Down Expand Up @@ -119,7 +118,9 @@ class Flush: AppLifecycle {
if success {
// remove
self.delegate?.flushSuccess(type: type, ids: ids)
mutableQueue = self.removeProcessedBatch(batchSize: batchSize, queue: mutableQueue, type: type)
mutableQueue = self.removeProcessedBatch(batchSize: batchSize,
queue: mutableQueue,
type: type)
}
shouldContinue = success
semaphore.signal()
Expand All @@ -143,7 +144,6 @@ class Flush: AppLifecycle {
return shadowQueue
}


// MARK: - Lifecycle
func applicationDidBecomeActive() {
startFlushTimer()
Expand Down
10 changes: 8 additions & 2 deletions Sources/Group.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ open class Group {
let lock: ReadWriteLock
let groupKey: String
let groupID: MixpanelType
var delegate: FlushDelegate?
weak var delegate: FlushDelegate?
let metadata: SessionMetadata
let mixpanelPersistence: MixpanelPersistence

init(apiToken: String, serialQueue: DispatchQueue, lock: ReadWriteLock, groupKey: String, groupID: MixpanelType, metadata: SessionMetadata, mixpanelPersistence: MixpanelPersistence) {
init(apiToken: String,
serialQueue: DispatchQueue,
lock: ReadWriteLock,
groupKey: String,
groupID: MixpanelType,
metadata: SessionMetadata,
mixpanelPersistence: MixpanelPersistence) {
self.apiToken = apiToken
self.serialQueue = serialQueue
self.lock = lock
Expand Down
2 changes: 1 addition & 1 deletion Sources/JSONHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class JSONHandler {
}

class func deserializeData(_ data: Data) -> MPObjectToParse? {
var object: MPObjectToParse? = nil
var object: MPObjectToParse?
do {
object = try JSONSerialization.jsonObject(with: data, options: [])
} catch {
Expand Down
Loading

0 comments on commit 6ee1f2c

Please sign in to comment.