Skip to content

Commit

Permalink
feat: internal refactoring to enable use of descriptor format in appl…
Browse files Browse the repository at this point in the history
…ication core.
  • Loading branch information
aanorbel committed Jun 19, 2024
1 parent 4c3e06a commit d0ffa8e
Show file tree
Hide file tree
Showing 8 changed files with 309 additions and 41 deletions.
18 changes: 18 additions & 0 deletions ooniprobe.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
7940AA8B28117E9000C0EB5D /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7940AA8A28117E9000C0EB5D /* ShareViewController.swift */; };
7940AA8E28117E9000C0EB5D /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7940AA8C28117E9000C0EB5D /* MainInterface.storyboard */; };
7940AA9228117E9000C0EB5D /* share.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7940AA8828117E9000C0EB5D /* share.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
7945903D2C21BFB1008116BF /* OONIDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7945903C2C21BFB1008116BF /* OONIDescriptor.swift */; };
79780FCF27E9F18E002A38B1 /* Languages.plist in Resources */ = {isa = PBXBuildFile; fileRef = 79780FCE27E9F18E002A38B1 /* Languages.plist */; };
7AED19812A6EC9A2003B265A /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AED19802A6EC9A2003B265A /* libresolv.tbd */; };
7AED19832A6EC9C7003B265A /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AED19822A6EC9C7003B265A /* libresolv.tbd */; };
Expand Down Expand Up @@ -225,6 +226,8 @@
7940AA8D28117E9000C0EB5D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
7940AA8F28117E9000C0EB5D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7940AA972811840900C0EB5D /* share.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = share.entitlements; sourceTree = "<group>"; };
7945903B2C21BFB1008116BF /* ooniprobe-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ooniprobe-Bridging-Header.h"; sourceTree = "<group>"; };
7945903C2C21BFB1008116BF /* OONIDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OONIDescriptor.swift; sourceTree = "<group>"; };
79780FCE27E9F18E002A38B1 /* Languages.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Languages.plist; sourceTree = "<group>"; };
79AA093C2A86E44400C23E27 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
79AA093D2A86E47600C23E27 /* my */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = my; path = my.lproj/Localizable.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -654,6 +657,7 @@
526C702925C99AB100C7A164 /* Colors.xcassets */,
D4A2F5EB1A6C3244001B8460 /* LaunchScreen.xib */,
D4A2F5DC1A6C3244001B8460 /* Supporting Files */,
7945903B2C21BFB1008116BF /* ooniprobe-Bridging-Header.h */,
);
path = ooniprobe;
sourceTree = "<group>";
Expand Down Expand Up @@ -720,6 +724,7 @@
ED25280F1CEA34DA0073A29B /* Model */ = {
isa = PBXGroup;
children = (
7945903C2C21BFB1008116BF /* OONIDescriptor.swift */,
ED90A91A2198DE5000204B46 /* Database */,
ED90A9232198DE5000204B46 /* Settings */,
EDB252A120FA46DA00B4EDE4 /* JsonResult */,
Expand Down Expand Up @@ -1276,6 +1281,7 @@
D4A2F5D81A6C3244001B8460 = {
CreatedOnToolsVersion = 6.1.1;
DevelopmentTeam = MADPSAYN6T;
LastSwiftMigration = 1540;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.BackgroundModes = {
Expand Down Expand Up @@ -1539,6 +1545,7 @@
buildActionMask = 2147483647;
files = (
EDB3D64F26204C9300724ECF /* Experimental.m in Sources */,
7945903D2C21BFB1008116BF /* OONIDescriptor.swift in Sources */,
ED4DF7B52607970C00521C5B /* Signal.m in Sources */,
ED365217223A40480093180B /* FailedTestDetailsViewController.m in Sources */,
ED1CC80220159D970041089A /* TestRunningViewController.m in Sources */,
Expand Down Expand Up @@ -1745,6 +1752,7 @@
17E7EDBC21BFEDD1001961C7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
Expand Down Expand Up @@ -1777,6 +1785,7 @@
17E7EDBD21BFEDD1001961C7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
Expand Down Expand Up @@ -2012,6 +2021,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ooniprobe/ooniprobe.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -2045,6 +2055,9 @@
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_OBJC_BRIDGING_HEADER = "ooniprobe/ooniprobe-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "";
VALID_ARCHS = "arm64 x86_64";
Expand All @@ -2060,6 +2073,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ooniprobe/ooniprobe.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -2095,6 +2109,8 @@
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_OBJC_BRIDGING_HEADER = "ooniprobe/ooniprobe-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "";
VALID_ARCHS = arm64;
Expand All @@ -2105,6 +2121,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = AC948DA31A71FB931BBB1BB3 /* Pods-OONIProbeUnitTests.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
Expand Down Expand Up @@ -2136,6 +2153,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = CAFF8CF760913F0065D0615D /* Pods-OONIProbeUnitTests.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
Expand Down
244 changes: 244 additions & 0 deletions ooniprobe/OONIDescriptor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
import Foundation
import UIKit

/// `NettestName` is an enumeration that defines a set of named constants for different nettests.
/// Each case in the enumeration represents a different nettest.
enum NettestName: String {
case webConnectivity = "web_connectivity" // Represents the Web Connectivity test
case whatsapp = "whatsapp" // Represents the WhatsApp test
case telegram = "telegram" // Represents the Telegram test
case facebookMessenger = "facebook_messenger" // Represents the Facebook Messenger test
case signal = "signal" // Represents the Signal test
case psiphon = "psiphon" // Represents the Psiphon test
case tor = "tor" // Represents the Tor test
case ndt = "ndt" // Represents the NDT test
case dash = "dash" // Represents the DASH test
case httpHeaderFieldManipulation = "http_header_field_manipulation" // Represents the HTTP Header Field Manipulation test
case httpInvalidRequestLine = "http_invalid_request_line" // Represents the HTTP Invalid Request Line test
case stunReachability = "stunreachability" // Represents the STUN Reachability test
case dnsCheck = "dnscheck" // Represents the DNS Check test
case riseupVPN = "riseupvpn" // Represents the RiseupVPN test
case echCheck = "echcheck" // Represents the ECH Check test
case torsf = "torsf" // Represents the TorSF test
case vanillaTor = "vanilla_tor" // Represents the Vanilla Tor test
}

/// `Nettest` is a class that represents a nettest.
/// It contains information about the nettest such as the name, inputs, etc.
/// The class also provides a method to get the test object for the nettest.
@objc(Nettest)
public class Nettest: NSObject {

// MARK: Initializers
init(name: String, inputs: [String]?) {
self.name = name
self.inputs = inputs
}

// MARK: Properties
@objc dynamic var name: String
@objc dynamic var inputs: [String]?

// MARK: Methods
@objc public func getTest() -> AbstractTest {
switch NettestName(rawValue: self.name) {
case .webConnectivity:
return WebConnectivity()
case .whatsapp:
return Whatsapp()
case .telegram:
return Telegram()
case .facebookMessenger:
return FacebookMessenger()
case .signal:
return Signal()
case .psiphon:
return Psiphon()
case .tor:
return Tor()
case .ndt:
return NdtTest()
case .dash:
return Dash()
case .httpHeaderFieldManipulation:
return HttpHeaderFieldManipulation()
case .httpInvalidRequestLine:
return HttpInvalidRequestLine()
case .riseupVPN:
return RiseupVPN()
default:
return Experimental(name: name)
}
}
}

/// `OONIDescriptor` is a class that represents an OONI descriptor.
/// It contains information about the descriptor such as the name, title, icon, color, etc.
/// It also contains information about the nettests that are part of the descriptor.
/// The class also provides a method to get the OONI descriptors for the OONI dashboard.
/// The class also provides a method to get the test suite for the current descriptor.
@objc(OONIDescriptor)
public class OONIDescriptor: NSObject {

// MARK: Initializers
init(name: String,
title: String,
shortDescription: String,
longDescription: String,
icon: String,
color: UIColor,
animation: String?,
dataUsage: String,
nettest: [Nettest],
longRunningTests: [Nettest]?) {
self.name = name
self.title = title
self.shortDescription = shortDescription
self.longDescription = longDescription
self.icon = icon
self.color = color
self.animation = animation
self.dataUsage = dataUsage
self.nettest = nettest
self.longRunningTests = longRunningTests
}

// MARK: Properties
@objc dynamic var name: String
@objc dynamic var title: String
@objc dynamic var shortDescription: String
@objc dynamic var longDescription: String
@objc dynamic var icon: String
@objc dynamic var color: UIColor
@objc dynamic var animation: String?
@objc dynamic var dataUsage: String
@objc dynamic var nettest: [Nettest]
@objc dynamic var longRunningTests: [Nettest]?

// MARK: Methods

// Get the OONI descriptors for the OONI dashboard.
@objc public static func getOONIDescriptors() -> [OONIDescriptor] {

[
OONIDescriptor(
name: "websites",
title: NSLocalizedString("Test.Websites.Fullname", comment: ""),
shortDescription: NSLocalizedString("Dashboard.Websites.Card.Description", comment: ""),
longDescription: NSLocalizedString("Dashboard.Websites.Overview.Paragraph", comment: ""),
icon: "websites",
color: UIColor(named: "color_indigo6")!,
animation: "websites",
dataUsage: "~ 8 MB",
nettest: [
Nettest(name: NettestName.webConnectivity.rawValue, inputs: [])
],
longRunningTests: []
),

OONIDescriptor(
name: "instant_messaging",
title: NSLocalizedString("Test.InstantMessaging.Fullname", comment: ""),
shortDescription: NSLocalizedString("Dashboard.InstantMessaging.Card.Description", comment: ""),
longDescription: NSLocalizedString("Dashboard.InstantMessaging.Overview.Paragraph", comment: ""),
icon: "instant_messaging",
color: UIColor(named: "color_indigo5")!,
animation: "instant_messaging",
dataUsage: NSLocalizedString("small.datausage", comment: ""),
nettest: [
Nettest(name: NettestName.whatsapp.rawValue, inputs: []),
Nettest(name: NettestName.telegram.rawValue, inputs: []),
Nettest(name: NettestName.facebookMessenger.rawValue, inputs: []),
Nettest(name: NettestName.signal.rawValue, inputs: [])
],
longRunningTests: []
),

OONIDescriptor(
name: "circumvention",
title: NSLocalizedString("Test.Circumvention.Fullname", comment: ""),
shortDescription: NSLocalizedString("Dashboard.Circumvention.Card.Description", comment: ""),
longDescription: NSLocalizedString("Dashboard.Circumvention.Overview.Paragraph", comment: ""),
icon: "circumvention",
color: UIColor(named: "color_indigo2")!,
animation: "circumvention",
dataUsage: NSLocalizedString("small.datausage", comment: ""),
nettest: [
Nettest(name: NettestName.psiphon.rawValue, inputs: []),
Nettest(name: NettestName.tor.rawValue, inputs: [])
],
longRunningTests: []
),

OONIDescriptor(
name: "performance",
title: NSLocalizedString("Test.Performance.Fullname", comment: ""),
shortDescription: NSLocalizedString("Dashboard.Performance.Card.Description", comment: ""),
longDescription: NSLocalizedString("Dashboard.Performance.Overview.Paragraph", comment: ""),
icon: "performance",
color: UIColor(named: "color_indigo4")!,
animation: "performance",
dataUsage: NSLocalizedString("performance.datausage", comment: ""),
nettest: [
Nettest(name: NettestName.ndt.rawValue, inputs: []),
Nettest(name: NettestName.dash.rawValue, inputs: []),
Nettest(name: NettestName.httpHeaderFieldManipulation.rawValue, inputs: []),
Nettest(name: NettestName.httpInvalidRequestLine.rawValue, inputs: [])
],
longRunningTests: []
),

OONIDescriptor(
name: "experimental",
title: NSLocalizedString("Test.Experimental.Fullname", comment: ""),
shortDescription: NSLocalizedString("Dashboard.Experimental.Card.Description", comment: ""),
longDescription: NSLocalizedString("Dashboard.Experimental.Overview.Paragraph", comment: ""),
icon: "experimental",
color: UIColor(named: "color_indigo1")!,
animation: "experimental",
dataUsage: NSLocalizedString("TestResults.NotAvailable", comment: ""),
nettest: [
Nettest(name: "stunreachability", inputs: []),
Nettest(name: "dnscheck", inputs: []),
Nettest(name: "riseupvpn", inputs: []),
Nettest(name: "echcheck", inputs: []),
],
longRunningTests: [
Nettest(name: "torsf", inputs: []),
Nettest(name: "vanilla_tor", inputs: []),
]
)
]
}


/// Returns the test suite for the current descriptor.
///
/// @return DynamicTestSuite representing the test suite for the current descriptor.
@objc public func getTestSuites() -> Any {
DynamicTestSuite(descriptor: self)
}
}


/// This class is used to create [AbstractTest] dynamically for all instances where a Test Suite is required.
/// It is used to create a test suite from a Descriptor.
/// It acts as a bridge between the Descriptor format and the [AbstractSuite].
@objc(DynamicTestSuite)
class DynamicTestSuite: AbstractSuite {
// MARK: Initializers
@objc init(descriptor: OONIDescriptor) {
self.descriptor = descriptor
super.init()
self.name = descriptor.name
self.dataUsage = descriptor.dataUsage
let tests = NSMutableArray()
tests.addObjects(from: descriptor.nettest.map { nettest in
nettest.getTest()
})
self.testList = tests
}

// MARK: Properties
@objc dynamic var descriptor: OONIDescriptor
}
Loading

0 comments on commit d0ffa8e

Please sign in to comment.