Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MOR-103: Add unit tests for core code #51

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f086ce3
Issue-22: Added unit tests for core User and ArbitraryKeys structs
klown Jul 20, 2020
e7d8114
Issue-22: Added partial tests for Preferences core object
klown Jul 20, 2020
c381f1f
Issue-22: Improved Preferences tests and removed extra whitespace
klown Jul 21, 2020
e7cb9f7
Issue-22: Merged upstream master branch into issue-22
klown Jul 21, 2020
d58f52b
Issue-22: Improved Preferences tests
klown Jul 21, 2020
ceab047
Issue-22: Unit test for Preferences; fixed bugs in remove(key:)
klown Jul 22, 2020
6e07a6f
Issue-22: Added unit tests for Storage
klown Jul 24, 2020
791d310
Issue-22: Merged upstream master branch into issue-22
klown Jul 24, 2020
40ef825
Issue-22: Auto-changes to project meta data, e.g., project.pbxproj
klown Jul 27, 2020
fe9e08b
Issue-22: Merged changes from upstream master branch
klown Jul 27, 2020
470a556
Issue-22: Merged changes from upstream master branch
klown Jul 28, 2020
8313538
MOR-103: Minor improvements
klown Jul 30, 2020
0f39677
MOR-103: Merged upstream master branch into issue-22
klown Aug 4, 2020
8a4ff32
Issue-22: Merged changes from upstream master branch
klown Aug 6, 2020
7801df9
MOR-103: Merged change from upstream master branch
klown Aug 7, 2020
3023769
MOR-103: Asynchronous tests and test for loading default preferences
klown Aug 10, 2020
24b77e2
MOR-103: Merged changes from upstream master branch
klown Aug 10, 2020
ce4b91a
MOR-103: Forced sequence of asynchronous tests
klown Aug 10, 2020
3e15eed
MOR-103: Merged changes from upstream master branch
klown Aug 11, 2020
83fbfc1
MOR-103: Updated Storage tests
klown Aug 11, 2020
e2b352e
MOR-103: Merged changes from upstream master branch
klown Aug 12, 2020
eb8977b
MOR-103: Attempt at removing Preferences files created for testing
klown Aug 14, 2020
b5e3959
MOR-103: Added remove() to Storage
klown Aug 14, 2020
250454a
MOR-103: Fixed typo
klown Aug 14, 2020
b613829
MOR-103: Merged master branch into feature/klown-morphic-core-unit-tests
klown Aug 31, 2020
7ef7f9e
MOR-103: Replaced general XCTAssert() with specific assertion functions
klown Aug 31, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion MorphicCore/MorphicCore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
31A0A5AD2405B75500166668 /* UserDeafults+Morphic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A0A5AC2405B75500166668 /* UserDeafults+Morphic.swift */; };
31DDA6A32424130900F18A43 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31DDA6A22424130900F18A43 /* Storage.swift */; };
31DDA6A624241CF900F18A43 /* Record.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31DDA6A524241CF900F18A43 /* Record.swift */; };
8011AF9424C61EAE00A49F96 /* UserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8011AF9324C61EAE00A49F96 /* UserTests.swift */; };
8011AF9624C61FB200A49F96 /* ArbitraryKeysTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8011AF9524C61FB200A49F96 /* ArbitraryKeysTests.swift */; };
8011AF9824C6256400A49F96 /* PreferencesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8011AF9724C6256400A49F96 /* PreferencesTests.swift */; };
806C04D224CA08AF0022E647 /* StorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 806C04D124CA08AF0022E647 /* StorageTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -45,6 +49,10 @@
31A0A5AC2405B75500166668 /* UserDeafults+Morphic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDeafults+Morphic.swift"; sourceTree = "<group>"; };
31DDA6A22424130900F18A43 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = "<group>"; };
31DDA6A524241CF900F18A43 /* Record.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Record.swift; sourceTree = "<group>"; };
8011AF9324C61EAE00A49F96 /* UserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserTests.swift; sourceTree = "<group>"; };
8011AF9524C61FB200A49F96 /* ArbitraryKeysTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArbitraryKeysTests.swift; sourceTree = "<group>"; };
8011AF9724C6256400A49F96 /* PreferencesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesTests.swift; sourceTree = "<group>"; };
806C04D124CA08AF0022E647 /* StorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -104,8 +112,12 @@
31A0A5602405965600166668 /* MorphicCoreTests */ = {
isa = PBXGroup;
children = (
8011AF9724C6256400A49F96 /* PreferencesTests.swift */,
31A0A5612405965600166668 /* MorphicCoreTests.swift */,
31A0A5632405965600166668 /* Info.plist */,
8011AF9324C61EAE00A49F96 /* UserTests.swift */,
8011AF9524C61FB200A49F96 /* ArbitraryKeysTests.swift */,
806C04D124CA08AF0022E647 /* StorageTests.swift */,
);
path = MorphicCoreTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -167,7 +179,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1130;
LastUpgradeCheck = 1130;
LastUpgradeCheck = 1160;
ORGANIZATIONNAME = "Raising the Floor";
TargetAttributes = {
31A0A5522405965600166668 = {
Expand Down Expand Up @@ -235,7 +247,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8011AF9424C61EAE00A49F96 /* UserTests.swift in Sources */,
31A0A5622405965600166668 /* MorphicCoreTests.swift in Sources */,
8011AF9824C6256400A49F96 /* PreferencesTests.swift in Sources */,
806C04D224CA08AF0022E647 /* StorageTests.swift in Sources */,
8011AF9624C61FB200A49F96 /* ArbitraryKeysTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1150"
LastUpgradeVersion = "1160"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
10 changes: 5 additions & 5 deletions MorphicCore/MorphicCore/Preferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,16 @@ public struct Preferences: Codable, Record {
return defaults?[key.solution]?.values[key.preference] ?? nil
}

public func remove(key: Key) {
guard var defaults = defaults else {
public mutating func remove(key: Key) {
guard defaults != nil else {
return
}
guard var solution = defaults[key.solution] else {
guard var solution = defaults?[key.solution] else {
return
}
solution.values.removeValue(forKey: key.preference)
if solution.values.count == 0 {
defaults.removeValue(forKey: key.solution)
if solution.values.isEmpty {
defaults?.removeValue(forKey: key.solution)
}
}

Expand Down
26 changes: 25 additions & 1 deletion MorphicCore/MorphicCore/Storage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,31 @@ public class Storage {
}
}
}

/// Delete the object
/// - parameters:
/// - record: The record to remove
internal func remove<RecordType>(record: RecordType, completion: @escaping (_ status: LoadStatus, _ document: RecordType?) -> Void) throws where RecordType: Record {
guard let prefsUrl = url(for: record.identifier, type: RecordType.self) else {
os_log(.error, log: logger, "Could not obtain a valid file url for removing")
DispatchQueue.main.async {
completion(.fileUrlMissing, record)
}
return
}
// Same logic as contains() where file doesn't exist
// i.e. doesn't exist? "already" removed.
guard fileManager.fileExists(atPath: prefsUrl.path) else {
DispatchQueue.main.async {
completion(.success, record)
}
return
}
try fileManager.removeItem(at: prefsUrl)
DispatchQueue.main.async {
completion(.success, record)
}
}

/// Check if a record exists
/// - parameters:
/// - identifier: The identifier of the object to load
Expand Down
1 change: 1 addition & 0 deletions MorphicCore/MorphicCore/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public struct User: Codable, Record {
try container.encode(preferencesId, forKey: .preferencesId)
try container.encode(firstName, forKey: .firstName)
try container.encode(lastName, forKey: .lastName)
try container.encode(email, forKey: .email)
}

// MARK: - Identification
Expand Down
54 changes: 54 additions & 0 deletions MorphicCore/MorphicCoreTests/ArbitraryKeysTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2020 Raising the Floor - International
// Copyright 2020 OCAD University
//
// Licensed under the New BSD license. You may not use this file except in
// compliance with this License.
//
// You may obtain a copy of the License at
// https://github.com/GPII/universal/blob/master/LICENSE.txt
//
// The R&D leading to these results received funding from the:
// * Rehabilitation Services Administration, US Dept. of Education under
// grant H421A150006 (APCP)
// * National Institute on Disability, Independent Living, and
// Rehabilitation Research (NIDILRR)
// * Administration for Independent Living & Dept. of Education under grants
// H133E080022 (RERC-IT) and H133E130028/90RE5003-01-00 (UIITA-RERC)
// * European Union's Seventh Framework Programme (FP7/2007-2013) grant
// agreement nos. 289016 (Cloud4all) and 610510 (Prosperity4All)
// * William and Flora Hewlett Foundation
// * Ontario Ministry of Research and Innovation
// * Canadian Foundation for Innovation
// * Adobe Foundation
// * Consumer Electronics Association Foundation
//
// ArbitraryKeysTests.swift
// MorphicCoreTests

import XCTest
@testable import MorphicCore

class ArbitraryKeysTests: XCTestCase {

var aKeyGivenInt: ArbitraryKeys!
var aKeyGivenString: ArbitraryKeys!

let testInt = 42
let testString = "stringKey"

override func setUpWithError() throws {
try super.setUpWithError()
aKeyGivenInt = ArbitraryKeys(intValue: testInt)
aKeyGivenString = ArbitraryKeys(stringValue: testString)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
aKeyGivenInt = nil
aKeyGivenString = nil
}

func testInits() throws {
XCTAssertEqual(aKeyGivenInt.intValue, testInt, "ArbitraryKey created with integer")
XCTAssertEqual(aKeyGivenString.stringValue, testString, "Arbitrary key created with string")
}
}
133 changes: 133 additions & 0 deletions MorphicCore/MorphicCoreTests/PreferencesTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Copyright 2020 Raising the Floor - International
// Copyright 2020 OCAD University
//
// Licensed under the New BSD license. You may not use this file except in
// compliance with this License.
//
// You may obtain a copy of the License at
// https://github.com/GPII/universal/blob/master/LICENSE.txt
//
// The R&D leading to these results received funding from the:
// * Rehabilitation Services Administration, US Dept. of Education under
// grant H421A150006 (APCP)
// * National Institute on Disability, Independent Living, and
// Rehabilitation Research (NIDILRR)
// * Administration for Independent Living & Dept. of Education under grants
// H133E080022 (RERC-IT) and H133E130028/90RE5003-01-00 (UIITA-RERC)
// * European Union's Seventh Framework Programme (FP7/2007-2013) grant
// agreement nos. 289016 (Cloud4all) and 610510 (Prosperity4All)
// * William and Flora Hewlett Foundation
// * Ontario Ministry of Research and Innovation
// * Canadian Foundation for Innovation
// * Adobe Foundation
// * Consumer Electronics Association Foundation
//
// PreferencesTests.swift
// MorphicCoreTests

import XCTest
@testable import MorphicCore

class PreferencesTests: XCTestCase {

var carlaPrefs: Preferences!
let prefsId = UUID().uuidString
let carlaId = UUID().uuidString

var magFactorKey: Preferences.Key!
let magnifierName = "Magnifier"
let magFactorPref = "magfactor"
let magFactorVal: Double = 2.0

var inverseVideoKey: Preferences.Key!
let inverseVideoPref = "inverse_video"
let inverseVideoVal: Bool = true

var nonExistentKey: Preferences.Key!
let nonExistentSolution = "nonSolution"
let nonExistentPref = "nullPref"
let nonExistentVal: Int = 0

override func setUpWithError() throws {
carlaPrefs = Preferences(identifier: prefsId)
carlaPrefs.userId = carlaId
magFactorKey = Preferences.Key(solution: magnifierName, preference: magFactorPref)
inverseVideoKey = Preferences.Key(solution: magnifierName, preference: inverseVideoPref)
nonExistentKey = Preferences.Key(solution: nonExistentSolution, preference: nonExistentPref)
}

override func tearDownWithError() throws {
carlaPrefs = nil
magFactorKey = nil
inverseVideoKey = nil
nonExistentKey = nil
}

func testCreation() {
XCTAssertEqual(type(of: carlaPrefs).typeName, Preferences.typeName, "Check type name")
XCTAssertEqual(carlaPrefs.identifier, prefsId, "Check preferences id")
XCTAssertEqual(carlaPrefs.userId, carlaId, "Check user id")
XCTAssertNil(carlaPrefs.defaults, "Check empty default preferences values")
}

func testSetGet() {
carlaPrefs.set(nil, for: magFactorKey)
XCTAssertNil(carlaPrefs.get(key: magFactorKey), "Test set()/get() with magnification factor of nil")

carlaPrefs.set(magFactorVal, for: magFactorKey)
XCTAssertEqual(magFactorVal, carlaPrefs.get(key: magFactorKey) as! Double, "Test set()/get() with magnification factor")

carlaPrefs.set(inverseVideoVal, for: inverseVideoKey)
XCTAssertEqual(inverseVideoVal, carlaPrefs.get(key: inverseVideoKey) as! Bool, "Test set()/get() with inverse video")
}

func testRemove() {
// Check that there is no magnification factor, then initialize it and confirm that
// it is set.
XCTAssertNil(carlaPrefs.get(key: magFactorKey), "Magnification factor nil before set()")
carlaPrefs.set(magFactorVal, for: magFactorKey)
XCTAssertNotNil(carlaPrefs.get(key: magFactorKey), "Magnification factor set")

// Test "removal" of non-existent preferences and that the mag factor is unaffected.
XCTAssertNil(carlaPrefs.get(key: nonExistentKey), "Test non-existent preference before removal")
carlaPrefs.remove(key: nonExistentKey)
XCTAssertNil(carlaPrefs.get(key: nonExistentKey), "Test non-existent preference after removal")
XCTAssertNotNil(carlaPrefs.get(key: magFactorKey), "Test magnification factor still present after removing non-existent preference")

// Remove mag factor preference.
carlaPrefs.remove(key: magFactorKey)
XCTAssertNil(carlaPrefs.get(key: magFactorKey), "Magnification factor nil after remove()")
}

func testKeyValueTuples() {
// At start, there should be no preferences
var prefsTuples = carlaPrefs.keyValueTuples()
XCTAssertTrue(prefsTuples.isEmpty, "Check for zero preferences")

// Add two preferences
carlaPrefs.set(magFactorVal, for: magFactorKey)
carlaPrefs.set(inverseVideoVal, for: inverseVideoKey)

// Check that the preferences were added
prefsTuples = carlaPrefs.keyValueTuples()
XCTAssert(2 == prefsTuples.count, "Check for two preferences")
XCTAssertTrue(containsTuple(magFactorKey, magFactorVal, prefsTuples), "Check presence of magnification factor preference")
XCTAssertTrue(containsTuple(inverseVideoKey, inverseVideoVal, prefsTuples), "Check presence of inverse video preference")

// Check that non-existent preference is absent
XCTAssertFalse(containsTuple(nonExistentKey, nonExistentVal, prefsTuples), "Check absence of non-existent preference")
}

func containsTuple(_ inKey: Preferences.Key, _ inValue: Interoperable, _ tuplesArray: [(Preferences.Key, Interoperable?)]) -> Bool {
guard !tuplesArray.isEmpty else {
return false
}
for (key, val) in tuplesArray {
if (inKey == key) &&
(inValue != nil && val != nil) {
return true
}
}
return false
}
}
Loading