// // Copyright 2019 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import XCTest import Foundation import SignalCoreKit @testable import SignalServiceKit class StickerManagerTest: SSKBaseTest { func testFirstEmoji() { XCTAssertNil(StickerManager.firstEmoji(inEmojiString: nil)) XCTAssertEqual("πŸ‡¨πŸ‡¦", StickerManager.firstEmoji(inEmojiString: "πŸ‡¨πŸ‡¦")) XCTAssertEqual("πŸ‡¨πŸ‡¦", StickerManager.firstEmoji(inEmojiString: "πŸ‡¨πŸ‡¦πŸ‡¨πŸ‡¦")) XCTAssertEqual("πŸ‡ΉπŸ‡Ή", StickerManager.firstEmoji(inEmojiString: "πŸ‡ΉπŸ‡ΉπŸŒΌπŸ‡ΉπŸ‡ΉπŸŒΌπŸ‡ΉπŸ‡Ή")) XCTAssertEqual("🌼", StickerManager.firstEmoji(inEmojiString: "πŸŒΌπŸ‡ΉπŸ‡ΉπŸŒΌπŸ‡ΉπŸ‡Ή")) XCTAssertEqual("πŸ‘ŒπŸ½", StickerManager.firstEmoji(inEmojiString: "πŸ‘ŒπŸ½πŸ‘ŒπŸΎ")) XCTAssertEqual("πŸ‘ŒπŸΎ", StickerManager.firstEmoji(inEmojiString: "πŸ‘ŒπŸΎπŸ‘ŒπŸ½")) XCTAssertEqual("πŸ‘Ύ", StickerManager.firstEmoji(inEmojiString: "πŸ‘ΎπŸ™‡πŸ’πŸ™…πŸ™†πŸ™‹πŸ™ŽπŸ™")) XCTAssertEqual("πŸ‘Ύ", StickerManager.firstEmoji(inEmojiString: "πŸ‘ΎπŸ™‡πŸ’πŸ™…πŸ™†πŸ™‹πŸ™ŽπŸ™")) } func testAllEmoji() { XCTAssertEqual([], StickerManager.allEmoji(inEmojiString: nil)) XCTAssertEqual(["πŸ‡¨πŸ‡¦"], StickerManager.allEmoji(inEmojiString: "πŸ‡¨πŸ‡¦")) XCTAssertEqual(["πŸ‡¨πŸ‡¦", "πŸ‡¨πŸ‡¦"], StickerManager.allEmoji(inEmojiString: "πŸ‡¨πŸ‡¦πŸ‡¨πŸ‡¦")) XCTAssertEqual(["πŸ‡ΉπŸ‡Ή", "🌼", "πŸ‡ΉπŸ‡Ή", "🌼", "πŸ‡ΉπŸ‡Ή"], StickerManager.allEmoji(inEmojiString: "πŸ‡ΉπŸ‡ΉπŸŒΌπŸ‡ΉπŸ‡ΉπŸŒΌπŸ‡ΉπŸ‡Ή")) XCTAssertEqual(["🌼", "πŸ‡ΉπŸ‡Ή", "🌼", "πŸ‡ΉπŸ‡Ή"], StickerManager.allEmoji(inEmojiString: "πŸŒΌπŸ‡ΉπŸ‡ΉπŸŒΌπŸ‡ΉπŸ‡Ή")) XCTAssertEqual(["πŸ‘ŒπŸ½", "πŸ‘ŒπŸΎ"], StickerManager.allEmoji(inEmojiString: "πŸ‘ŒπŸ½πŸ‘ŒπŸΎ")) XCTAssertEqual(["πŸ‘ŒπŸΎ", "πŸ‘ŒπŸ½"], StickerManager.allEmoji(inEmojiString: "πŸ‘ŒπŸΎπŸ‘ŒπŸ½")) XCTAssertEqual(["πŸ‘Ύ", "πŸ™‡", "πŸ’", "πŸ™…", "πŸ™†", "πŸ™‹", "πŸ™Ž", "πŸ™"], StickerManager.allEmoji(inEmojiString: "πŸ‘ΎπŸ™‡πŸ’πŸ™…πŸ™†πŸ™‹πŸ™ŽπŸ™")) XCTAssertEqual(["πŸ‡¨πŸ‡¦"], StickerManager.allEmoji(inEmojiString: "aπŸ‡¨πŸ‡¦a")) XCTAssertEqual(["πŸ‡¨πŸ‡¦", "πŸ‡ΉπŸ‡Ή"], StickerManager.allEmoji(inEmojiString: "aπŸ‡¨πŸ‡¦bπŸ‡ΉπŸ‡Ήc")) } func testSuggestedStickers_uncached() { // The "StickerManager.suggestedStickers" instance method does caching; // the class method does not. XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "Hey Bob, what's up?").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦πŸ‡ΉπŸ‡Ή").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "This is a flag: πŸ‡¨πŸ‡¦").count) let stickerInfo = StickerInfo.defaultValue let stickerData = Randomness.generateRandomBytes(1) let temporaryFile = OWSFileSystem.temporaryFileUrl() try! stickerData.write(to: temporaryFile) let success = StickerManager.installSticker(stickerInfo: stickerInfo, stickerUrl: temporaryFile, contentType: MimeType.imageWebp.rawValue, emojiString: "πŸŒΌπŸ‡¨πŸ‡¦") XCTAssertTrue(success) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "Hey Bob, what's up?").count) // The sticker should only be suggested if user enters a single emoji // (and nothing else) that is associated with the sticker. XCTAssertEqual(1, StickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦").count) XCTAssertEqual(1, StickerManager.suggestedStickers(forTextInput: "🌼").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "πŸ‡ΉπŸ‡Ή").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "aπŸ‡¨πŸ‡¦").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦a").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦πŸ‡ΉπŸ‡Ή").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "πŸŒΌπŸ‡¨πŸ‡¦").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "This is a flag: πŸ‡¨πŸ‡¦").count) databaseStorage.write { (transaction) in // Don't bother calling completion. StickerManager.uninstallSticker(stickerInfo: stickerInfo, transaction: transaction) } XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "Hey Bob, what's up?").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦πŸ‡ΉπŸ‡Ή").count) XCTAssertEqual(0, StickerManager.suggestedStickers(forTextInput: "This is a flag: πŸ‡¨πŸ‡¦").count) } func testSuggestedStickers_cached() { // The "StickerManager.suggestedStickers" instance method does caching; // the class method does not. let stickerManager = StickerManager.shared XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "Hey Bob, what's up?").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦πŸ‡ΉπŸ‡Ή").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "This is a flag: πŸ‡¨πŸ‡¦").count) let stickerInfo = StickerInfo.defaultValue let stickerData = Randomness.generateRandomBytes(1) let temporaryFile = OWSFileSystem.temporaryFileUrl() try! stickerData.write(to: temporaryFile) let success = StickerManager.installSticker(stickerInfo: stickerInfo, stickerUrl: temporaryFile, contentType: MimeType.imageWebp.rawValue, emojiString: "πŸŒΌπŸ‡¨πŸ‡¦") XCTAssertTrue(success) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "Hey Bob, what's up?").count) // The sticker should only be suggested if user enters a single emoji // (and nothing else) that is associated with the sticker. XCTAssertEqual(1, stickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦").count) XCTAssertEqual(1, stickerManager.suggestedStickers(forTextInput: "🌼").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "πŸ‡ΉπŸ‡Ή").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "aπŸ‡¨πŸ‡¦").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦a").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦πŸ‡ΉπŸ‡Ή").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "πŸŒΌπŸ‡¨πŸ‡¦").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "This is a flag: πŸ‡¨πŸ‡¦").count) databaseStorage.write { (transaction) in // Don't bother calling completion. StickerManager.uninstallSticker(stickerInfo: stickerInfo, transaction: transaction) } XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "Hey Bob, what's up?").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "πŸ‡¨πŸ‡¦πŸ‡ΉπŸ‡Ή").count) XCTAssertEqual(0, stickerManager.suggestedStickers(forTextInput: "This is a flag: πŸ‡¨πŸ‡¦").count) } func testInfos() { let packId = Randomness.generateRandomBytes(16) let packKey = Randomness.generateRandomBytes(Int32(StickerManager.packKeyLength)) let stickerId: UInt32 = 0 XCTAssertEqual(StickerPackInfo(packId: packId, packKey: packKey), StickerPackInfo(packId: packId, packKey: packKey)) XCTAssertTrue(StickerPackInfo(packId: packId, packKey: packKey) == StickerPackInfo(packId: packId, packKey: packKey)) XCTAssertEqual(StickerInfo(packId: packId, packKey: packKey, stickerId: stickerId), StickerInfo(packId: packId, packKey: packKey, stickerId: stickerId)) XCTAssertTrue(StickerInfo(packId: packId, packKey: packKey, stickerId: stickerId) == StickerInfo(packId: packId, packKey: packKey, stickerId: stickerId)) } func testDecryption() { // From the Zozo the French Bulldog sticker pack let packKey = Data([ 0x17, 0xe9, 0x71, 0xc1, 0x34, 0x03, 0x56, 0x22, 0x78, 0x1d, 0x2e, 0xe2, 0x49, 0xe6, 0x47, 0x3b, 0x77, 0x45, 0x83, 0x75, 0x0b, 0x68, 0xc1, 0x1b, 0xb8, 0x2b, 0x75, 0x09, 0xc6, 0x8b, 0x6d, 0xfd ]) let bundle = Bundle(for: StickerManagerTest.self) let encryptedStickerURL = bundle.url(forResource: "sample-sticker", withExtension: "encrypted")! let decryptedStickerURL = bundle.url(forResource: "sample-sticker", withExtension: "webp")! let decryptedStickerData = try! Data(contentsOf: decryptedStickerURL) let outputUrl = try! StickerManager.decrypt(at: encryptedStickerURL, packKey: packKey) let outputData = try! Data(contentsOf: outputUrl) XCTAssertEqual(outputData, decryptedStickerData) } }