diff --git a/Package.swift b/Package.swift index c048bb3..73d655f 100644 --- a/Package.swift +++ b/Package.swift @@ -99,6 +99,11 @@ let package = Package( dependencies: [ "AndroidFileManager" ]), + .testTarget( + name: "AndroidConfigurationTests", + dependencies: [ + "AndroidFileManager" + ]), .target( name: "AndroidContext", dependencies: [ diff --git a/Sources/AndroidFileManager/Configuration.swift b/Sources/AndroidFileManager/Configuration.swift index 657bf9d..9fd1096 100644 --- a/Sources/AndroidFileManager/Configuration.swift +++ b/Sources/AndroidFileManager/Configuration.swift @@ -40,16 +40,16 @@ public struct Configuration: ~Copyable { public extension Configuration { /// Creates a new, empty configuration object. - init() throws(AndroidFileManagerError) { + init() { guard let pointer = AConfiguration_new() else { - throw .invalidConfiguration + fatalError("AConfiguration_new() failed") } self.init(pointer: pointer) } /// Creates a configuration populated from the current asset manager state. - init(assetManager: borrowing AssetManager) throws(AndroidFileManagerError) { - try self.init() + init(assetManager: borrowing AssetManager) { + self.init() AConfiguration_fromAssetManager(pointer, assetManager.pointer) } } @@ -192,7 +192,7 @@ public extension Configuration { @available(Android 30, *) var screenRound: ScreenRound { get { ScreenRound(rawValue: AConfiguration_getScreenRound(pointer)) ?? .any } - set { AConfiguration_setScreenRound(pointer, newValue.rawValue) } + //set { AConfiguration_setScreenRound(pointer, newValue.rawValue) } } /// UI mode type (car, desk, television, etc.). diff --git a/Sources/AndroidFileManager/Error.swift b/Sources/AndroidFileManager/Error.swift index 3726656..5ead87e 100644 --- a/Sources/AndroidFileManager/Error.swift +++ b/Sources/AndroidFileManager/Error.swift @@ -15,12 +15,6 @@ /// Android file manager error. public enum AndroidFileManagerError: Swift.Error, Equatable, Sendable { - /// Unable to initialize an `AConfiguration` instance. - case invalidConfiguration - - /// Unable to initialize an `AStorageManager` instance. - case invalidStorageManager - /// Unable to open asset at the specified path. case openAsset(String) diff --git a/Sources/AndroidFileManager/ObbFile.swift b/Sources/AndroidFileManager/ObbFile.swift index b73c8d0..84a91c3 100644 --- a/Sources/AndroidFileManager/ObbFile.swift +++ b/Sources/AndroidFileManager/ObbFile.swift @@ -44,8 +44,8 @@ public actor ObbFile { /// - Parameter path: The path to the OBB file. /// - Throws: `AndroidFileManagerError.invalidStorageManager` if the underlying /// `AStorageManager` instance could not be created. - public init(path: String) throws(AndroidFileManagerError) { - let manager = try StorageManager() + public init(path: String) { + let manager = StorageManager() self.init(path: path, manager: manager) } diff --git a/Sources/AndroidFileManager/StorageManager.swift b/Sources/AndroidFileManager/StorageManager.swift index c229152..9a84365 100644 --- a/Sources/AndroidFileManager/StorageManager.swift +++ b/Sources/AndroidFileManager/StorageManager.swift @@ -36,9 +36,9 @@ public struct StorageManager: ~Copyable, @unchecked Sendable { public extension StorageManager { /// Creates an `AStorageManager` instance. - init() throws(AndroidFileManagerError) { + init() { guard let handle = Handle.create() else { - throw .invalidStorageManager + fatalError("AStorageManager_new() failed") } self.init(handle) } diff --git a/Tests/AndroidConfigurationTests/AndroidConfigurationTests.swift b/Tests/AndroidConfigurationTests/AndroidConfigurationTests.swift new file mode 100644 index 0000000..de49c53 --- /dev/null +++ b/Tests/AndroidConfigurationTests/AndroidConfigurationTests.swift @@ -0,0 +1,138 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftAndroidNative open source project +// +// Copyright (c) 2024-2026 Skip.dev and SwiftAndroidNative project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftAndroidNative project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Testing +import AndroidFileManager + +struct AndroidConfigurationTests { + + @Test func testProperties() throws { + var config = Configuration() + + config.mobileCountryCode = 310 + #expect(config.mobileCountryCode == 310) + + config.mobileNetworkCode = 260 + #expect(config.mobileNetworkCode == 260) + + config.languageCode = "en" + #expect(config.languageCode == "en") + + config.countryCode = "US" + #expect(config.countryCode == "US") + + config.orientation = .portrait + #expect(config.orientation == .portrait) + + config.touchscreen = .finger + #expect(config.touchscreen == .finger) + + config.density = .xHigh + #expect(config.density == .xHigh) + + config.keyboard = .qwerty + #expect(config.keyboard == .qwerty) + + config.navigation = .dpad + #expect(config.navigation == .dpad) + + config.keysHidden = .hidden + #expect(config.keysHidden == .hidden) + + config.navHidden = .hidden + #expect(config.navHidden == .hidden) + + config.sdkVersion = 33 + #expect(config.sdkVersion == 33) + + config.screenSize = .large + #expect(config.screenSize == .large) + + config.screenLong = .long + #expect(config.screenLong == .long) + + config.uiModeType = .normal + #expect(config.uiModeType == .normal) + + config.uiModeNight = .dark + #expect(config.uiModeNight == .dark) + + config.screenWidthDp = 1080 + #expect(config.screenWidthDp == 1080) + + config.screenHeightDp = 1920 + #expect(config.screenHeightDp == 1920) + + config.smallestScreenWidthDp = 360 + #expect(config.smallestScreenWidthDp == 360) + + if #available(Android 17, *) { + config.layoutDirection = .rightToLeft + #expect(config.layoutDirection == .rightToLeft) + } + + if #available(Android 30, *) { + //config.screenRound = .round + #expect(config.screenRound == .any) + } + + if #available(Android 34, *) { + config.grammaticalGender = .feminine + #expect(config.grammaticalGender == .feminine) + } + } + + @Test func testMatches() throws { + // Two default configurations should match each other + let a = Configuration() + let b = Configuration() + let defaultsMatch = a.matches(b) + #expect(defaultsMatch) + + // A portrait configuration should match a portrait request + var portrait = Configuration() + portrait.orientation = .portrait + var requestedPortrait = Configuration() + requestedPortrait.orientation = .portrait + let portraitMatch = portrait.matches(requestedPortrait) + #expect(portraitMatch) + + // A portrait configuration should not match a landscape request + var requestedLandscape = Configuration() + requestedLandscape.orientation = .landscape + let landscapeMismatch = portrait.matches(requestedLandscape) + #expect(!landscapeMismatch) + } + + @Test func testDiff() throws { + // Two default configurations should have no differences + let a = Configuration() + let b = Configuration() + let zeroDiff = a.diff(b) + #expect(zeroDiff == 0) + + // Configurations differing by MCC should produce a non-zero diff + var c = Configuration() + c.mobileCountryCode = 310 + let mccDiff = a.diff(c) + #expect(mccDiff != 0) + + // Multiple differing fields should each contribute to the diff mask + var d = Configuration() + d.orientation = .landscape + d.uiModeNight = .dark + let mask = a.diff(d) + #expect(mask != 0) + } +}