summaryrefslogtreecommitdiff
path: root/tests/t_iovec.c
blob: 89f3fda82b65938f28b7b6bc13c0b46547422b67 (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
113
114
115
116
117
118
119
120
121
122
123
124
/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
   It is considered beerware. Prost. Skol. Cheers or whatever.

   $id$ */

/* System */
#include <stdlib.h>
#include <string.h>
#include <sys/uio.h>

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

static void case_increase_and_length(void) {
  size_t        entries = 0;
  struct iovec *vector  = NULL;
  void         *first, *second;

  test_case("increase appends an entry and length is their sum");
  first = iovec_increase(&entries, &vector, 100);
  CHECK(first != NULL);
  CHECK_INT(entries, 1);
  CHECK_INT(vector[0].iov_len, 100);
  CHECK_PTR(vector[0].iov_base, first);

  second = iovec_increase(&entries, &vector, 50);
  CHECK(second != NULL);
  CHECK_INT(entries, 2);
  CHECK_INT(vector[1].iov_len, 50);
  CHECK_INT(iovec_length(&entries, (const struct iovec **)&vector), 150);

  iovec_free(&entries, &vector);
}

static void case_free_resets(void) {
  size_t        entries = 0;
  struct iovec *vector  = NULL;

  test_case("free releases the entries and resets the vector");
  CHECK(iovec_increase(&entries, &vector, 10) != NULL);
  CHECK(iovec_increase(&entries, &vector, 10) != NULL);
  iovec_free(&entries, &vector);
  CHECK_INT(entries, 0);
  CHECK_PTR(vector, NULL);
  CHECK_INT(iovec_length(&entries, (const struct iovec **)&vector), 0);
}

static void case_fixlast_shrinks(void) {
  size_t        entries = 0;
  struct iovec *vector  = NULL;
  char         *block;

  test_case("fixlast trims the last entry to the bytes actually used");
  CHECK(iovec_increase(&entries, &vector, 64) != NULL);
  block = iovec_increase(&entries, &vector, 1000);
  CHECK(block != NULL);
  memset(block, 'x', 20);

  iovec_fixlast(&entries, &vector, block + 20);
  CHECK_INT(entries, 2);
  CHECK_INT(vector[1].iov_len, 20);
  CHECK_INT(iovec_length(&entries, (const struct iovec **)&vector), 84);
  CHECK_MEM(vector[1].iov_base, "xxxxxxxxxxxxxxxxxxxx", 20);

  iovec_free(&entries, &vector);
}

static void case_fixlast_on_empty(void) {
  size_t        entries = 0;
  struct iovec *vector  = NULL;

  test_case("fixlast on an empty vector does nothing");
  iovec_fixlast(&entries, &vector, NULL);
  CHECK_INT(entries, 0);
  CHECK_PTR(vector, NULL);
}

static void case_append_takes_ownership(void) {
  size_t        entries = 0;
  struct iovec *vector  = NULL;
  struct iovec  source;

  test_case("append moves the buffer and clears the source");
  source.iov_base = malloc(10);
  CHECK(source.iov_base != NULL);
  memcpy(source.iov_base, "0123456789", 10);
  source.iov_len = 10;

  CHECK(iovec_append(&entries, &vector, &source) != NULL);
  CHECK_INT(entries, 1);
  CHECK_INT(vector[0].iov_len, 10);
  CHECK_MEM(vector[0].iov_base, "0123456789", 10);
  CHECK_PTR(source.iov_base, NULL);
  CHECK_INT(source.iov_len, 0);

  iovec_free(&entries, &vector);
}

static void case_fix_increase(void) {
  size_t        entries = 0;
  struct iovec *vector  = NULL;
  char         *block;

  test_case("fix_increase trims the previous entry and adds a new one");
  block = iovec_increase(&entries, &vector, 500);
  CHECK(block != NULL);
  block = iovec_fix_increase_or_free(&entries, &vector, block + 30, 200);
  CHECK(block != NULL);
  CHECK_INT(entries, 2);
  CHECK_INT(vector[0].iov_len, 30);
  CHECK_INT(vector[1].iov_len, 200);

  iovec_free(&entries, &vector);
}

void test_iovec(void) {
  case_increase_and_length();
  case_free_resets();
  case_fixlast_shrinks();
  case_fixlast_on_empty();
  case_append_takes_ownership();
  case_fix_increase();
}