DailyView/Carthage/Checkouts/facebook-ios-sdk/FBSDKGamingServicesKit/FBSDKGamingServicesKitTests/GamingVideoUploaderTests.swift
2025-12-30 16:40:31 +08:00

250 lines
8.1 KiB
Swift

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
*/
@testable import FBSDKGamingServicesKit
import FBSDKCoreKit
import TestTools
import XCTest
final class GamingVideoUploaderTests: XCTestCase {
var videoURL = URL(string: "file://video.mp4")! // swiftlint:disable:this force_unwrapping
lazy var configuration = createConfiguration(url: videoURL)
let fileHandle = TestFileHandler()
let fileHandleFactory = TestFileHandleFactory()
let videoUploader = TestVideoUploader()
let videoUploaderFactory = TestVideoUploaderFactory()
lazy var uploader = GamingVideoUploader(
fileHandleFactory: fileHandleFactory,
videoUploaderFactory: videoUploaderFactory
)
override func setUp() {
super.setUp()
fileHandle.stubbedSeekToEndOfFile = UInt64.random(in: 1 ... 1000)
fileHandleFactory.stubbedFileHandle = fileHandle
videoUploaderFactory.stubbedVideoUploader = videoUploader
AccessToken.current = SampleAccessTokens.validToken
}
func testDefaults() {
XCTAssertTrue(
GamingVideoUploader.shared.fileHandleFactory is FileHandleFactory,
"Should have the expected file handle factory by default"
)
XCTAssertTrue(
GamingVideoUploader.shared.videoUploaderFactory is VideoUploaderFactory,
"Should have the expected video uploader factory by default"
)
}
func testCreatingWithDependencies() {
XCTAssertTrue(
uploader.fileHandleFactory is TestFileHandleFactory,
"Should be able to create an uploader with a custom file handle factory"
)
XCTAssertTrue(
uploader.videoUploaderFactory is TestVideoUploaderFactory,
"Should be able to create an uploader with a custom video uploader factory"
)
}
func testFailureWhenNoValidAccessTokenPresent() {
AccessToken.current = nil
var wasCompletionCalled = false
GamingVideoUploader.uploadVideo(configuration: configuration) { _, _, error in
XCTAssertEqual(
(error as NSError?)?.code,
CoreError.errorAccessTokenRequired.rawValue,
"Expected error requiring a valid access token"
)
wasCompletionCalled = true
}
XCTAssertTrue(wasCompletionCalled)
}
func testBadVideoURLFails() {
videoURL = URL(string: "file://not-a-video.mp4")! // swiftlint:disable:this force_unwrapping
var wasCompletionCalled = false
GamingVideoUploader.uploadVideo(configuration: configuration) { _, _, error in
XCTAssertEqual(
(error as NSError?)?.code,
CoreError.errorInvalidArgument.rawValue,
"Expected error requiring a non nil video url"
)
wasCompletionCalled = true
}
XCTAssertTrue(wasCompletionCalled)
}
func testCreatesFileHandle() {
uploader.uploadVideo(configuration: configuration) { _, _, _ in
XCTFail("Should not invoke the completion handler")
}
XCTAssertEqual(
fileHandleFactory.capturedURL,
videoURL,
"Should create a file handle with the url from the configuration"
)
}
func testUploadingEmptyFile() {
fileHandle.stubbedSeekToEndOfFile = 0
fileHandleFactory.stubbedFileHandle = fileHandle
var wasCompletionCalled = false
uploader.uploadVideo(configuration: configuration) { _, _, error in
XCTAssertEqual(
(error as NSError?)?.code,
CoreError.errorInvalidArgument.rawValue,
"Expected error requiring a non empty video file"
)
wasCompletionCalled = true
}
XCTAssertTrue(wasCompletionCalled)
}
func testCreatesAndStartsUploader() {
uploader.uploadVideo(configuration: configuration) { _, _, _ in
XCTFail("Should not invoke the completion handler")
}
XCTAssertTrue(
videoUploaderFactory.capturedDelegate is GamingVideoUploader,
"Should create an uploader with the expected delegate type"
)
XCTAssertEqual(
videoUploaderFactory.capturedVideoName,
videoURL.lastPathComponent,
"Should use the video url to derive the video name"
)
XCTAssertTrue(
videoUploaderFactory.capturedParameters.isEmpty,
"Should not create an uploader with parameters"
)
XCTAssertEqual(
videoUploaderFactory.capturedVideoSize,
UInt(fileHandle.fb_seekToEndOfFile()),
"Should create an uploader with the size of the video being uploaded"
)
XCTAssertTrue(
videoUploader.wasStartCalled,
"Should start the upload"
)
}
// MARK: Delegate methods
func testUploadErrorsHandled() throws {
var wasCompletionCalled = false
uploader.uploadVideo(configuration: configuration) { _, _, error in
XCTAssertTrue(error is SampleError)
wasCompletionCalled = true
}
let delegate = try XCTUnwrap(videoUploaderFactory.capturedDelegate)
let dummyUploader = VideoUploader(videoName: "dummy", videoSize: 0, parameters: [:], delegate: delegate)
_ = delegate.videoUploader(dummyUploader, didFailWithError: SampleError())
XCTAssertTrue(wasCompletionCalled)
}
func testVideoUploaderErrorOnUnsuccessful() throws {
var wasCompletionCalled = false
uploader.uploadVideo(configuration: configuration) { _, _, error in
XCTAssertEqual(
(error as NSError?)?.code,
CoreError.errorUnknown.rawValue,
"Should callback with an unknown error when the result indicates failure"
)
wasCompletionCalled = true
}
let delegate = try XCTUnwrap(videoUploaderFactory.capturedDelegate)
let dummyUploader = VideoUploader(videoName: "dummy", videoSize: 0, parameters: [:], delegate: delegate)
delegate.videoUploader(dummyUploader, didCompleteWithResults: ["success": false])
XCTAssertTrue(wasCompletionCalled)
}
func testVideoUploaderSucceeds() throws {
var wasCompletionCalled = false
uploader.uploadVideo(configuration: configuration) { success, _, error in
XCTAssertNil(error, "Should not receive an error when the uploader succeeds")
XCTAssertTrue(success, "Should indicate success in the completion")
wasCompletionCalled = true
}
let delegate = try XCTUnwrap(videoUploaderFactory.capturedDelegate)
let dummyUploader = VideoUploader(videoName: "dummy", videoSize: 0, parameters: [:], delegate: delegate)
delegate.videoUploader(dummyUploader, didCompleteWithResults: ["success": "1"])
XCTAssertTrue(wasCompletionCalled)
}
func testVideoUploaderProgress() throws {
var expectedBytesSent: Int64 = 0
var expectedTotalSent: Int64 = 0
var expectedTotalExpected: Int64 = 999
var completionCallCount = 0
let verifyProgress: GamingServiceProgressHandler = { bytesSent, totalSent, totalExpected in
XCTAssertEqual(bytesSent, expectedBytesSent)
XCTAssertEqual(totalSent, expectedTotalSent)
XCTAssertEqual(totalExpected, expectedTotalExpected)
completionCallCount += 1
}
fileHandle.stubbedSeekToEndOfFile = 999
fileHandle.stubbedReadData = Data(Array(repeating: 1, count: 500))
uploader.uploadVideo(
configuration: configuration,
completion: { _, _, _ in },
progressHandler: verifyProgress
)
let delegate = try XCTUnwrap(videoUploaderFactory.capturedDelegate)
let dummyUploader = VideoUploader(videoName: "dummy", videoSize: 0, parameters: [:], delegate: delegate)
// Send first chunk of data
_ = delegate.videoChunkData(for: dummyUploader, startOffset: 0, endOffset: 500)
// Set expectations
expectedBytesSent = 500
expectedTotalSent = 500
expectedTotalExpected = 999
fileHandle.stubbedReadData = Data(Array(repeating: 1, count: 499))
// Send second chunk of data
_ = delegate.videoChunkData(for: dummyUploader, startOffset: 500, endOffset: 999)
// Set expectations
expectedBytesSent = 499
expectedTotalSent = 999
expectedTotalExpected = 999
// Completing calls the progress handler with the final total bytes
delegate.videoUploader(dummyUploader, didCompleteWithResults: ["success": true])
XCTAssertEqual(completionCallCount, 3)
}
// MARK: - Helpers
func createConfiguration(url: URL) -> GamingVideoUploaderConfiguration {
GamingVideoUploaderConfiguration(videoURL: url, caption: "Cool Video")
}
}