merge/upstream-full #105

Manually merged
jabber.developer merged 407 commits from merge/upstream-full into master 2026-05-26 17:54:34 +00:00
345 changed files with 11629 additions and 28866 deletions
Showing only changes of commit 4401e817d0 - Show all commits

View File

@@ -44,14 +44,3 @@
* Commit `Start new cycle`
* Push
## Updating website
Make changes to the git repo including uploading the new artefacts at:
https://github.com/profanity-im/profanity-im.github.io
* Add .xz and .zip tarballs to `tarballs` directory
* Copy generated main_fragment.html and toc_fragment.html to `guide/latest`
* Copy `guide/latest` to `guide/newversion`
* Tarball location, name, checksum in index.html will be updated automatically during `make` / GH Action
* Update profanity_version.txt
* Take results from profanity.doap and put them into xeps.html

View File

@@ -313,25 +313,25 @@ gboolean
strtoi_range(const char* str, int* saveptr, int min, int max, gchar** err_msg)
{
char* ptr;
int val;
long lval;
if (str == NULL) {
if (err_msg)
*err_msg = g_strdup_printf("'str' input pointer can not be NULL");
return FALSE;
}
errno = 0;
val = (int)strtol(str, &ptr, 0);
lval = strtol(str, &ptr, 0);
if (errno != 0 || *str == '\0' || *ptr != '\0') {
if (err_msg)
*err_msg = g_strdup_printf("Could not convert \"%s\" to a number.", str);
return FALSE;
} else if (val < min || val > max) {
} else if (lval < (long)min || lval > (long)max) {
if (err_msg)
*err_msg = g_strdup_printf("Value %s out of range. Must be in %d..%d.", str, min, max);
return FALSE;
}
*saveptr = val;
*saveptr = (int)lval;
return TRUE;
}

View File

@@ -237,24 +237,16 @@ _name_to_tlscert_name_(const char* in, tls_cert_name_t* out, const char* name)
}
}
static gchar*
_checked_g_strdup(const char* in)
{
if (in == NULL)
return NULL;
return g_strdup(in);
}
TLSCertificate*
tlscerts_new(const char* fingerprint_sha1, int version, const char* serialnumber, const char* subjectname,
const char* issuername, const char* notbefore, const char* notafter,
const char* key_alg, const char* signature_alg, const char* pem,
const char* fingerprint_sha256, const char* pubkey_fingerprint)
jabber.developer marked this conversation as resolved
Review

Why though?
According to official doc, g_strdup:

Duplicates a string. If str is NULL it returns NULL.

Though maybe earlier glib versions are less safe...

