1#include "util.h"
2
3#include <stdlib.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <fcntl.h>
7#include <string.h>
8
9#include "machine.h"
10#include "symbol.h"
11#include "tests.h"
12
13static char *test_file(int size)
14{
15	static char buf_templ[] = "/tmp/test-XXXXXX";
16	char *templ = buf_templ;
17	int fd, i;
18	unsigned char *buf;
19
20	fd = mkstemp(templ);
21	if (fd < 0) {
22		perror("mkstemp failed");
23		return NULL;
24	}
25
26	buf = malloc(size);
27	if (!buf) {
28		close(fd);
29		return NULL;
30	}
31
32	for (i = 0; i < size; i++)
33		buf[i] = (unsigned char) ((int) i % 10);
34
35	if (size != write(fd, buf, size))
36		templ = NULL;
37
38	close(fd);
39	return templ;
40}
41
42#define TEST_FILE_SIZE (DSO__DATA_CACHE_SIZE * 20)
43
44struct test_data_offset {
45	off_t offset;
46	u8 data[10];
47	int size;
48};
49
50struct test_data_offset offsets[] = {
51	/* Fill first cache page. */
52	{
53		.offset = 10,
54		.data   = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
55		.size   = 10,
56	},
57	/* Read first cache page. */
58	{
59		.offset = 10,
60		.data   = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
61		.size   = 10,
62	},
63	/* Fill cache boundary pages. */
64	{
65		.offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10,
66		.data   = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
67		.size   = 10,
68	},
69	/* Read cache boundary pages. */
70	{
71		.offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10,
72		.data   = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
73		.size   = 10,
74	},
75	/* Fill final cache page. */
76	{
77		.offset = TEST_FILE_SIZE - 10,
78		.data   = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
79		.size   = 10,
80	},
81	/* Read final cache page. */
82	{
83		.offset = TEST_FILE_SIZE - 10,
84		.data   = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
85		.size   = 10,
86	},
87	/* Read final cache page. */
88	{
89		.offset = TEST_FILE_SIZE - 3,
90		.data   = { 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 },
91		.size   = 3,
92	},
93};
94
95int test__dso_data(void)
96{
97	struct machine machine;
98	struct dso *dso;
99	char *file = test_file(TEST_FILE_SIZE);
100	size_t i;
101
102	TEST_ASSERT_VAL("No test file", file);
103
104	memset(&machine, 0, sizeof(machine));
105
106	dso = dso__new((const char *)file);
107
108	/* Basic 10 bytes tests. */
109	for (i = 0; i < ARRAY_SIZE(offsets); i++) {
110		struct test_data_offset *data = &offsets[i];
111		ssize_t size;
112		u8 buf[10];
113
114		memset(buf, 0, 10);
115		size = dso__data_read_offset(dso, &machine, data->offset,
116				     buf, 10);
117
118		TEST_ASSERT_VAL("Wrong size", size == data->size);
119		TEST_ASSERT_VAL("Wrong data", !memcmp(buf, data->data, 10));
120	}
121
122	/* Read cross multiple cache pages. */
123	{
124		ssize_t size;
125		int c;
126		u8 *buf;
127
128		buf = malloc(TEST_FILE_SIZE);
129		TEST_ASSERT_VAL("ENOMEM\n", buf);
130
131		/* First iteration to fill caches, second one to read them. */
132		for (c = 0; c < 2; c++) {
133			memset(buf, 0, TEST_FILE_SIZE);
134			size = dso__data_read_offset(dso, &machine, 10,
135						     buf, TEST_FILE_SIZE);
136
137			TEST_ASSERT_VAL("Wrong size",
138				size == (TEST_FILE_SIZE - 10));
139
140			for (i = 0; i < (size_t)size; i++)
141				TEST_ASSERT_VAL("Wrong data",
142					buf[i] == (i % 10));
143		}
144
145		free(buf);
146	}
147
148	dso__delete(dso);
149	unlink(file);
150	return 0;
151}
152