summaryrefslogtreecommitdiffstats
path: root/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift')
-rw-r--r--toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift232
1 files changed, 232 insertions, 0 deletions
diff --git a/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift
new file mode 100644
index 0000000000..d9f47058ed
--- /dev/null
+++ b/toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.swift
@@ -0,0 +1,232 @@
+import rondpoint
+
+let dico = Dictionnaire(un: .deux, deux: false, petitNombre: 0, grosNombre: 123456789)
+let copyDico = copieDictionnaire(d: dico)
+assert(dico == copyDico)
+
+assert(copieEnumeration(e: .deux) == .deux)
+assert(copieEnumerations(e: [.un, .deux]) == [.un, .deux])
+assert(copieCarte(c:
+ ["0": .zero,
+ "1": .un(premier: 1),
+ "2": .deux(premier: 2, second: "deux")
+]) == [
+ "0": .zero,
+ "1": .un(premier: 1),
+ "2": .deux(premier: 2, second: "deux")
+])
+
+assert(EnumerationAvecDonnees.zero != EnumerationAvecDonnees.un(premier: 1))
+assert(EnumerationAvecDonnees.un(premier: 1) == EnumerationAvecDonnees.un(premier: 1))
+assert(EnumerationAvecDonnees.un(premier: 1) != EnumerationAvecDonnees.un(premier: 2))
+
+
+assert(switcheroo(b: false))
+
+// Test the roundtrip across the FFI.
+// This shows that the values we send come back in exactly the same state as we sent them.
+// i.e. it shows that lowering from swift and lifting into rust is symmetrical with
+// lowering from rust and lifting into swift.
+let rt = Retourneur()
+
+// Booleans
+[true, false].affirmAllerRetour(rt.identiqueBoolean)
+
+// Bytes.
+[.min, .max].affirmAllerRetour(rt.identiqueI8)
+[0x00, 0xFF].map { $0 as UInt8 }.affirmAllerRetour(rt.identiqueU8)
+
+// Shorts
+[.min, .max].affirmAllerRetour(rt.identiqueI16)
+[0x0000, 0xFFFF].map { $0 as UInt16 }.affirmAllerRetour(rt.identiqueU16)
+
+// Ints
+[0, 1, -1, .min, .max].affirmAllerRetour(rt.identiqueI32)
+[0x00000000, 0xFFFFFFFF].map { $0 as UInt32 }.affirmAllerRetour(rt.identiqueU32)
+
+// Longs
+[.zero, 1, -1, .min, .max].affirmAllerRetour(rt.identiqueI64)
+[.zero, 1, .min, .max].affirmAllerRetour(rt.identiqueU64)
+
+// Floats
+[.zero, 1, 0.25, .leastNonzeroMagnitude, .greatestFiniteMagnitude].affirmAllerRetour(rt.identiqueFloat)
+
+// Doubles
+[0.0, 1.0, .leastNonzeroMagnitude, .greatestFiniteMagnitude].affirmAllerRetour(rt.identiqueDouble)
+
+// Strings
+["", "abc", "null\0byte", "été", "ښي لاس ته لوستلو لوستل", "😻emoji 👨‍👧‍👦multi-emoji, 🇨🇭a flag, a canal, panama"]
+ .affirmAllerRetour(rt.identiqueString)
+
+// Test one way across the FFI.
+//
+// We send one representation of a value to lib.rs, and it transforms it into another, a string.
+// lib.rs sends the string back, and then we compare here in swift.
+//
+// This shows that the values are transformed into strings the same way in both swift and rust.
+// i.e. if we assume that the string return works (we test this assumption elsewhere)
+// we show that lowering from swift and lifting into rust has values that both swift and rust
+// both stringify in the same way. i.e. the same values.
+//
+// If we roundtripping proves the symmetry of our lowering/lifting from here to rust, and lowering/lifting from rust t here,
+// and this convinces us that lowering/lifting from here to rust is correct, then
+// together, we've shown the correctness of the return leg.
+let st = Stringifier()
+
+// Test the effigacy of the string transport from rust. If this fails, but everything else
+// works, then things are very weird.
+let wellKnown = st.wellKnownString(value: "swift")
+assert("uniffi 💚 swift!" == wellKnown, "wellKnownString 'uniffi 💚 swift!' == '\(wellKnown)'")
+
+// Booleans
+[true, false].affirmEnchaine(st.toStringBoolean)
+
+// Bytes.
+[.min, .max].affirmEnchaine(st.toStringI8)
+[.min, .max].affirmEnchaine(st.toStringU8)
+
+// Shorts
+[.min, .max].affirmEnchaine(st.toStringI16)
+[.min, .max].affirmEnchaine(st.toStringU16)
+
+// Ints
+[0, 1, -1, .min, .max].affirmEnchaine(st.toStringI32)
+[0, 1, .min, .max].affirmEnchaine(st.toStringU32)
+
+// Longs
+[.zero, 1, -1, .min, .max].affirmEnchaine(st.toStringI64)
+[.zero, 1, .min, .max].affirmEnchaine(st.toStringU64)
+
+// Floats
+[.zero, 1, -1, .leastNonzeroMagnitude, .greatestFiniteMagnitude].affirmEnchaine(st.toStringFloat) { Float.init($0) == $1 }
+
+// Doubles
+[.zero, 1, -1, .leastNonzeroMagnitude, .greatestFiniteMagnitude].affirmEnchaine(st.toStringDouble) { Double.init($0) == $1 }
+
+// Some extension functions for testing the results of roundtripping and stringifying
+extension Array where Element: Equatable {
+ static func defaultEquals(_ observed: String, expected: Element) -> Bool {
+ let exp = "\(expected)"
+ return observed == exp
+ }
+
+ func affirmEnchaine(_ fn: (Element) -> String, equals: (String, Element) -> Bool = defaultEquals) {
+ self.forEach { v in
+ let obs = fn(v)
+ assert(equals(obs, v), "toString_\(type(of:v))(\(v)): observed=\(obs), expected=\(v)")
+ }
+ }
+
+ func affirmAllerRetour(_ fn: (Element) -> Element) {
+ self.forEach { v in
+ assert(fn(v) == v, "identique_\(type(of:v))(\(v))")
+ }
+ }
+}
+
+// Prove to ourselves that default arguments are being used.
+// Step 1: call the methods without arguments, and check against the UDL.
+let op = Optionneur()
+
+assert(op.sinonString() == "default")
+
+assert(op.sinonBoolean() == false)
+
+assert(op.sinonSequence() == [])
+
+// optionals
+assert(op.sinonNull() == nil)
+assert(op.sinonZero() == 0)
+
+// decimal integers
+assert(op.sinonU8Dec() == UInt8(42))
+assert(op.sinonI8Dec() == Int8(-42))
+assert(op.sinonU16Dec() == UInt16(42))
+assert(op.sinonI16Dec() == Int16(42))
+assert(op.sinonU32Dec() == UInt32(42))
+assert(op.sinonI32Dec() == Int32(42))
+assert(op.sinonU64Dec() == UInt64(42))
+assert(op.sinonI64Dec() == Int64(42))
+
+// hexadecimal integers
+assert(op.sinonU8Hex() == UInt8(0xff))
+assert(op.sinonI8Hex() == Int8(-0x7f))
+assert(op.sinonU16Hex() == UInt16(0xffff))
+assert(op.sinonI16Hex() == Int16(0x7f))
+assert(op.sinonU32Hex() == UInt32(0xffffffff))
+assert(op.sinonI32Hex() == Int32(0x7fffffff))
+assert(op.sinonU64Hex() == UInt64(0xffffffffffffffff))
+assert(op.sinonI64Hex() == Int64(0x7fffffffffffffff))
+
+// octal integers
+assert(op.sinonU32Oct() == UInt32(0o755))
+
+// floats
+assert(op.sinonF32() == 42.0)
+assert(op.sinonF64() == Double(42.1))
+
+// enums
+assert(op.sinonEnum() == .trois)
+
+// Step 2. Convince ourselves that if we pass something else, then that changes the output.
+// We have shown something coming out of the sinon methods, but without eyeballing the Rust
+// we can't be sure that the arguments will change the return value.
+["foo", "bar"].affirmAllerRetour(op.sinonString)
+[true, false].affirmAllerRetour(op.sinonBoolean)
+[["a", "b"], []].affirmAllerRetour(op.sinonSequence)
+
+// optionals
+["0", "1"].affirmAllerRetour(op.sinonNull)
+[0, 1].affirmAllerRetour(op.sinonZero)
+
+// integers
+[0, 1].affirmAllerRetour(op.sinonU8Dec)
+[0, 1].affirmAllerRetour(op.sinonI8Dec)
+[0, 1].affirmAllerRetour(op.sinonU16Dec)
+[0, 1].affirmAllerRetour(op.sinonI16Dec)
+[0, 1].affirmAllerRetour(op.sinonU32Dec)
+[0, 1].affirmAllerRetour(op.sinonI32Dec)
+[0, 1].affirmAllerRetour(op.sinonU64Dec)
+[0, 1].affirmAllerRetour(op.sinonI64Dec)
+
+[0, 1].affirmAllerRetour(op.sinonU8Hex)
+[0, 1].affirmAllerRetour(op.sinonI8Hex)
+[0, 1].affirmAllerRetour(op.sinonU16Hex)
+[0, 1].affirmAllerRetour(op.sinonI16Hex)
+[0, 1].affirmAllerRetour(op.sinonU32Hex)
+[0, 1].affirmAllerRetour(op.sinonI32Hex)
+[0, 1].affirmAllerRetour(op.sinonU64Hex)
+[0, 1].affirmAllerRetour(op.sinonI64Hex)
+
+[0, 1].affirmAllerRetour(op.sinonU32Oct)
+
+// floats
+[0.0, 1.0].affirmAllerRetour(op.sinonF32)
+[0.0, 1.0].affirmAllerRetour(op.sinonF64)
+
+// enums
+[.un, .deux, .trois].affirmAllerRetour(op.sinonEnum)
+
+// Testing defaulting properties in record types.
+let defaultes = OptionneurDictionnaire()
+let explicites = OptionneurDictionnaire(
+ i8Var: Int8(-8),
+ u8Var: UInt8(8),
+ i16Var: Int16(-16),
+ u16Var: UInt16(0x10),
+ i32Var: -32,
+ u32Var: UInt32(32),
+ i64Var: Int64(-64),
+ u64Var: UInt64(64),
+ floatVar: Float(4.0),
+ doubleVar: Double(8.0),
+ booleanVar: true,
+ stringVar: "default",
+ listVar: [],
+ enumerationVar: .deux,
+ dictionnaireVar: nil
+)
+
+// …and makes sure they travel across and back the FFI.
+assert(defaultes == explicites)
+[defaultes].affirmAllerRetour(rt.identiqueOptionneurDictionnaire)