Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dev] OONI Run v2 #564

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading