From 485925634a2a5f959a1f26295460aafefa8895bb Mon Sep 17 00:00:00 2001 From: zonble Date: Fri, 28 Jan 2022 20:43:43 +0800 Subject: [PATCH] Adds unit tests for the key handler. --- McBopomofo.xcodeproj/project.pbxproj | 31 +++ McBopomofoTests/KeyHandlerTests.mm | 230 ++++++++++++++++++ .../McBopomofoTests-Bridging-Header.h | 4 + McBopomofoTests/PreferencesTests.swift | 2 +- Source/KeyHandler.h | 7 +- Source/KeyHandler.mm | 1 + 6 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 McBopomofoTests/KeyHandlerTests.mm create mode 100644 McBopomofoTests/McBopomofoTests-Bridging-Header.h diff --git a/McBopomofo.xcodeproj/project.pbxproj b/McBopomofo.xcodeproj/project.pbxproj index e6b48956..0e608666 100644 --- a/McBopomofo.xcodeproj/project.pbxproj +++ b/McBopomofo.xcodeproj/project.pbxproj @@ -60,6 +60,12 @@ D485D3B92796A8A000657FF3 /* PreferencesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D485D3B82796A8A000657FF3 /* PreferencesTests.swift */; }; D485D3C02796CE3200657FF3 /* VersionUpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D485D3BF2796CE3200657FF3 /* VersionUpdateTests.swift */; }; D4E569DC27A34D0E00AC2CEF /* KeyHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */; }; + D4E569DF27A40F1400AC2CEF /* KeyHandlerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D4E569DE27A40F1400AC2CEF /* KeyHandlerTests.mm */; }; + D4E569E027A4123200AC2CEF /* KeyHandlerInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = D456576D279E4F7B00DF6BC9 /* KeyHandlerInput.swift */; }; + D4E569E127A4128300AC2CEF /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D461B791279DAC010070E734 /* InputState.swift */; }; + D4E569E227A412E700AC2CEF /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74427915555003C80A6 /* Preferences.swift */; }; + D4E569E427A414CB00AC2CEF /* data-plain-bpmf.txt in Resources */ = {isa = PBXBuildFile; fileRef = 6AD7CBC715FE555000691B5B /* data-plain-bpmf.txt */; }; + D4E569E527A414CB00AC2CEF /* data.txt in Resources */ = {isa = PBXBuildFile; fileRef = 6A38BBF615FC117A00A8A51F /* data.txt */; }; D4F0BBDF279AF1AF0071253C /* ArchiveUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */; }; D4F0BBE1279AF8B30071253C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBE0279AF8B30071253C /* AppDelegate.swift */; }; D4F0BBE4279B08900071253C /* BundleTranslocate.m in Sources */ = {isa = PBXBuildFile; fileRef = D4F0BBE3279B08900071253C /* BundleTranslocate.m */; }; @@ -217,6 +223,8 @@ D485D3BF2796CE3200657FF3 /* VersionUpdateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionUpdateTests.swift; sourceTree = ""; }; D4E569DA27A34CC100AC2CEF /* KeyHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyHandler.h; sourceTree = ""; }; D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyHandler.mm; sourceTree = ""; }; + D4E569DD27A40F1300AC2CEF /* McBopomofoTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "McBopomofoTests-Bridging-Header.h"; sourceTree = ""; }; + D4E569DE27A40F1400AC2CEF /* KeyHandlerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyHandlerTests.mm; sourceTree = ""; }; D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveUtil.swift; sourceTree = ""; }; D4F0BBE0279AF8B30071253C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D4F0BBE2279B08900071253C /* BundleTranslocate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BundleTranslocate.h; sourceTree = ""; }; @@ -494,6 +502,8 @@ children = ( D485D3B82796A8A000657FF3 /* PreferencesTests.swift */, D485D3BF2796CE3200657FF3 /* VersionUpdateTests.swift */, + D4E569DE27A40F1400AC2CEF /* KeyHandlerTests.mm */, + D4E569DD27A40F1300AC2CEF /* McBopomofoTests-Bridging-Header.h */, ); path = McBopomofoTests; sourceTree = ""; @@ -601,6 +611,7 @@ }; D485D3B52796A8A000657FF3 = { CreatedOnToolsVersion = 13.2.1; + LastSwiftMigration = 1320; TestTargetID = 6A0D4EA115FC0D2D00ABF4B3; }; }; @@ -672,6 +683,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4E569E527A414CB00AC2CEF /* data.txt in Resources */, + D4E569E427A414CB00AC2CEF /* data-plain-bpmf.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -737,8 +750,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D4E569DF27A40F1400AC2CEF /* KeyHandlerTests.mm in Sources */, D485D3B92796A8A000657FF3 /* PreferencesTests.swift in Sources */, + D4E569E227A412E700AC2CEF /* Preferences.swift in Sources */, + D4E569E127A4128300AC2CEF /* InputState.swift in Sources */, D485D3C02796CE3200657FF3 /* VersionUpdateTests.swift in Sources */, + D4E569E027A4123200AC2CEF /* KeyHandlerInput.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1236,6 +1253,7 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -1256,6 +1274,11 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); MACOSX_DEPLOYMENT_TARGET = 10.10; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; @@ -1265,6 +1288,7 @@ SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OBJC_BRIDGING_HEADER = "McBopomofoTests/McBopomofoTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/McBopomofo.app/Contents/MacOS/McBopomofo"; @@ -1280,6 +1304,7 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -1295,6 +1320,11 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); MACOSX_DEPLOYMENT_TARGET = 10.10; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = NO; @@ -1303,6 +1333,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OBJC_BRIDGING_HEADER = "McBopomofoTests/McBopomofoTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/McBopomofo.app/Contents/MacOS/McBopomofo"; diff --git a/McBopomofoTests/KeyHandlerTests.mm b/McBopomofoTests/KeyHandlerTests.mm new file mode 100644 index 00000000..696e79b1 --- /dev/null +++ b/McBopomofoTests/KeyHandlerTests.mm @@ -0,0 +1,230 @@ +#import +#import "KeyHandler.h" +#import "LanguageModelManager.h" +#import "McBopomofoTests-Swift.h" + +@interface KeyHandlerTests : XCTestCase + +@end + +@implementation KeyHandlerTests + +- (void)setUp +{ + [LanguageModelManager loadDataModels]; +} + +- (void)tearDown +{ +} + +- (void)testInputtingNihaoUsingMcBopomofo +{ + KeyHandler *handler = [[KeyHandler alloc] init]; + handler.inputMode = kBopomofoModeIdentifier; + + KeyHandlerInput *input; + __block InputState *state; + state = [[InputStateEmpty alloc] init]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"s" keyCode:0 charCode:'s' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"u" keyCode:0 charCode:'u' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"3" keyCode:0 charCode:'3' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"c" keyCode:0 charCode:'c' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"l" keyCode:0 charCode:'l' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"3" keyCode:0 charCode:'3' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + XCTAssertTrue([state isKindOfClass:NSClassFromString(@"McBopomofo.InputStateInputting")], @"It should be an inputting state %@.", NSStringFromClass([state class])); + NSString *composingBuffer = [(InputStateInputting *)state composingBuffer]; + XCTAssertTrue([composingBuffer isEqualToString:@"你好"], @"It should be 你好 but %@", composingBuffer); +} + +- (void)testComittingNihaoUsingMcBopomofo +{ + KeyHandler *handler = [[KeyHandler alloc] init]; + handler.inputMode = kBopomofoModeIdentifier; + + KeyHandlerInput *input; + __block InputState *state; + state = [[InputStateEmpty alloc] init]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"s" keyCode:0 charCode:'s' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"u" keyCode:0 charCode:'u' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"3" keyCode:0 charCode:'3' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"c" keyCode:0 charCode:'c' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"l" keyCode:0 charCode:'l' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"3" keyCode:0 charCode:'3' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + __block NSInteger count = 0; + + __block InputState *empty; + + input = [[KeyHandlerInput alloc] initWithInputText:@" " keyCode:0 charCode:13 flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + if (!count) { + state = inState; + } + empty = inState; + count++; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + XCTAssertTrue([state isKindOfClass:NSClassFromString(@"McBopomofo.InputStateCommitting")], @"It should be a committing state %@.", NSStringFromClass([state class])); + NSString *poppedText = [(InputStateCommitting *)state poppedText]; + XCTAssertTrue([poppedText isEqualToString:@"你好"], @"It should be 你好 but %@", poppedText); + + XCTAssertTrue([empty isKindOfClass:NSClassFromString(@"McBopomofo.InputStateEmpty")], @"It should be an empty state %@.", NSStringFromClass([state class])); +} + + +- (void)testBackspaceUsingMcBopomofo +{ + KeyHandler *handler = [[KeyHandler alloc] init]; + handler.inputMode = kBopomofoModeIdentifier; + + KeyHandlerInput *input; + __block InputState *state; + state = [[InputStateEmpty alloc] init]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"s" keyCode:0 charCode:'s' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"u" keyCode:0 charCode:'u' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"3" keyCode:0 charCode:'3' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"c" keyCode:0 charCode:'c' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"l" keyCode:0 charCode:'l' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + input = [[KeyHandlerInput alloc] initWithInputText:@"3" keyCode:0 charCode:'3' flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + XCTAssertTrue([state isKindOfClass:NSClassFromString(@"McBopomofo.InputStateInputting")], @"It should be an inputting state %@.", NSStringFromClass([state class])); + NSString *composingBuffer = [(InputStateInputting *)state composingBuffer]; + XCTAssertTrue([composingBuffer isEqualToString:@"你好"], @"It should be 你好 but %@", composingBuffer); + + input = [[KeyHandlerInput alloc] initWithInputText:@" " keyCode:0 charCode:8 flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + state = (InputStateInputting *)inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + XCTAssertTrue([state isKindOfClass:NSClassFromString(@"McBopomofo.InputStateInputting")], @"It should be a inputting state %@.", NSStringFromClass([state class])); + composingBuffer = [(InputStateInputting *)state composingBuffer]; + XCTAssertTrue([composingBuffer isEqualToString:@"你"], @"It should be 你 but %@", composingBuffer); + + __block InputStateEmpty *empty; + + input = [[KeyHandlerInput alloc] initWithInputText:@" " keyCode:0 charCode:8 flags:0 isVerticalMode:0]; + [handler handleInput:input state:state stateCallback:^(InputState * inState) { + empty = (InputStateEmpty *)inState; + } candidateSelectionCallback:^{ + } errorCallback:^{ + }]; + + XCTAssertTrue([empty isKindOfClass:NSClassFromString(@"McBopomofo.InputStateEmptyIgnoringPreviousState")], @"It should be a inputting state %@.", NSStringFromClass([state class])); +} + +@end + diff --git a/McBopomofoTests/McBopomofoTests-Bridging-Header.h b/McBopomofoTests/McBopomofoTests-Bridging-Header.h new file mode 100644 index 00000000..1b2cb5d6 --- /dev/null +++ b/McBopomofoTests/McBopomofoTests-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/McBopomofoTests/PreferencesTests.swift b/McBopomofoTests/PreferencesTests.swift index 03e71781..5d966f6d 100644 --- a/McBopomofoTests/PreferencesTests.swift +++ b/McBopomofoTests/PreferencesTests.swift @@ -1,5 +1,5 @@ import XCTest -@testable import McBopomofo +//@testable import McBopomofo class PreferencesTests: XCTestCase { diff --git a/Source/KeyHandler.h b/Source/KeyHandler.h index cb51bbab..ac531d6a 100644 --- a/Source/KeyHandler.h +++ b/Source/KeyHandler.h @@ -22,9 +22,14 @@ // OTHER DEALINGS IN THE SOFTWARE. #import -#import "McBopomofo-Swift.h" +#import @import CandidateUI; +@class KeyHandlerInput; +@class InputState; +@class InputStateInputting; +@class InputStateMarking; + NS_ASSUME_NONNULL_BEGIN extern NSString *const kBopomofoModeIdentifier; diff --git a/Source/KeyHandler.mm b/Source/KeyHandler.mm index 7e8e1823..efe095ec 100644 --- a/Source/KeyHandler.mm +++ b/Source/KeyHandler.mm @@ -28,6 +28,7 @@ #import "LanguageModelManager.h" #import "OVUTF8Helper.h" #import "KeyHandler.h" +#import "McBopomofo-Swift.h" // C++ namespace usages using namespace std;