diff options
-rwxr-xr-x | build-mac/mailcore2.xcodeproj/project.pbxproj | 166 | ||||
-rw-r--r-- | src/core/basetypes/MCArray.cpp | 18 | ||||
-rw-r--r-- | src/core/basetypes/MCArray.h | 3 | ||||
-rw-r--r-- | src/core/basetypes/MCHashMap.cpp | 23 | ||||
-rw-r--r-- | src/core/basetypes/MCHashMap.h | 3 | ||||
-rw-r--r-- | src/core/basetypes/MCNull.cpp | 14 | ||||
-rw-r--r-- | src/core/basetypes/MCString.cpp | 49 | ||||
-rw-r--r-- | src/core/basetypes/MCString.h | 6 | ||||
-rw-r--r-- | unittest/unittest.cpp | 323 | ||||
-rw-r--r-- | unittest/unittest.mm | 1 |
10 files changed, 594 insertions, 12 deletions
diff --git a/build-mac/mailcore2.xcodeproj/project.pbxproj b/build-mac/mailcore2.xcodeproj/project.pbxproj index 73897013..81c82fb0 100755 --- a/build-mac/mailcore2.xcodeproj/project.pbxproj +++ b/build-mac/mailcore2.xcodeproj/project.pbxproj @@ -169,6 +169,11 @@ C07AD5D7FD82F8ACAB576231 /* NSError+MCO.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = C07AD44B013BB42A240B4F04 /* NSError+MCO.h */; }; C07AD99B2E2054C684DB8FF6 /* NSError+MCO.mm in Sources */ = {isa = PBXBuildFile; fileRef = C07ADFE43E22B38EFF23ADB5 /* NSError+MCO.mm */; }; C07ADC28B83E7959BF114D46 /* MCOIMAPSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = C07AD057D3C8FBDC7AC95733 /* MCOIMAPSession.mm */; }; + C600B61C1A242C6A000728F1 /* unittest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C600B61B1A242C6A000728F1 /* unittest.cpp */; }; + C600B61D1A244BD1000728F1 /* libMailCore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C64EA537169E772200778456 /* libMailCore.a */; }; + C600B6201A244C9A000728F1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6ED6D1917A1919500A4A14C /* Security.framework */; }; + C600B6211A244CB2000728F1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6BD2893170BD71100A91AC1 /* Foundation.framework */; }; + C600B6231A244CC3000728F1 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C600B6221A244CC3000728F1 /* CFNetwork.framework */; }; C608167517759967001F1018 /* MCSMTPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C608167317759967001F1018 /* MCSMTPDisconnectOperation.cpp */; }; C608167617759968001F1018 /* MCSMTPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C608167317759967001F1018 /* MCSMTPDisconnectOperation.cpp */; }; C608167B177635D2001F1018 /* MCIMAPDisconnectOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6081679177635D2001F1018 /* MCIMAPDisconnectOperation.cpp */; }; @@ -884,6 +889,13 @@ remoteGlobalIDString = C6BA2B091705F4E6003F0E9E; remoteInfo = "static mailcore2 ios"; }; + C600B61E1A244BD8000728F1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C64EA52E169E772200778456 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C64EA536169E772200778456; + remoteInfo = "static mailcore2 osx"; + }; C6A81BB01706852200882C15 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = C64EA52E169E772200778456 /* Project object */; @@ -915,6 +927,15 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + C600B6121A242C3F000728F1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; C64EA74B169E854B00778456 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1465,6 +1486,9 @@ C07AD057D3C8FBDC7AC95733 /* MCOIMAPSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOIMAPSession.mm; sourceTree = "<group>"; }; C07AD44B013BB42A240B4F04 /* NSError+MCO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+MCO.h"; sourceTree = "<group>"; }; C07ADFE43E22B38EFF23ADB5 /* NSError+MCO.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSError+MCO.mm"; sourceTree = "<group>"; }; + C600B6141A242C3F000728F1 /* unittestcpp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unittestcpp; sourceTree = BUILT_PRODUCTS_DIR; }; + C600B61B1A242C6A000728F1 /* unittest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unittest.cpp; sourceTree = "<group>"; }; + C600B6221A244CC3000728F1 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; C60136941776B96600A5AF45 /* MCOSMTPOperation+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MCOSMTPOperation+Private.h"; sourceTree = "<group>"; }; C60136951776C31000A5AF45 /* MCOPOPOperation+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MCOPOPOperation+Private.h"; sourceTree = "<group>"; }; C608167317759967001F1018 /* MCSMTPDisconnectOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MCSMTPDisconnectOperation.cpp; sourceTree = "<group>"; }; @@ -1886,6 +1910,17 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + C600B6111A242C3F000728F1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C600B6231A244CC3000728F1 /* CFNetwork.framework in Frameworks */, + C600B6211A244CB2000728F1 /* Foundation.framework in Frameworks */, + C600B6201A244C9A000728F1 /* Security.framework in Frameworks */, + C600B61D1A244BD1000728F1 /* libMailCore.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C64EA534169E772200778456 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -2136,6 +2171,7 @@ C6BD288D170BD71100A91AC1 /* MailCore.framework */, 27780C3A19CF9CD100C77E44 /* MailCore.framework */, C6B5AE0219F630B3001352A6 /* unittest.xctest */, + C600B6141A242C3F000728F1 /* unittestcpp */, ); name = Products; sourceTree = "<group>"; @@ -2472,6 +2508,7 @@ C64EA78E169F259200778456 /* Frameworks */ = { isa = PBXGroup; children = ( + C600B6221A244CC3000728F1 /* CFNetwork.framework */, C6B5AE1119F63496001352A6 /* Foundation.framework */, C6B5AE0F19F6347C001352A6 /* Security.framework */, 27780D3419CFA19500C77E44 /* libstdc++.dylib */, @@ -2519,6 +2556,7 @@ children = ( C6B5B08F19F63542001352A6 /* data */, C6B5AE0619F630B3001352A6 /* unittest.mm */, + C600B61B1A242C6A000728F1 /* unittest.cpp */, C6B5AE0419F630B3001352A6 /* Supporting Files */, ); name = unittest; @@ -2791,6 +2829,24 @@ productReference = 27780C3A19CF9CD100C77E44 /* MailCore.framework */; productType = "com.apple.product-type.framework"; }; + C600B6131A242C3F000728F1 /* unittestcpp */ = { + isa = PBXNativeTarget; + buildConfigurationList = C600B61A1A242C3F000728F1 /* Build configuration list for PBXNativeTarget "unittestcpp" */; + buildPhases = ( + C600B6101A242C3F000728F1 /* Sources */, + C600B6111A242C3F000728F1 /* Frameworks */, + C600B6121A242C3F000728F1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + C600B61F1A244BD8000728F1 /* PBXTargetDependency */, + ); + name = unittestcpp; + productName = unittestcpp; + productReference = C600B6141A242C3F000728F1 /* unittestcpp */; + productType = "com.apple.product-type.tool"; + }; C64EA536169E772200778456 /* static mailcore2 osx */ = { isa = PBXNativeTarget; buildConfigurationList = C64EA53B169E772200778456 /* Build configuration list for PBXNativeTarget "static mailcore2 osx" */; @@ -2912,6 +2968,9 @@ LastUpgradeCheck = 0610; ORGANIZATIONNAME = MailCore; TargetAttributes = { + C600B6131A242C3F000728F1 = { + CreatedOnToolsVersion = 6.0; + }; C6B5AE0119F630B3001352A6 = { CreatedOnToolsVersion = 6.0; }; @@ -2936,6 +2995,7 @@ C6BD288C170BD71100A91AC1 /* mailcore osx */, 27780C2A19CF9CD100C77E44 /* mailcore ios */, C6B5AE0119F630B3001352A6 /* unittest */, + C600B6131A242C3F000728F1 /* unittestcpp */, ); }; /* End PBXProject section */ @@ -3053,6 +3113,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + C600B6101A242C3F000728F1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C600B61C1A242C6A000728F1 /* unittest.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C64EA533169E772200778456 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3528,6 +3596,11 @@ target = C6BA2B091705F4E6003F0E9E /* static mailcore2 ios */; targetProxy = 27780C3F19CF9DE600C77E44 /* PBXContainerItemProxy */; }; + C600B61F1A244BD8000728F1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C64EA536169E772200778456 /* static mailcore2 osx */; + targetProxy = C600B61E1A244BD8000728F1 /* PBXContainerItemProxy */; + }; C6A81BB11706852200882C15 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = C6BA2B091705F4E6003F0E9E /* static mailcore2 ios */; @@ -3605,6 +3678,91 @@ }; name = Release; }; + C600B6181A242C3F000728F1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ( + "-luchardet", + "-lctemplate", + "-letpan", + "-lxml2", + "-lsasl2", + "-liconv", + "-ltidy", + "-lz", + "-lc++", + "-stdlib=libc++", + "-ObjC", + "-lcrypto", + "-lssl", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + C600B6191A242C3F000728F1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-luchardet", + "-lctemplate", + "-letpan", + "-lxml2", + "-lsasl2", + "-liconv", + "-ltidy", + "-lz", + "-lc++", + "-stdlib=libc++", + "-ObjC", + "-lcrypto", + "-lssl", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; C64EA539169E772200778456 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -3963,6 +4121,14 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + C600B61A1A242C3F000728F1 /* Build configuration list for PBXNativeTarget "unittestcpp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C600B6181A242C3F000728F1 /* Debug */, + C600B6191A242C3F000728F1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; C64EA531169E772200778456 /* Build configuration list for PBXProject "mailcore2" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/src/core/basetypes/MCArray.cpp b/src/core/basetypes/MCArray.cpp index 787dd0ba..9fa69ccb 100644 --- a/src/core/basetypes/MCArray.cpp +++ b/src/core/basetypes/MCArray.cpp @@ -253,6 +253,24 @@ String * Array::componentsJoinedByString(String * delimiter) return result; } +bool Array::isEqual(Object * otherObject) +{ + Array * otherArray = (Array *) otherObject; + if (otherArray->count() != count()) { + return false; + } + bool result = true; + mc_foreacharrayIndex(i, Object, value, this) { + Object * otherValue = otherArray->objectAtIndex(i); + if (!value->isEqual(otherValue)) { + result = false; + break; + } + } + + return result; +} + HashMap * Array::serializable() { HashMap * result = Object::serializable(); diff --git a/src/core/basetypes/MCArray.h b/src/core/basetypes/MCArray.h index 7e82ad9e..655eee5f 100644 --- a/src/core/basetypes/MCArray.h +++ b/src/core/basetypes/MCArray.h @@ -45,7 +45,8 @@ namespace mailcore { virtual Object * copy(); virtual HashMap * serializable(); virtual void importSerializable(HashMap * serializable); - + virtual bool isEqual(Object * otherObject); + private: carray * mArray; void init(); diff --git a/src/core/basetypes/MCHashMap.cpp b/src/core/basetypes/MCHashMap.cpp index 046aad90..486707e9 100644 --- a/src/core/basetypes/MCHashMap.cpp +++ b/src/core/basetypes/MCHashMap.cpp @@ -281,6 +281,29 @@ void HashMap::removeAllObjects() mCount = 0; } +bool HashMap::isEqual(Object * otherObject) +{ + HashMap * otherMap = (HashMap *) otherObject; + if (otherMap->count() != count()) { + return false; + } + bool result = true; + mc_foreachhashmapKeyAndValue(Object, key, Object, value, this) { + Object * otherValue = otherMap->objectForKey(key); + if (otherValue == NULL) { + result = false; + break; + } + if (!value->isEqual(otherValue)) { + fprintf(stderr, "%s: %s %s\n", MCUTF8(key), MCUTF8(value), MCUTF8(otherValue)); + result = false; + break; + } + } + + return result; +} + HashMap * HashMap::serializable() { HashMap * result = Object::serializable(); diff --git a/src/core/basetypes/MCHashMap.h b/src/core/basetypes/MCHashMap.h index 93938383..b6ac6d2f 100644 --- a/src/core/basetypes/MCHashMap.h +++ b/src/core/basetypes/MCHashMap.h @@ -34,7 +34,8 @@ namespace mailcore { virtual Object * copy(); virtual HashMap * serializable(); virtual void importSerializable(HashMap * serializable); - + virtual bool isEqual(Object * otherObject); + private: unsigned int mAllocated; unsigned int mCount; diff --git a/src/core/basetypes/MCNull.cpp b/src/core/basetypes/MCNull.cpp index cdb8335f..53d50622 100644 --- a/src/core/basetypes/MCNull.cpp +++ b/src/core/basetypes/MCNull.cpp @@ -10,10 +10,16 @@ using namespace mailcore; -Null * Null::null() +static Null * s_null = NULL; +static pthread_once_t s_once; + +static void init_null(void) { - Null * result = new Null(); - result->autorelease(); - return result; + s_null = new Null(); } +Null * Null::null() +{ + pthread_once(&s_once, init_null); + return s_null; +} diff --git a/src/core/basetypes/MCString.cpp b/src/core/basetypes/MCString.cpp index c17c7074..b3beeb40 100644 --- a/src/core/basetypes/MCString.cpp +++ b/src/core/basetypes/MCString.cpp @@ -1184,6 +1184,9 @@ Data * String::encodedMIMEHeaderValueForSubject() int String::compareWithCaseSensitive(String * otherString, bool caseSensitive) { + if ((length() == 0) && (otherString->length() == 0)) { + return 0; + } if ((unicodeCharacters() == NULL) && (otherString->unicodeCharacters() != NULL)) { return 0; } @@ -1486,6 +1489,17 @@ int String::locationOfString(String * occurrence) return (int) (location - mUnicodeChars); } +int String::lastLocationOfString(String * occurrence) +{ + UChar * location; + location = u_strrstr(mUnicodeChars, occurrence->unicodeCharacters()); + if (location == NULL) { + return -1; + } + + return (int) (location - mUnicodeChars); +} + #pragma mark strip HTML struct parserState { @@ -2143,10 +2157,37 @@ String * String::stringByAppendingPathComponent(String * component) String * String::stringByDeletingLastPathComponent() { - String * component = lastPathComponent(); - String * result = (String *) this->copy()->autorelease(); - result->deleteCharactersInRange(RangeMake(result->length() - component->length(), component->length())); - return result; + String * currentString = this; + if (currentString->isEqual(MCSTR("/"))) { + return currentString; + } + if (currentString->length() == 0) { + return currentString; + } + if (currentString->unicodeCharacters()[currentString->length() - 1] == '/') { + currentString = currentString->substringToIndex(currentString->length() - 1); + } + String * component = currentString->lastPathComponent(); + currentString = currentString->substringToIndex(currentString->length() - component->length()); + if (currentString->isEqual(MCSTR("/"))) { + return currentString; + } + if (currentString->length() == 0) { + return currentString; + } + if (currentString->unicodeCharacters()[currentString->length() - 1] == '/') { + currentString = currentString->substringToIndex(currentString->length() - 1); + } + return currentString; +} + +String * String::stringByDeletingPathExtension() +{ + int location = lastLocationOfString(MCSTR(".")); + if ((location == -1) || (location == 0)) { + return this; + } + return substringToIndex(location); } Array * String::componentsSeparatedByString(String * separator) diff --git a/src/core/basetypes/MCString.h b/src/core/basetypes/MCString.h index 842ff5b8..cbe5538b 100644 --- a/src/core/basetypes/MCString.h +++ b/src/core/basetypes/MCString.h @@ -52,7 +52,8 @@ namespace mailcore { virtual String * stringByAppendingCharacters(const UChar * unicodeCharacters); virtual String * stringByAppendingPathComponent(String * component); virtual String * stringByDeletingLastPathComponent(); - + virtual String * stringByDeletingPathExtension(); + virtual int compare(String * otherString); virtual int caseInsensitiveCompare(String * otherString); virtual String * lowercaseString(); @@ -62,7 +63,8 @@ namespace mailcore { virtual void deleteCharactersInRange(Range range); virtual unsigned int replaceOccurrencesOfString(String * occurrence, String * replacement); virtual int locationOfString(String * occurrence); - + virtual int lastLocationOfString(String * occurrence); + virtual Array * componentsSeparatedByString(String * separator); virtual bool isEqualCaseInsensitive(String * otherString); diff --git a/unittest/unittest.cpp b/unittest/unittest.cpp new file mode 100644 index 00000000..a96a82e2 --- /dev/null +++ b/unittest/unittest.cpp @@ -0,0 +1,323 @@ +#include <MailCore/MailCore.h> +#include <dirent.h> + +using namespace mailcore; + +static int global_failure = 0; +static int global_success = 0; + +static time_t referenceDate(void) +{ + struct tm aTm; + memset(&aTm, 0, sizeof(aTm)); + aTm.tm_sec = 0; + aTm.tm_min = 0; + aTm.tm_hour = 16; + aTm.tm_mday = 31; + aTm.tm_mon = 11; + aTm.tm_year = 2000 - 1900; + time_t date = mktime(&aTm); + return date; +} + +static void testMessageBuilder1(String * path) +{ + printf("testMessageBuilder1\n"); + MessageBuilder * builder = new MessageBuilder(); + builder->header()->setFrom(Address::addressWithRFC822String(MCSTR("Hoà <dinh.viet.hoa@gmail.com>"))); + builder->header()->setTo(Array::arrayWithObject(Address::addressWithRFC822String(MCSTR("Foo Bar <dinh.viet.hoa@gmail.com>")))); + builder->header()->setSubject(MCSTR("testMessageBuilder1")); + builder->header()->setDate(referenceDate()); + builder->header()->setMessageID(MCSTR("MyMessageID123@mail.gmail.com")); + builder->setHTMLBody(MCSTR("<html><body>This is a HTML content</body></html>")); + Array * boundaries = Array::array(); + boundaries->addObject(MCSTR("1")); + boundaries->addObject(MCSTR("2")); + boundaries->addObject(MCSTR("3")); + boundaries->addObject(MCSTR("4")); + boundaries->addObject(MCSTR("5")); + builder->setBoundaries(boundaries); + String * outputPath = path->stringByAppendingPathComponent(MCSTR("output/builder1.eml")); + Data * expectedData = Data::dataWithContentsOfFile(outputPath); + if (!builder->data()->isEqual(expectedData)) { + printf("testMessageBuilder1 failed\n"); + fprintf(stderr, "current:\n%s\n", MCUTF8(builder->data()->stringWithCharset("utf-8"))); + fprintf(stderr, "expected:\n%s\n", MCUTF8(expectedData->stringWithCharset("utf-8"))); + global_failure ++; + return; + } + printf("testMessageBuilder1 ok\n"); + global_success ++; +} + +static void testMessageBuilder2(String * path) +{ + printf("testMessageBuilder2\n"); + MessageBuilder * builder = new MessageBuilder(); + builder->header()->setFrom(Address::addressWithRFC822String(MCSTR("Hoà <dinh.viet.hoa@gmail.com>"))); + Array * to = Array::array(); + to->addObject(Address::addressWithRFC822String(MCSTR("Foo Bar <dinh.viet.hoa@gmail.com>"))); + to->addObject(Address::addressWithRFC822String(MCSTR("Other Recipient <another-foobar@to-recipient.org>"))); + builder->header()->setTo(to); + Array * cc = Array::array(); + cc->addObject(Address::addressWithRFC822String(MCSTR("Carbon Copy <dinh.viet.hoa@gmail.com>"))); + cc->addObject(Address::addressWithRFC822String(MCSTR("Other Recipient <another-foobar@to-recipient.org>"))); + builder->header()->setCc(cc); + builder->header()->setSubject(MCSTR("testMessageBuilder2")); + builder->header()->setDate(referenceDate()); + builder->header()->setMessageID(MCSTR("MyMessageID123@mail.gmail.com")); + builder->setHTMLBody(MCSTR("<html><body>This is a HTML content</body></html>")); + String * attachmentPath = path->stringByAppendingPathComponent(MCSTR("input/photo.jpg")); + builder->addAttachment(Attachment::attachmentWithContentsOfFile(attachmentPath)); + attachmentPath = path->stringByAppendingPathComponent(MCSTR("input/photo2.jpg")); + builder->addAttachment(Attachment::attachmentWithContentsOfFile(attachmentPath)); + Array * boundaries = Array::array(); + boundaries->addObject(MCSTR("1")); + boundaries->addObject(MCSTR("2")); + boundaries->addObject(MCSTR("3")); + boundaries->addObject(MCSTR("4")); + boundaries->addObject(MCSTR("5")); + builder->setBoundaries(boundaries); + String * outputPath = path->stringByAppendingPathComponent(MCSTR("output/builder2.eml")); + Data * expectedData = Data::dataWithContentsOfFile(outputPath); + if (!builder->data()->isEqual(expectedData)) { + printf("testMessageBuilder2 failed\n"); + fprintf(stderr, "current:\n%s\n", MCUTF8(builder->data()->stringWithCharset("utf-8"))); + fprintf(stderr, "expected:\n%s\n", MCUTF8(expectedData->stringWithCharset("utf-8"))); + global_failure ++; + return; + } + printf("testMessageBuilder2 ok\n"); + global_success ++; +} + +static void testMessageBuilder3(String * path) +{ + printf("testMessageBuilder3\n"); + MessageBuilder * builder = new MessageBuilder(); + builder->header()->setFrom(Address::addressWithRFC822String(MCSTR("Hoà <dinh.viet.hoa@gmail.com>"))); + Array * to = Array::array(); + to->addObject(Address::addressWithRFC822String(MCSTR("Foo Bar <dinh.viet.hoa@gmail.com>"))); + to->addObject(Address::addressWithRFC822String(MCSTR("Other Recipient <another-foobar@to-recipient.org>"))); + builder->header()->setTo(to); + Array * cc = Array::array(); + cc->addObject(Address::addressWithRFC822String(MCSTR("Carbon Copy <dinh.viet.hoa@gmail.com>"))); + cc->addObject(Address::addressWithRFC822String(MCSTR("Other Recipient <another-foobar@to-recipient.org>"))); + builder->header()->setCc(cc); + builder->header()->setSubject(MCSTR("testMessageBuilder3")); + builder->header()->setDate(referenceDate()); + builder->header()->setMessageID(MCSTR("MyMessageID123@mail.gmail.com")); + builder->setHTMLBody(MCSTR("<html><body><div>This is a HTML content</div><div><img src=\"cid:123\"></div></body></html>")); + String * attachmentPath = path->stringByAppendingPathComponent(MCSTR("input/photo.jpg")); + builder->addAttachment(Attachment::attachmentWithContentsOfFile(attachmentPath)); + attachmentPath = path->stringByAppendingPathComponent(MCSTR("input/photo2.jpg")); + Attachment * attachment = Attachment::attachmentWithContentsOfFile(attachmentPath); + attachment->setContentID(MCSTR("123")); + builder->addRelatedAttachment(attachment); + Array * boundaries = Array::array(); + boundaries->addObject(MCSTR("1")); + boundaries->addObject(MCSTR("2")); + boundaries->addObject(MCSTR("3")); + boundaries->addObject(MCSTR("4")); + boundaries->addObject(MCSTR("5")); + builder->setBoundaries(boundaries); + String * outputPath = path->stringByAppendingPathComponent(MCSTR("output/builder3.eml")); + Data * expectedData = Data::dataWithContentsOfFile(outputPath); + if (!builder->data()->isEqual(expectedData)) { + printf("testMessageBuilder3 failed\n"); + fprintf(stderr, "current:\n%s\n", MCUTF8(builder->data()->stringWithCharset("utf-8"))); + fprintf(stderr, "expected:\n%s\n", MCUTF8(expectedData->stringWithCharset("utf-8"))); + global_failure ++; + return; + } + printf("testMessageBuilder3 ok\n"); + global_success ++; +} + +static Array * pathsInDirectory(String * directory) +{ + Array * result = Array::array(); + + DIR * dir = opendir(directory->fileSystemRepresentation()); + if (dir == NULL) { + return result; + } + + struct dirent * ent; + while ((ent = readdir(dir)) != NULL) { + if (ent->d_name[0] == '.') { + continue; + } + + String * subpath = directory->stringByAppendingPathComponent(String::stringWithFileSystemRepresentation(ent->d_name)); + if (ent->d_type == DT_DIR) { + result->addObjectsFromArray(pathsInDirectory(subpath)); + } + else { + result->addObject(subpath); + } + } + closedir(dir); + + return result; +} + +static void prepareHeaderForUnitTest(MessageHeader * header) +{ + time_t now = time(NULL); + if (fabs(now - header->date()) <= 2) { + // Date might be generated, set to known date. + header->setDate(referenceDate()); + } + if (fabs(header->receivedDate() - now) <= 2) { + // Date might be generated, set to known date. + header->setReceivedDate(referenceDate()); + } + if (header->isMessageIDAutoGenerated()) { + header->setMessageID(MCSTR("MyMessageID123@mail.gmail.com")); + } +} + +static void preparePartForUnitTest(AbstractPart * part) +{ + if (part->className()->isEqual(MCSTR("mailcore::Multipart"))) { + Multipart * multipart = (Multipart *) part; + for(unsigned int i = 0 ; i < multipart->parts()->count() ; i ++) { + preparePartForUnitTest((AbstractPart *) multipart->parts()->objectAtIndex(i)); + } + } + else if (part->className()->isEqual(MCSTR("mailcore::MessagePart"))) { + prepareHeaderForUnitTest(((MessagePart *) part)->header()); + preparePartForUnitTest(((MessagePart *) part)->mainPart()); + } +} + +static void testMessageParser(String * path) +{ + printf("testMessageParser\n"); + String * inputPath = path->stringByAppendingPathComponent(MCSTR("input")); + String * outputPath = path->stringByAppendingPathComponent(MCSTR("output")); + Array * list = pathsInDirectory(inputPath); + int failure = 0; + int success = 0; + mc_foreacharray(String, filename, list) { + MessageParser * parser = MessageParser::messageParserWithContentsOfFile(filename); + prepareHeaderForUnitTest(parser->header()); + preparePartForUnitTest(parser->mainPart()); + HashMap * result = parser->serializable(); + String * expectedPath = outputPath->stringByAppendingPathComponent(filename->substringFromIndex(inputPath->length())); + //fprintf(stderr, "expected: %s\n", MCUTF8(expectedPath)); + HashMap * expectedResult = (HashMap *) JSON::objectFromJSONData(Data::dataWithContentsOfFile(expectedPath)); + if (result->isEqual(expectedResult)) { + success ++; + } + else { + fprintf(stderr, "testMessageParser: failed for %s\n", MCUTF8(filename)); + fprintf(stderr, "expected: %s\n", MCUTF8(expectedResult)); + fprintf(stderr, "got: %s\n", MCUTF8(result)); + failure ++; + } + } + if (failure > 0) { + printf("testMessageParser ok: %i succeeded, %i failed\n", success, failure); + global_failure ++; + return; + } + printf("testMessageParser ok: %i succeeded\n", success); + global_success ++; +} + +static void testCharsetDetection(String * path) +{ + printf("testCharsetDetection\n"); + String * inputPath = path->stringByAppendingPathComponent(MCSTR("input")); + Array * list = pathsInDirectory(inputPath); + int failure = 0; + int success = 0; + mc_foreacharray(String, filename, list) { + Data * data = Data::dataWithContentsOfFile(filename); + String * charset = data->charsetWithFilteredHTML(false); + charset = charset->lowercaseString(); + if (!filename->lastPathComponent()->stringByDeletingPathExtension()->isEqual(charset)) { + failure ++; + fprintf(stderr, "testCharsetDetection: failed for %s\n", MCUTF8(filename)); + fprintf(stderr, "got: %s\n", MCUTF8(charset)); + } + else { + success ++; + } + } + if (failure > 0) { + printf("testCharsetDetection ok: %i succeeded, %i failed\n", success, failure); + global_failure ++; + return; + } + printf("testCharsetDetection ok: %i succeeded\n", success); + global_success ++; +} + +static void testSummary(String * path) +{ + printf("testSummary\n"); + String * inputPath = path->stringByAppendingPathComponent(MCSTR("input")); + String * outputPath = path->stringByAppendingPathComponent(MCSTR("output")); + Array * list = pathsInDirectory(inputPath); + int failure = 0; + int success = 0; + mc_foreacharray(String, filename, list) { + MessageParser * parser = MessageParser::messageParserWithContentsOfFile(filename); + prepareHeaderForUnitTest(parser->header()); + preparePartForUnitTest(parser->mainPart()); + String * str = parser->plainTextRendering(); + String * resultPath = outputPath->stringByAppendingPathComponent(filename->substringFromIndex(inputPath->length())); + resultPath = resultPath->stringByDeletingPathExtension()->stringByAppendingString(MCSTR(".txt")); + Data * resultData = Data::dataWithContentsOfFile(resultPath); + if (resultData == nil) { + fprintf(stderr, "test %s is a well-known failing test", MCUTF8(filename)); + continue; + } + + if (!resultData->stringWithCharset("utf-8")->isEqual(str)) { + failure ++; + fprintf(stderr, "testSummary: failed for %s\n", MCUTF8(filename)); + fprintf(stderr, "got: %s\n", MCUTF8(str)); + fprintf(stderr, "expected: %s\n", MCUTF8(resultData->stringWithCharset("utf-8"))); + } + else { + success ++; + } + } + if (failure > 0) { + printf("testSummary ok: %i succeeded, %i failed\n", success, failure); + global_failure ++; + return; + } + printf("testSummary ok: %i succeeded\n", success); + global_success ++; +} + +int main(int argc, char ** argv) +{ + if (argc < 2) { + fprintf(stderr, "syntax: unittestcpp [unittestdatadir]\n"); + exit(EXIT_FAILURE); + } + + AutoreleasePool * pool = new AutoreleasePool(); + + String * path = String::stringWithUTF8Characters(argv[1]); + printf("data path: %s\n", MCUTF8(path)); + + testMessageBuilder1(path->stringByAppendingPathComponent(MCSTR("builder"))); + testMessageBuilder2(path->stringByAppendingPathComponent(MCSTR("builder"))); + testMessageBuilder3(path->stringByAppendingPathComponent(MCSTR("builder"))); + testMessageParser(path->stringByAppendingPathComponent(MCSTR("parser"))); + testCharsetDetection(path->stringByAppendingPathComponent(MCSTR("charset-detection"))); + testSummary(path->stringByAppendingPathComponent(MCSTR("summary"))); + + printf("%i tests succeeded, %i tests failed\n", global_success, global_failure); + + pool->release(); + + exit(EXIT_SUCCESS); +}
\ No newline at end of file diff --git a/unittest/unittest.mm b/unittest/unittest.mm index ed5f94d5..2563e9aa 100644 --- a/unittest/unittest.mm +++ b/unittest/unittest.mm @@ -225,6 +225,7 @@ NSData * data = [NSData dataWithContentsOfFile:path]; MCOMessageParser * parser = [MCOMessageParser messageParserWithData:data]; [[parser header] prepareForUnitTest]; + [[parser mainPart] prepareForUnitTest]; NSString * str = [parser plainTextRendering]; // NSString * outputPath = [@"/Users/hoa/mc2-results/summary" stringByAppendingPathComponent:name]; |