mirror of
https://github.com/systemd/systemd.git
synced 2025-01-09 01:18:19 +03:00
Merge pull request #33955 from yuwata/sd-journal-fix-sd_journal_seek_monotonic_usec
sd-journal: fix sd_journal_seek_monotonic_usec()
This commit is contained in:
commit
6ddf879ce8
@ -164,7 +164,7 @@ enum {
|
||||
STATE_OFFLINE = 0,
|
||||
STATE_ONLINE = 1,
|
||||
STATE_ARCHIVED = 2,
|
||||
_STATE_MAX
|
||||
_STATE_MAX,
|
||||
};
|
||||
|
||||
/* Header flags */
|
||||
|
@ -46,7 +46,7 @@ typedef enum LocationType {
|
||||
|
||||
/* We should seek to the precise location specified, and
|
||||
* return it, as we haven't read it yet. */
|
||||
LOCATION_SEEK
|
||||
LOCATION_SEEK,
|
||||
} LocationType;
|
||||
|
||||
typedef enum OfflineState {
|
||||
@ -56,7 +56,7 @@ typedef enum OfflineState {
|
||||
OFFLINE_CANCEL,
|
||||
OFFLINE_AGAIN_FROM_SYNCING,
|
||||
OFFLINE_AGAIN_FROM_OFFLINING,
|
||||
OFFLINE_DONE
|
||||
OFFLINE_DONE,
|
||||
} OfflineState;
|
||||
|
||||
typedef struct JournalFile {
|
||||
|
@ -25,7 +25,7 @@ typedef struct Directory Directory;
|
||||
typedef enum MatchType {
|
||||
MATCH_DISCRETE,
|
||||
MATCH_OR_TERM,
|
||||
MATCH_AND_TERM
|
||||
MATCH_AND_TERM,
|
||||
} MatchType;
|
||||
|
||||
struct Match {
|
||||
|
@ -62,7 +62,6 @@ static void journal_file_unlink_newest_by_boot_id(sd_journal *j, JournalFile *f)
|
||||
|
||||
static int journal_put_error(sd_journal *j, int r, const char *path) {
|
||||
_cleanup_free_ char *copy = NULL;
|
||||
int k;
|
||||
|
||||
/* Memorize an error we encountered, and store which
|
||||
* file/directory it was generated from. Note that we store
|
||||
@ -84,13 +83,11 @@ static int journal_put_error(sd_journal *j, int r, const char *path) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
k = hashmap_ensure_put(&j->errors, NULL, INT_TO_PTR(r), copy);
|
||||
if (k < 0) {
|
||||
if (k == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return k;
|
||||
}
|
||||
r = hashmap_ensure_put(&j->errors, NULL, INT_TO_PTR(r), copy);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_PTR(copy);
|
||||
return 0;
|
||||
@ -675,7 +672,7 @@ static int next_for_match(
|
||||
uint64_t after_offset,
|
||||
direction_t direction,
|
||||
Object **ret,
|
||||
uint64_t *offset) {
|
||||
uint64_t *ret_offset) {
|
||||
|
||||
int r;
|
||||
uint64_t np = 0;
|
||||
@ -699,7 +696,7 @@ static int next_for_match(
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
return journal_file_move_to_entry_by_offset_for_data(f, d, after_offset, direction, ret, offset);
|
||||
return journal_file_move_to_entry_by_offset_for_data(f, d, after_offset, direction, ret, ret_offset);
|
||||
|
||||
} else if (m->type == MATCH_OR_TERM) {
|
||||
|
||||
@ -760,19 +757,68 @@ static int next_for_match(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (offset)
|
||||
*offset = np;
|
||||
if (ret_offset)
|
||||
*ret_offset = np;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int move_by_boot_for_data(
|
||||
sd_journal *j,
|
||||
JournalFile *f,
|
||||
direction_t direction,
|
||||
sd_id128_t boot_id,
|
||||
uint64_t data_offset,
|
||||
Object **ret,
|
||||
uint64_t *ret_offset) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(j);
|
||||
assert(f);
|
||||
assert(IN_SET(direction, DIRECTION_DOWN, DIRECTION_UP));
|
||||
|
||||
for (;;) {
|
||||
/* First, move to the last (or first when DIRECTION_UP) entry for the boot. */
|
||||
uint64_t p = 0;
|
||||
r = journal_file_move_to_entry_by_monotonic(f, boot_id,
|
||||
direction == DIRECTION_DOWN ? USEC_INFINITY : 0,
|
||||
direction == DIRECTION_DOWN ? DIRECTION_UP : DIRECTION_DOWN,
|
||||
NULL, &p);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
/* Then, move to the first entry of the next boot (or the last entry of the previous boot with DIRECTION_UP). */
|
||||
Object *entry;
|
||||
r = journal_file_next_entry(f, p, direction, &entry, NULL);
|
||||
if (r <= 0) /* r == 0 means that no next (or previous) boot found. That is, we are at HEAD or TAIL now. */
|
||||
return r;
|
||||
|
||||
assert(entry->object.type == OBJECT_ENTRY);
|
||||
boot_id = entry->entry.boot_id;
|
||||
|
||||
/* Note, this object cannot be reused, as journal_file_move_to_entry_by_monotonic() may invalidate the object. */
|
||||
Object *data;
|
||||
r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &data);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Then, move to the matching entry. */
|
||||
r = journal_file_move_to_entry_by_monotonic_for_data(f, data, boot_id,
|
||||
direction == DIRECTION_DOWN ? 0 : USEC_INFINITY, direction,
|
||||
ret, ret_offset);
|
||||
if (r != 0) /* Here r == 0 is OK, as that means the boot contains no entry matching with the data. */
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
static int find_location_for_match(
|
||||
sd_journal *j,
|
||||
Match *m,
|
||||
JournalFile *f,
|
||||
direction_t direction,
|
||||
Object **ret,
|
||||
uint64_t *offset) {
|
||||
uint64_t *ret_offset) {
|
||||
|
||||
int r;
|
||||
|
||||
@ -793,16 +839,14 @@ static int find_location_for_match(
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
/* FIXME: missing: find by monotonic */
|
||||
|
||||
if (j->current_location.type == LOCATION_HEAD)
|
||||
return direction == DIRECTION_DOWN ? journal_file_move_to_entry_for_data(f, d, DIRECTION_DOWN, ret, offset) : 0;
|
||||
return direction == DIRECTION_DOWN ? journal_file_move_to_entry_for_data(f, d, DIRECTION_DOWN, ret, ret_offset) : 0;
|
||||
if (j->current_location.type == LOCATION_TAIL)
|
||||
return direction == DIRECTION_UP ? journal_file_move_to_entry_for_data(f, d, DIRECTION_UP, ret, offset) : 0;
|
||||
return direction == DIRECTION_UP ? journal_file_move_to_entry_for_data(f, d, DIRECTION_UP, ret, ret_offset) : 0;
|
||||
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
|
||||
return journal_file_move_to_entry_by_seqnum_for_data(f, d, j->current_location.seqnum, direction, ret, offset);
|
||||
return journal_file_move_to_entry_by_seqnum_for_data(f, d, j->current_location.seqnum, direction, ret, ret_offset);
|
||||
if (j->current_location.monotonic_set) {
|
||||
r = journal_file_move_to_entry_by_monotonic_for_data(f, d, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
|
||||
r = journal_file_move_to_entry_by_monotonic_for_data(f, d, j->current_location.boot_id, j->current_location.monotonic, direction, ret, ret_offset);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
@ -810,11 +854,17 @@ static int find_location_for_match(
|
||||
r = journal_file_move_to_object(f, OBJECT_DATA, dp, &d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* If not found, fall back to realtime if set, or go to the first entry of the next boot
|
||||
* (or the last entry of the previous boot when DIRECTION_UP). */
|
||||
}
|
||||
if (j->current_location.realtime_set)
|
||||
return journal_file_move_to_entry_by_realtime_for_data(f, d, j->current_location.realtime, direction, ret, offset);
|
||||
return journal_file_move_to_entry_by_realtime_for_data(f, d, j->current_location.realtime, direction, ret, ret_offset);
|
||||
|
||||
return journal_file_move_to_entry_for_data(f, d, direction, ret, offset);
|
||||
if (j->current_location.monotonic_set)
|
||||
return move_by_boot_for_data(j, f, direction, j->current_location.boot_id, dp, ret, ret_offset);
|
||||
|
||||
return journal_file_move_to_entry_for_data(f, d, direction, ret, ret_offset);
|
||||
|
||||
} else if (m->type == MATCH_OR_TERM) {
|
||||
uint64_t np = 0;
|
||||
@ -842,8 +892,8 @@ static int find_location_for_match(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (offset)
|
||||
*offset = np;
|
||||
if (ret_offset)
|
||||
*ret_offset = np;
|
||||
|
||||
return 1;
|
||||
|
||||
@ -869,7 +919,7 @@ static int find_location_for_match(
|
||||
np = cp;
|
||||
}
|
||||
|
||||
return next_for_match(j, m, f, np, direction, ret, offset);
|
||||
return next_for_match(j, m, f, np, direction, ret, ret_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -878,35 +928,51 @@ static int find_location_with_matches(
|
||||
JournalFile *f,
|
||||
direction_t direction,
|
||||
Object **ret,
|
||||
uint64_t *offset) {
|
||||
uint64_t *ret_offset) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(j);
|
||||
assert(f);
|
||||
assert(ret);
|
||||
assert(offset);
|
||||
|
||||
if (!j->level0) {
|
||||
/* No matches is simple */
|
||||
if (j->level0)
|
||||
return find_location_for_match(j, j->level0, f, direction, ret, ret_offset);
|
||||
|
||||
if (j->current_location.type == LOCATION_HEAD)
|
||||
return direction == DIRECTION_DOWN ? journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset) : 0;
|
||||
if (j->current_location.type == LOCATION_TAIL)
|
||||
return direction == DIRECTION_UP ? journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset) : 0;
|
||||
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
|
||||
return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
|
||||
if (j->current_location.monotonic_set) {
|
||||
r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
if (j->current_location.realtime_set)
|
||||
return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset);
|
||||
/* No matches is simple */
|
||||
|
||||
return journal_file_next_entry(f, 0, direction, ret, offset);
|
||||
} else
|
||||
return find_location_for_match(j, j->level0, f, direction, ret, offset);
|
||||
if (j->current_location.type == LOCATION_HEAD)
|
||||
return direction == DIRECTION_DOWN ? journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, ret_offset) : 0;
|
||||
if (j->current_location.type == LOCATION_TAIL)
|
||||
return direction == DIRECTION_UP ? journal_file_next_entry(f, 0, DIRECTION_UP, ret, ret_offset) : 0;
|
||||
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
|
||||
return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, ret_offset);
|
||||
if (j->current_location.monotonic_set) {
|
||||
r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, ret_offset);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
/* If not found, fall back to realtime if set, or go to the first entry of the next boot
|
||||
* (or the last entry of the previous boot when DIRECTION_UP). */
|
||||
}
|
||||
if (j->current_location.realtime_set)
|
||||
return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, ret_offset);
|
||||
|
||||
if (j->current_location.monotonic_set) {
|
||||
uint64_t p = 0;
|
||||
|
||||
/* If not found in the above, first move to the last (or first when DIRECTION_UP) entry for the boot. */
|
||||
r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id,
|
||||
direction == DIRECTION_DOWN ? USEC_INFINITY : 0,
|
||||
direction == DIRECTION_DOWN ? DIRECTION_UP : DIRECTION_DOWN,
|
||||
NULL, &p);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
/* Then, move to the next or previous boot. */
|
||||
return journal_file_next_entry(f, p, direction, ret, ret_offset);
|
||||
}
|
||||
|
||||
return journal_file_next_entry(f, 0, direction, ret, ret_offset);
|
||||
}
|
||||
|
||||
static int next_with_matches(
|
||||
@ -914,24 +980,22 @@ static int next_with_matches(
|
||||
JournalFile *f,
|
||||
direction_t direction,
|
||||
Object **ret,
|
||||
uint64_t *offset) {
|
||||
uint64_t *ret_offset) {
|
||||
|
||||
assert(j);
|
||||
assert(f);
|
||||
assert(ret);
|
||||
assert(offset);
|
||||
|
||||
/* No matches is easy. We simple advance the file
|
||||
* pointer by one. */
|
||||
if (!j->level0)
|
||||
return journal_file_next_entry(f, f->current_offset, direction, ret, offset);
|
||||
return journal_file_next_entry(f, f->current_offset, direction, ret, ret_offset);
|
||||
|
||||
/* If we have a match then we look for the next matching entry
|
||||
* with an offset at least one step larger */
|
||||
return next_for_match(j, j->level0, f,
|
||||
direction == DIRECTION_DOWN ? f->current_offset + 1
|
||||
: f->current_offset - 1,
|
||||
direction, ret, offset);
|
||||
direction, ret, ret_offset);
|
||||
}
|
||||
|
||||
static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction) {
|
||||
@ -967,9 +1031,18 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
|
||||
journal_file_save_location(f, c, cp);
|
||||
}
|
||||
} else {
|
||||
f->last_direction = direction;
|
||||
|
||||
r = find_location_with_matches(j, f, direction, &c, &cp);
|
||||
/* LOCATION_SEEK specified to j->current_location.type here means that this is called first
|
||||
* after sd_journal_seek_monotonic_usec() or friends was called. In that case, this file may
|
||||
* not contain any matching entries with the user-specified location, but another file may
|
||||
* contain them. If so, the second call of this function will use the seqnum, and we may find
|
||||
* an entry in _this_ file with the seqnum. To prevent the second call of this function exits
|
||||
* earlier by the first 'if' block of this function, do not save the direction if the current
|
||||
* location is LOCATION_SEEK. */
|
||||
if (r > 0 || j->current_location.type != LOCATION_SEEK)
|
||||
f->last_direction = direction;
|
||||
else
|
||||
assert(f->last_direction == _DIRECTION_INVALID);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@ -986,11 +1059,8 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
|
||||
bool found;
|
||||
|
||||
if (j->current_location.type == LOCATION_DISCRETE) {
|
||||
int k;
|
||||
|
||||
k = compare_with_location(j, f, &j->current_location, j->current_file);
|
||||
|
||||
found = direction == DIRECTION_DOWN ? k > 0 : k < 0;
|
||||
r = compare_with_location(j, f, &j->current_location, j->current_file);
|
||||
found = direction == DIRECTION_DOWN ? r > 0 : r < 0;
|
||||
} else
|
||||
found = true;
|
||||
|
||||
@ -1084,11 +1154,8 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
|
||||
if (!new_file)
|
||||
found = true;
|
||||
else {
|
||||
int k;
|
||||
|
||||
k = compare_locations(j, f, new_file);
|
||||
|
||||
found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
|
||||
r = compare_locations(j, f, new_file);
|
||||
found = direction == DIRECTION_DOWN ? r < 0 : r > 0;
|
||||
}
|
||||
|
||||
if (found)
|
||||
@ -1315,7 +1382,6 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
|
||||
_cleanup_free_ char *item = NULL;
|
||||
unsigned long long ll;
|
||||
sd_id128_t id;
|
||||
int k = 0;
|
||||
|
||||
r = extract_first_word(&cursor, &item, ";", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||
if (r < 0)
|
||||
@ -1330,9 +1396,9 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
|
||||
switch (item[0]) {
|
||||
|
||||
case 's':
|
||||
k = sd_id128_from_string(item+2, &id);
|
||||
if (k < 0)
|
||||
return k;
|
||||
r = sd_id128_from_string(item+2, &id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!sd_id128_equal(id, j->current_file->header->seqnum_id))
|
||||
return 0;
|
||||
break;
|
||||
@ -1345,9 +1411,9 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
k = sd_id128_from_string(item+2, &id);
|
||||
if (k < 0)
|
||||
return k;
|
||||
r = sd_id128_from_string(item+2, &id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!sd_id128_equal(id, o->entry.boot_id))
|
||||
return 0;
|
||||
break;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -555,7 +555,7 @@ TEST(dns_cache_lookup_success) {
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "www.example.com");
|
||||
ASSERT_NOT_NULL(key);
|
||||
query_flags = 0;
|
||||
ASSERT_TRUE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
ASSERT_OK_POSITIVE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
|
||||
ASSERT_EQ(cache.n_hit, 1u);
|
||||
ASSERT_EQ(cache.n_miss, 0u);
|
||||
@ -592,7 +592,7 @@ TEST(dns_cache_lookup_clamp_ttl) {
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "www.example.com");
|
||||
ASSERT_NOT_NULL(key);
|
||||
query_flags = SD_RESOLVED_CLAMP_TTL;
|
||||
ASSERT_TRUE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
ASSERT_OK_POSITIVE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
|
||||
ASSERT_EQ(cache.n_hit, 1u);
|
||||
ASSERT_EQ(cache.n_miss, 0u);
|
||||
@ -635,7 +635,7 @@ TEST(dns_cache_lookup_returns_most_recent_response) {
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "www.example.com");
|
||||
ASSERT_NOT_NULL(key);
|
||||
query_flags = 0;
|
||||
ASSERT_TRUE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
ASSERT_OK_POSITIVE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
|
||||
ASSERT_EQ(cache.n_hit, 1u);
|
||||
ASSERT_EQ(cache.n_miss, 0u);
|
||||
@ -680,7 +680,7 @@ TEST(dns_cache_lookup_retains_multiple_answers_from_one_response) {
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "www.example.com");
|
||||
ASSERT_NOT_NULL(key);
|
||||
query_flags = 0;
|
||||
ASSERT_TRUE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
ASSERT_OK_POSITIVE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
|
||||
ASSERT_EQ(cache.n_hit, 1u);
|
||||
ASSERT_EQ(cache.n_miss, 0u);
|
||||
@ -724,7 +724,7 @@ TEST(dns_cache_lookup_nxdomain) {
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "www.example.com");
|
||||
ASSERT_NOT_NULL(key);
|
||||
query_flags = 0;
|
||||
ASSERT_TRUE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
ASSERT_OK_POSITIVE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
|
||||
ASSERT_EQ(cache.n_hit, 1u);
|
||||
ASSERT_EQ(cache.n_miss, 0u);
|
||||
@ -809,7 +809,7 @@ TEST(dns_cache_lookup_mdns_multiple_shared_responses_are_cached) {
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "example.com");
|
||||
ASSERT_NOT_NULL(key);
|
||||
query_flags = 0;
|
||||
ASSERT_TRUE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
ASSERT_OK_POSITIVE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
dns_resource_key_unref(key);
|
||||
|
||||
ASSERT_EQ(cache.n_hit, 1u);
|
||||
@ -865,7 +865,7 @@ TEST(dns_cache_lookup_mdns_multiple_unshared_responses_are_not_cached) {
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "example.com");
|
||||
ASSERT_NOT_NULL(key);
|
||||
query_flags = 0;
|
||||
ASSERT_TRUE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
ASSERT_OK_POSITIVE(dns_cache_lookup(&cache, key, query_flags, &ret_rcode, &ret_answer, &ret_full_packet, &ret_query_flags, NULL));
|
||||
dns_resource_key_unref(key);
|
||||
|
||||
ASSERT_EQ(cache.n_hit, 1u);
|
||||
|
@ -217,6 +217,39 @@ static inline int run_test_table(void) {
|
||||
} \
|
||||
})
|
||||
|
||||
/* For funtions that return a boolean on success and a negative errno on failure. */
|
||||
#define ASSERT_OK_POSITIVE(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
if (_result < 0) { \
|
||||
log_error_errno(_result, "%s:%i: Assertion failed: expected \"%s\" to succeed but got the following error: %m", \
|
||||
PROJECT_FILE, __LINE__, #expr); \
|
||||
abort(); \
|
||||
} \
|
||||
if (_result == 0) { \
|
||||
log_error("%s:%i: Assertion failed: expected \"%s\" to be positive, but it is zero.", \
|
||||
PROJECT_FILE, __LINE__, #expr); \
|
||||
abort(); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ASSERT_OK_ZERO(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
if (_result < 0) { \
|
||||
log_error_errno(_result, "%s:%i: Assertion failed: expected \"%s\" to succeed but got the following error: %m", \
|
||||
PROJECT_FILE, __LINE__, #expr); \
|
||||
abort(); \
|
||||
} \
|
||||
if (_result != 0) { \
|
||||
char _sexpr[DECIMAL_STR_MAX(typeof(expr))]; \
|
||||
xsprintf(_sexpr, DECIMAL_STR_FMT(_result), _result); \
|
||||
log_error("%s:%i: Assertion failed: expected \"%s\" to be zero, but it is %s.", \
|
||||
PROJECT_FILE, __LINE__, #expr, _sexpr); \
|
||||
abort(); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ASSERT_OK_ERRNO(expr) \
|
||||
({ \
|
||||
typeof(expr) _result = (expr); \
|
||||
|
@ -1117,6 +1117,18 @@ TEST(ASSERT) {
|
||||
ASSERT_SIGNAL(ASSERT_OK(-1), SIGABRT);
|
||||
ASSERT_SIGNAL(ASSERT_OK(-ENOANO), SIGABRT);
|
||||
|
||||
ASSERT_OK_POSITIVE(1);
|
||||
ASSERT_OK_POSITIVE(255);
|
||||
ASSERT_SIGNAL(ASSERT_OK_POSITIVE(0), SIGABRT);
|
||||
ASSERT_SIGNAL(ASSERT_OK_POSITIVE(-1), SIGABRT);
|
||||
ASSERT_SIGNAL(ASSERT_OK_POSITIVE(-ENOANO), SIGABRT);
|
||||
|
||||
ASSERT_OK_ZERO(0);
|
||||
ASSERT_SIGNAL(ASSERT_OK_ZERO(1), SIGABRT);
|
||||
ASSERT_SIGNAL(ASSERT_OK_ZERO(255), SIGABRT);
|
||||
ASSERT_SIGNAL(ASSERT_OK_ZERO(-1), SIGABRT);
|
||||
ASSERT_SIGNAL(ASSERT_OK_ZERO(-ENOANO), SIGABRT);
|
||||
|
||||
ASSERT_OK_ERRNO(0 >= 0);
|
||||
ASSERT_OK_ERRNO(255 >= 0);
|
||||
ASSERT_OK_ERRNO(printf("Hello world\n"));
|
||||
|
Loading…
Reference in New Issue
Block a user