xmpp-vala: improve namespace handling, add some tests
This commit is contained in:
parent
dd88db7556
commit
6904bda756
6
configure
vendored
6
configure
vendored
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
OPTS=`getopt -o "h" --long \
|
OPTS=`getopt -o "h" --long \
|
||||||
help,fetch-only,no-debug,disable-fast-vapi,\
|
help,fetch-only,no-debug,disable-fast-vapi,with-tests,\
|
||||||
enable-plugin:,disable-plugin:,\
|
enable-plugin:,disable-plugin:,\
|
||||||
prefix:,program-prefix:,exec-prefix:,lib-suffix:,\
|
prefix:,program-prefix:,exec-prefix:,lib-suffix:,\
|
||||||
bindir:,libdir:,includedir:,datadir:,\
|
bindir:,libdir:,includedir:,datadir:,\
|
||||||
|
@ -16,6 +16,7 @@ eval set -- "$OPTS"
|
||||||
PREFIX=${PREFIX:-/usr/local}
|
PREFIX=${PREFIX:-/usr/local}
|
||||||
ENABLED_PLUGINS=
|
ENABLED_PLUGINS=
|
||||||
DISABLED_PLUGINS=
|
DISABLED_PLUGINS=
|
||||||
|
BUILD_TESTS=
|
||||||
DISABLE_FAST_VAPI=
|
DISABLE_FAST_VAPI=
|
||||||
LIB_SUFFIX=
|
LIB_SUFFIX=
|
||||||
NO_DEBUG=
|
NO_DEBUG=
|
||||||
|
@ -51,6 +52,7 @@ Configuration:
|
||||||
feature. fast-vapi mode is slower when doing
|
feature. fast-vapi mode is slower when doing
|
||||||
clean builds, but faster when doing incremental
|
clean builds, but faster when doing incremental
|
||||||
builds (during development).
|
builds (during development).
|
||||||
|
--with-tests Also build tests.
|
||||||
|
|
||||||
Plugin configuration:
|
Plugin configuration:
|
||||||
--enable-plugin=PLUGIN Enable compilation of plugin PLUGIN.
|
--enable-plugin=PLUGIN Enable compilation of plugin PLUGIN.
|
||||||
|
@ -108,6 +110,7 @@ while true; do
|
||||||
--disable-fast-vapi ) DISABLE_FAST_VAPI=yes; shift ;;
|
--disable-fast-vapi ) DISABLE_FAST_VAPI=yes; shift ;;
|
||||||
--no-debug ) NO_DEBUG=yes; shift ;;
|
--no-debug ) NO_DEBUG=yes; shift ;;
|
||||||
--fetch-only ) FETCH_ONLY=yes; shift ;;
|
--fetch-only ) FETCH_ONLY=yes; shift ;;
|
||||||
|
--with-tests ) BUILD_TESTS=yes; shift ;;
|
||||||
# Autotools paths
|
# Autotools paths
|
||||||
--program-prefix ) PREFIX="$2"; shift; shift ;;
|
--program-prefix ) PREFIX="$2"; shift; shift ;;
|
||||||
--exec-prefix ) EXEC_PREFIX="$2"; shift; shift ;;
|
--exec-prefix ) EXEC_PREFIX="$2"; shift; shift ;;
|
||||||
|
@ -238,6 +241,7 @@ cmake -G "$cmake_type" \
|
||||||
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
|
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
|
||||||
-DENABLED_PLUGINS="$ENABLED_PLUGINS" \
|
-DENABLED_PLUGINS="$ENABLED_PLUGINS" \
|
||||||
-DDISABLED_PLUGINS="$DISABLED_PLUGINS" \
|
-DDISABLED_PLUGINS="$DISABLED_PLUGINS" \
|
||||||
|
-DBUILD_TESTS="$BUILD_TESTS" \
|
||||||
-DVALA_EXECUTABLE="$VALAC" \
|
-DVALA_EXECUTABLE="$VALAC" \
|
||||||
-DCMAKE_VALA_FLAGS="$VALACFLAGS" \
|
-DCMAKE_VALA_FLAGS="$VALACFLAGS" \
|
||||||
-DDISABLE_FAST_VAPI="$DISABLE_FAST_VAPI" \
|
-DDISABLE_FAST_VAPI="$DISABLE_FAST_VAPI" \
|
||||||
|
|
|
@ -85,3 +85,21 @@ set_target_properties(xmpp-vala PROPERTIES VERSION 0.1 SOVERSION 0)
|
||||||
install(TARGETS xmpp-vala ${TARGET_INSTALL})
|
install(TARGETS xmpp-vala ${TARGET_INSTALL})
|
||||||
install(FILES ${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi ${CMAKE_BINARY_DIR}/exports/xmpp-vala.deps DESTINATION ${VAPI_INSTALL_DIR})
|
install(FILES ${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi ${CMAKE_BINARY_DIR}/exports/xmpp-vala.deps DESTINATION ${VAPI_INSTALL_DIR})
|
||||||
install(FILES ${CMAKE_BINARY_DIR}/exports/xmpp-vala.h DESTINATION ${INCLUDE_INSTALL_DIR})
|
install(FILES ${CMAKE_BINARY_DIR}/exports/xmpp-vala.h DESTINATION ${INCLUDE_INSTALL_DIR})
|
||||||
|
|
||||||
|
if(BUILD_TESTS)
|
||||||
|
vala_precompile(ENGINE_TEST_VALA_C
|
||||||
|
SOURCES
|
||||||
|
"tests/common.vala"
|
||||||
|
"tests/testcase.vala"
|
||||||
|
|
||||||
|
"tests/stanza.vala"
|
||||||
|
CUSTOM_VAPIS
|
||||||
|
${CMAKE_BINARY_DIR}/exports/xmpp-vala_internal.vapi
|
||||||
|
PACKAGES
|
||||||
|
${ENGINE_PACKAGES}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_definitions(${VALA_CFLAGS})
|
||||||
|
add_executable(xmpp-vala-test ${ENGINE_TEST_VALA_C})
|
||||||
|
target_link_libraries(xmpp-vala-test xmpp-vala ${SIGNAL_PROTOCOL_PACKAGES})
|
||||||
|
endif(BUILD_TESTS)
|
||||||
|
|
|
@ -1,68 +1,80 @@
|
||||||
using Gee;
|
using Gee;
|
||||||
|
|
||||||
namespace Xmpp.Core {
|
namespace Xmpp.Core {
|
||||||
|
|
||||||
public class NamespaceState {
|
public class NamespaceState {
|
||||||
private HashMap<string, string> uri_to_name = new HashMap<string, string> ();
|
private HashMap<string, string> uri_to_name = new HashMap<string, string> ();
|
||||||
private HashMap<string, string> name_to_uri = new HashMap<string, string> ();
|
private HashMap<string, string> name_to_uri = new HashMap<string, string> ();
|
||||||
public string current_ns_uri;
|
public string current_ns_uri;
|
||||||
|
|
||||||
public NamespaceState () {
|
private NamespaceState parent;
|
||||||
|
|
||||||
|
public NamespaceState() {
|
||||||
add_assoc(XMLNS_URI, "xmlns");
|
add_assoc(XMLNS_URI, "xmlns");
|
||||||
add_assoc("http://www.w3.org/XML/1998/namespace", "xml");
|
add_assoc(XML_URI, "xml");
|
||||||
current_ns_uri = "http://www.w3.org/XML/1998/namespace";
|
current_ns_uri = XML_URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NamespaceState.for_stanza () {
|
public NamespaceState.for_stanza() {
|
||||||
this();
|
this();
|
||||||
add_assoc("http://etherx.jabber.org/streams", "stream");
|
add_assoc("http://etherx.jabber.org/streams", "stream");
|
||||||
current_ns_uri = "jabber:client";
|
current_ns_uri = "jabber:client";
|
||||||
}
|
}
|
||||||
|
|
||||||
public NamespaceState.copy (NamespaceState old) {
|
private NamespaceState.copy(NamespaceState old) {
|
||||||
foreach (string key in old.uri_to_name.keys) {
|
foreach (string key in old.uri_to_name.keys) {
|
||||||
add_assoc(key, old.uri_to_name[key]);
|
add_assoc(key, old.uri_to_name[key]);
|
||||||
}
|
}
|
||||||
set_current(old.current_ns_uri);
|
set_current(old.current_ns_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NamespaceState.with_assoc (NamespaceState old, string ns_uri, string name) {
|
private NamespaceState.with_parent(NamespaceState parent) {
|
||||||
|
this.copy(parent);
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NamespaceState.with_assoc(NamespaceState old, string ns_uri, string name) {
|
||||||
this.copy(old);
|
this.copy(old);
|
||||||
add_assoc(ns_uri, name);
|
add_assoc(ns_uri, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NamespaceState.with_current (NamespaceState old, string current_ns_uri) {
|
public NamespaceState.with_current(NamespaceState old, string current_ns_uri) {
|
||||||
this.copy(old);
|
this.copy(old);
|
||||||
set_current(current_ns_uri);
|
set_current(current_ns_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_assoc (string ns_uri, string name) {
|
public void add_assoc(string ns_uri, string name) {
|
||||||
name_to_uri[name] = ns_uri;
|
name_to_uri[name] = ns_uri;
|
||||||
uri_to_name[ns_uri] = name;
|
uri_to_name[ns_uri] = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_current (string current_ns_uri) {
|
public void set_current(string current_ns_uri) {
|
||||||
this.current_ns_uri = current_ns_uri;
|
this.current_ns_uri = current_ns_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string find_name (string ns_uri) throws XmlError {
|
public string find_name(string ns_uri) throws XmlError {
|
||||||
if (uri_to_name.has_key(ns_uri)) {
|
if (uri_to_name.has_key(ns_uri)) {
|
||||||
return uri_to_name[ns_uri];
|
return uri_to_name[ns_uri];
|
||||||
}
|
}
|
||||||
throw new XmlError.NS_DICT_ERROR(@"NS URI $ns_uri not found.");
|
throw new XmlError.NS_DICT_ERROR(@"NS URI $ns_uri not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string find_uri (string name) throws XmlError {
|
public string find_uri(string name) throws XmlError {
|
||||||
if (name_to_uri.has_key(name)) {
|
if (name_to_uri.has_key(name)) {
|
||||||
return name_to_uri[name];
|
return name_to_uri[name];
|
||||||
}
|
}
|
||||||
throw new XmlError.NS_DICT_ERROR(@"NS name $name not found.");
|
throw new XmlError.NS_DICT_ERROR(@"NS name $name not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public NamespaceState clone() {
|
public NamespaceState push() {
|
||||||
return new NamespaceState.copy(this);
|
return new NamespaceState.with_parent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string to_string () {
|
public NamespaceState pop() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string to_string() {
|
||||||
StringBuilder sb = new StringBuilder ();
|
StringBuilder sb = new StringBuilder ();
|
||||||
sb.append ("NamespaceState{");
|
sb.append ("NamespaceState{");
|
||||||
foreach (string key in uri_to_name.keys) {
|
foreach (string key in uri_to_name.keys) {
|
||||||
|
@ -77,4 +89,5 @@ public class NamespaceState {
|
||||||
return sb.str;
|
return sb.str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,13 @@ public class StanzaAttribute : StanzaEntry {
|
||||||
this.val = val;
|
this.val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool equals(StanzaAttribute other) {
|
||||||
|
if (other.ns_uri != ns_uri) return false;
|
||||||
|
if (other.name != name) return false;
|
||||||
|
if (other.val != val) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
internal string printf(string fmt, bool no_ns = false, string? ns_name = null) {
|
internal string printf(string fmt, bool no_ns = false, string? ns_name = null) {
|
||||||
if (no_ns) {
|
if (no_ns) {
|
||||||
return fmt.printf(name, (!)val);
|
return fmt.printf(name, (!)val);
|
||||||
|
|
|
@ -300,6 +300,25 @@ public class StanzaNode : StanzaEntry {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool equals(StanzaNode other) {
|
||||||
|
if (other.name != name) return false;
|
||||||
|
if (other.val != val) return false;
|
||||||
|
if (name == "#text") return true;
|
||||||
|
if (other.ns_uri != ns_uri) return false;
|
||||||
|
|
||||||
|
if (other.sub_nodes.size != sub_nodes.size) return false;
|
||||||
|
for (int i = 0; i < sub_nodes.size; i++) {
|
||||||
|
if (!other.sub_nodes[i].equals(sub_nodes[i])) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other.attributes.size != attributes.size) return false;
|
||||||
|
for (int i = 0; i < attributes.size; i++) {
|
||||||
|
if (!other.attributes[i].equals(attributes[i])) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private const string TAG_START_BEGIN_FORMAT = "%s<{%s}:%s";
|
private const string TAG_START_BEGIN_FORMAT = "%s<{%s}:%s";
|
||||||
private const string TAG_START_EMPTY_END = " />\n";
|
private const string TAG_START_EMPTY_END = " />\n";
|
||||||
private const string TAG_START_CONTENT_END = ">\n";
|
private const string TAG_START_CONTENT_END = ">\n";
|
||||||
|
@ -358,12 +377,13 @@ public class StanzaNode : StanzaEntry {
|
||||||
public string to_xml(NamespaceState? state = null) throws XmlError {
|
public string to_xml(NamespaceState? state = null) throws XmlError {
|
||||||
NamespaceState my_state = state ?? new NamespaceState.for_stanza();
|
NamespaceState my_state = state ?? new NamespaceState.for_stanza();
|
||||||
if (name == "#text") return val == null ? "" : (!)encoded_val;
|
if (name == "#text") return val == null ? "" : (!)encoded_val;
|
||||||
|
my_state = my_state.push();
|
||||||
foreach (var xmlns in get_attributes_by_ns_uri (XMLNS_URI)) {
|
foreach (var xmlns in get_attributes_by_ns_uri (XMLNS_URI)) {
|
||||||
if (xmlns.val == null) continue;
|
if (xmlns.val == null) continue;
|
||||||
if (xmlns.name == "xmlns") {
|
if (xmlns.name == "xmlns") {
|
||||||
my_state = new NamespaceState.with_current(my_state, (!)xmlns.val);
|
my_state.set_current((!)xmlns.val);
|
||||||
} else {
|
} else {
|
||||||
my_state = new NamespaceState.with_assoc(my_state, (!)xmlns.val, xmlns.name);
|
my_state.add_assoc((!)xmlns.val, xmlns.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
@ -391,6 +411,7 @@ public class StanzaNode : StanzaEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
my_state = my_state.pop();
|
||||||
return sb.str;
|
return sb.str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using Gee;
|
using Gee;
|
||||||
|
|
||||||
namespace Xmpp.Core {
|
namespace Xmpp.Core {
|
||||||
|
|
||||||
public const string XMLNS_URI = "http://www.w3.org/2000/xmlns/";
|
public const string XMLNS_URI = "http://www.w3.org/2000/xmlns/";
|
||||||
|
public const string XML_URI = "http://www.w3.org/XML/1998/namespace";
|
||||||
public const string JABBER_URI = "jabber:client";
|
public const string JABBER_URI = "jabber:client";
|
||||||
|
|
||||||
public errordomain XmlError {
|
public errordomain XmlError {
|
||||||
|
@ -85,7 +87,7 @@ public class StanzaReader {
|
||||||
private string read_until_ws() throws XmlError {
|
private string read_until_ws() throws XmlError {
|
||||||
var res = new StringBuilder();
|
var res = new StringBuilder();
|
||||||
var what = peek_single();
|
var what = peek_single();
|
||||||
while(!is_ws(what)) {
|
while (!is_ws(what)) {
|
||||||
res.append_c(read_single());
|
res.append_c(read_single());
|
||||||
what = peek_single();
|
what = peek_single();
|
||||||
}
|
}
|
||||||
|
@ -95,7 +97,7 @@ public class StanzaReader {
|
||||||
private string read_until_char_or_ws(char x, char y = 0) throws XmlError {
|
private string read_until_char_or_ws(char x, char y = 0) throws XmlError {
|
||||||
var res = new StringBuilder();
|
var res = new StringBuilder();
|
||||||
var what = peek_single();
|
var what = peek_single();
|
||||||
while(what != x && what != y && !is_ws(what)) {
|
while (what != x && what != y && !is_ws(what)) {
|
||||||
res.append_c(read_single());
|
res.append_c(read_single());
|
||||||
what = peek_single();
|
what = peek_single();
|
||||||
}
|
}
|
||||||
|
@ -105,11 +107,11 @@ public class StanzaReader {
|
||||||
private string read_until_char(char x) throws XmlError {
|
private string read_until_char(char x) throws XmlError {
|
||||||
var res = new StringBuilder();
|
var res = new StringBuilder();
|
||||||
var what = peek_single();
|
var what = peek_single();
|
||||||
while(what != x) {
|
while (what != x) {
|
||||||
res.append_c(read_single());
|
res.append_c(read_single());
|
||||||
what = peek_single();
|
what = peek_single();
|
||||||
}
|
}
|
||||||
return res.str;
|
return res.str;
|
||||||
}
|
}
|
||||||
|
|
||||||
private StanzaAttribute read_attribute() throws XmlError {
|
private StanzaAttribute read_attribute() throws XmlError {
|
||||||
|
@ -169,7 +171,7 @@ public class StanzaReader {
|
||||||
eof = true;
|
eof = true;
|
||||||
skip_single();
|
skip_single();
|
||||||
res.name = read_until_char_or_ws('>');
|
res.name = read_until_char_or_ws('>');
|
||||||
while(peek_single() != '>') {
|
while (peek_single() != '>') {
|
||||||
skip_single();
|
skip_single();
|
||||||
}
|
}
|
||||||
skip_single();
|
skip_single();
|
||||||
|
@ -184,7 +186,7 @@ public class StanzaReader {
|
||||||
res.attributes.add(read_attribute());
|
res.attributes.add(read_attribute());
|
||||||
skip_until_non_ws();
|
skip_until_non_ws();
|
||||||
}
|
}
|
||||||
if (read_single() == '/' || res.pseudo ) {
|
if (read_single() == '/' || res.pseudo) {
|
||||||
res.has_nodes = false;
|
res.has_nodes = false;
|
||||||
skip_single();
|
skip_single();
|
||||||
} else {
|
} else {
|
||||||
|
@ -215,8 +217,8 @@ public class StanzaReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public StanzaNode read_stanza_node(NamespaceState? baseNs = null) throws XmlError {
|
public StanzaNode read_stanza_node() throws XmlError {
|
||||||
ns_state = baseNs ?? new NamespaceState.for_stanza();
|
ns_state = ns_state.push();
|
||||||
var res = read_node_start();
|
var res = read_node_start();
|
||||||
if (res.has_nodes) {
|
if (res.has_nodes) {
|
||||||
bool finishNodeSeen = false;
|
bool finishNodeSeen = false;
|
||||||
|
@ -238,8 +240,7 @@ public class StanzaReader {
|
||||||
}
|
}
|
||||||
finishNodeSeen = true;
|
finishNodeSeen = true;
|
||||||
} else {
|
} else {
|
||||||
res.sub_nodes.add(read_stanza_node(ns_state.clone()));
|
res.sub_nodes.add(read_stanza_node());
|
||||||
ns_state = baseNs ?? new NamespaceState.for_stanza();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res.sub_nodes.add(read_text_node());
|
res.sub_nodes.add(read_text_node());
|
||||||
|
@ -247,16 +248,18 @@ public class StanzaReader {
|
||||||
} while (!finishNodeSeen);
|
} while (!finishNodeSeen);
|
||||||
if (res.sub_nodes.size == 0) res.has_nodes = false;
|
if (res.sub_nodes.size == 0) res.has_nodes = false;
|
||||||
}
|
}
|
||||||
|
ns_state = ns_state.pop();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StanzaNode read_node(NamespaceState? baseNs = null) throws XmlError {
|
public StanzaNode read_node() throws XmlError {
|
||||||
skip_until_non_ws();
|
skip_until_non_ws();
|
||||||
if (peek_single() == '<') {
|
if (peek_single() == '<') {
|
||||||
return read_stanza_node(baseNs ?? new NamespaceState.for_stanza());
|
return read_stanza_node();
|
||||||
} else {
|
} else {
|
||||||
return read_text_node();
|
return read_text_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public errordomain IOStreamError {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class XmppStream {
|
public class XmppStream {
|
||||||
private static string NS_URI = "http://etherx.jabber.org/streams";
|
public const string NS_URI = "http://etherx.jabber.org/streams";
|
||||||
|
|
||||||
public string remote_name;
|
public string remote_name;
|
||||||
public XmppLog log = new XmppLog();
|
public XmppLog log = new XmppLog();
|
||||||
|
|
93
xmpp-vala/tests/common.vala
Normal file
93
xmpp-vala/tests/common.vala
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
namespace Xmpp.Test {
|
||||||
|
|
||||||
|
int main(string[] args) {
|
||||||
|
GLib.Test.init(ref args);
|
||||||
|
GLib.Test.set_nonfatal_assertions();
|
||||||
|
TestSuite.get_root().add_suite(new Xmpp.Test.StanzaTest().get_suite());
|
||||||
|
return GLib.Test.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if(bool exp, string? reason = null) {
|
||||||
|
if (exp) {
|
||||||
|
if (reason != null) GLib.Test.message(reason);
|
||||||
|
GLib.Test.fail();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fail_if_reached(string? reason = null) {
|
||||||
|
fail_if(true, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate void ErrorFunc() throws Error;
|
||||||
|
|
||||||
|
void fail_if_not_error_code(ErrorFunc func, int expectedCode, string? reason = null) {
|
||||||
|
try {
|
||||||
|
func();
|
||||||
|
fail_if_reached(@"$(reason + ": " ?? "")no error thrown");
|
||||||
|
} catch (Error e) {
|
||||||
|
fail_if_not_eq_int(e.code, expectedCode, @"$(reason + ": " ?? "")catched unexpected error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_not(bool exp, string? reason = null) {
|
||||||
|
return fail_if(!exp, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_eq_int(int left, int right, string? reason = null) {
|
||||||
|
return fail_if(left == right, @"$(reason + ": " ?? "")$left == $right");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_not_eq_node(Core.StanzaNode left, Core.StanzaNode right, string? reason = null) {
|
||||||
|
if (fail_if_not_eq_str(left.name, right.name, @"$(reason + ": " ?? "")name mismatch")) return true;
|
||||||
|
if (fail_if_not_eq_str(left.val, right.val, @"$(reason + ": " ?? "")val mismatch")) return true;
|
||||||
|
if (left.name == "#text") return false;
|
||||||
|
if (fail_if_not_eq_str(left.ns_uri, right.ns_uri, @"$(reason + ": " ?? "")ns_uri mismatch")) return true;
|
||||||
|
if (fail_if_not_eq_int(left.sub_nodes.size, right.sub_nodes.size, @"$(reason + ": " ?? "")sub node count mismatch")) return true;
|
||||||
|
if (fail_if_not_eq_int(left.attributes.size, right.attributes.size, @"$(reason + ": " ?? "")attributes count mismatch")) return true;
|
||||||
|
for (var i = 0; i < left.sub_nodes.size; i++) {
|
||||||
|
if (fail_if_not_eq_node(left.sub_nodes[i], right.sub_nodes[i], @"$(reason + ": " ?? "")$(i+1)th subnode mismatch")) return true;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < left.attributes.size; i++) {
|
||||||
|
if (fail_if_not_eq_attr(left.attributes[i], right.attributes[i], @"$(reason + ": " ?? "")$(i+1)th attribute mismatch")) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_not_eq_attr(Core.StanzaAttribute left, Core.StanzaAttribute right, string? reason = null) {
|
||||||
|
if (fail_if_not_eq_str(left.name, right.name, @"$(reason + ": " ?? "")name mismatch")) return true;
|
||||||
|
if (fail_if_not_eq_str(left.val, right.val, @"$(reason + ": " ?? "")val mismatch")) return true;
|
||||||
|
if (fail_if_not_eq_str(left.ns_uri, right.ns_uri, @"$(reason + ": " ?? "")ns_uri mismatch")) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_not_eq_int(int left, int right, string? reason = null) {
|
||||||
|
return fail_if_not(left == right, @"$(reason + ": " ?? "")$left != $right");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_not_eq_str(string? left, string? right, string? reason = null) {
|
||||||
|
bool nullcheck = (left == null || right == null) && (left != null && right != null);
|
||||||
|
if (left == null) left = "(null)";
|
||||||
|
if (right == null) right = "(null)";
|
||||||
|
return fail_if_not(!nullcheck && left == right, @"$(reason + ": " ?? "")$left != $right");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_not_eq_uint8_arr(uint8[] left, uint8[] right, string? reason = null) {
|
||||||
|
if (fail_if_not_eq_int(left.length, right.length, @"$(reason + ": " ?? "")array length not equal")) return true;
|
||||||
|
return fail_if_not_eq_str(Base64.encode(left), Base64.encode(right), reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_not_zero_int(int zero, string? reason = null) {
|
||||||
|
return fail_if_not_eq_int(zero, 0, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_zero_int(int zero, string? reason = null) {
|
||||||
|
return fail_if_eq_int(zero, 0, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fail_if_null(void* what, string? reason = null) {
|
||||||
|
return fail_if(what == null || (size_t)what == 0, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
105
xmpp-vala/tests/stanza.vala
Normal file
105
xmpp-vala/tests/stanza.vala
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
using Xmpp.Core;
|
||||||
|
|
||||||
|
namespace Xmpp.Test {
|
||||||
|
|
||||||
|
class StanzaTest : Gee.TestCase {
|
||||||
|
public StanzaTest() {
|
||||||
|
base("Stanza");
|
||||||
|
|
||||||
|
add_test("node_one", test_node_one);
|
||||||
|
add_test("typical_stream", test_typical_stream);
|
||||||
|
add_test("ack_stream", test_ack_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void test_node_one() {
|
||||||
|
var node1 = new StanzaNode.build("test", "ns1_uri")
|
||||||
|
.add_self_xmlns()
|
||||||
|
.put_attribute("ns2", "ns2_uri", XMLNS_URI)
|
||||||
|
.put_attribute("bla", "blub")
|
||||||
|
.put_node(new StanzaNode.build("testaa", "ns2_uri")
|
||||||
|
.put_attribute("ns3", "ns3_uri", XMLNS_URI))
|
||||||
|
.put_node(new StanzaNode.build("testbb", "ns3_uri")
|
||||||
|
.add_self_xmlns());
|
||||||
|
|
||||||
|
var xml1 = node1.to_xml();
|
||||||
|
var node2 = new StanzaReader.for_string(xml1).read_node();
|
||||||
|
fail_if_not(node1.equals(node2));
|
||||||
|
fail_if_not_eq_str(node1.to_string(), node2.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void test_typical_stream() {
|
||||||
|
var stream = """
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<stream:stream
|
||||||
|
to='example.com'
|
||||||
|
xmlns='jabber:client'
|
||||||
|
xmlns:stream='http://etherx.jabber.org/streams'
|
||||||
|
version='1.0'>
|
||||||
|
<message from='laurence@example.net/churchyard'
|
||||||
|
to='juliet@example.com'
|
||||||
|
xml:lang='en'>
|
||||||
|
<body>I'll send a friar with speed, to Mantua, with my letters to thy lord.</body>
|
||||||
|
</message>
|
||||||
|
</stream:stream>
|
||||||
|
""";
|
||||||
|
var root_node_cmp = new StanzaNode.build("stream", "http://etherx.jabber.org/streams")
|
||||||
|
.put_attribute("to", "example.com")
|
||||||
|
.put_attribute("xmlns", "jabber:client")
|
||||||
|
.put_attribute("stream", "http://etherx.jabber.org/streams", XMLNS_URI)
|
||||||
|
.put_attribute("version", "1.0");
|
||||||
|
var node_cmp = new StanzaNode.build("message")
|
||||||
|
.put_attribute("from", "laurence@example.net/churchyard")
|
||||||
|
.put_attribute("to", "juliet@example.com")
|
||||||
|
.put_attribute("lang", "en", XML_URI)
|
||||||
|
.put_node(new StanzaNode.build("body")
|
||||||
|
.put_node(new StanzaNode.text("I'll send a friar with speed, to Mantua, with my letters to thy lord.")));
|
||||||
|
|
||||||
|
var reader = new StanzaReader.for_string(stream);
|
||||||
|
fail_if_not_eq_node(root_node_cmp, reader.read_root_node());
|
||||||
|
fail_if_not_eq_node(node_cmp, reader.read_node());
|
||||||
|
reader.read_node();
|
||||||
|
fail_if_not_error_code(() => reader.read_node(), 3, "end of stream should be reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void test_ack_stream() {
|
||||||
|
var stream = """
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<stream:stream
|
||||||
|
to='example.com'
|
||||||
|
xmlns='jabber:client'
|
||||||
|
xmlns:stream='http://etherx.jabber.org/streams'
|
||||||
|
xmlns:ack='http://jabber.org/protocol/ack'
|
||||||
|
version='1.0'>
|
||||||
|
<stream:features>
|
||||||
|
<ack:ack/>
|
||||||
|
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
|
||||||
|
<required/>
|
||||||
|
</bind>
|
||||||
|
</stream:features>
|
||||||
|
<ack:r/>
|
||||||
|
</stream:stream>
|
||||||
|
""";
|
||||||
|
var root_node_cmp = new StanzaNode.build("stream", "http://etherx.jabber.org/streams")
|
||||||
|
.put_attribute("to", "example.com")
|
||||||
|
.put_attribute("xmlns", "jabber:client")
|
||||||
|
.put_attribute("stream", "http://etherx.jabber.org/streams", XMLNS_URI)
|
||||||
|
.put_attribute("ack", "http://jabber.org/protocol/ack", XMLNS_URI)
|
||||||
|
.put_attribute("version", "1.0");
|
||||||
|
var node_cmp = new StanzaNode.build("features", XmppStream.NS_URI)
|
||||||
|
.put_node(new StanzaNode.build("ack", "http://jabber.org/protocol/ack"))
|
||||||
|
.put_node(new StanzaNode.build("bind", "urn:ietf:params:xml:ns:xmpp-bind")
|
||||||
|
.add_self_xmlns()
|
||||||
|
.put_node(new StanzaNode.build("required", "urn:ietf:params:xml:ns:xmpp-bind")));
|
||||||
|
var node2_cmp = new StanzaNode.build("r", "http://jabber.org/protocol/ack");
|
||||||
|
|
||||||
|
var reader = new StanzaReader.for_string(stream);
|
||||||
|
fail_if_not_eq_node(root_node_cmp, reader.read_root_node());
|
||||||
|
fail_if_not_eq_node(node_cmp, reader.read_node());
|
||||||
|
fail_if_not_eq_node(node2_cmp, reader.read_node());
|
||||||
|
reader.read_node();
|
||||||
|
fail_if_not_error_code(() => reader.read_node(), 3, "end of stream should be reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
80
xmpp-vala/tests/testcase.vala
Normal file
80
xmpp-vala/tests/testcase.vala
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/* testcase.vala
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Julien Peeters
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Author:
|
||||||
|
* Julien Peeters <contact@julienpeeters.fr>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class Gee.TestCase : Object {
|
||||||
|
|
||||||
|
private GLib.TestSuite suite;
|
||||||
|
private Adaptor[] adaptors = new Adaptor[0];
|
||||||
|
|
||||||
|
public delegate void TestMethod ();
|
||||||
|
|
||||||
|
public TestCase (string name) {
|
||||||
|
this.suite = new GLib.TestSuite (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add_test (string name, owned TestMethod test) {
|
||||||
|
var adaptor = new Adaptor (name, (owned)test, this);
|
||||||
|
this.adaptors += adaptor;
|
||||||
|
|
||||||
|
this.suite.add (new GLib.TestCase (adaptor.name,
|
||||||
|
adaptor.set_up,
|
||||||
|
adaptor.run,
|
||||||
|
adaptor.tear_down ));
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void set_up () {
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void tear_down () {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GLib.TestSuite get_suite () {
|
||||||
|
return this.suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Adaptor {
|
||||||
|
[CCode (notify = false)]
|
||||||
|
public string name { get; private set; }
|
||||||
|
private TestMethod test;
|
||||||
|
private TestCase test_case;
|
||||||
|
|
||||||
|
public Adaptor (string name,
|
||||||
|
owned TestMethod test,
|
||||||
|
TestCase test_case) {
|
||||||
|
this.name = name;
|
||||||
|
this.test = (owned)test;
|
||||||
|
this.test_case = test_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_up (void* fixture) {
|
||||||
|
this.test_case.set_up ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run (void* fixture) {
|
||||||
|
this.test ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tear_down (void* fixture) {
|
||||||
|
this.test_case.tear_down ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue