diff --git a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample.xcodeproj/project.pbxproj b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample.xcodeproj/project.pbxproj index 8af66d0..b94c257 100644 --- a/Example/SwiftUploadSDKExample/SwiftUploadSDKExample.xcodeproj/project.pbxproj +++ b/Example/SwiftUploadSDKExample/SwiftUploadSDKExample.xcodeproj/project.pbxproj @@ -26,11 +26,7 @@ 19822A772A4CA69700CFA822 /* UploadCTA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19822A662A4CA69700CFA822 /* UploadCTA.swift */; }; 19822A792A4CA69700CFA822 /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19822A682A4CA69700CFA822 /* ImagePicker.swift */; }; 19DCD95B2A4CA567001FBBF6 /* MuxUploadSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 19DCD95A2A4CA567001FBBF6 /* MuxUploadSDK */; }; - F38876CA2B86DBEB00B82A86 /* MemoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38876C92B86DBEB00B82A86 /* MemoryTests.swift */; }; F38876D22B86DCFB00B82A86 /* MuxUploadSDK in Frameworks */ = {isa = PBXBuildFile; productRef = F38876D12B86DCFB00B82A86 /* MuxUploadSDK */; }; - F38876D72B86DD4A00B82A86 /* FakeBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38876D52B86DD4A00B82A86 /* FakeBackend.swift */; }; - F38876D82B86DD4A00B82A86 /* EnvironmentVariables.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38876D62B86DD4A00B82A86 /* EnvironmentVariables.swift */; }; - F3DB262A2B8F792D0000C39B /* five_min.mov in Resources */ = {isa = PBXBuildFile; fileRef = F3DB26282B8F5D430000C39B /* five_min.mov */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -72,11 +68,7 @@ 19DCD9592A4CA546001FBBF6 /* swift-upload-sdk */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "swift-upload-sdk"; path = ../..; sourceTree = ""; }; 358E3C7729A92167005261CB /* SwiftUploadSDKExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUploadSDKExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 358E3C9129A92168005261CB /* SwiftUploadSDKExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftUploadSDKExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - F38876C72B86DBEB00B82A86 /* SwiftUploadSDKExampleUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftUploadSDKExampleUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - F38876C92B86DBEB00B82A86 /* MemoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryTests.swift; sourceTree = ""; }; - F38876D52B86DD4A00B82A86 /* FakeBackend.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FakeBackend.swift; sourceTree = ""; }; - F38876D62B86DD4A00B82A86 /* EnvironmentVariables.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnvironmentVariables.swift; sourceTree = ""; }; - F3DB26282B8F5D430000C39B /* five_min.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; name = five_min.mov; path = "../../Tests/MuxUploadSDKTests/Upload Tests/five_min.mov"; sourceTree = ""; }; + F38876C72B86DBEB00B82A86 /* .xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = .xctest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -197,7 +189,6 @@ 358E3C6E29A92167005261CB = { isa = PBXGroup; children = ( - F3DB26282B8F5D430000C39B /* five_min.mov */, 358E3CC329A9221F005261CB /* Packages */, 19822A502A4CA69700CFA822 /* SwiftUploadSDKExample */, 19822A7A2A4CA6A300CFA822 /* SwiftUploadSDKExampleTests */, @@ -212,7 +203,7 @@ children = ( 358E3C7729A92167005261CB /* SwiftUploadSDKExample.app */, 358E3C9129A92168005261CB /* SwiftUploadSDKExampleTests.xctest */, - F38876C72B86DBEB00B82A86 /* SwiftUploadSDKExampleUnitTests.xctest */, + F38876C72B86DBEB00B82A86 /* .xctest */, ); name = Products; sourceTree = ""; @@ -235,22 +226,10 @@ F38876C82B86DBEB00B82A86 /* SwiftUploadSDKExampleUnitTests */ = { isa = PBXGroup; children = ( - F38876D42B86DD4A00B82A86 /* Helpers */, - F38876C92B86DBEB00B82A86 /* MemoryTests.swift */, ); path = SwiftUploadSDKExampleUnitTests; sourceTree = ""; }; - F38876D42B86DD4A00B82A86 /* Helpers */ = { - isa = PBXGroup; - children = ( - F38876D52B86DD4A00B82A86 /* FakeBackend.swift */, - F38876D62B86DD4A00B82A86 /* EnvironmentVariables.swift */, - ); - name = Helpers; - path = ../../../Tests/MuxUploadSDKTests/Helpers; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -310,7 +289,7 @@ F38876D12B86DCFB00B82A86 /* MuxUploadSDK */, ); productName = SwiftUploadSDKExampleUnitTests; - productReference = F38876C72B86DBEB00B82A86 /* SwiftUploadSDKExampleUnitTests.xctest */; + productReference = F38876C72B86DBEB00B82A86 /* .xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -381,7 +360,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - F3DB262A2B8F792D0000C39B /* five_min.mov in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -421,9 +399,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - F38876CA2B86DBEB00B82A86 /* MemoryTests.swift in Sources */, - F38876D72B86DD4A00B82A86 /* FakeBackend.swift in Sources */, - F38876D82B86DD4A00B82A86 /* EnvironmentVariables.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -565,7 +540,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"SwiftUploadSDKExample/Preview Content\""; - DEVELOPMENT_TEAM = XX95P4Y787; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "This app uploads photos from your camera roll"; @@ -580,7 +555,6 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.mux.video.upload.Test-App"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -597,7 +571,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"SwiftUploadSDKExample/Preview Content\""; - DEVELOPMENT_TEAM = XX95P4Y787; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "This app uploads photos from your camera roll"; @@ -612,7 +586,6 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.mux.video.upload.Test-App"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; @@ -627,11 +600,9 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = XX95P4Y787; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.mux.video.upload.Test-AppUITests"; - "PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = "com.mux.video-uploader"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; @@ -646,11 +617,9 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = XX95P4Y787; + DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.mux.video.upload.Test-AppUITests"; - "PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = "com.mux.video-uploader"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; @@ -666,15 +635,13 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = XX95P4Y787; + DEVELOPMENT_TEAM = ""; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 17.0; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.mux.spaces.sdk.SwiftUploadSDKExampleUnitTests; - PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; @@ -690,15 +657,13 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = XX95P4Y787; + DEVELOPMENT_TEAM = ""; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 17.0; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.mux.spaces.sdk.SwiftUploadSDKExampleUnitTests; - PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Example/SwiftUploadSDKExample/SwiftUploadSDKExampleUnitTests/MemoryTests.swift b/Example/SwiftUploadSDKExample/SwiftUploadSDKExampleUnitTests/MemoryTests.swift deleted file mode 100644 index 01036a7..0000000 --- a/Example/SwiftUploadSDKExample/SwiftUploadSDKExampleUnitTests/MemoryTests.swift +++ /dev/null @@ -1,148 +0,0 @@ -// -// SwiftUploadSDKExampleUnitTests.swift -// SwiftUploadSDKExampleUnitTests -// -// Created by Tomislav Kordic on 22.2.24.. -// - -import XCTest -@testable import MuxUploadSDK - -import MuxUploadSDK - -final class MemoryTests: XCTestCase { - - private let myServerBackend = FakeBackend(urlSession: URLSession(configuration: URLSessionConfiguration.default)) - - func memoryFootprint() -> mach_vm_size_t? { - // The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too - // complex for the Swift C importer, so we have to define them ourselves. - let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) - let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout.size) - var info = task_vm_info_data_t() - var count = TASK_VM_INFO_COUNT - let kr = withUnsafeMutablePointer(to: &info) { infoPtr in - infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { intPtr in - task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count) - } - } - guard - kr == KERN_SUCCESS, - count >= TASK_VM_INFO_REV1_COUNT - else { return nil } - return info.phys_footprint - } - - func getUploadFilePath() -> URL? { - let bundle = Bundle(for: MemoryTests.self) - let fileManager = FileManager.default - let cwd = bundle.bundlePath - guard let content = try? fileManager.contentsOfDirectory(atPath: cwd) else { - XCTFail("five_min.mov file not found") - return nil - } - guard let videoURL = try? bundle.url(forResource: "five_min", withExtension: "mov") else { - XCTFail("five_min.mov file not found") - return nil - } - return videoURL - } - - func testChunkWorkerMemoryUsage() async throws { - let chunkSizeInBytes = 6 * 1024 * 1024 - let videoURL = getUploadFilePath() - let uploadURL = try await self.myServerBackend.createDirectUpload() - let chunkedFile = ChunkedFile(chunkSize: chunkSizeInBytes) - try chunkedFile.openFile(fileURL: videoURL!) - try chunkedFile.seekTo(byte: 0) - let startMemory = memoryFootprint() - repeat { - let chunk = try chunkedFile.readNextChunk().get() - if (chunk.size() == 0) { - break; - } - let chunkProgress = Progress(totalUnitCount: Int64(chunk.size())) - let worker = ChunkWorker( - uploadURL: uploadURL, - chunkProgress: chunkProgress, - maxRetries: 3 - ) - try await worker.directUpload(chunk: chunk) - } while (true) - let endMemory = memoryFootprint() - if ((startMemory! * 2) < endMemory!) { - XCTFail("We have mem leak, started with \(startMemory!) bytes, ended up with \(endMemory!) bytes") - } - } - - func testChunkedFileMemoryUsage() throws { - let videoURL = getUploadFilePath() - let chunkSizeInBytes = 6 * 1024 * 1024 - let chunkedFile = ChunkedFile(chunkSize: chunkSizeInBytes) - try chunkedFile.openFile(fileURL: videoURL!) - try chunkedFile.seekTo(byte: 0) - let startMemory = memoryFootprint() - repeat { - let chunk = try chunkedFile.readNextChunk().get() - Swift.print("Got chunk at position: \(chunk.startByte)") - if (chunk.size() == 0) { - break; - } - } while (true) - let endMemory = memoryFootprint() - if ((startMemory! * 2) < endMemory!) { - XCTFail("We have mem leak, started with \(startMemory!) bytes, ended up with \(endMemory!) bytes") - } - } - - func testLargeUpload() async throws { - // Construct custom upload options to upload a file in 6MB chunks - let chunkSizeInBytes = 6 * 1024 * 1024 - let options = DirectUploadOptions( - inputStandardization: .skipped, - chunkSizeInBytes: chunkSizeInBytes, - retryLimitPerChunk: 5 - ) - let putURL = try await self.myServerBackend.createDirectUpload() - let videoURL = getUploadFilePath() - - let muxDirectUpload = DirectUpload( - uploadURL: putURL, - inputFileURL: videoURL!, - options: options - ) - - muxDirectUpload.progressHandler = { state in - // TODO: print progress, print memory usage - Swift.print("Upload progress: " + (state.progress?.fractionCompleted.description)!) - } - let expectation = XCTestExpectation(description: "Upload task done(completed or failed)") - muxDirectUpload.resultHandler = { result in - switch result { - case .success(let success): - Swift.print("File uploaded successfully ") - expectation.fulfill() - case .failure(let error): - Swift.print("Failed to upload file") - expectation.fulfill() - } - } - Swift.print("Starting upload video") - muxDirectUpload.start() - - let result = await XCTWaiter().fulfillment(of: [expectation], timeout: 9000.0) - switch result { - // case .completed: XCTAssertEqual(muxDirectUpload.complete, true) - case .timedOut: do { - Swift.print("Test timedout after 9000 seconds !!!") - XCTFail() - } - default: do { - Swift.print("Test default option is to fail !!!") - XCTFail() - } - } - Swift.print("All done !!!") - } - -} diff --git a/Tests/MuxUploadSDKTests/Helpers/EnvironmentVariables.swift b/Tests/MuxUploadSDKTests/Helpers/EnvironmentVariables.swift deleted file mode 100644 index db06150..0000000 --- a/Tests/MuxUploadSDKTests/Helpers/EnvironmentVariables.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created for UploadTests. -// -// Copyright © 2022 Mux, Inc. -// Licensed under the MIT License. -// - -import Foundation - -/// Functions to fetch environment variables containing Mux-related -/// API tokens or signing key parameters -/// - -enum EnvironmentVariableError: Error { - case missing(variableName: String) -} - -enum EnvironmentVariable: String { - case tokenID = "MUX_ACCESS_TOKEN_ID" - case tokenSecret = "MUX_ACCESS_SECRET_KEY" -} - -func fetchEnvironmentVariable( - _ variable: EnvironmentVariable -) throws -> String { - guard let variable = ProcessInfo.processInfo.environment[ - variable.rawValue - ] else { - throw EnvironmentVariableError.missing( - variableName: variable.rawValue - ) - } - - return variable -} - - -func fetchTokenID() throws -> String { - try fetchEnvironmentVariable( - .tokenID - ) -} - -func fetchTokenSecret() throws -> String { - try fetchEnvironmentVariable( - .tokenSecret - ) -} diff --git a/Tests/MuxUploadSDKTests/Helpers/FakeBackend.swift b/Tests/MuxUploadSDKTests/Helpers/FakeBackend.swift deleted file mode 100644 index ebb688a..0000000 --- a/Tests/MuxUploadSDKTests/Helpers/FakeBackend.swift +++ /dev/null @@ -1,99 +0,0 @@ -// -// Created for UploadTests. -// -// Copyright © 2022 Mux, Inc. -// Licensed under the MIT License. -// - -import Foundation - -/// This class "fakes" the server backend necessary to compvare an upload workflow. -/// In your production use case, a backend server should take care of creating upload URLs -/// -/// **You should never build Mux server API ceredentials into a real app**. We do it in this example for brevity only -class FakeBackend { - - func createDirectUpload() async throws -> URL { - let request = try { - var req = try URLRequest(url:fullURL(forEndpoint: "uploads")) - req.httpBody = try jsonEncoder.encode(CreateUploadPost()) - req.httpMethod = "POST" - req.addValue("application/json", forHTTPHeaderField: "Content-Type") - req.addValue("application/json", forHTTPHeaderField: "accept") - - guard let basicAuthCredential = try? ("\(fetchTokenID()):\(fetchTokenSecret())".data(using: .utf8)!.base64EncodedString()) else { - Swift.print("ERROR>> Failed to get Mux credentails from environment") - throw CreateUploadError(message: "Missing credentials in environment") - } - req.addValue("Basic \(basicAuthCredential)", forHTTPHeaderField: "Authorization") - - return req - }() - - let (data, response) = try await urlSession.data(for: request) - let httpResponse = response as! HTTPURLResponse - if (200...299).contains(httpResponse.statusCode) { - let responseData = try jsonDecoder.decode(CreateUploadResponseContainer.self, from: data).data - guard let uploadURL = URL(string:responseData.url) else { - throw CreateUploadError(message: "invalid upload url") - } - return uploadURL - } else { - Swift.print("ERROR>> Upload POST failed: HTTP \(httpResponse.statusCode):\n\(String(decoding: data, as: UTF8.self))") - throw CreateUploadError(message: "Upload POST failed: HTTP \(httpResponse.statusCode):\n\(String(decoding: data, as: UTF8.self))") - } - } - - /// Generates a full URL for a given endpoint in the Mux Video public API - private func fullURL(forEndpoint: String) throws -> URL { - guard let url = URL(string: "https://api.mux.com/video/v1/\(forEndpoint)") else { - throw CreateUploadError(message: "bad endpoint") - } - return url - } - - let urlSession: URLSession - let jsonEncoder: JSONEncoder - let jsonDecoder: JSONDecoder - - init(urlSession: URLSession) { - self.urlSession = urlSession - self.jsonEncoder = JSONEncoder() - self.jsonEncoder.keyEncodingStrategy = JSONEncoder.KeyEncodingStrategy.convertToSnakeCase - self.jsonDecoder = JSONDecoder() - self.jsonDecoder.keyDecodingStrategy = JSONDecoder.KeyDecodingStrategy.convertFromSnakeCase - } - - convenience init() { - self.init(urlSession: URLSession(configuration: URLSessionConfiguration.default)) - } -} - -struct CreateUploadError : Error { - let message: String -} - - -fileprivate struct CreateUploadPost: Codable { - var newAssetSettings: NewAssetSettings = NewAssetSettings() - var corsOrigin: String = "*" -} - -fileprivate struct NewAssetSettings: Codable { - var playbackPolicy: [String] = ["public"] - var passthrough: String = "Extra video data. This can be any data and it's for your use" - var mp4Support: String = "standard" - var normalizeAudio: Bool = true - var test: Bool = false -} - -fileprivate struct CreateUploadResponse: Decodable { - var url: String - var id: String - var timeout: Int64 - var status: String -} - -fileprivate struct CreateUploadResponseContainer: Decodable { - var data: CreateUploadResponse -}