mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-19 21:27:57 +00:00
Add Route Swift API
Uses the Route REST API internally. Create the 'allswift' test script that aggregates the Keyring and Route Swift API tests.
This commit is contained in:
parent
dce8b378d2
commit
a691a39870
@ -27,11 +27,12 @@ var arg0 : String = ""
|
||||
|
||||
func usage() {
|
||||
// Once no longer supporting Swift 3, change this to a multi-line string literal.
|
||||
print("Usage: \(arg0) [options] keyring --pin PIN list")
|
||||
print(" \(arg0) [options] keyring --pin PIN get SID")
|
||||
print(" \(arg0) [options] keyring --pin PIN add [ did DID ] [ name NAME ]")
|
||||
print(" \(arg0) [options] keyring --pin PIN remove SID")
|
||||
print(" \(arg0) [options] keyring --pin PIN set SID [ did DID ] [ name NAME ]")
|
||||
print("Usage: \(arg0) [options] keyring [ --pin PIN ] list")
|
||||
print(" \(arg0) [options] keyring [ --pin PIN ] get SID")
|
||||
print(" \(arg0) [options] keyring [ --pin PIN ] add [ did DID ] [ name NAME ]")
|
||||
print(" \(arg0) [options] keyring [ --pin PIN ] remove SID")
|
||||
print(" \(arg0) [options] keyring [ --pin PIN ] set SID [ did DID ] [ name NAME ]")
|
||||
print(" \(arg0) [options] route list")
|
||||
print("Options:")
|
||||
print(" --pin PIN")
|
||||
print(" --user USER")
|
||||
@ -54,6 +55,8 @@ func main() {
|
||||
switch (cmd) {
|
||||
case "keyring":
|
||||
exit(keyring(&args, configuration: restful_config))
|
||||
case "route":
|
||||
exit(route(&args, configuration: restful_config))
|
||||
default:
|
||||
usage()
|
||||
exit(1)
|
||||
@ -237,4 +240,38 @@ func keyring(_ args: inout [String], configuration: ServalRestfulClient.Configur
|
||||
return status
|
||||
}
|
||||
|
||||
func route(_ args: inout [String], configuration: ServalRestfulClient.Configuration) -> Int32 {
|
||||
let cmd = args.isEmpty ? "" : args.remove(at: 0)
|
||||
var status : Int32 = 0
|
||||
switch (cmd) {
|
||||
case "list":
|
||||
precondition(args.isEmpty)
|
||||
print("8")
|
||||
print("sid:did:name:is_self:hop_count:reachable_broadcast:reachable_unicast:reachable_indirect")
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
let client = ServalRestfulClient(configuration: configuration)
|
||||
let request = ServalRoute.listIdentities(client: client) { (identities, error) in
|
||||
if let error = error {
|
||||
print(error, to: &errorStream)
|
||||
status = 2
|
||||
}
|
||||
else if let identities = identities {
|
||||
for identity in identities {
|
||||
print("\(identity.sid.hexUpper):\(identity.did ?? ""):\(identity.name ?? ""):\(identity.is_self ? 1 : 0):\(identity.hop_count):\(identity.reachable_broadcast ? 1 : 0):\(identity.reachable_unicast ? 1 : 0):\(identity.reachable_indirect ? 1 : 0)")
|
||||
}
|
||||
}
|
||||
semaphore.signal()
|
||||
}
|
||||
print("Waiting...", to: &debugStream)
|
||||
semaphore.wait()
|
||||
print("Done", to: &debugStream)
|
||||
request.close()
|
||||
|
||||
default:
|
||||
usage()
|
||||
status = 1
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
main()
|
||||
|
137
swift-client-api/package/Sources/route.swift
Normal file
137
swift-client-api/package/Sources/route.swift
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
Serval DNA Swift API
|
||||
Copyright (C) 2018 Flinders University
|
||||
|
||||
This program 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 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
private protocol OptionalProtocol {
|
||||
func wrappedType() -> Any.Type
|
||||
}
|
||||
|
||||
extension Optional: OptionalProtocol {
|
||||
func wrappedType() -> Any.Type {
|
||||
return Wrapped.self
|
||||
}
|
||||
}
|
||||
|
||||
public class ServalRoute {
|
||||
|
||||
public struct Identity {
|
||||
public let sid : SubscriberId
|
||||
public let did : String?
|
||||
public let name : String?
|
||||
public let is_self : Bool
|
||||
public let hop_count : Int
|
||||
public let reachable_broadcast : Bool
|
||||
public let reachable_unicast : Bool
|
||||
public let reachable_indirect : Bool
|
||||
}
|
||||
|
||||
private static func unpackField<T, U>(_ json: [String: Any?], _ key: String, _ convert: (T) throws -> U) throws -> U {
|
||||
guard let opt = json[key] else {
|
||||
throw ServalRestfulClient.Exception.invalidJson(reason: "missing \"\(key)\" element")
|
||||
}
|
||||
if let typed = opt as? T {
|
||||
return try convert(typed)
|
||||
}
|
||||
throw ServalRestfulClient.Exception.invalidJson(reason: "\(key) value is not \(String(describing: T.self)): \(opt ?? "nil")")
|
||||
}
|
||||
|
||||
/* I cannot work out any way to combine this function into unpackField() by
|
||||
* detecting when T and U are Optional<> types.
|
||||
*/
|
||||
private static func unpackOptionalField<T, U>(_ json: [String: Any?], _ key: String, _ convert: (T) throws -> U?) throws -> U? {
|
||||
guard let opt = json[key] else {
|
||||
throw ServalRestfulClient.Exception.invalidJson(reason: "missing \"\(key)\" element")
|
||||
}
|
||||
guard let any = opt else {
|
||||
return nil
|
||||
}
|
||||
if let typed = any as? T {
|
||||
return try convert(typed)
|
||||
}
|
||||
throw ServalRestfulClient.Exception.invalidJson(reason: "\(key) value is not \(String(describing: T.self)): \(any)")
|
||||
}
|
||||
|
||||
private static func convertSID(_ sidhex: String) throws -> SubscriberId {
|
||||
guard let sid = SubscriberId(fromHex: sidhex) else {
|
||||
throw ServalRestfulClient.Exception.invalidJson(reason: "sid value is not hex: \(sidhex)")
|
||||
}
|
||||
return sid
|
||||
}
|
||||
|
||||
private static func nonEmptyStringOrNil(_ s: String) -> String? {
|
||||
return s.isEmpty ? nil : s
|
||||
}
|
||||
|
||||
private static func isBool(_ b: Bool) -> Bool {
|
||||
return b
|
||||
}
|
||||
|
||||
private static func nonNegativeInt(i: Int) throws -> Int {
|
||||
if i < 0 {
|
||||
throw ServalRestfulClient.Exception.invalidJson(reason: "integer value is negative: \(i)")
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
private static func unpackIdentity(fromJsonDict json: [String: Any?]) throws -> Identity
|
||||
{
|
||||
return Identity(sid: try unpackField(json, "sid", convertSID),
|
||||
did: try unpackOptionalField(json, "did", nonEmptyStringOrNil),
|
||||
name: try unpackOptionalField(json, "name", nonEmptyStringOrNil),
|
||||
is_self: try unpackField(json, "is_self", isBool),
|
||||
hop_count: try unpackField(json, "hop_count", nonNegativeInt),
|
||||
reachable_broadcast: try unpackField(json, "reachable_broadcast", isBool),
|
||||
reachable_unicast: try unpackField(json, "reachable_unicast", isBool),
|
||||
reachable_indirect: try unpackField(json, "reachable_indirect", isBool))
|
||||
}
|
||||
|
||||
public static func listIdentities(client: ServalRestfulClient = ServalRestfulClient(),
|
||||
pin: String? = nil,
|
||||
completionHandler: @escaping ([Identity]?, Error?) -> Void)
|
||||
-> ServalRestfulClient.Request
|
||||
{
|
||||
var param = [String: String]()
|
||||
if pin != nil { param["pin"] = pin }
|
||||
return client.createRequest(verb: "GET",
|
||||
path: "restful/route/all.json",
|
||||
query: param) { (statusCode, json, error) in
|
||||
if let error = error {
|
||||
completionHandler(nil, error)
|
||||
return
|
||||
}
|
||||
guard statusCode! == 200 else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.requestFailed(statusCode: statusCode!))
|
||||
return
|
||||
}
|
||||
var identities : [Identity] = []
|
||||
do {
|
||||
for row in try ServalRestfulClient.transformJsonTable(json: json) {
|
||||
identities.append(try unpackIdentity(fromJsonDict: row))
|
||||
}
|
||||
}
|
||||
catch let e {
|
||||
completionHandler(nil, e)
|
||||
return
|
||||
}
|
||||
completionHandler(identities, nil)
|
||||
}!
|
||||
}
|
||||
|
||||
}
|
@ -44,7 +44,7 @@ if type -p "$JAVAC" >/dev/null; then
|
||||
includeTests alljava
|
||||
fi
|
||||
if type -p "$SWIFTC" >/dev/null; then
|
||||
includeTests keyringswift
|
||||
includeTests allswift
|
||||
fi
|
||||
|
||||
runTests "$@"
|
||||
|
27
tests/allswift
Executable file
27
tests/allswift
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Aggregation of all Swift API tests.
|
||||
#
|
||||
# Copyright 2018 Flinders University
|
||||
#
|
||||
# This program 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 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
source "${0%/*}/../testframework.sh"
|
||||
source "${0%/*}/../testdefs.sh"
|
||||
|
||||
includeTests keyringswift
|
||||
includeTests routeswift
|
||||
|
||||
runTests "$@"
|
72
tests/routeswift
Executable file
72
tests/routeswift
Executable file
@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tests for Route Swift API.
|
||||
#
|
||||
# Copyright 2018 Flinders University
|
||||
#
|
||||
# This program 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 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
source "${0%/*}/../testframework.sh"
|
||||
source "${0%/*}/../testdefs.sh"
|
||||
source "${0%/*}/../testdefs_routing.sh"
|
||||
source "${0%/*}/../testdefs_swift.sh"
|
||||
|
||||
setup() {
|
||||
setup_servald
|
||||
setup_swift_config +A
|
||||
set_instance +A
|
||||
setup_route_config
|
||||
export SERVALD_RHIZOME_DB_RETRY_LIMIT_MS=60000
|
||||
}
|
||||
|
||||
teardown() {
|
||||
stop_all_servald_servers
|
||||
kill_all_servald_processes
|
||||
assert_no_servald_processes
|
||||
report_all_servald_servers
|
||||
}
|
||||
|
||||
doc_RouteListAll="Swift API list entire routing table"
|
||||
setup_RouteListAll() {
|
||||
setup
|
||||
DIDA1=565656
|
||||
NAMEA1="Neddy Seagoon"
|
||||
DIDA2=3020304
|
||||
NAMEA2="Spike Milligan"
|
||||
foreach_instance +A +B create_identities 2
|
||||
foreach_instance +A +B add_servald_interface 1
|
||||
foreach_instance +A +B start_servald_server
|
||||
wait_until_swift_server_ready +A
|
||||
get_servald_primary_sid +B PRIMARY_SIDB
|
||||
wait_until --timeout=20 path_exists +A +B
|
||||
wait_until --timeout=10 path_exists +B +A
|
||||
set_instance +A
|
||||
}
|
||||
test_RouteListAll() {
|
||||
executeSwiftOk route list
|
||||
tfw_cat --stdout --stderr
|
||||
assertStdoutLineCount == 6
|
||||
assertStdoutGrep --line=2 "^sid:did:name:is_self:hop_count:reachable_broadcast:reachable_unicast:reachable_indirect$"
|
||||
assertStdoutGrep --matches=1 "^$SIDA1:$DIDA1:$NAMEA1:1:0:[01]:[01]:[01]$"
|
||||
assertStdoutGrep --matches=1 "^$SIDA2:$DIDA2:$NAMEA2:1:0:[01]:[01]:[01]$"
|
||||
assertStdoutGrep --matches=1 "^$PRIMARY_SIDB:::0:1:[01]:1:0$"
|
||||
for SID in "${SIDB[@]}"; do
|
||||
if [ "$SID" != "$PRIMARY_SIDB" ]; then
|
||||
assertStdoutGrep --matches=1 "^$SID:::0:2:[01]:0:1$"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
runTests "$@"
|
Loading…
Reference in New Issue
Block a user