summaryrefslogtreecommitdiff
path: root/tests/test_string.c
blob: 7c9ed02f311a4fe6620c40a3d1dfdfe32d5d8a9f (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
109
110
111
112

#undef NDEBUG  /* ensure tests always assert. */
#include "upb_string.h"

char static_str[] = "Static string.";
upb_string static_upbstr = UPB_STATIC_STRING(static_str);

static void test_static() {
  // Static string is initialized appropriately.
  assert(upb_streql(&static_upbstr, UPB_STRLIT("Static string.")));

  // Taking a ref on a static string returns the same string, and repeated
  // refs don't get the string in a confused state.
  assert(upb_string_getref(&static_upbstr) == &static_upbstr);
  assert(upb_string_getref(&static_upbstr) == &static_upbstr);
  assert(upb_string_getref(&static_upbstr) == &static_upbstr);

  // Unreffing a static string does nothing (is not harmful).
  upb_string_unref(&static_upbstr);
  upb_string_unref(&static_upbstr);
  upb_string_unref(&static_upbstr);
  upb_string_unref(&static_upbstr);
  upb_string_unref(&static_upbstr);

  // Recycling a static string returns a new string (that can be modified).
  upb_string *str = upb_string_tryrecycle(&static_upbstr);
  assert(str != &static_upbstr);

  upb_string_unref(str);
}

static void test_dynamic() {
  upb_string *str = upb_string_new();
  assert(str != NULL);
  upb_string_unref(str);

  // Can also create a string by tryrecycle(NULL).
  str = upb_string_tryrecycle(NULL);
  assert(str != NULL);

  upb_strcpyc(str, static_str);
  assert(upb_string_len(str) == (sizeof(static_str) - 1));
  const char *robuf = upb_string_getrobuf(str);
  assert(robuf != NULL);
  assert(upb_streqlc(str, static_str));
  upb_string_endread(str);

  upb_string *str2 = upb_string_tryrecycle(str);
  // No other referents, so should return the same string.
  assert(str2 == str);

  // Write a shorter string, the same memory should be reused.
  upb_strcpyc(str, "XX");
  const char *robuf2 = upb_string_getrobuf(str);
  assert(robuf2 == robuf);
  assert(upb_streqlc(str, "XX"));
  assert(upb_streql(str, UPB_STRLIT("XX")));

  // Make string alias part of another string.
  str2 = upb_strdupc("WXYZ");
  str = upb_string_tryrecycle(str);
  upb_string_substr(str, str2, 1, 2);
  assert(upb_string_len(str) == 2);
  assert(upb_string_len(str2) == 4);
  // The two string should be aliasing the same data.
  const char *robuf3 = upb_string_getrobuf(str);
  const char *robuf4 = upb_string_getrobuf(str2);
  assert(robuf3 == robuf4 + 1);
  // The aliased string should have an extra ref.
  assert(upb_atomic_read(&str2->refcount) == 2);

  // Recycling str should eliminate the extra ref.
  str = upb_string_tryrecycle(str);
  assert(upb_atomic_read(&str2->refcount) == 1);

  // Resetting str should reuse its old data.
  upb_strcpyc(str, "XX");
  const char *robuf5 = upb_string_getrobuf(str);
  assert(robuf5 == robuf);

  // Resetting str to something very long should require new data to be
  // allocated.
  str = upb_string_tryrecycle(str);
  const char longstring[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  upb_strcpyc(str, longstring);
  const char *robuf6 = upb_string_getrobuf(str);
  assert(robuf6 != robuf);
  assert(upb_streqlc(str, longstring));

  // Test printf.
  str = upb_string_tryrecycle(str);
  upb_string_printf(str, "Number: %d, String: %s", 5, "YO!");
  assert(upb_streqlc(str, "Number: 5, String: YO!"));

  // Test asprintf
  upb_string *str3 = upb_string_asprintf("Yo %s: " UPB_STRFMT "\n",
                                         "Josh", UPB_STRARG(str));
  const char expected[] = "Yo Josh: Number: 5, String: YO!\n";
  assert(upb_streqlc(str3, expected));

  upb_string_unref(str);
  upb_string_unref(str2);
  upb_string_unref(str3);

  // Unref of NULL is harmless.
  upb_string_unref(NULL);
}

int main() {
  test_static();
  test_dynamic();
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback