gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-ios] branch master updated: fix amount parsing and add test


From: gnunet
Subject: [taler-taler-ios] branch master updated: fix amount parsing and add tests to reflect kotlin api tests
Date: Wed, 15 Jun 2022 22:38:39 +0200

This is an automated email from the git hooks/post-receive script.

jonathan-buchanan pushed a commit to branch master
in repository taler-ios.

The following commit(s) were added to refs/heads/master by this push:
     new 9da8903  fix amount parsing and add tests to reflect kotlin api tests
9da8903 is described below

commit 9da8903e826aea2ff2d780b975d085512f0b21fa
Author: Jonathan Buchanan <jonathan.russ.buchanan@gmail.com>
AuthorDate: Wed Jun 15 16:38:23 2022 -0400

    fix amount parsing and add tests to reflect kotlin api tests
---
 Taler.xcodeproj/project.pbxproj                    |   4 -
 .../UserInterfaceState.xcuserstate                 | Bin 30487 -> 35145 bytes
 TalerTests/TalerTests.swift                        |  42 ---
 taler-swift/Sources/taler-swift/Amount.swift       | 380 +++++++++------------
 taler-swift/Sources/taler-swift/taler_swift.swift  |   6 -
 .../Tests/taler-swiftTests/AmountTests.swift       | 145 ++++++--
 .../Tests/taler-swiftTests/taler_swiftTests.swift  |  11 -
 7 files changed, 266 insertions(+), 322 deletions(-)

diff --git a/Taler.xcodeproj/project.pbxproj b/Taler.xcodeproj/project.pbxproj
index a1be70f..d88fb8e 100644
--- a/Taler.xcodeproj/project.pbxproj
+++ b/Taler.xcodeproj/project.pbxproj
@@ -11,7 +11,6 @@
                D112510026B12E3200D02E00 /* taler-wallet-embedded.js in 
CopyFiles */ = {isa = PBXBuildFile; fileRef = D11250FF26B12E3200D02E00 /* 
taler-wallet-embedded.js */; };
                D14AFD2124D232B300C51073 /* AppDelegate.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14AFD2024D232B300C51073 /* AppDelegate.swift 
*/; };
                D14AFD2324D232B300C51073 /* SceneDelegate.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14AFD2224D232B300C51073 /* SceneDelegate.swift 
*/; };
-               D14AFD3824D232B500C51073 /* TalerTests.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14AFD3724D232B500C51073 /* TalerTests.swift */; 
};
                D14AFD4324D232B500C51073 /* TalerUITests.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14AFD4224D232B500C51073 /* TalerUITests.swift 
*/; };
                D14CE1B226C39E5D00612DBE /* BalanceRow.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14CE1B126C39E5D00612DBE /* BalanceRow.swift */; 
};
                D14CE1B426C3A2D400612DBE /* BalanceList.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14CE1B326C3A2D400612DBE /* BalanceList.swift 
*/; };
@@ -122,7 +121,6 @@
                D14AFD2C24D232B500C51073 /* Base */ = {isa = PBXFileReference; 
lastKnownFileType = file.storyboard; name = Base; path = 
Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
                D14AFD2E24D232B500C51073 /* Info.plist */ = {isa = 
PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; 
sourceTree = "<group>"; };
                D14AFD3324D232B500C51073 /* TalerTests.xctest */ = {isa = 
PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path 
= TalerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-               D14AFD3724D232B500C51073 /* TalerTests.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
TalerTests.swift; sourceTree = "<group>"; };
                D14AFD3924D232B500C51073 /* Info.plist */ = {isa = 
PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; 
sourceTree = "<group>"; };
                D14AFD3E24D232B500C51073 /* TalerUITests.xctest */ = {isa = 
PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path 
= TalerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
                D14AFD4224D232B500C51073 /* TalerUITests.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
TalerUITests.swift; sourceTree = "<group>"; };
@@ -286,7 +284,6 @@
                D14AFD3624D232B500C51073 /* TalerTests */ = {
                        isa = PBXGroup;
                        children = (
-                               D14AFD3724D232B500C51073 /* TalerTests.swift */,
                                D14AFD3924D232B500C51073 /* Info.plist */,
                                D18DBB5D26DF160D00A4480D /* 
TimestampTests.swift */,
                        );
@@ -604,7 +601,6 @@
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               D14AFD3824D232B500C51073 /* TalerTests.swift in 
Sources */,
                                D18DBB5E26DF160D00A4480D /* 
TimestampTests.swift in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
diff --git 
a/Taler.xcodeproj/project.xcworkspace/xcuserdata/jonathan.xcuserdatad/UserInterfaceState.xcuserstate
 
b/Taler.xcodeproj/project.xcworkspace/xcuserdata/jonathan.xcuserdatad/UserInterfaceState.xcuserstate
index f65f460..74ac5da 100644
Binary files 
a/Taler.xcodeproj/project.xcworkspace/xcuserdata/jonathan.xcuserdatad/UserInterfaceState.xcuserstate
 and 
b/Taler.xcodeproj/project.xcworkspace/xcuserdata/jonathan.xcuserdatad/UserInterfaceState.xcuserstate
 differ
diff --git a/TalerTests/TalerTests.swift b/TalerTests/TalerTests.swift
deleted file mode 100644
index 3200278..0000000
--- a/TalerTests/TalerTests.swift
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This file is part of GNU Taler
- * (C) 2021 Taler Systems S.A.
- *
- * GNU Taler is free software; you can redistribute it and/or modify it under 
the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 3, or (at your option) any later version.
- *
- * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
- * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-import XCTest
-@testable import Taler
-
-class TalerTests: XCTestCase {
-
-    override func setUpWithError() throws {
-        // Put setup code here. This method is called before the invocation of 
each test method in the class.
-    }
-
-    override func tearDownWithError() throws {
-        // Put teardown code here. This method is called after the invocation 
of each test method in the class.
-    }
-
-    func testExample() throws {
-        // This is an example of a functional test case.
-        // Use XCTAssert and related functions to verify your tests produce 
the correct results.
-    }
-
-    func testPerformanceExample() throws {
-        // This is an example of a performance test case.
-        self.measure {
-            // Put the code you want to measure the time of here.
-        }
-    }
-
-}
diff --git a/taler-swift/Sources/taler-swift/Amount.swift 
b/taler-swift/Sources/taler-swift/Amount.swift
index e775a65..b2f005f 100644
--- a/taler-swift/Sources/taler-swift/Amount.swift
+++ b/taler-swift/Sources/taler-swift/Amount.swift
@@ -1,6 +1,6 @@
 /*
  * This file is part of GNU Taler
- * (C) 2021 Taler Systems S.A.
+ * (C) 2022 Taler Systems S.A.
  *
  * GNU Taler is free software; you can redistribute it and/or modify it under 
the
  * terms of the GNU General Public License as published by the Free Software
@@ -16,73 +16,48 @@
 
 import Foundation
 
-/**
-    Errors for `Amount`.
- */
+/// Errors for `Amount`.
 enum AmountError: Error {
-    /**
-        The string cannot be parsed to create an `Amount`.
-     */
+    /// The string cannot be parsed to create an `Amount`.
     case invalidStringRepresentation
     
-    /**
-        Could not compare or operate on two `Amount`s of different currencies.
-     */
+    /// Could not compare or operate on two `Amount`s of different currencies.
     case incompatibleCurrency
     
-    /**
-        The amount is invalid. The value is either greater than the maximum, 
or the currency is the empty string.
-     */
+    /// The amount is invalid. The value is either greater than the maximum, 
or the currency string is not 1-12 characters long.
     case invalidAmount
     
-    /**
-        The result of the operation would yield a negative amount.
-     */
+    /// The result of the operation would yield a negative amount.
     case negativeAmount
     
-    /**
-        The operation was division by zero.
-     */
+    /// The operation was division by zero.
     case divideByZero
 }
 
-/**
-    A value of a currency.
- */
+/// A value of some currency.
 public class Amount: Codable, CustomStringConvertible {
-    /**
-        The largest possible value that can be represented.
-     */
+    /// Format that a currency must match.
+    private static let currencyRegex = #"^[-_*A-Za-z0-9]{1,12}$"#
+    
+    /// The largest possible value that can be represented.
     private static let maxValue: UInt64 = 1 << 52
     
-    /**
-        The size of `value` in relation to `fraction`.
-     */
+    /// The size of `value` in relation to `fraction`.
     private static let fractionalBase: UInt32 = 100000000
     
-    /**
-        The greatest number of decimal digits that can be represented.
-     */
+    /// The greatest number of decimal digits that can be represented.
     private static let fractionalBaseDigits: UInt = 8
     
-    /**
-        The currency of the amount.
-     */
+    /// The currency of the amount.
     var currency: String
     
-    /**
-        The value of the amount (number to the left of the decimal point).
-     */
+    /// The value of the amount (number to the left of the decimal point).
     var value: UInt64
     
-    /**
-        The fractional value of the amount (number to the right of the decimal 
point).
-     */
+    /// The fractional value of the amount (number to the right of the decimal 
point).
     var fraction: UInt32
     
-    /**
-        The string representation of the amount, formatted as 
"`currency`:`value`.`fraction`".
-     */
+    /// The string representation of the amount, formatted as 
"`currency`:`value`.`fraction`".
     public var description: String {
         if fraction == 0 {
             return "\(currency):\(value)"
@@ -97,135 +72,105 @@ public class Amount: Codable, CustomStringConvertible {
         }
     }
     
-    /**
-        Whether the value is valid. An amount is valid if and only if the 
currency is not empty and the value is less than the maximum allowed value.
-     */
+    /// Whether the value is valid. An amount is valid if and only if the 
currency is not empty and the value is less than the maximum allowed value.
     var valid: Bool {
+        if currency.range(of: Amount.currencyRegex, options: 
.regularExpression) == nil {
+            return false
+        }
         return (value <= Amount.maxValue && currency != "")
     }
     
-    /**
-        Initializes an amount by parsing a string representing the amount. The 
string should be formatted as "`currency`:`value`.`fraction`".
-     
-        - Parameters:
-            - fromString: The string to parse.
-     
-        - Throws:
-            - `AmountError.invalidStringRepresentation` if the string cannot 
be parsed.
-            - `AmountError.invalidAmount` if the string can be parsed, but the 
resulting amount is not valid.
-     */
+    /// Whether this amount is zero or not.
+    var isZero: Bool {
+        return value == 0 && fraction == 0
+    }
+    
+    /// Initializes an amount by parsing a string representing the amount. The 
string should be formatted as "`currency`:`value`.`fraction`".
+    /// - Parameters:
+    ///   - fromString: The string to parse.
+    /// - Throws:
+    ///   - `AmountError.invalidStringRepresentation` if the string cannot be 
parsed.
+    ///   - `AmountError.invalidAmount` if the string can be parsed, but the 
resulting amount is not valid.
     public init(fromString string: String) throws {
-        guard let separatorIndex = string.firstIndex(of: ":") else { throw 
AmountError.invalidStringRepresentation }
-        self.currency = String(string[..<separatorIndex])
-        let amountStr = String(string[string.index(separatorIndex, offsetBy: 
1)...])
-        if let dotIndex = amountStr.firstIndex(of: ".") {
-            let valueStr = String(amountStr[..<dotIndex])
-            let fractionStr = String(amountStr[string.index(dotIndex, 
offsetBy: 1)...])
-            guard let _value = UInt64(valueStr) else { throw 
AmountError.invalidStringRepresentation }
-            self.value = _value
-            self.fraction = 0
-            var digitValue = Amount.fractionalBase / 10
-            for char in fractionStr {
-                guard let digit = char.wholeNumberValue else { throw 
AmountError.invalidStringRepresentation }
-                self.fraction += digitValue * UInt32(digit)
-                digitValue /= 10
+        if let separatorIndex = string.firstIndex(of: ":") {
+            self.currency = String(string[..<separatorIndex])
+            let amountStr = String(string[string.index(separatorIndex, 
offsetBy: 1)...])
+            if let dotIndex = amountStr.firstIndex(of: ".") {
+                let valueStr = String(amountStr[..<dotIndex])
+                let fractionStr = String(amountStr[string.index(dotIndex, 
offsetBy: 1)...])
+                if (fractionStr.count > Amount.fractionalBaseDigits) {
+                    throw AmountError.invalidStringRepresentation
+                }
+                guard let _value = UInt64(valueStr) else { throw 
AmountError.invalidStringRepresentation }
+                self.value = _value
+                self.fraction = 0
+                var digitValue = Amount.fractionalBase / 10
+                for char in fractionStr {
+                    guard let digit = char.wholeNumberValue else { throw 
AmountError.invalidStringRepresentation }
+                    self.fraction += digitValue * UInt32(digit)
+                    digitValue /= 10
+                }
+            } else {
+                guard let _value = UInt64(amountStr) else { throw 
AmountError.invalidStringRepresentation }
+                self.value = _value
+                self.fraction = 0
             }
         } else {
-            guard let _value = UInt64(amountStr) else { throw 
AmountError.invalidStringRepresentation }
-            self.value = _value
+            self.currency = string
+            self.value = 0
             self.fraction = 0
         }
         guard self.valid else { throw AmountError.invalidAmount }
     }
     
-    /**
-        Initializes an amount with the specified currency, value, and fraction.
-     
-        - Parameters:
-            - currency: The currency of the amount.
-            - value: The value of the amount (number to the left of the 
decimal point).
-            - fraction: The fractional value of the amount (number to the 
right of the decimal point).
-     */
-    init(currency: String, value: UInt64, fraction: UInt32) {
+    /// Initializes an amount with the specified currency, value, and fraction.
+    /// - Parameters:
+    ///   - currency: The currency of the amount.
+    ///   - value: The value of the amount (number to the left of the decimal 
point).
+    ///   - fraction: The fractional value of the amount (number to the right 
of the decimal point).
+    public init(currency: String, value: UInt64, fraction: UInt32) {
         self.currency = currency
         self.value = value
         self.fraction = fraction
     }
     
-    /**
-        Initializes an amount from a decoder.
-     
-        - Parameters:
-            - fromDecoder: The decoder to extract the amount from.
-     
-        - Throws:
-            - `AmountError.invalidStringRepresentation` if the string cannot 
be parsed.
-            - `AmountError.invalidAmount` if the string can be parsed, but the 
resulting amount is not valid.
-     */
-    init(fromDecoder decoder: Decoder) throws {
+    /// Initializes an amount from a decoder.
+    /// - Parameters:
+    ///   - from: The decoder to extract the amount from.
+    /// - Throws:
+    ///   - `AmountError.invalidStringRepresentation` if the string cannot be 
parsed.
+    ///   - `AmountError.invalidAmount` if the string can be parsed, but the 
resulting amount is not valid.
+    required public convenience init(from decoder: Decoder) throws {
         let container = try decoder.singleValueContainer()
         let string = try container.decode(String.self)
-        /* TODO: de-duplicate */
-        guard let separatorIndex = string.firstIndex(of: ":") else { throw 
AmountError.invalidStringRepresentation }
-        self.currency = String(string[..<separatorIndex])
-        let amountStr = String(string[string.index(separatorIndex, offsetBy: 
1)...])
-        if let dotIndex = amountStr.firstIndex(of: ".") {
-            let valueStr = String(amountStr[..<dotIndex])
-            let fractionStr = String(amountStr[string.index(dotIndex, 
offsetBy: 1)...])
-            guard let _value = UInt64(valueStr) else { throw 
AmountError.invalidStringRepresentation }
-            self.value = _value
-            self.fraction = 0
-            var digitValue = Amount.fractionalBase / 10
-            for char in fractionStr {
-                guard let digit = char.wholeNumberValue else { throw 
AmountError.invalidStringRepresentation }
-                self.fraction += digitValue * UInt32(digit)
-                digitValue /= 10
-            }
-        } else {
-            guard let _value = UInt64(amountStr) else { throw 
AmountError.invalidStringRepresentation }
-            self.value = _value
-            self.fraction = 0
-        }
-        guard self.valid else { throw AmountError.invalidAmount }
+        try self.init(fromString: string)
     }
     
-    /**
-        Copies an amount.
-     
-        - Returns: A copy of the amount.
-     */
+    /// Copies an amount.
+    /// - Returns: A copy of the amount.
     func copy() -> Amount {
         return Amount(currency: self.currency, value: self.value, fraction: 
self.fraction)
     }
     
-    /**
-        Creates a normalized copy of an amount.
-     
-        - Returns: A copy of the amount that has been normalized
-     */
+    /// Creates a normalized copy of an amount (the fractional part is 
strictly less than one unit of currency).
+    /// - Returns: A copy of the amount that has been normalized
     func normalizedCopy() throws -> Amount {
         let amount = self.copy()
         try amount.normalize()
         return amount
     }
     
-    /**
-        Encodes an amount.
-     
-        - Parameters:
-            - to: The encoder to encode the amount with.
-     */
+    /// Encodes an amount.
+    /// - Parameters:
+    ///   - to: The encoder to encode the amount with.
     public func encode(to encoder: Encoder) throws {
         var container = encoder.singleValueContainer()
         try container.encode(self.description)
     }
     
-    /**
-        Normalizes an amount by reducing `fraction` until it is less than 
`Amount.fractionalBase`, increasing `value` appropriately.
-     
-        - Throws:
-            - `AmountError.invalidAmount` if the amount is invalid either 
before or after normalization.
-     */
+    /// Normalizes an amount by reducing `fraction` until it is less than 
`Amount.fractionalBase`, increasing `value` appropriately.
+    /// - Throws:
+    ///   - `AmountError.invalidAmount` if the amount is invalid either before 
or after normalization.
     func normalize() throws {
         if !valid {
             throw AmountError.invalidAmount
@@ -237,18 +182,13 @@ public class Amount: Codable, CustomStringConvertible {
         }
     }
     
-    /**
-        Adds two amounts together.
-     
-        - Parameters:
-            - left: The amount on the left.
-            - right: The amount on the right.
-     
-        - Throws:
-            - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
-     
-        - Returns: The sum of `left` and `right`, normalized.
-     */
+    /// Adds two amounts together.
+    /// - Parameters:
+    ///   - left: The amount on the left.
+    ///   - right: The amount on the right.
+    /// - Throws:
+    ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
+    /// - Returns: The sum of `left` and `right`, normalized.
     static func + (left: Amount, right: Amount) throws -> Amount {
         if left.currency != right.currency {
             throw AmountError.incompatibleCurrency
@@ -262,18 +202,13 @@ public class Amount: Codable, CustomStringConvertible {
         return result
     }
     
-    /**
-        Subtracts one amount from another.
-     
-        - Parameters:
-            - left: The amount on the left.
-            - right: The amount on the right.
-     
-        - Throws:
-            - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
-     
-        - Returns: The difference of `left` and `right`, normalized.
-     */
+    /// Subtracts one amount from another.
+    /// - Parameters:
+    ///   - left: The amount on the left.
+    ///   - right: The amount on the right.
+    /// - Throws:
+    ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
+    /// - Returns: The difference of `left` and `right`, normalized.
     static func - (left: Amount, right: Amount) throws -> Amount {
         if left.currency != right.currency {
             throw AmountError.incompatibleCurrency
@@ -293,15 +228,11 @@ public class Amount: Codable, CustomStringConvertible {
         return diff
     }
     
-    /**
-        Divides an amount by a scalar, possibly introducing rounding error.
-     
-        - Parameters:
-            - dividend: The amount to divide.
-            - divisor: The scalar dividing `dividend`.
-     
-        - Returns: The quotient of `dividend` and `divisor`, normalized.
-     */
+    /// Divides an amount by a scalar, possibly introducing rounding error.
+    /// - Parameters:
+    ///   - dividend: The amount to divide.
+    ///   - divisor: The scalar dividing `dividend`.
+    /// - Returns: The quotient of `dividend` and `divisor`, normalized.
     static func / (dividend: Amount, divisor: UInt32) throws -> Amount {
         guard divisor != 0 else { throw AmountError.divideByZero }
         let result = try dividend.normalizedCopy()
@@ -316,15 +247,11 @@ public class Amount: Codable, CustomStringConvertible {
         return result
     }
     
-    /**
-        Multiply an amount by a scalar.
-     
-        - Parameters:
-            - amount: The amount to multiply.
-            - factor: The scalar multiplying `amount`.
-     
-        - Returns: The product of `amount` and `factor`, normalized.
-     */
+    /// Multiply an amount by a scalar.
+    /// - Parameters:
+    ///   - amount: The amount to multiply.
+    ///   - factor: The scalar multiplying `amount`.
+    /// - Returns: The product of `amount` and `factor`, normalized.
     static func * (amount: Amount, factor: UInt32) throws -> Amount {
         let result = try amount.normalizedCopy()
         result.value = result.value * UInt64(factor)
@@ -334,19 +261,14 @@ public class Amount: Codable, CustomStringConvertible {
         return result
     }
     
-    /**
-        Compares two amounts.
-     
-        - Parameters:
-            - left: The first amount.
-            - right: The second amount.
-     
-        - Throws:
-            - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
-     
-        - Returns: `true` if and only if the amounts have the same `value` and 
`fraction` after normalization, `false` otherwise.
-     */
-    static func == (left: Amount, right: Amount) throws -> Bool {
+    /// Compares two amounts.
+    /// - Parameters:
+    ///   - left: The first amount.
+    ///   - right: The second amount.
+    /// - Throws:
+    ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
+    /// - Returns: `true` if and only if the amounts have the same `value` and 
`fraction` after normalization, `false` otherwise.
+    public static func == (left: Amount, right: Amount) throws -> Bool {
         if left.currency != right.currency {
             throw AmountError.incompatibleCurrency
         }
@@ -355,19 +277,14 @@ public class Amount: Codable, CustomStringConvertible {
         return (leftNormalized.value == rightNormalized.value && 
leftNormalized.fraction == rightNormalized.fraction)
     }
     
-    /**
-        Compares two amounts.
-     
-        - Parameters:
-            - left: The amount on the left.
-            - right: The amount on the right.
-     
-        - Throws:
-            - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
-     
-        - Returns: `true` if and only if `left` is smaller than `right` after 
normalization, `false` otherwise.
-     */
-    static func < (left: Amount, right: Amount) throws -> Bool {
+    /// Compares two amounts.
+    /// - Parameters:
+    ///   - left: The amount on the left.
+    ///   - right: The amount on the right.
+    /// - Throws:
+    ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
+    /// - Returns: `true` if and only if `left` is lesser than `right` after 
normalization, `false` otherwise.
+    public static func < (left: Amount, right: Amount) throws -> Bool {
         if left.currency != right.currency {
             throw AmountError.incompatibleCurrency
         }
@@ -380,30 +297,43 @@ public class Amount: Codable, CustomStringConvertible {
         }
     }
     
-    /**
-        Compares two amounts.
-     
-        - Parameters:
-            - left: The amount on the left.
-            - right: The amount on the right.
-     
-        - Throws:
-            - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
-     
-        - Returns: `true` if and only if `left` is bigger than `right` after 
normalization, `false` otherwise.
-     */
-    static func > (left: Amount, right: Amount) throws -> Bool {
+    /// Compares two amounts.
+    /// - Parameters:
+    ///   - left: The amount on the left.
+    ///   - right: The amount on the right.
+    /// - Throws:
+    ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
+    /// - Returns: `true` if and only if `left` is lesser than or equal to 
`right` after normalization, `false` otherwise.
+    public static func <= (left: Amount, right: Amount) throws -> Bool {
+        return try left < right || left == right
+    }
+    
+    /// Compares two amounts.
+    /// - Parameters:
+    ///   - left: The amount on the left.
+    ///   - right: The amount on the right.
+    /// - Throws:
+    ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
+    /// - Returns: `true` if and only if `left` is greater than `right` after 
normalization, `false` otherwise.
+    public static func > (left: Amount, right: Amount) throws -> Bool {
         return try right < left
     }
     
-    /**
-        Creates the amount representing zero in a given currency.
-     
-        - Parameters:
-            - currency: The currency to use.
-     
-        - Returns: The zero amount for `currency`.
-     */
+    /// Compares two amounts.
+    /// - Parameters:
+    ///   - left: The amount on the left.
+    ///   - right: The amount on the right.
+    /// - Throws:
+    ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
+    /// - Returns: `true` if and only if `left` is greater than or equal 
`right` after normalization, `false` otherwise.
+    public static func >= (left: Amount, right: Amount) throws -> Bool {
+        return try left > right || left == right
+    }
+    
+    /// Creates the amount representing zero in a given currency.
+    /// - Parameters:
+    ///   - currency: The currency to use.
+    /// - Returns: The zero amount for `currency`.
     static func zero(currency: String) -> Amount {
         return Amount(currency: currency, value: 0, fraction: 0)
     }
diff --git a/taler-swift/Sources/taler-swift/taler_swift.swift 
b/taler-swift/Sources/taler-swift/taler_swift.swift
deleted file mode 100644
index 79438a4..0000000
--- a/taler-swift/Sources/taler-swift/taler_swift.swift
+++ /dev/null
@@ -1,6 +0,0 @@
-public struct taler_swift {
-    public private(set) var text = "Hello, World!"
-
-    public init() {
-    }
-}
diff --git a/taler-swift/Tests/taler-swiftTests/AmountTests.swift 
b/taler-swift/Tests/taler-swiftTests/AmountTests.swift
index 6cbbf77..58f981f 100644
--- a/taler-swift/Tests/taler-swiftTests/AmountTests.swift
+++ b/taler-swift/Tests/taler-swiftTests/AmountTests.swift
@@ -15,10 +15,9 @@
  */
 
 import XCTest
-@testable import Taler
+@testable import taler_swift
 
 class AmountTests: XCTestCase {
-
     override func setUpWithError() throws {
         // Put setup code here. This method is called before the invocation of 
each test method in the class.
     }
@@ -27,41 +26,119 @@ class AmountTests: XCTestCase {
         // Put teardown code here. This method is called after the invocation 
of each test method in the class.
     }
 
-    func testAmounts() throws {
-        var amount: Amount = try! Amount(fromString: "EUR:633.59")
-        XCTAssert(amount.currency == "EUR")
-        XCTAssert(amount.value == 633)
-        XCTAssert(amount.fraction == 59000000)
-        XCTAssert(amount.description == "EUR:633.59")
-        XCTAssert(try amount == Amount(currency: "EUR", value: 633, fraction: 
59000000))
-        XCTAssert(try amount == amount)
-        
-        amount = try! Amount(fromString: "EUR:883")
-        XCTAssert(amount.currency == "EUR")
-        XCTAssert(amount.value == 883)
-        XCTAssert(amount.fraction == 0)
-        XCTAssert(amount.description == "EUR:883")
+    func testParsing() {
+        var str = "TESTKUDOS:23.42"
+        var amt = try! Amount(fromString: str)
+        XCTAssert(str == amt.description)
+        XCTAssert("TESTKUDOS" == amt.currency)
+        XCTAssert(23 == amt.value)
+        XCTAssert(UInt64(0.42 * 1e8) == amt.fraction)
         
-        XCTAssertThrowsError(try Amount(fromString: "EUR:6548$f.59.**"))
+        str = "EUR:500000000.00000001"
+        amt = try! Amount(fromString: str)
+        XCTAssert(str == amt.description)
+        XCTAssert("EUR" == amt.currency)
+        XCTAssert(500000000 == amt.value)
+        XCTAssert(1 == amt.fraction)
         
-        let amount2: Amount = try! Amount(fromString: "EUR:971.32")
-        XCTAssert(try amount < amount2)
-        XCTAssert(try amount2 > amount)
-        XCTAssert(try (amount + amount2) == Amount(fromString: "EUR:1854.32"))
-        XCTAssert(try (amount2 - amount) == Amount(fromString: "EUR:88.32"))
-        XCTAssertThrowsError(try amount - amount2)
+        str = "EUR:1500000000.00000003"
+        amt = try! Amount(fromString: str)
+        XCTAssert(str == amt.description)
+        XCTAssert("EUR" == amt.currency)
+        XCTAssert(1500000000 == amt.value)
+        XCTAssert(3 == amt.fraction)
         
-        let amount3: Amount = try! Amount(fromString: "USD:12.34")
-        XCTAssertThrowsError(try amount == amount3)
-        XCTAssertThrowsError(try amount < amount3)
-        XCTAssertThrowsError(try amount > amount3)
-        XCTAssertThrowsError(try amount + amount3)
-        XCTAssertThrowsError(try amount - amount3)
+        let maxValue = 4503599627370496
+        str = "TESTKUDOS123:\(maxValue).99999999"
+        amt = try! Amount(fromString: str)
+        XCTAssert(str == amt.description)
+        XCTAssert("TESTKUDOS123" == amt.currency)
+        XCTAssert(maxValue == amt.value)
         
-        XCTAssertThrowsError(try amount3 / 0)
-        XCTAssert(try (amount3 / 1) == amount3)
-        XCTAssert(try (amount3 / 3) == Amount(fromString: "USD:4.11333333"))
-        XCTAssert(try (amount3 * 5) == Amount(fromString: "USD:61.7"))
+        XCTAssertThrowsError(try Amount(fromString: 
"TESTKUDOS1234:\(maxValue).99999999"))
+        XCTAssertThrowsError(try Amount(fromString: "TESTKUDOS123:\(maxValue + 
1).99999999"))
+        XCTAssertThrowsError(try Amount(fromString: 
"TESTKUDOS123:\(maxValue).999999990"))
+        XCTAssertThrowsError(try Amount(fromString: "TESTKUDOS:0,5"))
+        XCTAssertThrowsError(try Amount(fromString: "+TESTKUDOS:0.5"))
+        XCTAssertThrowsError(try Amount(fromString: "0.5"))
+        XCTAssertThrowsError(try Amount(fromString: ":0.5"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR::0.5"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR:.5"))
+    }
+    
+    func testAddition() {
+        XCTAssert(try Amount(fromString: "EUR:1") + Amount(fromString: 
"EUR:1") == Amount(fromString: "EUR:2"))
+        XCTAssert(try Amount(fromString: "EUR:1.5") + Amount(fromString: 
"EUR:1.5") == Amount(fromString: "EUR:3"))
+        XCTAssert(try Amount(fromString: "EUR:500000000.00000001") + 
Amount(fromString: "EUR:0.00000001") == Amount(fromString: 
"EUR:500000000.00000002"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR:1") + 
Amount(fromString: "USD:1"))
+        XCTAssertThrowsError(try Amount(fromString: 
"EUR:4503599627370496.99999999") + Amount(fromString: 
"EUR:4503599627370496.99999999"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR:4000000000000000") + 
Amount(fromString: "EUR:4000000000000000"))
+    }
+    
+    func testSubtraction() {
+        XCTAssert(try Amount(fromString: "EUR:1") - Amount(fromString: 
"EUR:1") == Amount(fromString: "EUR:0"))
+        XCTAssert(try Amount(fromString: "EUR:3") - Amount(fromString: 
"EUR:1.5") == Amount(fromString: "EUR:1.5"))
+        XCTAssert(try Amount(fromString: "EUR:500000000.00000002") - 
Amount(fromString: "EUR:0.00000001") == Amount(fromString: 
"EUR:500000000.00000001"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR:3") - 
Amount(fromString: "USD:1.5"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR:23.42") - 
Amount(fromString: "EUR:42.23"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR:0.5") - 
Amount(fromString: "EUR:0.50000001"))
+    }
+    
+    func testMultiplication() {
+        XCTAssert(try Amount(fromString: "EUR:2") * 1 == Amount(fromString: 
"EUR:2"))
+        XCTAssert(try Amount(fromString: "EUR:1") * 2 == Amount(fromString: 
"EUR:2"))
+        XCTAssert(try Amount(fromString: "EUR:1.5") * 3 == Amount(fromString: 
"EUR:4.5"))
+        XCTAssert(try Amount(fromString: "EUR:1.11") * 0 == Amount(fromString: 
"EUR:0"))
+        XCTAssert(try Amount(fromString: "EUR:1.11") * 1 == Amount(fromString: 
"EUR:1.11"))
+        XCTAssert(try Amount(fromString: "EUR:1.11") * 2 == Amount(fromString: 
"EUR:2.22"))
+        XCTAssert(try Amount(fromString: "EUR:1.11") * 3 == Amount(fromString: 
"EUR:3.33"))
+        XCTAssert(try Amount(fromString: "EUR:1.11") * 4 == Amount(fromString: 
"EUR:4.44"))
+        XCTAssert(try Amount(fromString: "EUR:1.11") * 5 == Amount(fromString: 
"EUR:5.55"))
+        XCTAssert(try Amount(fromString: "EUR:500000000.00000001") * 3 == 
Amount(fromString: "EUR:1500000000.00000003"))
+        XCTAssertThrowsError(try Amount(fromString: "4000000000000000") * 2)
+    }
+    
+    func testDivision() {
+        XCTAssert(try Amount(fromString: "EUR:2") / 1 == Amount(fromString: 
"EUR:2"))
+        XCTAssert(try Amount(fromString: "EUR:2") / 2 == Amount(fromString: 
"EUR:1"))
+        XCTAssert(try Amount(fromString: "EUR:4.5") / 3 == Amount(fromString: 
"EUR:1.5"))
+        XCTAssert(try Amount(fromString: "EUR:0") / 5 == Amount(fromString: 
"EUR:0"))
+        XCTAssert(try Amount(fromString: "EUR:1.11") / 1 == Amount(fromString: 
"EUR:1.11"))
+        XCTAssert(try Amount(fromString: "EUR:2.22") / 2 == Amount(fromString: 
"EUR:1.11"))
+        XCTAssert(try Amount(fromString: "EUR:3.33") / 3 == Amount(fromString: 
"EUR:1.11"))
+        XCTAssert(try Amount(fromString: "EUR:4.44") / 4 == Amount(fromString: 
"EUR:1.11"))
+        XCTAssert(try Amount(fromString: "EUR:5.55") / 5 == Amount(fromString: 
"EUR:1.11"))
+        XCTAssert(try Amount(fromString: "EUR:1500000000.00000003") / 3 == 
Amount(fromString: "EUR:500000000.00000001"))
+        XCTAssert(try Amount(fromString: "EUR:0.00000003") / 2 == 
Amount(fromString: "EUR:0.00000001"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR:1") / 0)
+    }
+    
+    func testZero() {
+        XCTAssert(try Amount(fromString: "EUR") == Amount.zero(currency: 
"EUR"))
+        XCTAssert(Amount.zero(currency: "EUR").isZero)
+        XCTAssert(try Amount(fromString: "EUR:0").isZero)
+        XCTAssert(try Amount(fromString: "EUR:0.0").isZero)
+        XCTAssert(try Amount(fromString: "EUR:0.00000").isZero)
+        XCTAssert(try (Amount(fromString: "EUR:1.001") - Amount(fromString: 
"EUR:1.001")).isZero)
+        XCTAssert(try !Amount(fromString: "EUR:0.00000001").isZero)
+        XCTAssert(try !Amount(fromString: "EUR:1.0").isZero)
+        XCTAssert(try !Amount(fromString: "EUR:0001.0").isZero)
+    }
+    
+    func testComparison() {
+        XCTAssert(try Amount(fromString: "EUR:0") <= Amount(fromString: 
"EUR:0"))
+        XCTAssert(try Amount(fromString: "EUR:0") <= Amount(fromString: 
"EUR:0.00000001"))
+        XCTAssert(try Amount(fromString: "EUR:0") < Amount(fromString: 
"EUR:0.00000001"))
+        XCTAssert(try Amount(fromString: "EUR:0") < Amount(fromString: 
"EUR:1"))
+        XCTAssert(try Amount(fromString: "EUR:0") == Amount(fromString: 
"EUR:0"))
+        XCTAssert(try Amount(fromString: "EUR:42") == Amount(fromString: 
"EUR:42"))
+        XCTAssert(try Amount(fromString: "EUR:42.00000001") == 
Amount(fromString: "EUR:42.00000001"))
+        XCTAssert(try Amount(fromString: "EUR:42.00000001") >= 
Amount(fromString: "EUR:42.00000001"))
+        XCTAssert(try Amount(fromString: "EUR:42.00000002") >= 
Amount(fromString: "EUR:42.00000001"))
+        XCTAssert(try Amount(fromString: "EUR:42.00000002") > 
Amount(fromString: "EUR:42.00000001"))
+        XCTAssert(try Amount(fromString: "EUR:0.00000002") > 
Amount(fromString: "EUR:0.00000001"))
+        XCTAssert(try Amount(fromString: "EUR:0.00000001") > 
Amount(fromString: "EUR:0"))
+        XCTAssert(try Amount(fromString: "EUR:2") > Amount(fromString: 
"EUR:1"))
+        XCTAssertThrowsError(try Amount(fromString: "EUR:0.5") < 
Amount(fromString: "USD:0.50000001"))
     }
-
 }
diff --git a/taler-swift/Tests/taler-swiftTests/taler_swiftTests.swift 
b/taler-swift/Tests/taler-swiftTests/taler_swiftTests.swift
deleted file mode 100644
index d7b1c8f..0000000
--- a/taler-swift/Tests/taler-swiftTests/taler_swiftTests.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-import XCTest
-@testable import taler_swift
-
-final class taler_swiftTests: XCTestCase {
-    func testExample() throws {
-        // This is an example of a functional test case.
-        // Use XCTAssert and related functions to verify your tests produce 
the correct
-        // results.
-        XCTAssertEqual(taler_swift().text, "Hello, World!")
-    }
-}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]