summaryrefslogtreecommitdiff
path: root/tests/t_fmt.c
blob: bc23ed58e384d33a100e8a3371456a49c6974ae7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
   It is considered beerware. Prost. Skol. Cheers or whatever.

   $id$ */

/* System */
#include <string.h>

/* Opentracker */
#include "ot_fmt.h"
#include "test.h"

static void case_appends_in_sequence(void) {
  char  buffer[64];
  char *r = buffer, *re = buffer + sizeof(buffer);

  test_case("appends follow each other and advance the cursor");
  fmt_append(&r, re, "d8:completei%zde", (size_t)7);
  fmt_append(&r, re, "ee");
  *r = 0;
  CHECK_STR(buffer, "d8:completei7eee");
  CHECK_INT(r - buffer, 16);
}

static void case_truncation_stops_at_the_end(void) {
  char  buffer[16];
  char *r = buffer, *re = buffer + 8; /* pretend the buffer ends early */

  memset(buffer, '#', sizeof(buffer));
  test_case("a value too long for the room left stops at the end");
  fmt_append(&r, re, "%s", "0123456789");
  CHECK_PTR(r, re);

  test_case("and writes nothing past it");
  CHECK_INT(buffer[8], '#');
  CHECK_INT(buffer[15], '#');
}

static void case_a_full_buffer_takes_nothing_more(void) {
  char  buffer[16];
  char *r = buffer + 8, *re = buffer + 8;

  memset(buffer, '#', sizeof(buffer));
  test_case("appending to a cursor already at the end changes nothing");
  fmt_append(&r, re, "more");
  CHECK_PTR(r, re);
  CHECK_INT(buffer[8], '#');
}

static void case_an_append_that_just_fits(void) {
  char  buffer[8];
  char *r = buffer, *re = buffer + 3;

  memset(buffer, '#', sizeof(buffer));
  test_case("three characters into three bytes of room still truncate");
  fmt_append(&r, re, "abc");
  CHECK_PTR(r, re);
  CHECK_INT(buffer[0], 'a');
  CHECK_INT(buffer[1], 'b');

  test_case("because snprintf spends the last byte on its terminator");
  CHECK_INT(buffer[2], 0);
  CHECK_INT(buffer[3], '#');
}

static void case_bytes_are_all_or_nothing(void) {
  char  buffer[16];
  char *r = buffer, *re = buffer + 8;

  memset(buffer, '#', sizeof(buffer));
  test_case("a run of bytes is written when it fits");
  fmt_bytes(&r, re, "\0\1\2\3", 4);
  CHECK_PTR(r, buffer + 4);
  CHECK_MEM(buffer, "\0\1\2\3", 4);

  test_case("a run that would not fit is refused whole");
  fmt_bytes(&r, re, "abcde", 5);
  CHECK_PTR(r, re);
  CHECK_INT(buffer[4], '#');

  test_case("a run of exactly the room left is written");
  r = buffer + 4;
  fmt_bytes(&r, re, "wxyz", 4);
  CHECK_PTR(r, re);
  CHECK_MEM(buffer + 4, "wxyz", 4);
  CHECK_INT(buffer[8], '#');
}

static void case_bytes_do_not_terminate(void) {
  char  buffer[8];
  char *r = buffer, *re = buffer + 4;

  memset(buffer, '#', sizeof(buffer));
  test_case("unlike an append, a run of bytes may fill the room exactly");
  fmt_bytes(&r, re, "abcd", 4);
  CHECK_PTR(r, re);
  CHECK_MEM(buffer, "abcd", 4);
  CHECK_INT(buffer[4], '#');
}

void test_fmt(void) {
  case_appends_in_sequence();
  case_truncation_stops_at_the_end();
  case_a_full_buffer_takes_nothing_more();
  case_an_append_that_just_fits();
  case_bytes_are_all_or_nothing();
  case_bytes_do_not_terminate();
}