Why though? According to [official doc](https://docs.gtk.org/glib/func.strdup.html), `g_strdup`: > Duplicates a string. If str is NULL it returns NULL. Though maybe earlier glib versions are less safe...
{
return _tlscerts_new(_checked_g_strdup(fingerprint_sha1), version, _checked_g_strdup(serialnumber), _checked_g_strdup(subjectname),
_checked_g_strdup(issuername), _checked_g_strdup(notbefore), _checked_g_strdup(notafter),
_checked_g_strdup(key_alg), _checked_g_strdup(signature_alg), _checked_g_strdup(pem),
_checked_g_strdup(fingerprint_sha256), _checked_g_strdup(pubkey_fingerprint));
return _tlscerts_new(g_strdup(fingerprint_sha1), version, g_strdup(serialnumber), g_strdup(subjectname),
g_strdup(issuername), g_strdup(notbefore), g_strdup(notafter),
g_strdup(key_alg), g_strdup(signature_alg), g_strdup(pem),
g_strdup(fingerprint_sha256), g_strdup(pubkey_fingerprint));
}
static void

View File

@@ -581,7 +581,8 @@ _add_to_db(ProfMessage* message, const char* type, const Jid* const from_jid, co
if (rc == SQLITE_ROW) {
log_debug("Successfully inserted message into database.");
} else if (rc == SQLITE_DONE) {
log_debug("Message already exists in database (archive_id: %s), skipping.", message->stanzaid);
log_warning("Message already exists in database (archive_id: %s), skipping.", message->stanzaid);
jabber.developer marked this conversation as resolved Outdated

It deserves at least warning level. We can't just silently not write message to log: the message might contain important information for user. The error also should be extremely rare and it should represent invalid state, so it makes sense to cons_show_error it to alert the user.

It deserves at least `warning` level. We can't just silently not write message to log: the message might contain important information for user. The error also should be extremely rare and it should represent invalid state, so it makes sense to `cons_show_error` it to alert the user.
cons_show_error("Duplicate message detected (archive_id: %s), skipping.", message->stanzaid);
} else {
log_error("SQLite error in _add_to_db() (step): %s", sqlite3_errmsg(g_chatlog_database));
}
@@ -758,7 +759,7 @@ _migrate_to_v3(void)
cleanup:
if (SQLITE_OK != sqlite3_exec(g_chatlog_database, "ROLLBACK;", NULL, 0, &err_msg)) {
jabber.developer marked this conversation as resolved Outdated

Why not?
log_error("[DB Migration] Unable to ROLLBACK: %s", err_msg);

[ is missing (likely a strange typo)

Why not? ` log_error("[DB Migration] Unable to ROLLBACK: %s", err_msg);` `[` is missing (likely a strange typo)
log_error("DB Migration] Unable to ROLLBACK: %s", err_msg);
log_error("[DB Migration] Unable to ROLLBACK: %s", err_msg);
if (err_msg) {
sqlite3_free(err_msg);
}

View File

@@ -525,25 +525,29 @@ omemo_set_device_list(const char* const from, GList* device_list)
}
}
if (!found) {
auto_gchar gchar* dev_id_str = g_strdup_printf("%u", dev_id);
if (!g_key_file_has_key(omemo_ctx.knowndevices.keyfile, jid->barejid, dev_id_str, NULL)) {
if (equals_our_barejid(jid->barejid)) {
if (dev_id != omemo_ctx.device_id) {
cons_show("New OMEMO device (ID: %u) added to your account.", dev_id);
}
} else {
ProfChatWin* chatwin = wins_get_chat(jid->barejid);
if (chatwin) {
win_println((ProfWin*)chatwin, THEME_DEFAULT, "!", "New OMEMO device (ID: %u) found for %s.", dev_id, jid->barejid);
} else {
ProfMucWin* mucwin = wins_get_muc(jid->barejid);
if (mucwin) {
win_println((ProfWin*)mucwin, THEME_DEFAULT, "!", "New OMEMO device (ID: %u) found for %s.", dev_id, jid->barejid);
}
}
}
if (found)
continue;
auto_gchar gchar* dev_id_str = g_strdup_printf("%u", dev_id);
if (g_key_file_has_key(omemo_ctx.knowndevices.keyfile, jid->barejid, dev_id_str, NULL))
continue;
if (equals_our_barejid(jid->barejid)) {
if (dev_id != omemo_ctx.device_id) {
cons_show("New OMEMO device (ID: %u) added to your account.", dev_id);
}
continue;
}
ProfChatWin* chatwin = wins_get_chat(jid->barejid);
jabber.developer marked this conversation as resolved Outdated

extremely excessive nesting

extremely excessive nesting
if (chatwin) {
win_println((ProfWin*)chatwin, THEME_DEFAULT, "!", "New OMEMO device (ID: %u) found for %s.", dev_id, jid->barejid);
continue;
}
ProfMucWin* mucwin = wins_get_muc(jid->barejid);
if (mucwin) {
win_println((ProfWin*)mucwin, THEME_DEFAULT, "!", "New OMEMO device (ID: %u) found for %s.", dev_id, jid->barejid);
}
}
}

View File

@@ -399,10 +399,9 @@ _search(Autocomplete ac, GList* curr, gboolean quote, search_direction direction
// We only use transliterated match if the search string conversion didn't result
// in unknown characters ('?'), to avoid false matches between different scripts.
if (strchr(search_str_ascii_lower, '?') == NULL) {
if (g_str_has_prefix(curr_ascii_lower, search_str_ascii_lower)) {
match = TRUE;
}
if (strchr(search_str_ascii_lower, '?') == NULL
&& g_str_has_prefix(curr_ascii_lower, search_str_ascii_lower)) {
jabber.developer marked this conversation as resolved Outdated

could be just && operator instead of nested condition

could be just `&&` operator instead of nested condition
match = TRUE;
}
}

View File

@@ -246,9 +246,8 @@ editor_process(ProfWin* window)
log_debug("[Editor] Exiting background mode");
}
// Deprecated synchronous editor call. Returns a message as returned_message.
// Please avoid using it, since it blocks execution of the message handling and other important functionality until the editor is closed.
// Returns true if an error occurred
// Returns a message via callback once the editor is closed.
jabber.developer marked this conversation as resolved Outdated

need to remove this comment since it doesn't reflect new version of this method

need to remove this comment since it doesn't reflect new version of this method
// Returns true if an error occurred.
gboolean
launch_editor(gchar* initial_content, void (*callback)(gchar* content, void* data), void* user_data)
{

View File

@@ -417,9 +417,8 @@ _inp_write(char* line, int offset)
end += next_ch_len;
}
char* word = g_strndup(&line[start], end - start);
auto_gchar gchar* word = g_strndup(&line[start], end - start);
gboolean misspelled = spellcheck_is_misspelled(word);
g_free(word);
if (misspelled) {
wattron(inp_win, theme_attrs(THEME_INPUT_MISSPELLED));

View File

@@ -45,6 +45,24 @@ static void _show_privacy(ProfChatWin* chatwin);
static void _show_muc_privacy(ProfMucWin* mucwin);
static void _show_scrolled(ProfWin* current);
static void _show_attention(ProfWin* current, gboolean attention);
static void _show_trust_indicator(gboolean trusted, int bracket_attrs, int trusted_attrs, int untrusted_attrs);
static inline void
_wprintw_withattr(WINDOW* w, const char* text, int attrs)
{
wattron(w, attrs);
wprintw(w, "%s", text);
wattroff(w, attrs);
}
static void
_show_trust_indicator(gboolean trusted, int bracket_attrs, int trusted_attrs, int untrusted_attrs)
{
wprintw(win, " ");
_wprintw_withattr(win, "[", bracket_attrs);
_wprintw_withattr(win, trusted ? "trusted" : "untrusted", trusted ? trusted_attrs : untrusted_attrs);
_wprintw_withattr(win, "]", bracket_attrs);
}
void
create_title_bar(void)
@@ -433,29 +451,7 @@ _show_muc_privacy(ProfMucWin* mucwin)
wattroff(win, bracket_attrs);
#ifdef HAVE_OMEMO
if (mucwin->omemo_trusted) {
wprintw(win, " ");
wattron(win, bracket_attrs);
wprintw(win, "[");
wattroff(win, bracket_attrs);
wattron(win, trusted_attrs);
wprintw(win, "trusted");
wattroff(win, trusted_attrs);
wattron(win, bracket_attrs);
wprintw(win, "]");
wattroff(win, bracket_attrs);
} else {
wprintw(win, " ");
wattron(win, bracket_attrs);
wprintw(win, "[");
wattroff(win, bracket_attrs);
wattron(win, untrusted_attrs);
wprintw(win, "untrusted");
wattroff(win, untrusted_attrs);
wattron(win, bracket_attrs);
wprintw(win, "]");
wattroff(win, bracket_attrs);
}
_show_trust_indicator(mucwin->omemo_trusted, bracket_attrs, trusted_attrs, untrusted_attrs);
#endif
return;
@@ -524,29 +520,7 @@ _show_privacy(ProfChatWin* chatwin)
wattron(win, bracket_attrs);
wprintw(win, "]");
wattroff(win, bracket_attrs);
if (chatwin->otr_is_trusted) {
wprintw(win, " ");
wattron(win, bracket_attrs);
wprintw(win, "[");
wattroff(win, bracket_attrs);
wattron(win, trusted_attrs);
wprintw(win, "trusted");
wattroff(win, trusted_attrs);
wattron(win, bracket_attrs);
wprintw(win, "]");
wattroff(win, bracket_attrs);
} else {
wprintw(win, " ");
wattron(win, bracket_attrs);
wprintw(win, "[");
wattroff(win, bracket_attrs);
wattron(win, untrusted_attrs);
wprintw(win, "untrusted");
wattroff(win, untrusted_attrs);
wattron(win, bracket_attrs);
wprintw(win, "]");
wattroff(win, bracket_attrs);
}
_show_trust_indicator(chatwin->otr_is_trusted, bracket_attrs, trusted_attrs, untrusted_attrs);
return;
}
@@ -588,29 +562,7 @@ _show_privacy(ProfChatWin* chatwin)
wattroff(win, bracket_attrs);
#ifdef HAVE_OMEMO
if (chatwin->omemo_trusted) {
wprintw(win, " ");
wattron(win, bracket_attrs);
wprintw(win, "[");
wattroff(win, bracket_attrs);
wattron(win, trusted_attrs);
wprintw(win, "trusted");
wattroff(win, trusted_attrs);
wattron(win, bracket_attrs);
wprintw(win, "]");
wattroff(win, bracket_attrs);
} else {
wprintw(win, " ");
wattron(win, bracket_attrs);
wprintw(win, "[");
wattroff(win, bracket_attrs);
wattron(win, untrusted_attrs);
wprintw(win, "untrusted");
wattroff(win, untrusted_attrs);
wattron(win, bracket_attrs);
wprintw(win, "]");
wattroff(win, bracket_attrs);
}
_show_trust_indicator(chatwin->omemo_trusted, bracket_attrs, trusted_attrs, untrusted_attrs);
#endif
return;

View File

@@ -65,11 +65,30 @@ static void _handle_pubsub(xmpp_stanza_t* const stanza, xmpp_stanza_t* const eve
static gboolean _handle_form(xmpp_stanza_t* const stanza);
static gboolean _handle_jingle_message(xmpp_stanza_t* const stanza);
static gboolean _should_ignore_based_on_silence(xmpp_stanza_t* const stanza);
#ifdef HAVE_OMEMO
static void _receive_omemo(xmpp_stanza_t* const stanza, ProfMessage* message);
#endif
#ifdef HAVE_LIBGPGME
static xmpp_stanza_t* _ox_openpgp_signcrypt(xmpp_ctx_t* ctx, const char* const to, const char* const text);
#endif // HAVE_LIBGPGME
#ifdef HAVE_OMEMO
static void
_receive_omemo(xmpp_stanza_t* const stanza, ProfMessage* message)
{
message->plain = omemo_receive_message(stanza, &message->trusted, &message->omemo_err);
if (message->omemo_err != OMEMO_ERR_NONE) {
message->enc = PROF_MSG_ENC_OMEMO;
if (message->plain == NULL) {
message->plain = omemo_error_to_string(message->omemo_err);
}
} else if (message->plain != NULL) {
message->enc = PROF_MSG_ENC_OMEMO;
}
}
#endif // HAVE_OMEMO
static GHashTable* pubsub_event_handlers;
gchar*
@@ -1088,15 +1107,7 @@ _handle_groupchat(xmpp_stanza_t* const stanza)
// check omemo encryption
#ifdef HAVE_OMEMO
message->plain = omemo_receive_message(stanza, &message->trusted, &message->omemo_err);
if (message->omemo_err != OMEMO_ERR_NONE) {
message->enc = PROF_MSG_ENC_OMEMO;
if (message->plain == NULL) {
message->plain = omemo_error_to_string(message->omemo_err);
}
} else if (message->plain != NULL) {
message->enc = PROF_MSG_ENC_OMEMO;
}
_receive_omemo(stanza, message);
#endif
if (!message->plain && !message->body) {
@@ -1253,15 +1264,7 @@ _handle_muc_private_message(xmpp_stanza_t* const stanza)
// check omemo encryption
#ifdef HAVE_OMEMO
message->plain = omemo_receive_message(stanza, &message->trusted, &message->omemo_err);
if (message->omemo_err != OMEMO_ERR_NONE) {
message->enc = PROF_MSG_ENC_OMEMO;
if (message->plain == NULL) {
message->plain = omemo_error_to_string(message->omemo_err);
}
} else if (message->plain != NULL) {
message->enc = PROF_MSG_ENC_OMEMO;
}
_receive_omemo(stanza, message);
#endif
message->timestamp = stanza_get_delay(stanza);
@@ -1428,15 +1431,7 @@ _handle_chat(xmpp_stanza_t* const stanza, gboolean is_mam, gboolean is_carbon, c
#ifdef HAVE_OMEMO
// check omemo encryption
message->plain = omemo_receive_message(stanza, &message->trusted, &message->omemo_err);
if (message->omemo_err != OMEMO_ERR_NONE) {
message->enc = PROF_MSG_ENC_OMEMO;
if (message->plain == NULL) {
message->plain = omemo_error_to_string(message->omemo_err);
}
} else if (message->plain != NULL) {
message->enc = PROF_MSG_ENC_OMEMO;
}
_receive_omemo(stanza, message);
#endif
xmpp_stanza_t* encrypted = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_ENCRYPTED);
jabber.developer marked this conversation as resolved Outdated

this code is duplicated 3 times.

this code is duplicated 3 times.

View File

@@ -708,7 +708,7 @@ _omemo_bundle_publish_configure_result(xmpp_stanza_t* const stanza, void* const
return 0;
}
char*
gchar*
jabber.developer marked this conversation as resolved Outdated

It should be gchar*

It should be `gchar*`
omemo_error_to_string(omemo_error_t error)
{
switch (error) {

View File

@@ -19,4 +19,4 @@ void omemo_bundle_request(const char* const jid, uint32_t device_id, ProfIqCallb
int omemo_start_device_session_handle_bundle(xmpp_stanza_t* const stanza, void* const userdata);
char* omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted, omemo_error_t* error) __attribute__((nonnull(2, 3)));
char* omemo_error_to_string(omemo_error_t error);
gchar* omemo_error_to_string(omemo_error_t error);

View File

@@ -70,7 +70,9 @@ resource_destroy(Resource* resource)
{
if (resource) {
g_free(resource->name);
resource->name = NULL;
g_free(resource->status);
jabber.developer marked this conversation as resolved
Review

we should set it to NULL for safety

we should set it to NULL for safety
Review

it wasn't addressed. The pointer still is not set to null, though with this function we can't actually do it, I guess. We need to pass pointer to pointer to actually do it. Instead, we can at least set it to null near each call to resource_destroy.

it wasn't addressed. The pointer still is not set to `null`, though with this function we can't actually do it, I guess. We need to pass pointer to pointer to actually do it. Instead, we can at least set it to null near each call to `resource_destroy`.

Addressed in 60da899bd via the caller-side route — see #1160 reply.

Addressed in 60da899bd via the caller-side route — see #1160 reply.
resource->status = NULL;
g_free(resource);
}
}

View File

@@ -1,4 +1,4 @@
[wrap-git]
url = https://github.com/strophe/libstrophe.git
url = https://git.jabber.space/devs/libstrophe-gh.git
jabber.developer marked this conversation as resolved Outdated

We might want to point to our fork

We might want to point to our fork

Done — wrap now points at devs/libstrophe-gh-mirror (live auto-mirror, 8h). 1e372f6fa.

Done — wrap now points at `devs/libstrophe-gh-mirror` (live auto-mirror, 8h). 1e372f6fa.
revision = HEAD
patch_directory = libstrophe

View File

@@ -17,7 +17,7 @@ _create_test_file(const char* path)
}
void
cmd_ac_complete_filepath__segfaults_when_empty(void** state)
cmd_ac_complete_filepath__no_segfault_when_empty(void** state)
jabber.developer marked this conversation as resolved Outdated

segfaults_when_empty? Is it an actual behavior*? Or is it what we try to avoid? It's either a really strange test that expects undesired behavior or poor choice of a test name

*Wouldn't it also result in a CI failure?

`segfaults_when_empty`? Is it an actual behavior*? Or is it what we try to avoid? It's either a really strange test that expects undesired behavior or poor choice of a test name \*Wouldn't it also result in a CI failure?
{
char* result = cmd_ac_complete_filepath("/sendfile ", "/sendfile", FALSE);
@@ -62,33 +62,44 @@ cmd_ac_complete_filepath__cycles_through_files(void** state)
mkdir("test_dir", 0755);
_create_test_file("test_dir/file1.txt");
_create_test_file("test_dir/file2.txt");
_create_test_file("test_dir/file3.txt");
// 1st TAB
// TAB forward: file1 -> file2 -> file3
char* res1 = cmd_ac_complete_filepath("/sendfile test_dir/file", "/sendfile", FALSE);
assert_non_null(res1);
assert_string_equal(res1, "/sendfile test_dir/file1.txt");
// 2nd TAB
char* res2 = cmd_ac_complete_filepath(res1, "/sendfile", FALSE);
assert_non_null(res2);
assert_string_equal(res2, "/sendfile test_dir/file2.txt");
// 3rd TAB
char* res3 = cmd_ac_complete_filepath(res2, "/sendfile", FALSE);
assert_non_null(res3);
assert_string_equal(res3, "/sendfile test_dir/file1.txt");
assert_string_equal(res3, "/sendfile test_dir/file3.txt");
// SHIFT-TAB
char* res4 = cmd_ac_complete_filepath(res3, "/sendfile", TRUE);
// TAB wraps around: file3 -> file1
char* res4 = cmd_ac_complete_filepath(res3, "/sendfile", FALSE);
jabber.developer marked this conversation as resolved Outdated

This case doesn't test much :) Whether tab or shift+tab, we'll get file2.txt. We need at least 3 files to make an actual test.

This case doesn't test much :) Whether `tab` or `shift+tab`, we'll get `file2.txt`. We need at least 3 files to make an actual test.
assert_non_null(res4);
assert_string_equal(res4, "/sendfile test_dir/file2.txt");
assert_string_equal(res4, "/sendfile test_dir/file1.txt");
// SHIFT-TAB goes backward: file1 -> file3, then file3 -> file2
char* res5 = cmd_ac_complete_filepath(res4, "/sendfile", TRUE);
assert_non_null(res5);
assert_string_equal(res5, "/sendfile test_dir/file3.txt");
char* res6 = cmd_ac_complete_filepath(res5, "/sendfile", TRUE);
assert_non_null(res6);
assert_string_equal(res6, "/sendfile test_dir/file2.txt");
free(res1);
free(res2);
free(res3);
free(res4);
free(res5);
free(res6);
remove("test_dir/file1.txt");
remove("test_dir/file2.txt");
remove("test_dir/file3.txt");
rmdir("test_dir");
}

View File

@@ -1,7 +1,7 @@
#ifndef TESTS_TEST_CMD_AC_H
#define TESTS_TEST_CMD_AC_H
void cmd_ac_complete_filepath__segfaults_when_empty(void** state);
void cmd_ac_complete_filepath__no_segfault_when_empty(void** state);
void cmd_ac_complete_filepath__finds_files_in_current_dir(void** state);
void cmd_ac_complete_filepath__finds_files_with_dot_slash(void** state);
void cmd_ac_complete_filepath__cycles_through_files(void** state);

View File

@@ -9,6 +9,8 @@
#include "xmpp/resource.h"
#include "common.h"
#include "prof_cmocka.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "tests/unittests/ui/stub_ui.h" // Include for mocking cons_show
@@ -519,6 +521,63 @@ strtoi_range__returns__correct_values_when_err_msg_null(void** state)
assert_false(result);
}
void
strtoi_range__returns__false_for_integer_overflow_underflow(void** state)
{
int value;
gchar* err_msg = NULL;
gboolean result;
char buf[64];
// INT_MAX + 1 overflows
snprintf(buf, sizeof(buf), "%lld", (long long)INT_MAX + 1);
result = strtoi_range(buf, &value, INT_MIN, INT_MAX, &err_msg);
assert_false(result);
g_free(err_msg);
err_msg = NULL;
// INT_MIN - 1 underflows
snprintf(buf, sizeof(buf), "%lld", (long long)INT_MIN - 1);
result = strtoi_range(buf, &value, INT_MIN, INT_MAX, &err_msg);
assert_false(result);
g_free(err_msg);
err_msg = NULL;
// Extreme overflow, larger than `long`
result = strtoi_range("9999999999999999999999999999999999", &value, INT_MIN, INT_MAX, &err_msg);
assert_false(result);
g_free(err_msg);
err_msg = NULL;
}
void
strtoi_range__returns_consistent_with_strtol_parsing(void** state)
{
int value;
gchar* err_msg = NULL;
gboolean result;
// Hexadecimal: "0x10" -> 16
result = strtoi_range("0x10", &value, 0, 100, &err_msg);
assert_true(result);
assert_int_equal(16, value);
g_free(err_msg);
err_msg = NULL;
// Octal: "010" -> 8
result = strtoi_range("010", &value, 0, 100, &err_msg);
assert_true(result);
assert_int_equal(8, value);
g_free(err_msg);
err_msg = NULL;
// Floating point "0.8" should fail: '.' is not a valid integer char
result = strtoi_range("0.8", &value, -10, 10, &err_msg);
assert_false(result);
g_free(err_msg);
err_msg = NULL;
}
void
string_to_verbosity__returns__correct_values(void** state)
{

View File

@@ -57,6 +57,8 @@ void strtoi_range__returns__false_for_out_of_range(void** state);
void strtoi_range__returns__false_for_invalid_input(void** state);
void strtoi_range__returns__false_for_null_empty_input(void** state);
void strtoi_range__returns__correct_values_when_err_msg_null(void** state);
void strtoi_range__returns__false_for_integer_overflow_underflow(void** state);
void strtoi_range__returns_consistent_with_strtol_parsing(void** state);
void string_matches_one_of__tests__edge_cases(void** state);
void valid_tls_policy_option__is__correct_for_various_inputs(void** state);
void get_mentions__tests__various(void** state);

View File

@@ -107,7 +107,7 @@ main(int argc, char* argv[])
cmocka_unit_test(unique_filename_from_url__tests__table_driven),
cmocka_unit_test(string_to_verbosity__returns__correct_values),
cmocka_unit_test(get_expanded_path__returns__expanded),
cmocka_unit_test_setup_teardown(cmd_ac_complete_filepath__segfaults_when_empty, load_preferences, close_preferences),
cmocka_unit_test_setup_teardown(cmd_ac_complete_filepath__no_segfault_when_empty, load_preferences, close_preferences),
cmocka_unit_test_setup_teardown(cmd_ac_complete_filepath__finds_files_in_current_dir, load_preferences, close_preferences),
cmocka_unit_test_setup_teardown(cmd_ac_complete_filepath__finds_files_with_dot_slash, load_preferences, close_preferences),
cmocka_unit_test_setup_teardown(cmd_ac_complete_filepath__cycles_through_files, load_preferences, close_preferences),
@@ -116,6 +116,8 @@ main(int argc, char* argv[])
cmocka_unit_test(strtoi_range__returns__false_for_invalid_input),
cmocka_unit_test(strtoi_range__returns__false_for_null_empty_input),
cmocka_unit_test(strtoi_range__returns__correct_values_when_err_msg_null),
cmocka_unit_test(strtoi_range__returns__false_for_integer_overflow_underflow),
cmocka_unit_test(strtoi_range__returns_consistent_with_strtol_parsing),
cmocka_unit_test(string_matches_one_of__tests__edge_cases),
cmocka_unit_test(valid_tls_policy_option__is__correct_for_various_inputs),
cmocka_unit_test(autocomplete_complete__returns__null_when_empty),
@@ -175,6 +177,7 @@ main(int argc, char* argv[])
cmocka_unit_test(jid_create__returns__null_from_multiple_at_in_bare),
cmocka_unit_test(jid_create__returns__correct_parts_with_at_in_resource_only),
cmocka_unit_test(jid_is_valid_user_jid__is__true_for_valid_user_jid),
cmocka_unit_test(jid_is_valid_user_jid__is__true_for_at_in_resource),
cmocka_unit_test(jid_is_valid_user_jid__is__false_for_domain_jid),
cmocka_unit_test(jid_is_valid_user_jid__is__false_for_invalid_jid),
cmocka_unit_test(jid_is_valid__is__true_for_valid_jid),

View File

@@ -319,6 +319,14 @@ jid_is_valid_user_jid__is__true_for_valid_user_jid(void** state)
assert_true(jid_is_valid_user_jid("myuser@mydomain"));
}
void
jid_is_valid_user_jid__is__true_for_at_in_resource(void** state)
{
// RFC 6122 section 2.4: '@' is allowed in the resourcepart.
assert_true(jid_is_valid_user_jid("myuser@mydomain/user@laptop"));
assert_true(jid_is_valid_user_jid("room@conference.example.org/user@host.example.org"));
}
void
jid_is_valid_user_jid__is__false_for_domain_jid(void** state)
{

View File

@@ -32,6 +32,7 @@ void jid_create__returns__null_from_empty_parts(void** state);
void jid_create__returns__null_from_multiple_at_in_bare(void** state);
void jid_create__returns__correct_parts_with_at_in_resource_only(void** state);
void jid_is_valid_user_jid__is__true_for_valid_user_jid(void** state);
void jid_is_valid_user_jid__is__true_for_at_in_resource(void** state);
void jid_is_valid_user_jid__is__false_for_domain_jid(void** state);
void jid_is_valid_user_jid__is__false_for_invalid_jid(void** state);
void jid_is_valid__is__true_for_valid_jid(void** state);