Skip to content

Commit

Permalink
Merge pull request #1454 from ychin/add-basic-macvim-objc-tests
Browse files Browse the repository at this point in the history
Add basic tests for MacVim
  • Loading branch information
ychin authored Oct 27, 2023
2 parents 1f30462 + 9fe55b0 commit 81d23bc
Show file tree
Hide file tree
Showing 12 changed files with 1,002 additions and 98 deletions.
16 changes: 13 additions & 3 deletions .github/workflows/ci-macvim.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ jobs:
# Later, we pass the --enable-sparkle_1 flag to configure to set the corresponding ifdef.
ln -fhs Sparkle_1.framework src/MacVim/Sparkle.framework
# Sparkle shows a dialog asking if the user wants to check for updates on 2nd launch of
# MacVim. On Sparkle 1 this is annoyingly a modal dialog box and interferes with tests.
# Just disable it by pre-setting to not check for updates.
defaults write org.vim.MacVim SUEnableAutomaticChecks 0
- name: Set up Xcode
if: matrix.xcode != ''
run: |
Expand Down Expand Up @@ -310,7 +315,12 @@ jobs:
echo 'MacVim_xcode8.xcodeproj is outdated. Run "make -C src macvim-xcodeproj-compat" to re-generate it.'; false
fi
- name: Build test binaries
- name: Test MacVim
timeout-minutes: 10
run: |
make ${MAKE_BUILD_ARGS} -C src macvim-tests
- name: Build Vim test binaries
run: |
# Build the unit test binaries first. With link-time-optimization they take some time to link. Running them
# separately de-couples them from the timeout in tests, and allow us to build in parallel jobs (since tests
Expand All @@ -320,11 +330,11 @@ jobs:
set -o verbose
make ${MAKE_BUILD_ARGS} -j${NPROC} -C src unittesttargets
- name: Test
- name: Test Vim
timeout-minutes: 20
run: make ${MAKE_BUILD_ARGS} test

- name: Test GUI
- name: Test Vim (GUI)
timeout-minutes: 20
run: |
make ${MAKE_BUILD_ARGS} -C src/testdir clean
Expand Down
157 changes: 72 additions & 85 deletions src/MacVim/MMAppController.m
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ - (NSArray *)filterOpenFiles:(NSArray *)filenames
- (void)handleXcodeModEvent:(NSAppleEventDescriptor *)event
replyEvent:(NSAppleEventDescriptor *)reply;
#endif
+ (NSDictionary*)parseOpenURL:(NSURL*)url;
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
replyEvent:(NSAppleEventDescriptor *)reply;
- (NSMutableDictionary *)extractArgumentsFromOdocEvent:
Expand Down Expand Up @@ -523,30 +524,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification
// If the current version is larger, set that to be stored. Don't
// want to do it otherwise to prevent testing older versions flipping
// the stored version back to an old one.
NSArray<NSString*> *lastUsedVersionItems = [lastUsedVersion componentsSeparatedByString:@"."];
NSArray<NSString*> *currentVersionItems = [currentVersion componentsSeparatedByString:@"."];
// Compare two arrays lexographically. We just assume that version
// numbers are also X.Y.Z… with no "beta" etc texts.
BOOL currentVersionLarger = NO;
for (int i = 0; i < currentVersionItems.count || i < lastUsedVersionItems.count; i++) {
if (i >= currentVersionItems.count) {
currentVersionLarger = NO;
break;
}
if (i >= lastUsedVersionItems.count) {
currentVersionLarger = YES;
break;
}
if (currentVersionItems[i].integerValue > lastUsedVersionItems[i].integerValue) {
currentVersionLarger = YES;
break;
}
else if (currentVersionItems[i].integerValue < lastUsedVersionItems[i].integerValue) {
currentVersionLarger = NO;
break;
}
}

const BOOL currentVersionLarger = (compareSemanticVersions(lastUsedVersion, currentVersion) == 1);
if (currentVersionLarger) {
[ud setValue:currentVersion forKey:MMLastUsedBundleVersionKey];

Expand Down Expand Up @@ -2130,6 +2108,73 @@ - (void)handleXcodeModEvent:(NSAppleEventDescriptor *)event
}
#endif

+ (NSDictionary*)parseOpenURL:(NSURL*)url
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];

// Parse query ("url=file://...&line=14") into a dictionary
NSArray *queries = [[url query] componentsSeparatedByString:@"&"];
NSEnumerator *enumerator = [queries objectEnumerator];
NSString *param;
while ((param = [enumerator nextObject])) {
// query: <field>=<value>
NSArray *arr = [param componentsSeparatedByString:@"="];
if ([arr count] == 2) {
// parse field
NSString *f = [arr objectAtIndex:0];
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
f = [f stringByRemovingPercentEncoding];
#else
f = [f stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
#endif

// parse value
NSString *v = [arr objectAtIndex:1];

// We need to decode the parameters here because most URL
// parsers treat the query component as needing to be decoded
// instead of treating it as is. It does mean that a link to
// open file "/tmp/file name.txt" will be
// mvim://open?url=file:///tmp/file%2520name.txt to encode a
// URL of file:///tmp/file%20name.txt. This double-encoding is
// intentional to follow the URL spec.
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
v = [v stringByRemovingPercentEncoding];
#else
v = [v stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
#endif

if ([f isEqualToString:@"url"]) {
// Since the URL scheme uses a double-encoding due to a
// file:// URL encoded in another mvim: one, existing tools
// like iTerm2 could sometimes erroneously only do a single
// encode. To maximize compatiblity, we re-encode invalid
// characters if we detect them as they would not work
// later on when we pass this string to URLWithString.
//
// E.g. mvim://open?uri=file:///foo%20bar => "file:///foo bar"
// which is not a valid URL, so we re-encode it to
// file:///foo%20bar here. The only important case is to
// not touch the "%" character as it introduces ambiguity
// and the re-encoding is a nice compatibility feature, but
// the canonical form should be double-encoded, i.e.
// mvim://open?uri=file:///foo%2520bar
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
if (AVAILABLE_MAC_OS(10, 10)) {
NSMutableCharacterSet *charSet = [NSMutableCharacterSet characterSetWithCharactersInString:@"%"];
[charSet formUnionWithCharacterSet:NSCharacterSet.URLHostAllowedCharacterSet];
[charSet formUnionWithCharacterSet:NSCharacterSet.URLPathAllowedCharacterSet];
v = [v stringByAddingPercentEncodingWithAllowedCharacters:charSet];
}
#endif
}

[dict setValue:v forKey:f];
}
}
return dict;
}

- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
replyEvent:(NSAppleEventDescriptor *)reply
{
Expand All @@ -2138,7 +2183,7 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
stringValue]];

// We try to be compatible with TextMate's URL scheme here, as documented
// at http://blog.macromates.com/2007/the-textmate-url-scheme/ . Currently,
// at https://macromates.com/blog/2007/the-textmate-url-scheme/ . Currently,
// this means that:
//
// The format is: mvim://open?<arguments> where arguments can be:
Expand All @@ -2151,66 +2196,8 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
// Example: mvim://open?url=file:///etc/profile&line=20

if ([[url host] isEqualToString:@"open"]) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];

// Parse query ("url=file://...&line=14") into a dictionary
NSArray *queries = [[url query] componentsSeparatedByString:@"&"];
NSEnumerator *enumerator = [queries objectEnumerator];
NSString *param;
while ((param = [enumerator nextObject])) {
// query: <field>=<value>
NSArray *arr = [param componentsSeparatedByString:@"="];
if ([arr count] == 2) {
// parse field
NSString *f = [arr objectAtIndex:0];
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
f = [f stringByRemovingPercentEncoding];
#else
f = [f stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
#endif

// parse value
NSString *v = [arr objectAtIndex:1];

// We need to decode the parameters here because most URL
// parsers treat the query component as needing to be decoded
// instead of treating it as is. It does mean that a link to
// open file "/tmp/file name.txt" will be
// mvim://open?url=file:///tmp/file%2520name.txt to encode a
// URL of file:///tmp/file%20name.txt. This double-encoding is
// intentional to follow the URL spec.
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
v = [v stringByRemovingPercentEncoding];
#else
v = [v stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
#endif

if ([f isEqualToString:@"url"]) {
// Since the URL scheme uses a double-encoding due to a
// file:// URL encoded in another mvim: one, existing tools
// like iTerm2 could sometimes erroneously only do a single
// encode. To maximize compatiblity, we re-encode invalid
// characters if we detect them as they would not work
// later on when we pass this string to URLWithString.
//
// E.g. mvim://open?uri=file:///foo%20bar => "file:///foo bar"
// which is not a valid URL, so we re-encode it to
// file:///foo%20bar here. The only important case is to
// not touch the "%" character as it introduces ambiguity
// and the re-encoding is a nice compatibility feature, but
// the canonical form should be double-encoded, i.e.
// mvim://open?uri=file:///foo%2520bar
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
NSMutableCharacterSet *charSet = [NSMutableCharacterSet characterSetWithCharactersInString:@"%"];
[charSet formUnionWithCharacterSet:NSCharacterSet.URLHostAllowedCharacterSet];
[charSet formUnionWithCharacterSet:NSCharacterSet.URLPathAllowedCharacterSet];
v = [v stringByAddingPercentEncodingWithAllowedCharacters:charSet];
#endif
}

[dict setValue:v forKey:f];
}
}
// Parse the URL and process it
NSDictionary *dict = [MMAppController parseOpenURL:url];

// Actually open the file.
NSString *file = [dict objectForKey:@"url"];
Expand Down
4 changes: 4 additions & 0 deletions src/MacVim/MMBackend.m
Original file line number Diff line number Diff line change
Expand Up @@ -2319,6 +2319,10 @@ - (void)handleInputEvent:(int)msgid data:(NSData *)data
[self setImState:NO];
} else if (BackingPropertiesChangedMsgID == msgid) {
[self redrawScreen];
} else if (LoopBackMsgID == msgid) {
// This is a debug message used for confirming a message has been
// received and echoed back to caller for synchronization purpose.
[self queueMessage:msgid data:nil];
} else {
ASLogWarn(@"Unknown message received (msgid=%d)", msgid);
}
Expand Down
1 change: 1 addition & 0 deletions src/MacVim/MacVim.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ extern const char * const MMVimMsgIDStrings[];
MSG(EnableThinStrokesMsgID) \
MSG(DisableThinStrokesMsgID) \
MSG(ShowDefinitionMsgID) \
MSG(LoopBackMsgID) /* Simple message that Vim will reflect back to MacVim */ \
MSG(LastMsgID) \

enum {
Expand Down
Loading

0 comments on commit 81d23bc

Please sign in to comment.