user: implement mlibc as the libc, finally.
It's finally done.. Signed-off-by: kaguya <vpshinomiya@protonmail.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
int main(){
|
||||
assert(abs(-10) == 10);
|
||||
assert(abs(2021) == 2021);
|
||||
|
||||
assert(labs(-256) == 256);
|
||||
assert(labs(10034890) == 10034890);
|
||||
|
||||
assert(llabs(-0x2deadbeef) == 0x2deadbeef);
|
||||
assert(llabs(49238706947) == 49238706947);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main() {
|
||||
void *p;
|
||||
|
||||
p = aligned_alloc(sizeof(void *), sizeof(void *));
|
||||
assert(p != NULL && (uintptr_t)p % sizeof(void *) == 0);
|
||||
free(p);
|
||||
|
||||
p = aligned_alloc(256, 256);
|
||||
assert(p != NULL && (uintptr_t)p % 256 == 0);
|
||||
free(p);
|
||||
|
||||
// small alignments are okay
|
||||
p = aligned_alloc(1, 8);
|
||||
assert(p != NULL);
|
||||
free(p);
|
||||
p = aligned_alloc(1, 1);
|
||||
assert(p != NULL);
|
||||
free(p);
|
||||
|
||||
// It seems that glibc doesn't report error in these cases.
|
||||
#if !(defined(USE_HOST_LIBC) && defined(__GLIBC__))
|
||||
// size % align must be 0
|
||||
p = aligned_alloc(256, 1);
|
||||
assert(errno == EINVAL);
|
||||
assert(p == NULL);
|
||||
|
||||
// align must be a 'valid alignment supported by the implementation'
|
||||
p = aligned_alloc(3, 1);
|
||||
assert(errno == EINVAL);
|
||||
assert(p == NULL);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
errno = 0;
|
||||
void *ptr = calloc((SIZE_MAX / 2) + 2, 2);
|
||||
assert(!ptr);
|
||||
assert(errno);
|
||||
|
||||
errno = 0;
|
||||
ptr = calloc(10, sizeof(size_t));
|
||||
assert(ptr);
|
||||
for(size_t i = 0; i < 10; i++) {
|
||||
size_t *p = ptr;
|
||||
assert(!p[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <complex.h>
|
||||
|
||||
// FIXME: We should create a proper floating point facility
|
||||
// in order for other functions to be tested properly
|
||||
|
||||
#define APPROXIMATELY_EQUAL(calculated, expected) fabs((calculated) - (expected)) <= 0.0000005
|
||||
#define APPROXIMATELY_EQUALF(calculated, expected) fabsf((calculated) - (expected)) <= 0.0000005f
|
||||
#define APPROXIMATELY_EQUALL(calculated, expected) fabsl((calculated) - (expected)) <= 0.0000005L
|
||||
|
||||
#define IS_COMPLEX_NUMBER(Z) \
|
||||
_Generic((Z), \
|
||||
double complex: 1, \
|
||||
float complex: 1, \
|
||||
long double complex: 1, \
|
||||
default: 0 \
|
||||
)
|
||||
|
||||
int main() {
|
||||
#if !(defined(USE_HOST_LIBC) && defined(__clang__))
|
||||
assert(IS_COMPLEX_NUMBER(CMPLX(5.2, 4.3)));
|
||||
double complex cz = CMPLX(5.2, 4.3);
|
||||
assert(APPROXIMATELY_EQUAL(creal(cz), 5.2));
|
||||
assert(APPROXIMATELY_EQUAL(cimag(cz), 4.3));
|
||||
|
||||
assert(IS_COMPLEX_NUMBER(CMPLXF(1.2f, 2.5f)));
|
||||
float complex czf = CMPLXF(1.2f, 2.5f);
|
||||
assert(APPROXIMATELY_EQUALF(crealf(czf), 1.2f));
|
||||
assert(APPROXIMATELY_EQUALF(cimagf(czf), 2.5f));
|
||||
|
||||
assert(IS_COMPLEX_NUMBER(CMPLXL(0.1L, 123.54L)));
|
||||
long double complex czl = CMPLXL(0.1L, 123.54L);
|
||||
assert(APPROXIMATELY_EQUALL(creall(czl), 0.1L));
|
||||
assert(APPROXIMATELY_EQUALL(cimagl(czl), 123.54L));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <fenv.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
/* qemu-m68k < version 9.1.0 cannot run the test due to missing FPU logic. */
|
||||
#ifdef __m68k__
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define NO_OPTIMIZE(x) asm volatile("" :: "r,m" (x) : "memory")
|
||||
|
||||
static void div_by_zero() {
|
||||
volatile float zero = 0.0f;
|
||||
NO_OPTIMIZE(69.0f / zero);
|
||||
}
|
||||
|
||||
static bool float_cmp(float a, float b) {
|
||||
return a == b || fabs(a - b) < (fabs(a) + fabs(b)) * FLT_EPSILON;
|
||||
}
|
||||
|
||||
static void test_rounding(float expectation1, float expectation2) {
|
||||
float x;
|
||||
volatile float f = 1.968750f;
|
||||
volatile float m = 0x1.0p23f;
|
||||
|
||||
NO_OPTIMIZE(x = f + m);
|
||||
assert(float_cmp(expectation1, x));
|
||||
NO_OPTIMIZE(x = x - m);
|
||||
assert(x == expectation2);
|
||||
}
|
||||
|
||||
void test0() {
|
||||
// test whether the divide-by-zero exception is raised
|
||||
feclearexcept(FE_ALL_EXCEPT);
|
||||
assert(fetestexcept(FE_ALL_EXCEPT) == 0);
|
||||
|
||||
div_by_zero();
|
||||
int raised = fetestexcept(FE_DIVBYZERO);
|
||||
assert((raised & FE_DIVBYZERO));
|
||||
}
|
||||
|
||||
void test1() {
|
||||
// test various rounding modes
|
||||
feclearexcept(FE_DIVBYZERO);
|
||||
assert(fetestexcept(FE_ALL_EXCEPT) == 0);
|
||||
|
||||
fesetround(FE_UPWARD);
|
||||
assert(fegetround() == FE_UPWARD);
|
||||
test_rounding(8388610.0f, 2.0f);
|
||||
|
||||
fesetround(FE_DOWNWARD);
|
||||
assert(fegetround() == FE_DOWNWARD);
|
||||
test_rounding(8388609.0f, 1.0f);
|
||||
|
||||
fesetround(FE_TONEAREST);
|
||||
assert(fegetround() == FE_TONEAREST);
|
||||
test_rounding(8388610.0f, 2.0f);
|
||||
|
||||
fesetround(FE_TOWARDZERO);
|
||||
assert(fegetround() == FE_TOWARDZERO);
|
||||
test_rounding(8388609.0f, 1.0f);
|
||||
}
|
||||
|
||||
void test2() {
|
||||
// test feraiseexcept
|
||||
feclearexcept(FE_ALL_EXCEPT);
|
||||
assert(fetestexcept(FE_ALL_EXCEPT) == 0);
|
||||
assert(feraiseexcept(FE_DIVBYZERO | FE_OVERFLOW) == 0);
|
||||
assert(fetestexcept(FE_ALL_EXCEPT) == (FE_DIVBYZERO | FE_OVERFLOW));
|
||||
}
|
||||
|
||||
void test3() {
|
||||
// test fe{get,set}env
|
||||
feclearexcept(FE_ALL_EXCEPT);
|
||||
assert(fetestexcept(FE_ALL_EXCEPT) == 0);
|
||||
assert(feraiseexcept(FE_OVERFLOW) == 0);
|
||||
|
||||
fenv_t state;
|
||||
assert(fegetenv(&state) == 0);
|
||||
assert(fetestexcept(FE_ALL_EXCEPT) == FE_OVERFLOW);
|
||||
|
||||
div_by_zero();
|
||||
assert(fetestexcept(FE_ALL_EXCEPT) == (FE_DIVBYZERO | FE_OVERFLOW));
|
||||
|
||||
assert(fesetenv(&state) == 0);
|
||||
assert(fetestexcept(FE_ALL_EXCEPT) == FE_OVERFLOW);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test0();
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
(void) argc;
|
||||
|
||||
FILE *f = fopen(argv[0], "r");
|
||||
assert(f);
|
||||
|
||||
int ret = fseek(f, 0, SEEK_SET);
|
||||
assert(!ret);
|
||||
|
||||
fpos_t start_pos;
|
||||
ret = fgetpos(f, &start_pos);
|
||||
assert(!ret);
|
||||
|
||||
ret = fseek(f, 0, SEEK_END);
|
||||
assert(!ret);
|
||||
|
||||
long end_off = ftell(f);
|
||||
|
||||
fpos_t end_pos;
|
||||
ret = fgetpos(f, &end_pos);
|
||||
assert(!ret);
|
||||
|
||||
ret = fsetpos(f, &start_pos);
|
||||
assert(!ret);
|
||||
assert(ftell(f) == 0);
|
||||
|
||||
ret = fsetpos(f, &end_pos);
|
||||
assert(!ret);
|
||||
assert(ftell(f) == end_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "fopen-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "fopen.tmp"
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
FILE *file;
|
||||
char str[] = "mlibc fopen test";
|
||||
char str2[] = " mlibc appending";
|
||||
char completestr[] = "mlibc fopen test mlibc appending";
|
||||
char buffer[100];
|
||||
char buffer2[100];
|
||||
|
||||
// Clear all the buffers to zero.
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
memset(buffer2, 0, sizeof(buffer2));
|
||||
|
||||
// Open the file for writing.
|
||||
file = fopen(TEST_FILE, "w");
|
||||
assert(file);
|
||||
|
||||
// Write string minus null terminator, flush and close.
|
||||
fwrite(str, 1, sizeof(str) - 1, file);
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
|
||||
// Open the file for reading.
|
||||
file = fopen(TEST_FILE, "r");
|
||||
assert(file);
|
||||
|
||||
// Verify that we read back the written string and close the file.
|
||||
assert(fread(buffer, 1, sizeof(str) - 1, file));
|
||||
assert(!strcmp(buffer, str));
|
||||
fclose(file);
|
||||
|
||||
// Open the file in appending mode, append string 2 (minus the null terminator) to the file, flush and close.
|
||||
file = fopen(TEST_FILE, "a");
|
||||
fwrite(str2, 1, sizeof(str2) - 1, file);
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
|
||||
// Open the file for reading again, verify the contents, close the file and return.
|
||||
file = fopen(TEST_FILE, "r");
|
||||
assert(fread(buffer2, 1, sizeof(completestr) - 1, file));
|
||||
assert(!strcmp(buffer2, completestr));
|
||||
fclose(file);
|
||||
|
||||
// Check that stdout, stdin and stderr can be closed by the application (issue #12).
|
||||
fclose(stdout);
|
||||
fclose(stdin);
|
||||
fclose(stderr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "fputs-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "fputs.tmp"
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
FILE *file;
|
||||
char str[] = "mlibc fputs test";
|
||||
char buffer[100];
|
||||
|
||||
// Clear the buffer to zero.
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
// Open the file for writing.
|
||||
file = fopen(TEST_FILE, "w");
|
||||
assert(file);
|
||||
|
||||
// Verify that we can write an empty string.
|
||||
assert(fputs("", file) != EOF);
|
||||
|
||||
// Write string, flush and close.
|
||||
assert(fputs(str, file) != EOF);
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
|
||||
// Open the file for reading.
|
||||
file = fopen(TEST_FILE, "r");
|
||||
assert(file);
|
||||
|
||||
// Verify that we read back the written string and close.
|
||||
assert(fread(buffer, 1, sizeof(str) - 1, file));
|
||||
assert(!strcmp(buffer, str));
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "freopen-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "freopen.tmp"
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
FILE *file = fopen(TEST_FILE, "w");
|
||||
assert(file);
|
||||
|
||||
assert(freopen("/dev/null", "w", file));
|
||||
|
||||
char str[] = "mlibc freopen test";
|
||||
fwrite(str, 1, sizeof(str) - 1, file);
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
|
||||
file = fopen(TEST_FILE, "r");
|
||||
assert(file);
|
||||
|
||||
char buf[sizeof(str)];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
int ret = fread(buf, 1, sizeof(buf) - 1, file);
|
||||
fprintf(stderr, "ret %d\n", ret);
|
||||
assert(ret == 0);
|
||||
fclose(file);
|
||||
|
||||
file = fopen("/dev/null", "w");
|
||||
assert(file);
|
||||
|
||||
assert(freopen(TEST_FILE, "w", file));
|
||||
fwrite(str, 1, sizeof(str) - 1, file);
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
file = fopen(TEST_FILE, "r");
|
||||
assert(fread(buf, 1, sizeof(buf) - 1, file));
|
||||
|
||||
fprintf(stderr, "buffer content '%s'\n", buf);
|
||||
assert(!strcmp(buf, "mlibc freopen test"));
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "ftell-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "ftell.tmp"
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
FILE *file;
|
||||
char str[] = "mlibc ftell test";
|
||||
size_t str_size = sizeof(str) - 1;
|
||||
char buffer[20];
|
||||
|
||||
// Clear buffer to zero
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
// Open the file for writing in binary mode, because ftell is unspecified
|
||||
// in text mode.
|
||||
file = fopen(TEST_FILE, "wb");
|
||||
assert(file);
|
||||
|
||||
// Write string minus null terminator, flush and close.
|
||||
assert(fwrite(str, 1, str_size, file) == str_size);
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
|
||||
// Open the file for reading in binary mode.
|
||||
file = fopen(TEST_FILE, "rb");
|
||||
assert(file);
|
||||
|
||||
// Check position indicator at the start of the file.
|
||||
assert(ftell(file) == 0);
|
||||
|
||||
// Read 4 bytes and check fread and ftell.
|
||||
assert(fread(buffer, 1, 4, file) == 4);
|
||||
assert(ftell(file) == 4);
|
||||
|
||||
// Rewind and check position indicator at the start of the file.
|
||||
rewind(file);
|
||||
assert(ftell(file) == 0);
|
||||
|
||||
// Read the entire file and check fread and ftell.
|
||||
assert(fread(buffer, 1, str_size, file) == str_size);
|
||||
assert((size_t) ftell(file) == str_size);
|
||||
|
||||
// Rewind and check how ftell interacts with getc.
|
||||
rewind(file);
|
||||
assert(fgetc(file) == 'm');
|
||||
assert(ftell(file) == 1);
|
||||
assert(fgetc(file) == 'l');
|
||||
assert(ftell(file) == 2);
|
||||
assert(fgetc(file) == 'i');
|
||||
assert(ftell(file) == 3);
|
||||
|
||||
// Check whether ftell is decremented after ungetc
|
||||
assert(ungetc('X', file) == 'X');
|
||||
int ftell_after_ungetc = ftell(file);
|
||||
fprintf(stderr, "ftell_after_ungetc: %d\n", ftell_after_ungetc);
|
||||
assert(ftell_after_ungetc == 2);
|
||||
ungetc('Y', file);
|
||||
assert(ftell(file) == 1);
|
||||
|
||||
// Check if rewind undoes ungetc's effects on ftell
|
||||
rewind(file);
|
||||
assert(ftell(file) == 0);
|
||||
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
wchar_t c = 0xC9;
|
||||
unsigned char buf[MB_LEN_MAX] = { 0 };
|
||||
setlocale(LC_ALL, "");
|
||||
if (sprintf(buf, "%lc", c) < 0)
|
||||
return -1;
|
||||
|
||||
assert(buf[0] == 0xc3 && buf[1] == 0x89
|
||||
&& buf[2] == '\0' && buf[3] == '\0');
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdnoreturn.h>
|
||||
#include <assert.h>
|
||||
|
||||
jmp_buf buf;
|
||||
|
||||
noreturn void do_jump(int arg) {
|
||||
longjmp(buf, 2 * arg);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
volatile int times_called = 0;
|
||||
|
||||
if (setjmp(buf) != 8) {
|
||||
do_jump(++times_called);
|
||||
}
|
||||
|
||||
assert(times_called == 4);
|
||||
|
||||
times_called = 0;
|
||||
int ret = setjmp(buf);
|
||||
assert(ret == times_called);
|
||||
|
||||
if (!ret) {
|
||||
times_called = 1;
|
||||
longjmp(buf, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include <assert.h>
|
||||
#include <locale.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <uchar.h>
|
||||
|
||||
struct {
|
||||
size_t ret;
|
||||
char32_t c32;
|
||||
uint8_t bytes[4];
|
||||
} expected_results[] = {
|
||||
{1, 0x7A, {0x7A, 0, 0, 0}},
|
||||
{2, 0xDF, {0xC3, 0x9F, 0, 0}},
|
||||
{3, 0x6C34, {0xE6, 0xB0, 0xB4, 0}},
|
||||
{4, 0x1F34C, {0xF0, 0x9F, 0x8D, 0x8C}},
|
||||
};
|
||||
|
||||
int main() {
|
||||
setlocale(LC_ALL, "en_US.utf8");
|
||||
|
||||
size_t ret = 0;
|
||||
|
||||
char *str = "z\u00df\u6c34\U0001F34C";
|
||||
|
||||
fprintf(stderr, "string: '%s'\n", str);
|
||||
|
||||
mbstate_t state = {};
|
||||
char32_t c32;
|
||||
size_t loop = 0;
|
||||
while((ret = mbrtoc32(&c32, str, strlen(str), &state))) {
|
||||
assert(ret != (size_t)-3);
|
||||
if(ret == (size_t)-1)
|
||||
break;
|
||||
if(ret == (size_t)-2)
|
||||
break;
|
||||
|
||||
fprintf(stderr, "Next UTF-32 char: 0x%x obtained from %zu bytes [", c32, ret);
|
||||
for(size_t n = 0; n < ret; ++n) {
|
||||
fprintf(stderr, " 0x%02x ", (uint8_t) str[n]);
|
||||
}
|
||||
fprintf(stderr, "]\n");
|
||||
|
||||
assert(ret == expected_results[loop].ret);
|
||||
assert(c32 == expected_results[loop].c32);
|
||||
for(size_t n = 0; n < ret; ++n) {
|
||||
assert((uint8_t) str[n] == expected_results[loop].bytes[n]);
|
||||
}
|
||||
|
||||
str += ret;
|
||||
loop++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
char *haystack = "abc123\0x45";
|
||||
|
||||
char *needle1 = "abc";
|
||||
void *rv = memmem(haystack, strlen(haystack), needle1, strlen(needle1));
|
||||
assert(rv == haystack);
|
||||
|
||||
char *needle2 = "123";
|
||||
rv = memmem(haystack, strlen(haystack), needle2, strlen(needle2));
|
||||
assert(rv == haystack + 3);
|
||||
|
||||
char *needle3 = "1234";
|
||||
rv = memmem(haystack, strlen(haystack), needle3, strlen(needle3));
|
||||
assert(rv == NULL);
|
||||
|
||||
char *needle4 = "23\0x45";
|
||||
rv = memmem(haystack, 10, needle4, 6);
|
||||
assert(rv == haystack + 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *arr[] = { "xyz", "abc", "ghi", "def" };
|
||||
|
||||
static const size_t magic = 0xDEADBEEF;
|
||||
|
||||
static int cmpstringp(const void *p1, const void *p2, void *ctx) {
|
||||
/* The actual arguments to this function are "pointers to
|
||||
* pointers to char", but strcmp(3) arguments are "pointers
|
||||
* to char", hence the following cast plus dereference. */
|
||||
assert(*(size_t *) ctx == magic);
|
||||
return strcmp(*(const char **) p1, *(const char **) p2);
|
||||
}
|
||||
|
||||
int main() {
|
||||
qsort_r(&arr[0], sizeof(arr) / sizeof(*arr), sizeof(char *), cmpstringp, (void *) &magic);
|
||||
|
||||
assert(!strcmp(arr[0], "abc"));
|
||||
assert(!strcmp(arr[1], "def"));
|
||||
assert(!strcmp(arr[2], "ghi"));
|
||||
assert(!strcmp(arr[3], "xyz"));
|
||||
|
||||
for(size_t i = 0; i < sizeof(arr) / sizeof(*arr); i++) {
|
||||
fprintf(stderr, "%s\n", arr[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <wctype.h>
|
||||
|
||||
int main() {
|
||||
char buffer[10];
|
||||
int ret = snprintf(buffer, 10, "%d", 123456789);
|
||||
assert(strncmp("123456789", buffer, 10) == 0);
|
||||
assert(ret == 9);
|
||||
|
||||
// We deliberately induce a warning here.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-truncation"
|
||||
ret = snprintf(buffer, 10, "%d", 1234567890);
|
||||
assert(strncmp("123456789", buffer, 10) == 0);
|
||||
assert(ret == 10);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// mlibc issue #118.
|
||||
ret = snprintf(NULL, 0, "%d", 123456789);
|
||||
assert(ret == 9);
|
||||
|
||||
char buf[128];
|
||||
assert(snprintf(buf, 2, "a") == 1);
|
||||
assert(strcmp(buf, "a") == 0);
|
||||
assert(snprintf(buf, 3, "abc") == 3);
|
||||
assert(strcmp(buf, "ab") == 0);
|
||||
assert(snprintf(buf, 128, "%%") == 1);
|
||||
assert(strcmp(buf, "%") == 0);
|
||||
assert(snprintf(buf, 128, "a%cc%c", 'b', 'd') == 4);
|
||||
assert(strcmp(buf, "abcd") == 0);
|
||||
assert(snprintf(buf, 128, "a%lcc%lc", (wint_t)L'b', (wint_t)L'd') == 4);
|
||||
assert(strcmp(buf, "abcd") == 0);
|
||||
assert(snprintf(buf, 128, "%s", "hello") == 5);
|
||||
assert(strcmp(buf, "hello") == 0);
|
||||
assert(snprintf(buf, 128, "%ls", L"hello") == 5);
|
||||
assert(strcmp(buf, "hello") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%d", 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%d", 0) == 1);
|
||||
assert(strcmp(buf, "0") == 0);
|
||||
assert(snprintf(buf, 128, "%d", -1234) == 5);
|
||||
assert(strcmp(buf, "-1234") == 0);
|
||||
assert(snprintf(buf, 128, "%hhd", 123) == 3);
|
||||
assert(strcmp(buf, "123") == 0);
|
||||
assert(snprintf(buf, 128, "%hd", 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%ld", 1234L) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%lld", 1234LL) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%jd", (intmax_t) 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%zd", (ssize_t) 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%td", (ptrdiff_t) 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%i", 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%i", 0) == 1);
|
||||
assert(strcmp(buf, "0") == 0);
|
||||
assert(snprintf(buf, 128, "%i", -1234) == 5);
|
||||
assert(strcmp(buf, "-1234") == 0);
|
||||
assert(snprintf(buf, 128, "%hhi", 123) == 3);
|
||||
assert(strcmp(buf, "123") == 0);
|
||||
assert(snprintf(buf, 128, "%hi", 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%li", 1234L) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%lli", 1234LL) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%ji", (intmax_t) 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%zi", (ssize_t) 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%ti", (ptrdiff_t) 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%b", 0b1011) == 4);
|
||||
assert(strcmp(buf, "1011") == 0);
|
||||
assert(snprintf(buf, 128, "%b", 0) == 1);
|
||||
assert(strcmp(buf, "0") == 0);
|
||||
assert(snprintf(buf, 128, "%hhb", 0b1011) == 4);
|
||||
assert(strcmp(buf, "1011") == 0);
|
||||
assert(snprintf(buf, 128, "%hb", 0b1011) == 4);
|
||||
assert(strcmp(buf, "1011") == 0);
|
||||
assert(snprintf(buf, 128, "%lb", 0b1011UL) == 4);
|
||||
assert(strcmp(buf, "1011") == 0);
|
||||
assert(snprintf(buf, 128, "%llb", 0b1011ULL) == 4);
|
||||
assert(strcmp(buf, "1011") == 0);
|
||||
assert(snprintf(buf, 128, "%jb", (uintmax_t) 0b1011) == 4);
|
||||
assert(strcmp(buf, "1011") == 0);
|
||||
assert(snprintf(buf, 128, "%zb", (size_t) 0b1011) == 4);
|
||||
assert(strcmp(buf, "1011") == 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
assert(snprintf(buf, 128, "%tb", 0b1011UL) == 4);
|
||||
assert(strcmp(buf, "1011") == 0);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
assert(snprintf(buf, 128, "%o", 01234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%o", 0) == 1);
|
||||
assert(strcmp(buf, "0") == 0);
|
||||
assert(snprintf(buf, 128, "%o", -01234) == 11);
|
||||
assert(strcmp(buf, "37777776544") == 0);
|
||||
assert(snprintf(buf, 128, "%hho", 012) == 2);
|
||||
assert(strcmp(buf, "12") == 0);
|
||||
assert(snprintf(buf, 128, "%ho", 01234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%lo", 01234UL) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%llo", 01234ULL) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%jo", (uintmax_t) 01234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%zo", (size_t) 01234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
assert(snprintf(buf, 128, "%to", 01234UL) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
assert(snprintf(buf, 128, "%x", 0x1234AB) == 6);
|
||||
assert(strcmp(buf, "1234ab") == 0);
|
||||
assert(snprintf(buf, 128, "%x", 0) == 1);
|
||||
assert(strcmp(buf, "0") == 0);
|
||||
assert(snprintf(buf, 128, "%x", -0x1234AB) == 8);
|
||||
assert(strcmp(buf, "ffedcb55") == 0);
|
||||
assert(snprintf(buf, 128, "%X", 0x1234AB) == 6);
|
||||
assert(strcmp(buf, "1234AB") == 0);
|
||||
assert(snprintf(buf, 128, "%hhx", 0xAB) == 2);
|
||||
assert(strcmp(buf, "ab") == 0);
|
||||
assert(snprintf(buf, 128, "%hx", 0x12AB) == 4);
|
||||
assert(strcmp(buf, "12ab") == 0);
|
||||
assert(snprintf(buf, 128, "%lx", 0x1234ABUL) == 6);
|
||||
assert(strcmp(buf, "1234ab") == 0);
|
||||
assert(snprintf(buf, 128, "%llx", 0x1234ABULL) == 6);
|
||||
assert(strcmp(buf, "1234ab") == 0);
|
||||
assert(snprintf(buf, 128, "%jx", (uintmax_t) 0x1234AB) == 6);
|
||||
assert(strcmp(buf, "1234ab") == 0);
|
||||
assert(snprintf(buf, 128, "%zx", (size_t) 0x1234AB) == 6);
|
||||
assert(strcmp(buf, "1234ab") == 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
assert(snprintf(buf, 128, "%tx", 0x1234ABUL) == 6);
|
||||
assert(strcmp(buf, "1234ab") == 0);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
assert(snprintf(buf, 128, "%u", 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%u", 0) == 1);
|
||||
assert(strcmp(buf, "0") == 0);
|
||||
assert(snprintf(buf, 128, "%u", -1234) == 10);
|
||||
assert(strcmp(buf, "4294966062") == 0);
|
||||
assert(snprintf(buf, 128, "%hhu", 123) == 3);
|
||||
assert(strcmp(buf, "123") == 0);
|
||||
assert(snprintf(buf, 128, "%hu", 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%lu", 1234UL) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%llu", 1234ULL) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%ju", (uintmax_t) 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
assert(snprintf(buf, 128, "%zu", (size_t) 1234) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
assert(snprintf(buf, 128, "%tu", 1234UL) == 4);
|
||||
assert(strcmp(buf, "1234") == 0);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
assert(snprintf(buf, 128, "%f", 1234.1234567) == 11);
|
||||
assert(strcmp(buf, "1234.123457") == 0);
|
||||
assert(snprintf(buf, 128, "%f", 0.0) == 8);
|
||||
assert(strcmp(buf, "0.000000") == 0);
|
||||
assert(snprintf(buf, 128, "%f", -1234.123456) == 12);
|
||||
assert(strcmp(buf, "-1234.123456") == 0);
|
||||
assert(snprintf(buf, 128, "%f", INFINITY) == 3);
|
||||
assert(strcmp(buf, "inf") == 0);
|
||||
assert(snprintf(buf, 128, "%04f", INFINITY) == 4);
|
||||
assert(strcmp(buf, " inf") == 0);
|
||||
assert(snprintf(buf, 128, "%-4f", INFINITY) == 4);
|
||||
assert(strcmp(buf, "inf ") == 0);
|
||||
assert(snprintf(buf, 128, "%f", NAN) == 3);
|
||||
assert(strcmp(buf, "nan") == 0);
|
||||
assert(snprintf(buf, 128, "%lf", 1234.123456) == 11);
|
||||
assert(strcmp(buf, "1234.123456") == 0);
|
||||
assert(snprintf(buf, 128, "%Lf", 1234.123456L) == 11);
|
||||
assert(strcmp(buf, "1234.123456") == 0);
|
||||
assert(snprintf(buf, 128, "%F", 1234.123456) == 11);
|
||||
assert(strcmp(buf, "1234.123456") == 0);
|
||||
assert(snprintf(buf, 128, "%F", INFINITY) == 3);
|
||||
assert(strcmp(buf, "INF") == 0);
|
||||
assert(snprintf(buf, 128, "%F", NAN) == 3);
|
||||
assert(strcmp(buf, "NAN") == 0);
|
||||
assert(snprintf(buf, 128, "%lF", 1234.123456) == 11);
|
||||
assert(strcmp(buf, "1234.123456") == 0);
|
||||
assert(snprintf(buf, 128, "%LF", 1234.123456L) == 11);
|
||||
assert(strcmp(buf, "1234.123456") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%e", 1.123456) == 12);
|
||||
assert(strcmp(buf, "1.123456e+00") == 0);
|
||||
assert(snprintf(buf, 128, "%e", 0.0) == 12);
|
||||
assert(strcmp(buf, "0.000000e+00") == 0);
|
||||
assert(snprintf(buf, 128, "%e", -1.123456) == 13);
|
||||
assert(strcmp(buf, "-1.123456e+00") == 0);
|
||||
assert(snprintf(buf, 128, "%e", 1.123456e12) == 12);
|
||||
assert(strcmp(buf, "1.123456e+12") == 0);
|
||||
assert(snprintf(buf, 128, "%e", -1.123456e12) == 13);
|
||||
assert(strcmp(buf, "-1.123456e+12") == 0);
|
||||
assert(snprintf(buf, 128, "%e", -1.123456e-12) == 13);
|
||||
assert(strcmp(buf, "-1.123456e-12") == 0);
|
||||
assert(snprintf(buf, 128, "%e", INFINITY) == 3);
|
||||
assert(strcmp(buf, "inf") == 0);
|
||||
assert(snprintf(buf, 128, "%e", NAN) == 3);
|
||||
assert(strcmp(buf, "nan") == 0);
|
||||
assert(snprintf(buf, 128, "%le", 1.123456e12) == 12);
|
||||
assert(strcmp(buf, "1.123456e+12") == 0);
|
||||
assert(snprintf(buf, 128, "%Le", 1.123456e12L) == 12);
|
||||
assert(strcmp(buf, "1.123456e+12") == 0);
|
||||
assert(snprintf(buf, 128, "%E", 1.123456e12) == 12);
|
||||
assert(strcmp(buf, "1.123456E+12") == 0);
|
||||
assert(snprintf(buf, 128, "%E", INFINITY) == 3);
|
||||
assert(strcmp(buf, "INF") == 0);
|
||||
assert(snprintf(buf, 128, "%E", NAN) == 3);
|
||||
assert(strcmp(buf, "NAN") == 0);
|
||||
assert(snprintf(buf, 128, "%lE", 1.123456e12) == 12);
|
||||
assert(strcmp(buf, "1.123456E+12") == 0);
|
||||
assert(snprintf(buf, 128, "%LE", 1.123456e12L) == 12);
|
||||
assert(strcmp(buf, "1.123456E+12") == 0);
|
||||
|
||||
/*assert(snprintf(buf, 128, "%a", 0x1.123456p0) == 13);
|
||||
assert(strcmp(buf, "0x1.123456p+0") == 0);
|
||||
assert(snprintf(buf, 128, "%a", 0.0) == 6);
|
||||
assert(strcmp(buf, "0x0p+0") == 0);
|
||||
assert(snprintf(buf, 128, "%a", 0x1.123456p12) == 14);
|
||||
assert(strcmp(buf, "0x1.123456p+12") == 0);
|
||||
assert(snprintf(buf, 128, "%a", -0x1.123456p-12) == 15);
|
||||
assert(strcmp(buf, "-0x1.123456p-12") == 0);
|
||||
assert(snprintf(buf, 128, "%a", INFINITY) == 3);
|
||||
assert(strcmp(buf, "inf") == 0);
|
||||
assert(snprintf(buf, 128, "%a", NAN) == 3);
|
||||
assert(strcmp(buf, "nan") == 0);
|
||||
assert(snprintf(buf, 128, "%la", 0x1.123456p12) == 14);
|
||||
assert(strcmp(buf, "0x1.123456p+12") == 0);
|
||||
assert(snprintf(buf, 128, "%La", 0x1.123456p12L) == 12);
|
||||
assert(strcmp(buf, "0x8.91a2bp+9") == 0);
|
||||
assert(snprintf(buf, 128, "%A", 0x1.123456p12) == 14);
|
||||
assert(strcmp(buf, "0X1.123456P+12") == 0);
|
||||
assert(snprintf(buf, 128, "%A", INFINITY) == 3);
|
||||
assert(strcmp(buf, "INF") == 0);
|
||||
assert(snprintf(buf, 128, "%A", NAN) == 3);
|
||||
assert(strcmp(buf, "NAN") == 0);
|
||||
assert(snprintf(buf, 128, "%lA", 0x1.123456p12) == 14);
|
||||
assert(strcmp(buf, "0X1.123456P+12") == 0);
|
||||
assert(snprintf(buf, 128, "%LA", 0x1.123456p12L) == 12);
|
||||
assert(strcmp(buf, "0X8.91A2BP+9") == 0);*/
|
||||
|
||||
assert(snprintf(buf, 128, "%g", 1.1234) == 6);
|
||||
assert(strcmp(buf, "1.1234") == 0);
|
||||
assert(snprintf(buf, 128, "%g", 0.0) == 1);
|
||||
assert(strcmp(buf, "0") == 0);
|
||||
assert(snprintf(buf, 128, "%g", -1.1234) == 7);
|
||||
assert(strcmp(buf, "-1.1234") == 0);
|
||||
assert(snprintf(buf, 128, "%g", 1.1234e12) == 10);
|
||||
assert(strcmp(buf, "1.1234e+12") == 0);
|
||||
assert(snprintf(buf, 128, "%g", -1.1234e-12) == 11);
|
||||
assert(strcmp(buf, "-1.1234e-12") == 0);
|
||||
assert(snprintf(buf, 128, "%g", INFINITY) == 3);
|
||||
assert(strcmp(buf, "inf") == 0);
|
||||
assert(snprintf(buf, 128, "%g", NAN) == 3);
|
||||
assert(strcmp(buf, "nan") == 0);
|
||||
assert(snprintf(buf, 128, "%lg", 1.1234e12) == 10);
|
||||
assert(strcmp(buf, "1.1234e+12") == 0);
|
||||
assert(snprintf(buf, 128, "%Lg", 1.1234e12L) == 10);
|
||||
assert(strcmp(buf, "1.1234e+12") == 0);
|
||||
assert(snprintf(buf, 128, "%G", 1.1234) == 6);
|
||||
assert(strcmp(buf, "1.1234") == 0);
|
||||
assert(snprintf(buf, 128, "%G", 1.1234e12) == 10);
|
||||
assert(strcmp(buf, "1.1234E+12") == 0);
|
||||
assert(snprintf(buf, 128, "%G", INFINITY) == 3);
|
||||
assert(strcmp(buf, "INF") == 0);
|
||||
assert(snprintf(buf, 128, "%G", NAN) == 3);
|
||||
assert(strcmp(buf, "NAN") == 0);
|
||||
assert(snprintf(buf, 128, "%lG", 1.1234e12) == 10);
|
||||
assert(strcmp(buf, "1.1234E+12") == 0);
|
||||
assert(snprintf(buf, 128, "%LG", 1.1234e12L) == 10);
|
||||
assert(strcmp(buf, "1.1234E+12") == 0);
|
||||
|
||||
signed char char_value = 0;
|
||||
assert(snprintf(buf, 128, "ab%hhnc", &char_value) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(char_value == 2);
|
||||
short short_value = 0;
|
||||
assert(snprintf(buf, 128, "ab%hnc", &short_value) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(short_value == 2);
|
||||
int int_value = 0;
|
||||
assert(snprintf(buf, 128, "ab%nc", &int_value) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(int_value == 2);
|
||||
long long_value = 0;
|
||||
assert(snprintf(buf, 128, "ab%lnc", &long_value) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(long_value == 2);
|
||||
long long long_long_value = 0;
|
||||
assert(snprintf(buf, 128, "ab%llnc", &long_long_value) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(long_long_value == 2);
|
||||
intmax_t intmax_value = 0;
|
||||
assert(snprintf(buf, 128, "ab%jnc", &intmax_value) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(intmax_value == 2);
|
||||
ssize_t size_value = 0;
|
||||
assert(snprintf(buf, 128, "ab%znc", &size_value) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(size_value == 2);
|
||||
ptrdiff_t ptrdiff_value = 0;
|
||||
assert(snprintf(buf, 128, "ab%tnc", &ptrdiff_value) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(ptrdiff_value == 2);
|
||||
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
uintptr_t ptr_value = 0xFFFFFFFFFFFFFFFF;
|
||||
assert(snprintf(buf, 128, "%p", (void *)ptr_value) == 18);
|
||||
assert(strcmp(buf, "0xffffffffffffffff") == 0);
|
||||
#else
|
||||
uintptr_t ptr_value = 0xFFFFFFFF;
|
||||
assert(snprintf(buf, 128, "%p", (void*)ptr_value) == 10);
|
||||
assert(strcmp(buf, "0xffffffff") == 0);
|
||||
#endif
|
||||
|
||||
ptr_value = 0xFFFF;
|
||||
assert(snprintf(buf, 128, "%p", (void*)ptr_value) == 6);
|
||||
assert(strcmp(buf, "0xffff") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%-4dhello", 12) == 9);
|
||||
assert(strcmp(buf, "12 hello") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%-4dhello", -12) == 9);
|
||||
assert(strcmp(buf, "-12 hello") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%#-4xhello", 0x12) == 9);
|
||||
assert(strcmp(buf, "0x12hello") == 0);
|
||||
assert(snprintf(buf, 128, "%#-4Xhello", 0x12) == 9);
|
||||
assert(strcmp(buf, "0X12hello") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%#b", 0b1011) == 6);
|
||||
assert(strcmp(buf, "0b1011") == 0);
|
||||
assert(snprintf(buf, 128, "%#B", 0b1011) == 6);
|
||||
assert(strcmp(buf, "0B1011") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%+d", 1234) == 5);
|
||||
assert(strcmp(buf, "+1234") == 0);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
assert(snprintf(buf, 128, "%+ d", 1234) == 5);
|
||||
assert(strcmp(buf, "+1234") == 0);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
assert(snprintf(buf, 128, "% d", 1234) == 5);
|
||||
assert(strcmp(buf, " 1234") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%4dhello", 12) == 9);
|
||||
assert(strcmp(buf, " 12hello") == 0);
|
||||
assert(snprintf(buf, 128, "%2dhello", 1234) == 9);
|
||||
assert(strcmp(buf, "1234hello") == 0);
|
||||
int width = 4;
|
||||
assert(snprintf(buf, 128, "%*dhello", width, 12) == 9);
|
||||
assert(strcmp(buf, " 12hello") == 0);
|
||||
width = -4;
|
||||
assert(snprintf(buf, 128, "%*dhello", width, 12) == 9);
|
||||
assert(strcmp(buf, "12 hello") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%04dhello", 12) == 9);
|
||||
assert(strcmp(buf, "0012hello") == 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
assert(snprintf(buf, 128, "%-04dhello", 12) == 9);
|
||||
assert(strcmp(buf, "12 hello") == 0);
|
||||
assert(snprintf(buf, 128, "%04.2dhello", 1) == 9);
|
||||
assert(strcmp(buf, " 01hello") == 0);
|
||||
#pragma GCC diagnostic pop
|
||||
assert(snprintf(buf, 128, "%.d", 0) == 0);
|
||||
assert(strcmp(buf, "") == 0);
|
||||
assert(snprintf(buf, 128, "%.0d", 0) == 0);
|
||||
assert(strcmp(buf, "") == 0);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
assert(snprintf(buf, 128, "%04.d", 0) == 4);
|
||||
assert(strcmp(buf, " ") == 0);
|
||||
assert(snprintf(buf, 128, "%#04.x", 0) == 4);
|
||||
assert(strcmp(buf, " ") == 0);
|
||||
assert(snprintf(buf, 128, "%+04.d", 0) == 4);
|
||||
assert(strcmp(buf, " +") == 0);
|
||||
assert(snprintf(buf, 128, "%+0.d", 0) == 1);
|
||||
assert(strcmp(buf, "+") == 0);
|
||||
#pragma GCC diagnostic pop
|
||||
int precision = 0;
|
||||
assert(snprintf(buf, 128, "%.*d", precision, 0) == 0);
|
||||
assert(strcmp(buf, "") == 0);
|
||||
precision = -1;
|
||||
assert(snprintf(buf, 128, "%.*d", precision, 0) == 1);
|
||||
assert(strcmp(buf, "0") == 0);
|
||||
assert(snprintf(buf, 128, "%.6d", 1234) == 6);
|
||||
assert(strcmp(buf, "001234") == 0);
|
||||
|
||||
assert(snprintf(buf, 128, "%.o", 0) == 0);
|
||||
assert(strcmp(buf, "") == 0);
|
||||
assert(snprintf(buf, 128, "%.0o", 0) == 0);
|
||||
assert(strcmp(buf, "") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
#include <fenv.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
char buf[64] = { 0 };
|
||||
sprintf(buf, "%d", 12);
|
||||
assert(!strcmp(buf, "12"));
|
||||
|
||||
sprintf(buf, "%f", 3.14);
|
||||
assert(!strcmp(buf, "3.140000"));
|
||||
sprintf(buf, "%.1f", 0.0);
|
||||
assert(!strcmp(buf, "0.0"));
|
||||
|
||||
// Test %g
|
||||
sprintf(buf, "%g", 0.0);
|
||||
assert(!strcmp(buf, "0"));
|
||||
sprintf(buf, "%.2g", 0.01234);
|
||||
assert(!strcmp(buf, "0.012"));
|
||||
sprintf(buf, "%.3g", 1.1);
|
||||
assert(!strcmp(buf, "1.1"));
|
||||
sprintf(buf, "%#.5g", 1.1);
|
||||
assert(!strcmp(buf, "1.1000"));
|
||||
sprintf(buf, "%g", 0.0000123);
|
||||
assert(!strcmp(buf, "1.23e-05"));
|
||||
|
||||
// Test %e
|
||||
sprintf(buf, "%4.3e", 0.0);
|
||||
assert(!strcmp(buf, "0.000e+00"));
|
||||
sprintf(buf, "%.3e", 6.9e27);
|
||||
assert(!strcmp(buf, "6.900e+27"));
|
||||
|
||||
// Test %c right padding.
|
||||
sprintf(buf, "%-2c", 'a');
|
||||
assert(!strcmp(buf, "a "));
|
||||
|
||||
// Test %c left padding.
|
||||
sprintf(buf, "%2c", 'a');
|
||||
assert(!strcmp(buf, " a"));
|
||||
|
||||
// Test %d right padding - mlibc issue #58.
|
||||
sprintf(buf, "%-2d", 1);
|
||||
assert(!strcmp(buf, "1 "));
|
||||
sprintf(buf, "%-2.2d", 1);
|
||||
assert(!strcmp(buf, "01"));
|
||||
sprintf(buf, "%-3.2d", 1);
|
||||
assert(!strcmp(buf, "01 "));
|
||||
sprintf(buf, "%-3.2d", 12);
|
||||
assert(!strcmp(buf, "12 "));
|
||||
sprintf(buf, "%-3.2d", 123);
|
||||
assert(!strcmp(buf, "123"));
|
||||
sprintf(buf, "%-3.2u", 12);
|
||||
assert(!strcmp(buf, "12 "));
|
||||
|
||||
// Test %d left padding.
|
||||
sprintf(buf, "%2d", 1);
|
||||
assert(!strcmp(buf, " 1"));
|
||||
sprintf(buf, "%3.2d", 1);
|
||||
assert(!strcmp(buf, " 01"));
|
||||
sprintf(buf, "%3.2d", 12);
|
||||
assert(!strcmp(buf, " 12"));
|
||||
sprintf(buf, "%3.2d", 123);
|
||||
assert(!strcmp(buf, "123"));
|
||||
sprintf(buf, "%3.2u", 12);
|
||||
assert(!strcmp(buf, " 12"));
|
||||
// Disable -Wformat here since we deliberately induce some warnings.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
sprintf(buf, "%04.3u", 12);
|
||||
assert(!strcmp(buf, " 012"));
|
||||
#pragma GCC diagnostic pop
|
||||
sprintf(buf, "%+04d", 0);
|
||||
assert(!strcmp(buf, "+000"));
|
||||
|
||||
// Test %f padding.
|
||||
// TODO: Test printing of huge numbers (larger than 2^64)
|
||||
sprintf(buf, "%2.f", 1.2);
|
||||
assert(!strcmp(buf, " 1"));
|
||||
sprintf(buf, "%2.f", 12.3);
|
||||
assert(!strcmp(buf, "12"));
|
||||
sprintf(buf, "%5.2f", 1.0);
|
||||
assert(!strcmp(buf, " 1.00"));
|
||||
sprintf(buf, "%.1f", -4.0);
|
||||
assert(!strcmp(buf, "-4.0"));
|
||||
sprintf(buf, "%-3.f", 8.0);
|
||||
assert(!strcmp(buf, "8 "));
|
||||
sprintf(buf, "%4f", INFINITY);
|
||||
assert(!strcmp(buf, " inf") || !strcmp(buf, "infinity"));
|
||||
sprintf(buf, "%4f", NAN);
|
||||
assert(!strcmp(buf, " nan"));
|
||||
sprintf(buf, "%4F", INFINITY);
|
||||
assert(!strcmp(buf, " INF") || !strcmp(buf, "INFINITY"));
|
||||
sprintf(buf, "%4F", NAN);
|
||||
assert(!strcmp(buf, " NAN"));
|
||||
sprintf(buf, "%05.2f", 1.0);
|
||||
assert(!strcmp(buf, "01.00"));
|
||||
sprintf(buf, "%09f", INFINITY); // 0 ignored when padding infs
|
||||
assert(!strcmp(buf, " inf") || !strcmp(buf, " infinity"));
|
||||
|
||||
// Test %f rounding
|
||||
sprintf(buf, "%5.2f", 1.2);
|
||||
assert(!strcmp(buf, " 1.20"));
|
||||
sprintf(buf, "%5.2f", 1.23);
|
||||
assert(!strcmp(buf, " 1.23"));
|
||||
sprintf(buf, "%5.2f", 1.234);
|
||||
assert(!strcmp(buf, " 1.23"));
|
||||
sprintf(buf, "%5.2f", 12.345);
|
||||
assert(!strcmp(buf, "12.35"));
|
||||
sprintf(buf, "%-5.2f", 1.2);
|
||||
assert(!strcmp(buf, "1.20 "));
|
||||
|
||||
// Test '+' and ' ' flags - mlibc issue #229.
|
||||
// Disable -Wformat here since we deliberately induce some warnings.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
sprintf(buf, "%+d", 12);
|
||||
assert(!strcmp(buf, "+12"));
|
||||
sprintf(buf, "% d", 12);
|
||||
assert(!strcmp(buf, " 12"));
|
||||
sprintf(buf, "% +d", 12);
|
||||
assert(!strcmp(buf, "+12"));
|
||||
sprintf(buf, "%+ d", 12);
|
||||
assert(!strcmp(buf, "+12"));
|
||||
sprintf(buf, "%+d", -12);
|
||||
assert(!strcmp(buf, "-12"));
|
||||
sprintf(buf, "% d", -12);
|
||||
assert(!strcmp(buf, "-12"));
|
||||
sprintf(buf, "% +d", -12);
|
||||
assert(!strcmp(buf, "-12"));
|
||||
sprintf(buf, "%+ d", -12);
|
||||
assert(!strcmp(buf, "-12"));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// Test '#' flag.
|
||||
// TODO: Test with a, A, e, E, f, F, g, G conversions.
|
||||
sprintf(buf, "%#x", 12);
|
||||
assert(!strcmp(buf, "0xc"));
|
||||
sprintf(buf, "%#X", 12);
|
||||
assert(!strcmp(buf, "0XC"));
|
||||
sprintf(buf, "%#o", 12);
|
||||
assert(!strcmp(buf, "014"));
|
||||
|
||||
sprintf(buf, "%#x", 0);
|
||||
assert(!strcmp(buf, "0"));
|
||||
sprintf(buf, "%#X", 0);
|
||||
assert(!strcmp(buf, "0"));
|
||||
sprintf(buf, "%#o", 0);
|
||||
assert(!strcmp(buf, "0"));
|
||||
|
||||
// Disable -Wformat here because the compiler might not know about the b specifier.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
sprintf(buf, "%#b", 12);
|
||||
assert(!strcmp(buf, "0b1100"));
|
||||
sprintf(buf, "%#B", 12);
|
||||
assert(!strcmp(buf, "0B1100"));
|
||||
sprintf(buf, "%#b", 0);
|
||||
assert(!strcmp(buf, "0"));
|
||||
sprintf(buf, "%#B", 0);
|
||||
assert(!strcmp(buf, "0"));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// Test 'd' with different size mods to see
|
||||
// if they work
|
||||
sprintf(buf, "%d", 12);
|
||||
assert(!strcmp(buf, "12"));
|
||||
sprintf(buf, "%ld", 12L);
|
||||
assert(!strcmp(buf, "12"));
|
||||
sprintf(buf, "%lld", 12LL);
|
||||
assert(!strcmp(buf, "12"));
|
||||
sprintf(buf, "%zd", (size_t)12);
|
||||
assert(!strcmp(buf, "12"));
|
||||
sprintf(buf, "%hd", (short) 12);
|
||||
assert(!strcmp(buf, "12"));
|
||||
sprintf(buf, "%hhd", (char) 12);
|
||||
assert(!strcmp(buf, "12"));
|
||||
|
||||
// Test 'x' with different size mods to see
|
||||
// if they work
|
||||
sprintf(buf, "%x", 12);
|
||||
assert(!strcmp(buf, "c"));
|
||||
sprintf(buf, "%lx", 12L);
|
||||
assert(!strcmp(buf, "c"));
|
||||
sprintf(buf, "%llx", 12LL);
|
||||
assert(!strcmp(buf, "c"));
|
||||
sprintf(buf, "%zx", (size_t)12);
|
||||
assert(!strcmp(buf, "c"));
|
||||
sprintf(buf, "%hx", (unsigned short) 12);
|
||||
assert(!strcmp(buf, "c"));
|
||||
sprintf(buf, "%hhx", (unsigned char) 12);
|
||||
assert(!strcmp(buf, "c"));
|
||||
|
||||
// Test 'X' with different size mods to see
|
||||
// if they work
|
||||
sprintf(buf, "%X", 12);
|
||||
assert(!strcmp(buf, "C"));
|
||||
sprintf(buf, "%lX", 12L);
|
||||
assert(!strcmp(buf, "C"));
|
||||
sprintf(buf, "%llX", 12LL);
|
||||
assert(!strcmp(buf, "C"));
|
||||
sprintf(buf, "%zX", (size_t)12);
|
||||
assert(!strcmp(buf, "C"));
|
||||
sprintf(buf, "%hX", (unsigned short) 12);
|
||||
assert(!strcmp(buf, "C"));
|
||||
sprintf(buf, "%hhX", (unsigned char) 12);
|
||||
assert(!strcmp(buf, "C"));
|
||||
|
||||
// Test 'o' with different size mods to see
|
||||
// if they work
|
||||
sprintf(buf, "%o", 12);
|
||||
assert(!strcmp(buf, "14"));
|
||||
sprintf(buf, "%lo", 12L);
|
||||
assert(!strcmp(buf, "14"));
|
||||
sprintf(buf, "%llo", 12LL);
|
||||
assert(!strcmp(buf, "14"));
|
||||
sprintf(buf, "%zo", (size_t)12);
|
||||
assert(!strcmp(buf, "14"));
|
||||
sprintf(buf, "%ho", (unsigned short) 12);
|
||||
assert(!strcmp(buf, "14"));
|
||||
sprintf(buf, "%hho", (unsigned char) 12);
|
||||
assert(!strcmp(buf, "14"));
|
||||
|
||||
// Disable -Wformat here because the compiler might not know about the b specifier.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
// Test 'b' with different size mods to see
|
||||
// if they work
|
||||
sprintf(buf, "%b", 12);
|
||||
assert(!strcmp(buf, "1100"));
|
||||
sprintf(buf, "%lb", 12L);
|
||||
assert(!strcmp(buf, "1100"));
|
||||
sprintf(buf, "%llb", 12LL);
|
||||
assert(!strcmp(buf, "1100"));
|
||||
sprintf(buf, "%zb", (size_t)12);
|
||||
assert(!strcmp(buf, "1100"));
|
||||
sprintf(buf, "%hb", (unsigned short) 12);
|
||||
assert(!strcmp(buf, "1100"));
|
||||
sprintf(buf, "%hhb", (unsigned char) 12);
|
||||
assert(!strcmp(buf, "1100"));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// Test %n$ syntax.
|
||||
sprintf(buf, "%1$d", 12);
|
||||
assert(!strcmp(buf, "12"));
|
||||
sprintf(buf, "%1$d %1$d", 12);
|
||||
assert(!strcmp(buf, "12 12"));
|
||||
sprintf(buf, "%1$d %2$d %1$d", 12, 14);
|
||||
assert(!strcmp(buf, "12 14 12"));
|
||||
sprintf(buf, "%1$d %2$s %2$s", 12, "foo");
|
||||
assert(!strcmp(buf, "12 foo foo"));
|
||||
|
||||
sprintf(buf, "%1$s%5$s%6$s%3$s%4$s%2$s", "a", "b", "u", "n", "h", "N");
|
||||
assert(!strcmp(buf, "ahNunb"));
|
||||
|
||||
// test negative precision
|
||||
sprintf(buf, "%.*g", -2, 15.1234567);
|
||||
assert(!strcmp(buf, "15.1235"));
|
||||
sprintf(buf, "%*g", -5, 15.1);
|
||||
assert(!strcmp(buf, "15.1 "));
|
||||
// Disable -Wformat as the compiler rightfully warns that the '0' flag is ignored
|
||||
// when the '0' flag is used
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
sprintf(buf, "%0-6g", 69.2);
|
||||
assert(!strcmp(buf, "69.2 "));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// More extensive floating point tests.
|
||||
// Test zero and negative zero
|
||||
sprintf(buf, "%f", 0.0);
|
||||
assert(!strcmp(buf, "0.000000"));
|
||||
sprintf(buf, "%f", -0.0);
|
||||
assert(!strcmp(buf, "-0.000000"));
|
||||
sprintf(buf, "%e", 0.0);
|
||||
assert(!strcmp(buf, "0.000000e+00"));
|
||||
sprintf(buf, "%e", -0.0);
|
||||
assert(!strcmp(buf, "-0.000000e+00"));
|
||||
sprintf(buf, "%g", 0.0);
|
||||
assert(!strcmp(buf, "0"));
|
||||
sprintf(buf, "%g", -0.0);
|
||||
assert(!strcmp(buf, "-0"));
|
||||
|
||||
// Test rounding
|
||||
sprintf(buf, "%.2f", 1.235);
|
||||
assert(!strcmp(buf, "1.24"));
|
||||
sprintf(buf, "%.2f", -1.235);
|
||||
assert(!strcmp(buf, "-1.24"));
|
||||
// 1.2349999999999998 is a double literal that is slightly less than 1.235
|
||||
sprintf(buf, "%.2f", 1.2349999999999998);
|
||||
assert(!strcmp(buf, "1.23"));
|
||||
sprintf(buf, "%.0f", 0.49);
|
||||
assert(!strcmp(buf, "0"));
|
||||
sprintf(buf, "%.0f", -0.49);
|
||||
assert(!strcmp(buf, "-0"));
|
||||
|
||||
// Test round-to-even behavior
|
||||
fesetround(FE_TONEAREST);
|
||||
|
||||
sprintf(buf, "%.0f", 0.5);
|
||||
assert(!strcmp(buf, "0"));
|
||||
sprintf(buf, "%.0f", -0.5);
|
||||
assert(!strcmp(buf, "-0"));
|
||||
sprintf(buf, "%.0f", 0.51);
|
||||
assert(!strcmp(buf, "1"));
|
||||
sprintf(buf, "%.0f", -0.51);
|
||||
assert(!strcmp(buf, "-1"));
|
||||
sprintf(buf, "%.0f", 2.5);
|
||||
assert(!strcmp(buf, "2"));
|
||||
sprintf(buf, "%.0f", -2.5);
|
||||
assert(!strcmp(buf, "-2"));
|
||||
sprintf(buf, "%.0f", 2.51);
|
||||
assert(!strcmp(buf, "3"));
|
||||
sprintf(buf, "%.0f", -2.51);
|
||||
assert(!strcmp(buf, "-3"));
|
||||
|
||||
// Test %e/%E
|
||||
sprintf(buf, "%.3e", 12345.0);
|
||||
assert(!strcmp(buf, "1.234e+04"));
|
||||
sprintf(buf, "%.3E", 12345.0);
|
||||
assert(!strcmp(buf, "1.234E+04"));
|
||||
sprintf(buf, "%.3e", 0.00012345);
|
||||
assert(!strcmp(buf, "1.234e-04"));
|
||||
sprintf(buf, "%.3E", -0.00012345);
|
||||
assert(!strcmp(buf, "-1.234E-04"));
|
||||
|
||||
// Test %g/%G behavior
|
||||
sprintf(buf, "%g", 123456.0); // Should not use e-notation
|
||||
assert(!strcmp(buf, "123456"));
|
||||
sprintf(buf, "%g", 1234567.0); // Should use e-notation
|
||||
assert(!strcmp(buf, "1.23457e+06"));
|
||||
sprintf(buf, "%g", 12345.0);
|
||||
assert(!strcmp(buf, "12345"));
|
||||
sprintf(buf, "%g", 1.2345);
|
||||
assert(!strcmp(buf, "1.2345"));
|
||||
sprintf(buf, "%g", 0.00012345); // Should not use e-notation
|
||||
assert(!strcmp(buf, "0.00012345"));
|
||||
sprintf(buf, "%g", 0.000012345); // Should use e-notation
|
||||
assert(!strcmp(buf, "1.2345e-05"));
|
||||
|
||||
// %g precision
|
||||
sprintf(buf, "%.3g", 12345.0);
|
||||
assert(!strcmp(buf, "1.23e+04"));
|
||||
sprintf(buf, "%.3G", 12345.0);
|
||||
assert(!strcmp(buf, "1.23E+04"));
|
||||
sprintf(buf, "%.3g", 1.234);
|
||||
assert(!strcmp(buf, "1.23"));
|
||||
sprintf(buf, "%.3g", 0.001234);
|
||||
assert(!strcmp(buf, "0.00123"));
|
||||
sprintf(buf, "%.3g", 0.0001234); // Should not use e-notation
|
||||
assert(!strcmp(buf, "0.000123"));
|
||||
sprintf(buf, "%.3g", 0.00001234); // Should use e-notation
|
||||
assert(!strcmp(buf, "1.23e-05"));
|
||||
sprintf(buf, "%08.1g", 69.2);
|
||||
assert(!strcmp(buf, "0007e+01"));
|
||||
sprintf(buf, "%#08.4g", 69.29854);
|
||||
assert(!strcmp(buf, "00069.30"));
|
||||
|
||||
// %g trailing zeros
|
||||
sprintf(buf, "%g", 1.200);
|
||||
assert(!strcmp(buf, "1.2"));
|
||||
sprintf(buf, "%#g", 1.200);
|
||||
assert(!strcmp(buf, "1.20000"));
|
||||
sprintf(buf, "%g", 1200.0);
|
||||
assert(!strcmp(buf, "1200"));
|
||||
sprintf(buf, "%#g", 1200.0);
|
||||
assert(!strcmp(buf, "1200.00"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <wchar.h>
|
||||
|
||||
struct format_test_cases {
|
||||
const char *format;
|
||||
const char *data;
|
||||
int expected_int;
|
||||
enum {
|
||||
T_INT,
|
||||
T_UINT,
|
||||
T_CHAR,
|
||||
T_NONE,
|
||||
} type;
|
||||
int ret;
|
||||
} formats[] = {
|
||||
{"%i", "0x420", 0x420, T_INT, 1},
|
||||
{"%i", "0420", 0420, T_INT, 1},
|
||||
{"%i", "420", 420, T_INT, 1},
|
||||
{"%i", "-420", -420, T_INT, 1},
|
||||
{"%d", "-12345", -12345, T_INT, 1},
|
||||
{"%u", "69", 69, T_UINT, 1},
|
||||
{"%u", "0420", 420, T_UINT, 1},
|
||||
{"%o", "0420", 0420, T_UINT, 1},
|
||||
{"%x", "0xCB7", 0xCB7, T_UINT, 1},
|
||||
#ifndef USE_HOST_LIBC
|
||||
{"%b", "0b1011", 0b1011, T_UINT, 1},
|
||||
{"%b", "0B1011", 0b1011, T_UINT, 1},
|
||||
#endif
|
||||
{"%%", "%", 0, T_NONE, 0},
|
||||
{"%c", " I am not a fan of this solution.", ' ', T_CHAR, 1},
|
||||
{" %c", " CBT (capybara therapy)", 'C', T_CHAR, 1},
|
||||
{"%d %d %d", " 111111 I<3Managarm 1234", 111111, T_UINT, 1},
|
||||
{"%c %d", "C", 'C', T_CHAR, 1}
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wformat-security"
|
||||
|
||||
static void test_matrix() {
|
||||
for(size_t i = 0; i < (sizeof(formats) / sizeof(*formats)); i++) {
|
||||
struct format_test_cases *f = &formats[i];
|
||||
int ret = -1;
|
||||
int data_int;
|
||||
unsigned int data_uint;
|
||||
char data_char;
|
||||
|
||||
switch(f->type) {
|
||||
case T_INT: {
|
||||
ret = sscanf(f->data, f->format, &data_int);
|
||||
assert(data_int == f->expected_int);
|
||||
break;
|
||||
}
|
||||
case T_UINT: {
|
||||
ret = sscanf(f->data, f->format, &data_uint);
|
||||
assert(data_uint == (unsigned int) f->expected_int);
|
||||
break;
|
||||
}
|
||||
case T_CHAR: {
|
||||
ret = sscanf(f->data, f->format, &data_char);
|
||||
assert(data_char == (unsigned char) f->expected_int);
|
||||
break;
|
||||
}
|
||||
case T_NONE: {
|
||||
ret = sscanf(f->data, f->format);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
assert(ret == f->ret);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
{
|
||||
int x = 0;
|
||||
char buf[] = "12345";
|
||||
sscanf(buf, "%d", &x);
|
||||
assert(x == 12345);
|
||||
}
|
||||
|
||||
{
|
||||
char c;
|
||||
int n1;
|
||||
int n2;
|
||||
char buf[] = "z$ 7 5 440";;
|
||||
int count = sscanf(buf, "%*c%c %d %*d %d", &c, &n1, &n2);
|
||||
assert(count == 3);
|
||||
assert(c == '$');
|
||||
assert(n1 == 7);
|
||||
assert(n2 == 440);
|
||||
}
|
||||
|
||||
{
|
||||
// From dsda-doom
|
||||
char buf[] = "process_priority 0\n";
|
||||
char def[80], strparm[128];
|
||||
memset(def, '!', 80);
|
||||
memset(strparm, '!', 128);
|
||||
sscanf(buf, "%s %[^\n]\n", def, strparm);
|
||||
assert(!strcmp(def, "process_priority"));
|
||||
assert(!strcmp(strparm, "0"));
|
||||
}
|
||||
|
||||
{
|
||||
char buf[] = "fffff100";
|
||||
unsigned long y = 0;
|
||||
sscanf(buf, "%lx", &y);
|
||||
assert(y == 0xfffff100);
|
||||
}
|
||||
|
||||
#if !defined(__i386__) && !defined(__m68k__)
|
||||
{
|
||||
char buf[] = "fffffffff100";
|
||||
unsigned long y = 0;
|
||||
sscanf(buf, "%lx", &y);
|
||||
assert(y == 0xfffffffff100);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
char buf[] = "410dc000";
|
||||
unsigned long y = 0;
|
||||
sscanf(buf, "%lx", &y);
|
||||
assert(y == 0x410dc000);
|
||||
}
|
||||
|
||||
{
|
||||
// From webkitgtk
|
||||
char buf[] = "MemTotal: 16299664 kB\n";
|
||||
char token[51] = {0};
|
||||
size_t amount = 0;
|
||||
int ret = sscanf(buf, "%50s%zukB", token, &amount);
|
||||
assert(ret == 2);
|
||||
assert(!strcmp(token, "MemTotal:"));
|
||||
assert(amount == 16299664);
|
||||
}
|
||||
|
||||
{
|
||||
char buf[] = "SIGINT";
|
||||
int sig;
|
||||
int ret = sscanf(buf, "%d", &sig);
|
||||
assert(!ret);
|
||||
}
|
||||
|
||||
{
|
||||
char buf[50];
|
||||
int ret = sscanf("", "%s", buf);
|
||||
assert(ret == EOF);
|
||||
}
|
||||
|
||||
{
|
||||
char *str = NULL;
|
||||
int ret = sscanf("Managarm", "%ms", &str);
|
||||
assert(ret == 1);
|
||||
assert(str != NULL);
|
||||
assert(!strcmp(str, "Managarm"));
|
||||
free(str);
|
||||
}
|
||||
|
||||
test_matrix();
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-zero-length"
|
||||
assert(sscanf("", "") == 0);
|
||||
#pragma GCC diagnostic pop
|
||||
assert(sscanf("", "a") == EOF);
|
||||
assert(sscanf(" \t\na", " a") == 0);
|
||||
assert(sscanf("a%", "a%%") == 0);
|
||||
assert(sscanf("ab", "abcd") == EOF);
|
||||
assert(sscanf("abab", "abcd") == 0);
|
||||
|
||||
char char_value[8];
|
||||
wchar_t wchar_value[8];
|
||||
|
||||
assert(sscanf("a", "%c", char_value) == 1);
|
||||
assert(char_value[0] == 'a');
|
||||
assert(sscanf("a", "%lc", wchar_value) == 1);
|
||||
assert(wchar_value[0] == L'a');
|
||||
assert(sscanf("hello", "%s", char_value) == 1);
|
||||
assert(strcmp(char_value, "hello") == 0);
|
||||
assert(sscanf("", "%s", char_value) == EOF);
|
||||
assert(sscanf(" ", "%s", char_value) == EOF);
|
||||
assert(sscanf(" a", "%sb", char_value) == 1);
|
||||
assert(sscanf("hello", "%ls", wchar_value) == 1);
|
||||
assert(wcscmp(wchar_value, L"hello") == 0);
|
||||
assert(sscanf("abcd", "%[ac]bcd", char_value) == 1);
|
||||
assert(strcmp(char_value, "a") == 0);
|
||||
assert(sscanf("abcd", "%l[ac]bcd", wchar_value) == 1);
|
||||
assert(wcscmp(wchar_value, L"a") == 0);
|
||||
assert(sscanf("aacd", "%[ac]bcd", char_value) == 1);
|
||||
assert(strcmp(char_value, "aac") == 0);
|
||||
assert(sscanf("aacd", "%[ac]bcd", char_value) == 1);
|
||||
assert(strcmp(char_value, "aac") == 0);
|
||||
assert(sscanf("]", "%[]]", char_value) == 1);
|
||||
assert(strcmp(char_value, "]") == 0);
|
||||
assert(sscanf("]", "%[^]]", char_value) == 0);
|
||||
assert(sscanf("abcd", "%[^ac]bcd", char_value) == 0);
|
||||
assert(sscanf("aacd", "%[^ac]bcd", char_value) == 0);
|
||||
assert(sscanf("aacd", "%[^ac]bcd", char_value) == 0);
|
||||
assert(sscanf("ddd", "%[^ac]bcd", char_value) == 1);
|
||||
assert(strcmp(char_value, "ddd") == 0);
|
||||
assert(sscanf("abcd", "%[0-9]", char_value) == 0);
|
||||
assert(sscanf("2a", "%[0-9]", char_value) == 1);
|
||||
assert(strcmp(char_value, "2") == 0);
|
||||
|
||||
unsigned char uchar_value;
|
||||
signed char schar_value;
|
||||
unsigned short ushort_value;
|
||||
short short_value;
|
||||
unsigned int uint_value;
|
||||
int int_value;
|
||||
unsigned long ulong_value;
|
||||
long long_value;
|
||||
unsigned long long ulonglong_value;
|
||||
long long longlong_value;
|
||||
uintmax_t uintmax_value;
|
||||
intmax_t intmax_value;
|
||||
size_t size_value;
|
||||
ptrdiff_t ptrdiff_value;
|
||||
|
||||
assert(sscanf("1234abc", "%d", &int_value) == 1);
|
||||
assert(int_value == 1234);
|
||||
assert(sscanf("123", "%hhd", &schar_value) == 1);
|
||||
assert(schar_value == 123);
|
||||
assert(sscanf("1234", "%hd", &short_value) == 1);
|
||||
assert(short_value == 1234);
|
||||
assert(sscanf("1234", "%ld", &long_value) == 1);
|
||||
assert(long_value == 1234);
|
||||
assert(sscanf("1234", "%lld", &longlong_value) == 1);
|
||||
assert(longlong_value == 1234);
|
||||
assert(sscanf("1234", "%jd", &intmax_value) == 1);
|
||||
assert(intmax_value == 1234);
|
||||
assert(sscanf("1234", "%zd", &size_value) == 1);
|
||||
assert(size_value == 1234);
|
||||
assert(sscanf("1234", "%td", &ptrdiff_value) == 1);
|
||||
assert(ptrdiff_value == 1234);
|
||||
assert(sscanf(" 1235abc", "%d", &int_value) == 1);
|
||||
assert(int_value == 1235);
|
||||
assert(sscanf("+1234abc", "%d", &int_value) == 1);
|
||||
assert(int_value == 1234);
|
||||
assert(sscanf("-1234abc", "%d", &int_value) == 1);
|
||||
assert(int_value == -1234);
|
||||
assert(sscanf("-abc", "%d", &int_value) == 0);
|
||||
assert(sscanf("-", "%d", &int_value) == 0);
|
||||
|
||||
assert(sscanf("1234abc", "%i", &int_value) == 1);
|
||||
assert(int_value == 1234);
|
||||
assert(sscanf("123", "%hhi", &schar_value) == 1);
|
||||
assert(schar_value == 123);
|
||||
assert(sscanf("1234", "%hi", &short_value) == 1);
|
||||
assert(short_value == 1234);
|
||||
assert(sscanf("1234", "%li", &long_value) == 1);
|
||||
assert(long_value == 1234);
|
||||
assert(sscanf("1234", "%lli", &longlong_value) == 1);
|
||||
assert(longlong_value == 1234);
|
||||
assert(sscanf("1234", "%ji", &intmax_value) == 1);
|
||||
assert(intmax_value == 1234);
|
||||
assert(sscanf("1234", "%zi", &size_value) == 1);
|
||||
assert(size_value == 1234);
|
||||
assert(sscanf("1234", "%ti", &ptrdiff_value) == 1);
|
||||
assert(ptrdiff_value == 1234);
|
||||
assert(sscanf(" 1235abc", "%i", &int_value) == 1);
|
||||
assert(int_value == 1235);
|
||||
assert(sscanf("+1234abc", "%i", &int_value) == 1);
|
||||
assert(int_value == 1234);
|
||||
assert(sscanf("-1234abc", "%i", &int_value) == 1);
|
||||
assert(int_value == -1234);
|
||||
assert(sscanf("-abc", "%i", &int_value) == 0);
|
||||
|
||||
assert(sscanf(" 0b1011", "%i", &int_value) == 1);
|
||||
assert(int_value == 0b1011);
|
||||
assert(sscanf(" 0B1010", "%i", &int_value) == 1);
|
||||
assert(int_value == 0b1010);
|
||||
assert(sscanf(" +0b1011", "%i", &int_value) == 1);
|
||||
assert(int_value == 0b1011);
|
||||
assert(sscanf(" -0b1111", "%i", &int_value) == 1);
|
||||
assert(int_value == -0b1111);
|
||||
|
||||
assert(sscanf(" 01234", "%i", &int_value) == 1);
|
||||
assert(int_value == 01234);
|
||||
assert(sscanf(" +01234", "%i", &int_value) == 1);
|
||||
assert(int_value == 01234);
|
||||
assert(sscanf(" -01234", "%i", &int_value) == 1);
|
||||
assert(int_value == -01234);
|
||||
|
||||
assert(sscanf(" 0xab12", "%i", &int_value) == 1);
|
||||
assert(int_value == 0xAB12);
|
||||
assert(sscanf(" 0xAB12", "%i", &int_value) == 1);
|
||||
assert(int_value == 0xAB12);
|
||||
assert(sscanf(" 0Xab12", "%i", &int_value) == 1);
|
||||
assert(int_value == 0xAB12);
|
||||
assert(sscanf(" +0xab12", "%i", &int_value) == 1);
|
||||
assert(int_value == 0xAB12);
|
||||
assert(sscanf(" -0xab12", "%i", &int_value) == 1);
|
||||
assert(int_value == -0xAB12);
|
||||
|
||||
assert(sscanf("1234abc", "%u", &uint_value) == 1);
|
||||
assert(uint_value == 1234);
|
||||
assert(sscanf("123", "%hhu", &uchar_value) == 1);
|
||||
assert(uchar_value == 123);
|
||||
assert(sscanf("1234", "%hu", &ushort_value) == 1);
|
||||
assert(ushort_value == 1234);
|
||||
assert(sscanf("1234", "%lu", &ulong_value) == 1);
|
||||
assert(ulong_value == 1234);
|
||||
assert(sscanf("1234", "%llu", &ulonglong_value) == 1);
|
||||
assert(ulonglong_value == 1234);
|
||||
assert(sscanf("1234", "%ju", &uintmax_value) == 1);
|
||||
assert(uintmax_value == 1234);
|
||||
assert(sscanf("1234", "%zu", &size_value) == 1);
|
||||
assert(size_value == 1234);
|
||||
assert(sscanf("1234", "%tu", &ptrdiff_value) == 1);
|
||||
assert(ptrdiff_value == 1234);
|
||||
assert(sscanf(" 1235abc", "%u", &int_value) == 1);
|
||||
assert(int_value == 1235);
|
||||
assert(sscanf("+1234abc", "%u", &int_value) == 1);
|
||||
assert(int_value == 1234);
|
||||
assert(sscanf("-1234abc", "%u", &int_value) == 1);
|
||||
assert(int_value == -1234);
|
||||
assert(sscanf("-abc", "%d", &int_value) == 0);
|
||||
|
||||
assert(sscanf(" 12345", "%o", &int_value) == 1);
|
||||
assert(int_value == 012345);
|
||||
assert(sscanf("12", "%hho", &uchar_value) == 1);
|
||||
assert(uchar_value == 012);
|
||||
assert(sscanf("1234", "%ho", &ushort_value) == 1);
|
||||
assert(ushort_value == 01234);
|
||||
assert(sscanf("1234", "%lo", &ulong_value) == 1);
|
||||
assert(ulong_value == 01234);
|
||||
assert(sscanf("1234", "%llo", &ulonglong_value) == 1);
|
||||
assert(ulonglong_value == 01234);
|
||||
assert(sscanf("1234", "%jo", &uintmax_value) == 1);
|
||||
assert(uintmax_value == 01234);
|
||||
assert(sscanf("1234", "%zo", &size_value) == 1);
|
||||
assert(size_value == 01234);
|
||||
assert(sscanf("1234", "%to", &ptrdiff_value) == 1);
|
||||
assert(ptrdiff_value == 01234);
|
||||
assert(sscanf(" 01234", "%o", &int_value) == 1);
|
||||
assert(int_value == 01234);
|
||||
assert(sscanf(" +01234", "%o", &int_value) == 1);
|
||||
assert(int_value == 01234);
|
||||
assert(sscanf(" -01234", "%o", &int_value) == 1);
|
||||
assert(int_value == -01234);
|
||||
|
||||
assert(sscanf(" 1234ab", "%x", &int_value) == 1);
|
||||
assert(int_value == 0x1234AB);
|
||||
assert(sscanf("12", "%hhx", &uchar_value) == 1);
|
||||
assert(uchar_value == 0x12);
|
||||
assert(sscanf("1234", "%hx", &ushort_value) == 1);
|
||||
assert(ushort_value == 0x1234);
|
||||
assert(sscanf("1234", "%lx", &ulong_value) == 1);
|
||||
assert(ulong_value == 0x1234);
|
||||
assert(sscanf("1234", "%llx", &ulonglong_value) == 1);
|
||||
assert(ulonglong_value == 0x1234);
|
||||
assert(sscanf("1234", "%jx", &uintmax_value) == 1);
|
||||
assert(uintmax_value == 0x1234);
|
||||
assert(sscanf("1234", "%zx", &size_value) == 1);
|
||||
assert(size_value == 0x1234);
|
||||
assert(sscanf("1234", "%tx", &ptrdiff_value) == 1);
|
||||
assert(ptrdiff_value == 0x1234);
|
||||
assert(sscanf(" 1234ABC", "%x", &int_value) == 1);
|
||||
assert(int_value == 0x1234ABC);
|
||||
assert(sscanf(" 1234ab", "%X", &int_value) == 1);
|
||||
assert(int_value == 0x1234AB);
|
||||
assert(sscanf(" 0x1234", "%x", &int_value) == 1);
|
||||
assert(int_value == 0x1234);
|
||||
assert(sscanf(" 0x1234A", "%x", &int_value) == 1);
|
||||
assert(int_value == 0x1234A);
|
||||
assert(sscanf(" 0X1234AB", "%x", &int_value) == 1);
|
||||
assert(int_value == 0x1234AB);
|
||||
assert(sscanf(" +0x1234", "%x", &int_value) == 1);
|
||||
assert(int_value == 0x1234);
|
||||
assert(sscanf(" -0x1234", "%x", &int_value) == 1);
|
||||
assert(int_value == -0x1234);
|
||||
|
||||
assert(sscanf("abc", "abc%n", &int_value) == 0);
|
||||
assert(int_value == 3);
|
||||
assert(sscanf("1234", "1234%hhn", &uchar_value) == 0);
|
||||
assert(uchar_value == 4);
|
||||
assert(sscanf("1234", "1234%hn", &ushort_value) == 0);
|
||||
assert(ushort_value == 4);
|
||||
assert(sscanf("1234", "1234%ln", &ulong_value) == 0);
|
||||
assert(ulong_value == 4);
|
||||
assert(sscanf("1234", "1234%lln", &ulonglong_value) == 0);
|
||||
assert(ulonglong_value == 4);
|
||||
assert(sscanf("1234", "1234%jn", &uintmax_value) == 0);
|
||||
assert(uintmax_value == 4);
|
||||
assert(sscanf("1234", "1234%zn", &size_value) == 0);
|
||||
assert(size_value == 4);
|
||||
assert(sscanf("1234", "1234%tn", &ptrdiff_value) == 0);
|
||||
assert(ptrdiff_value == 4);
|
||||
assert(sscanf("abcd", "ab%nc%c", &int_value, char_value) == 1);
|
||||
assert(int_value == 2);
|
||||
assert(char_value[0] == 'd');
|
||||
|
||||
float float_value;
|
||||
double double_value;
|
||||
long double long_double_value;
|
||||
(void)float_value;
|
||||
(void)double_value;
|
||||
(void)long_double_value;
|
||||
/*assert(sscanf("1.123", "%a", &float_value) == 1);
|
||||
assert(float_value >= 1.123f - 0.01 && float_value <= 1.123f + 0.01);
|
||||
assert(sscanf("1.123", "%la", &double_value) == 1);
|
||||
assert(double_value >= 1.123 - 0.01 && double_value <= 1.123 + 0.01);
|
||||
assert(sscanf("1.123", "%La", &long_double_value) == 1);
|
||||
assert(long_double_value >= 1.123L - 0.01 && long_double_value <= 1.123L + 0.01);
|
||||
assert(sscanf("1.1234", "%A", &float_value) == 1);
|
||||
assert(float_value >= 1.1234f - 0.01 && float_value <= 1.1234f + 0.01);
|
||||
assert(sscanf("1.123", "%e", &float_value) == 1);
|
||||
assert(float_value >= 1.123f - 0.01 && float_value <= 1.123f + 0.01);
|
||||
assert(sscanf("1.123", "%le", &double_value) == 1);
|
||||
assert(double_value >= 1.123 - 0.01 && double_value <= 1.123 + 0.01);
|
||||
assert(sscanf("1.123", "%Le", &long_double_value) == 1);
|
||||
assert(long_double_value >= 1.123L - 0.01 && long_double_value <= 1.123L + 0.01);
|
||||
assert(sscanf("1.1234", "%E", &float_value) == 1);
|
||||
assert(float_value >= 1.1234f - 0.01 && float_value <= 1.1234f + 0.01);
|
||||
assert(sscanf("1.123", "%f", &float_value) == 1);
|
||||
assert(float_value >= 1.123f - 0.01 && float_value <= 1.123f + 0.01);
|
||||
assert(sscanf("1.123", "%lf", &double_value) == 1);
|
||||
assert(double_value >= 1.123 - 0.01 && double_value <= 1.123 + 0.01);
|
||||
assert(sscanf("1.123", "%Lf", &long_double_value) == 1);
|
||||
assert(long_double_value >= 1.123L - 0.01 && long_double_value <= 1.123L + 0.01);
|
||||
assert(sscanf("1.1234", "%F", &float_value) == 1);
|
||||
assert(float_value >= 1.1234f - 0.01 && float_value <= 1.1234f + 0.01);
|
||||
assert(sscanf("1.123", "%g", &float_value) == 1);
|
||||
assert(float_value >= 1.123f - 0.01 && float_value <= 1.123f + 0.01);
|
||||
assert(sscanf("1.123", "%lg", &double_value) == 1);
|
||||
assert(double_value >= 1.123 - 0.01 && double_value <= 1.123 + 0.01);
|
||||
assert(sscanf("1.123", "%Lg", &long_double_value) == 1);
|
||||
assert(long_double_value >= 1.123L - 0.01 && long_double_value <= 1.123L + 0.01);
|
||||
assert(sscanf("1.1234", "%G", &float_value) == 1);
|
||||
assert(float_value >= 1.1234f - 0.01 && float_value <= 1.1234f + 0.01);
|
||||
assert(sscanf("+1.1234", "%f", &float_value) == 1);
|
||||
assert(float_value >= 1.1234f - 0.01 && float_value <= 1.1234f + 0.01);
|
||||
assert(sscanf("-1.1234", "%f", &float_value) == 1);
|
||||
assert(float_value >= -1.1234f - 0.01 && float_value <= -1.1234f + 0.01);
|
||||
assert(sscanf("1.1234e3", "%f", &float_value) == 1);
|
||||
assert(float_value >= 1.1234E3f - 0.01 && float_value <= 1.1234E3f + 0.01);
|
||||
assert(sscanf("1.1234E3", "%f", &float_value) == 1);
|
||||
assert(float_value >= 1.1234E3f - 0.01 && float_value <= 1.1234E3f + 0.01);
|
||||
assert(sscanf("0x1234", "%f", &float_value) == 1);
|
||||
assert(float_value >= 0x1234P0f - 0.01 && float_value <= 0x1234P0f + 0.01);
|
||||
assert(sscanf("0X1234", "%f", &float_value) == 1);
|
||||
assert(float_value >= 0x1234P0f - 0.01 && float_value <= 0x1234P0f + 0.01);
|
||||
assert(sscanf("0x1.1234", "%f", &float_value) == 1);
|
||||
assert(float_value >= 0x1.1234P0 - 0.01 && float_value <= 0x1.1234P0 + 0.01);
|
||||
assert(sscanf("0x1.abcdP3", "%f", &float_value) == 1);
|
||||
assert(float_value >= 0x1.ABCDP3 - 0.01 && float_value <= 0x1.ABCDP3 + 0.01);
|
||||
assert(sscanf("0x1.abcdP+3", "%f", &float_value) == 1);
|
||||
assert(float_value >= 0x1.ABCDP3 - 0.01 && float_value <= 0x1.ABCDP3 + 0.01);
|
||||
assert(sscanf("0x1.abcdP-3", "%f", &float_value) == 1);
|
||||
assert(float_value >= 0x1.ABCDP-3 - 0.01 && float_value <= 0x1.ABCDP-3 + 0.01);
|
||||
assert(sscanf("0x1.AbCdP-3", "%f", &float_value) == 1);
|
||||
assert(float_value >= 0x1.ABCDP-3 - 0.01 && float_value <= 0x1.ABCDP-3 + 0.01);
|
||||
assert(sscanf("inf", "%f", &float_value) == 1);
|
||||
assert(isinf(float_value));
|
||||
assert(sscanf("InF", "%f", &float_value) == 1);
|
||||
assert(isinf(float_value));
|
||||
assert(sscanf("+inf", "%f", &float_value) == 1);
|
||||
assert(isinf(float_value));
|
||||
assert(sscanf("-inf", "%f", &float_value) == 1);
|
||||
assert(isinf(float_value));
|
||||
assert(sscanf("INF", "%f", &float_value) == 1);
|
||||
assert(isinf(float_value));
|
||||
assert(sscanf("infinity", "%f", &float_value) == 1);
|
||||
assert(isinf(float_value));
|
||||
assert(sscanf("INFINITY", "%f", &float_value) == 1);
|
||||
assert(isinf(float_value));
|
||||
assert(sscanf("nan", "%f", &float_value) == 1);
|
||||
assert(isnan(float_value));
|
||||
assert(sscanf("NaN", "%f", &float_value) == 1);
|
||||
assert(isnan(float_value));
|
||||
assert(sscanf("+nan", "%f", &float_value) == 1);
|
||||
assert(isnan(float_value));
|
||||
assert(sscanf("-nan", "%f", &float_value) == 1);
|
||||
assert(isnan(float_value));
|
||||
assert(sscanf("0xhello", "%f", &float_value) == 0);
|
||||
assert(sscanf("0x1hello", "%f", &float_value) == 1);
|
||||
assert(float_value >= 0x1P0f - 0.01 && float_value <= 0x1P0f + 0.01);
|
||||
assert(sscanf("ab1.1234", "%f", &float_value) == 0);
|
||||
assert(sscanf(" 1.123", "%f", &float_value) == 1);
|
||||
assert(float_value >= 1.123f - 0.01 && float_value <= 1.123f + 0.01);*/
|
||||
|
||||
void* ptr;
|
||||
assert(sscanf("hello", "%p", &ptr) == 0);
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
assert(sscanf("0xabcdef12abcdef12", "%p", &ptr) == 1);
|
||||
assert(ptr == (void*)0xabcdef12abcdef12);
|
||||
#else
|
||||
assert(sscanf("0xabcdef12", "%p", &ptr) == 1);
|
||||
assert(ptr == (void*)0xabcdef12);
|
||||
#endif
|
||||
|
||||
assert(sscanf("a", "%*c") == 0);
|
||||
char_value[2] = 'q';
|
||||
assert(sscanf("abcd", "%2c", char_value) == 1);
|
||||
assert(char_value[2] == 'q');
|
||||
char_value[2] = 0;
|
||||
assert(strcmp(char_value, "ab") == 0);
|
||||
|
||||
assert(sscanf("cdef", "%2s", char_value) == 1);
|
||||
assert(strcmp(char_value, "cd") == 0);
|
||||
assert(sscanf("c def", "%2s", char_value) == 1);
|
||||
assert(strcmp(char_value, "c") == 0);
|
||||
|
||||
assert(sscanf("aacd", "%2[ac]", char_value) == 1);
|
||||
assert(strcmp(char_value, "aa") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int main() {
|
||||
char str[] = "This is a sample string";
|
||||
char *pch;
|
||||
// The character 's' is at position 4, 7, 11 and 18
|
||||
pch = strchr(str, 's');
|
||||
assert(pch - str + 1 == 4);
|
||||
pch = strchr(pch + 1, 's');
|
||||
assert(pch - str + 1 == 7);
|
||||
pch = strchr(pch + 1, 's');
|
||||
assert(pch - str + 1 == 11);
|
||||
pch = strchr(pch + 1, 's');
|
||||
assert(pch - str + 1 == 18);
|
||||
pch = strchr(pch + 1, 's');
|
||||
assert(pch == NULL);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
// Date representation depends on locale, here only C is tested.
|
||||
// Maybe consider testing more locales?
|
||||
if (setlocale (LC_ALL, "C") == NULL) {
|
||||
fputs("strftime testcase could not set locale, errors may be expected!", stderr);
|
||||
}
|
||||
|
||||
char timebuf[32];
|
||||
char result[32] = " 8";
|
||||
struct tm tm;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_min = 17;
|
||||
tm.tm_hour = 17;
|
||||
tm.tm_mday = 8;
|
||||
tm.tm_mon = 2;
|
||||
tm.tm_year = 121;
|
||||
tm.tm_wday = 2;
|
||||
tm.tm_yday = 39;
|
||||
tm.tm_gmtoff = 3600;
|
||||
strftime(timebuf, sizeof(timebuf), "%e", &tm);
|
||||
assert(!strcmp(timebuf, result));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%x", &tm);
|
||||
assert(!strcmp(timebuf, "03/08/21"));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%X", &tm);
|
||||
assert(!strcmp(timebuf, "17:17:00"));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%D", &tm);
|
||||
assert(!strcmp(timebuf, "03/08/21"));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%OB %Ob", &tm);
|
||||
assert(!strcmp(timebuf, "March Mar"));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%c", &tm);
|
||||
memset(result, 0, sizeof(result));
|
||||
strftime(result, sizeof(result), "%a %b %e %H:%M:%S %Y", &tm);
|
||||
assert(!strcmp(timebuf, result));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%k %p %P%n", &tm);
|
||||
assert(!strcmp(timebuf, "17 PM pm\n"));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%a %A", &tm);
|
||||
assert(!strcmp(timebuf, "Tue Tuesday"));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%b %B %h", &tm);
|
||||
assert(!strcmp(timebuf, "Mar March Mar"));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
assert(!strftime(timebuf, sizeof(timebuf), "%a %A %a %A %b %B %h", &tm));
|
||||
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
strftime(timebuf, sizeof(timebuf), "%z", &tm);
|
||||
assert(!strcmp(timebuf, "+0100"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
char str[] = "This is a sample string";
|
||||
char *pch;
|
||||
pch = strrchr(str, 's');
|
||||
// The last occurence of 's' is at position 18
|
||||
assert(pch - str + 1 == 18);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define FLT_RANGE 0.000001f
|
||||
#define DBL_RANGE 0.000001
|
||||
#define LDBL_RANGE 0.000001
|
||||
|
||||
#define DO_TEST(str, value, off, func, range) ({ \
|
||||
char s[] = (str); \
|
||||
char *pEnd = NULL; \
|
||||
__typeof(func(s, &pEnd)) result = func(s, &pEnd); \
|
||||
assert(result >= (value) - (range)); \
|
||||
assert(result <= (value) + (range)); \
|
||||
assert(pEnd == (off == -1 ? s + strlen(s) : s + off)); })
|
||||
|
||||
#define DO_TEST_SUCCESS_FUNC(str, success_func, off, func) ({ \
|
||||
char s[] = (str); \
|
||||
char *pEnd = NULL; \
|
||||
assert(success_func(func(s, &pEnd))); \
|
||||
assert(pEnd == (off == -1 ? s + strlen(s) : s + off)); })
|
||||
|
||||
int main () {
|
||||
DO_TEST("0", 0.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("0.12", 0.12f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("12", 12.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("12.13", 12.13f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("10.0e1", 100.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("10.0e10", 100000000000.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("100.0e-1", 10.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("0x0", 0.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("0x0.12", 0.0703125f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("0x12", 18.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("0x12.13", 18.07421875f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("0x10.0p1", 32.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("0x10.0p10", 16384.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST("0x100.0p-1", 128.0f, -1, strtof, FLT_RANGE);
|
||||
DO_TEST_SUCCESS_FUNC("NAN", isnan, -1, strtof);
|
||||
DO_TEST_SUCCESS_FUNC("nan", isnan, -1, strtof);
|
||||
DO_TEST_SUCCESS_FUNC("INF", isinf, -1, strtof);
|
||||
DO_TEST_SUCCESS_FUNC("INFINITY", isinf, -1, strtof);
|
||||
|
||||
DO_TEST("0", 0.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("0.12", 0.12, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("12", 12.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("12.13", 12.13, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("10.0e1", 100.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("10.0e10", 100000000000.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("100.0e-1", 10.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("0x0", 0.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("0x0.12", 0.0703125, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("0x12", 18.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("0x12.13", 18.07421875, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("0x10.0p1", 32.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("0x10.0p10", 16384.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST("0x100.0p-1", 128.0, -1, strtod, DBL_RANGE);
|
||||
DO_TEST_SUCCESS_FUNC("NAN", isnan, -1, strtod);
|
||||
DO_TEST_SUCCESS_FUNC("nan", isnan, -1, strtod);
|
||||
DO_TEST_SUCCESS_FUNC("INF", isinf, -1, strtod);
|
||||
DO_TEST_SUCCESS_FUNC("INFINITY", isinf, -1, strtod);
|
||||
|
||||
DO_TEST("0", 0.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("0.12", 0.12, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("12", 12.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("12.13", 12.13, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("10.0e1", 100.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("10.0e10", 100000000000.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("100.0e-1", 10.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("0x0", 0.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("0x0.12", 0.0703125, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("0x12", 18.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("0x12.13", 18.07421875, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("0x10.0p1", 32.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("0x10.0p10", 16384.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST("0x100.0p-1", 128.0, -1, strtold, LDBL_RANGE);
|
||||
DO_TEST_SUCCESS_FUNC("NAN", isnan, -1, strtold);
|
||||
DO_TEST_SUCCESS_FUNC("nan", isnan, -1, strtold);
|
||||
DO_TEST_SUCCESS_FUNC("INF", isinf, -1, strtold);
|
||||
DO_TEST_SUCCESS_FUNC("INFINITY", isinf, -1, strtold);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#define DO_TEST(str, value, off, func, base) ({ \
|
||||
char s[] = (str); \
|
||||
char *pEnd = NULL; \
|
||||
errno = 0; \
|
||||
assert(func(s, &pEnd, base) == (value)); \
|
||||
assert(errno == 0); \
|
||||
assert(pEnd == (off == -1 ? s + strlen(s) : s + off)); })
|
||||
|
||||
#define DO_ERR_TEST(str, value, err, func, base) ({ \
|
||||
char s[] = (str); \
|
||||
char *pEnd = NULL; \
|
||||
errno = 0; \
|
||||
assert(func(s, &pEnd, base) == (value)); \
|
||||
assert(errno == err); \
|
||||
assert(pEnd == (err == ERANGE ? s + strlen(s) : s)); })
|
||||
|
||||
#define DO_TESTL(str, value, off, func, base) ({ \
|
||||
wchar_t s[] = (str); \
|
||||
wchar_t *pEnd = NULL; \
|
||||
errno = 0; \
|
||||
assert(func(s, &pEnd, base) == (value)); \
|
||||
assert(errno == 0); \
|
||||
assert(pEnd == (off == -1 ? s + wcslen(s) : s + off)); })
|
||||
|
||||
#define DO_ERR_TESTL(str, value, err, func, base) ({ \
|
||||
wchar_t s[] = (str); \
|
||||
wchar_t *pEnd = NULL; \
|
||||
errno = 0; \
|
||||
assert(func(s, &pEnd, base) == (value)); \
|
||||
assert(errno == err); \
|
||||
assert(pEnd == (err == ERANGE ? s + wcslen(s) : s)); })
|
||||
|
||||
int main () {
|
||||
// A few generic checks.
|
||||
DO_TEST("0", 0, -1, strtol, 0);
|
||||
DO_TEST("0", 0, -1, strtol, 10);
|
||||
DO_TEST("2001", 2001, -1, strtol, 10);
|
||||
DO_TEST("+2001", 2001, -1, strtol, 10);
|
||||
DO_TEST("60c0c0", 0x60c0c0, -1, strtol, 16);
|
||||
DO_TEST("-1101110100110100100000", -3624224, -1, strtol, 2);
|
||||
DO_TEST("0x6fffff", 0x6fffff, -1, strtol, 0);
|
||||
DO_TEST("0666", 0666, -1, strtol, 0);
|
||||
#ifndef USE_HOST_LIBC
|
||||
DO_TEST("1100", 0b1100, -1, strtol, 2);
|
||||
DO_TEST("0b1100", 0b1100, -1, strtol, 0);
|
||||
DO_TEST("0B1100", 0b1100, -1, strtol, 0);
|
||||
DO_TEST("0b1zzz", 1, 3, strtol, 0);
|
||||
#endif
|
||||
DO_TEST("0xzzz", 0, 1, strtol, 0);
|
||||
DO_TEST("0yzzz", 0, 1, strtol, 0);
|
||||
DO_TEST("00xzz", 0, 2, strtol, 0);
|
||||
DO_ERR_TEST("", 0, 0, strtol, 10);
|
||||
DO_ERR_TEST("asd", 0, 0, strtol, 10);
|
||||
DO_ERR_TEST("999999999999999999999999999", LONG_MAX, ERANGE, strtol, 10);
|
||||
DO_ERR_TEST("-999999999999999999999999999", LONG_MIN, ERANGE, strtol, 10);
|
||||
|
||||
// strtol
|
||||
#if defined(__i386__) || defined(__m68k__)
|
||||
DO_TEST("-2147483648", LONG_MIN, -1, strtol, 10);
|
||||
DO_TEST("2147483647", LONG_MAX, -1, strtol, 10);
|
||||
DO_ERR_TEST("-2147483649", LONG_MIN, ERANGE, strtol, 10);
|
||||
DO_ERR_TEST("2147483648", LONG_MAX, ERANGE, strtol, 10);
|
||||
#else
|
||||
DO_TEST("-9223372036854775808", LONG_MIN, -1, strtol, 10);
|
||||
DO_TEST("9223372036854775807", LONG_MAX, -1, strtol, 10);
|
||||
DO_ERR_TEST("9223372036854775808", LONG_MAX, ERANGE, strtol, 10);
|
||||
DO_ERR_TEST("-9223372036854775809", LONG_MIN, ERANGE, strtol, 10);
|
||||
#endif
|
||||
|
||||
// wcstol
|
||||
#if defined(__i386__) || defined(__m68k__)
|
||||
DO_TESTL(L"-2147483648", LONG_MIN, -1, wcstol, 10);
|
||||
DO_TESTL(L"2147483647", LONG_MAX, -1, wcstol, 10);
|
||||
DO_ERR_TESTL(L"2147483648", LONG_MAX, ERANGE, wcstol, 10);
|
||||
DO_ERR_TESTL(L"-2147483649", LONG_MIN, ERANGE, wcstol, 10);
|
||||
#else
|
||||
DO_TESTL(L"-9223372036854775808", LONG_MIN, -1, wcstol, 10);
|
||||
DO_TESTL(L"9223372036854775807", LONG_MAX, -1, wcstol, 10);
|
||||
DO_ERR_TESTL(L"9223372036854775808", LONG_MAX, ERANGE, wcstol, 10);
|
||||
DO_ERR_TESTL(L"-9223372036854775809", LONG_MIN, ERANGE, wcstol, 10);
|
||||
#endif
|
||||
|
||||
// strtoll
|
||||
DO_TEST("-9223372036854775808", LLONG_MIN, -1, strtoll, 10);
|
||||
DO_TEST("9223372036854775807", LLONG_MAX, -1, strtoll, 10);
|
||||
DO_ERR_TEST("9223372036854775808", LLONG_MAX, ERANGE, strtoll, 10);
|
||||
DO_ERR_TEST("-9223372036854775809", LLONG_MIN, ERANGE, strtoll, 10);
|
||||
// wcstoll
|
||||
DO_TESTL(L"-9223372036854775808", LLONG_MIN, -1, wcstoll, 10);
|
||||
DO_TESTL(L"9223372036854775807", LLONG_MAX, -1, wcstoll, 10);
|
||||
DO_ERR_TESTL(L"9223372036854775808", LLONG_MAX, ERANGE, wcstoll, 10);
|
||||
DO_ERR_TESTL(L"-9223372036854775809", LLONG_MIN, ERANGE, wcstoll, 10);
|
||||
|
||||
// strtoul
|
||||
#if defined(__i386__) || defined(__m68k__)
|
||||
DO_TEST("-1", -(1UL), -1, strtoul, 10);
|
||||
DO_TEST("2147483647", LONG_MAX, -1, strtoul, 10);
|
||||
DO_TEST("4294967295", ULONG_MAX, -1, strtoul, 10);
|
||||
DO_TEST("-4294967295", 1UL, -1, strtoul, 10);
|
||||
DO_ERR_TEST("4294967296", ULONG_MAX, ERANGE, strtoul, 10);
|
||||
#else
|
||||
DO_TEST("-1", -(1UL), -1, strtoul, 10);
|
||||
DO_TEST("9223372036854775807", LONG_MAX, -1, strtoul, 10);
|
||||
DO_TEST("18446744073709551615", ULONG_MAX, -1, strtoul, 10);
|
||||
DO_TEST("-18446744073709551615", 1UL, -1, strtoul, 10);
|
||||
DO_ERR_TEST("18446744073709551616", ULONG_MAX, ERANGE, strtoul, 10);
|
||||
#endif
|
||||
|
||||
// wcstoul
|
||||
#if defined(__i386__) || defined(__m68k__)
|
||||
DO_TESTL(L"-1", -(1UL), -1, wcstoul, 10);
|
||||
DO_TESTL(L"2147483647", LONG_MAX, -1, wcstoul, 10);
|
||||
DO_TESTL(L"4294967295", ULONG_MAX, -1, wcstoul, 10);
|
||||
DO_TESTL(L"-4294967295", 1UL, -1, wcstoul, 10);
|
||||
DO_ERR_TESTL(L"4294967296", ULONG_MAX, ERANGE, wcstoul, 10);
|
||||
#else
|
||||
DO_TESTL(L"-1", -(1UL), -1, wcstoul, 10);
|
||||
DO_TESTL(L"9223372036854775807", LONG_MAX, -1, wcstoul, 10);
|
||||
DO_TESTL(L"18446744073709551615", ULONG_MAX, -1, wcstoul, 10);
|
||||
DO_TESTL(L"-18446744073709551615", 1UL, -1, wcstoul, 10);
|
||||
DO_ERR_TESTL(L"18446744073709551616", ULONG_MAX, ERANGE, wcstoul, 10);
|
||||
#endif
|
||||
|
||||
// strtoull
|
||||
DO_TEST("-1", -(1ULL), -1, strtoull, 10);
|
||||
DO_TEST("9223372036854775807", LLONG_MAX, -1, strtoull, 10);
|
||||
DO_TEST("18446744073709551615", ULLONG_MAX, -1, strtoull, 10);
|
||||
DO_TEST("-18446744073709551615", 1ULL, -1, strtoull, 10);
|
||||
DO_ERR_TEST("18446744073709551616", ULLONG_MAX, ERANGE, strtoull, 10);
|
||||
// wcstoull
|
||||
DO_TESTL(L"-1", -(1ULL), -1, wcstoull, 10);
|
||||
DO_TESTL(L"9223372036854775807", LLONG_MAX, -1, wcstoull, 10);
|
||||
DO_TESTL(L"18446744073709551615", ULLONG_MAX, -1, wcstoull, 10);
|
||||
DO_TESTL(L"-18446744073709551615", 1ULL, -1, wcstoull, 10);
|
||||
DO_ERR_TESTL(L"18446744073709551616", ULLONG_MAX, ERANGE, wcstoull, 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
int res;
|
||||
|
||||
res = strverscmp("jan1", "jan10");
|
||||
assert(res < 0);
|
||||
|
||||
res = strverscmp("jan11", "jan10");
|
||||
assert(res > 0);
|
||||
|
||||
res = strverscmp("jan1", "jan1");
|
||||
assert(res == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <assert.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
setlocale(LC_ALL, "C");
|
||||
|
||||
const char *buf = "cbtteststring";
|
||||
char dest[14];
|
||||
size_t ret = strxfrm(dest, buf, strlen(buf) + 1);
|
||||
assert(ret == 13);
|
||||
int cmp = strncmp(dest, buf, 13);
|
||||
assert(!cmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
struct tm soon = {};
|
||||
soon.tm_sec = 0;
|
||||
soon.tm_min = 0;
|
||||
soon.tm_hour = 0;
|
||||
soon.tm_mday = 1;
|
||||
soon.tm_mon = 0;
|
||||
soon.tm_year = 70;
|
||||
time_t result;
|
||||
time_t expected_result = 0;
|
||||
// This should be epoch.
|
||||
result = timegm(&soon);
|
||||
printf("epoch: %ld\n", result);
|
||||
assert(result == expected_result);
|
||||
|
||||
soon.tm_sec = 12;
|
||||
soon.tm_min = 8;
|
||||
soon.tm_hour = 16;
|
||||
soon.tm_mday = 17;
|
||||
soon.tm_mon = 4;
|
||||
soon.tm_year = 122;
|
||||
expected_result = 1652803692;
|
||||
result = timegm(&soon);
|
||||
// On my host, this returned 1652803692, verify this.
|
||||
printf("epoch: %ld\n", result);
|
||||
assert(result == expected_result);
|
||||
|
||||
soon.tm_sec = 45;
|
||||
soon.tm_min = 42;
|
||||
soon.tm_hour = 17;
|
||||
soon.tm_mday = 16;
|
||||
soon.tm_mon = 8;
|
||||
soon.tm_year = 69;
|
||||
expected_result = -9181035;
|
||||
result = timegm(&soon);
|
||||
// On my host, this returned -9181035, verify this.
|
||||
printf("epoch: %ld\n", result);
|
||||
assert(result == expected_result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
extern int daylight;
|
||||
extern long timezone;
|
||||
extern char *tzname[2];
|
||||
|
||||
int main() {
|
||||
tzset();
|
||||
printf("%s %s %ld %d\n", tzname[0], tzname[1], timezone, daylight);
|
||||
|
||||
time_t sometime_in_summer_in_the_north = 1752019200;
|
||||
struct tm *local = localtime(&sometime_in_summer_in_the_north);
|
||||
|
||||
// Print the current timezone offset from UTC in seconds, considering DST
|
||||
if (local) {
|
||||
long offset = local->tm_gmtoff;
|
||||
int hours = offset / 3600;
|
||||
int minutes = (offset % 3600) / 60;
|
||||
printf("UTC offset: %0d:%02d\n", hours, abs(minutes));
|
||||
} else {
|
||||
printf("localtime returned NULL\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from pyexpect import expect
|
||||
|
||||
exe_wrapper = os.environ.get("MESON_EXE_WRAPPER")
|
||||
wrapper = exe_wrapper.split(" ") if exe_wrapper else []
|
||||
|
||||
def check_tz(tz, expected):
|
||||
environ = os.environ.copy()
|
||||
environ["TZ"] = tz
|
||||
|
||||
output = subprocess.check_output(
|
||||
wrapper + sys.argv[1:],
|
||||
stderr=subprocess.STDOUT,
|
||||
env=environ,
|
||||
)
|
||||
|
||||
expect(expected).to_equal(output)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python3 tz.py <path to test program>", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
check_tz("UTC0", b"UTC UTC 0 0\nUTC offset: 0:00\n")
|
||||
check_tz("GMT0", b"GMT GMT 0 0\nUTC offset: 0:00\n")
|
||||
check_tz(":UTC0", b"UTC UTC 0 0\nUTC offset: 0:00\n")
|
||||
check_tz("EST+5", b"EST EST 18000 0\nUTC offset: -5:00\n")
|
||||
check_tz("EET-2", b"EET EET -7200 0\nUTC offset: 2:00\n")
|
||||
check_tz("<+03>-03", b"+03 +03 -10800 0\nUTC offset: 3:00\n")
|
||||
check_tz("NPT-05:45", b"NPT NPT -20700 0\nUTC offset: 5:45\n")
|
||||
check_tz("NST+03:30NDT", b"NST NDT 12600 1\nUTC offset: -2:30\n")
|
||||
check_tz("NZST-12NZDT-13,M9.5.0,M4.1.0/3", b"NZST NZDT -43200 1\nUTC offset: 12:00\n")
|
||||
check_tz("<PST-8>+8<PDT-7>+7", b"PST-8 PDT-7 28800 1\nUTC offset: -7:00\n")
|
||||
check_tz("<PST-8>+8<PDT-7>+7,M3.2.0,M11.1.0", b"PST-8 PDT-7 28800 1\nUTC offset: -7:00\n")
|
||||
|
||||
# These depend on tzdata, which may or may not exist.
|
||||
# Useful to check every now and then, but these also present subtle differences
|
||||
# between the host libc and mlibc, so we can't expect these to always hold up.
|
||||
# E.g. glibc will set `tzname` from the TZ environment variable even if it
|
||||
# cannot find the tzinfo file, however mlibc will use the name of the timezone
|
||||
# as read from the tzinfo file or the timezone that it defaults to (UTC).
|
||||
|
||||
# Would be b"Universal 0 0\n" on glibc.
|
||||
# check_tz("", b"UTC UTC 0 0\n")
|
||||
|
||||
# Would be b"UTC 0 0\n" on glibc.
|
||||
# check_tz("UTC", b"UTC UTC 0 0\n")
|
||||
# check_tz(":UTC", b"UTC UTC 0 0\n")
|
||||
|
||||
# Would be b"Universal 0 0\n" on glibc.
|
||||
# check_tz("Universal", b"UTC UTC 0 0\n")
|
||||
# check_tz(":Universal", b"UTC UTC 0 0\n")
|
||||
|
||||
# Would be b"ATimeZoneThatShouldHopefullyNeverBeInTzdata 0 0\n" on glibc.
|
||||
# check_tz("ATimeZoneThatShouldHopefullyNeverBeInTzdata", b"UTC UTC 0 0\n")
|
||||
# check_tz(":ATimeZoneThatShouldHopefullyNeverBeInTzdata", b"UTC UTC 0 0\n")
|
||||
@@ -0,0 +1,76 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "ungetc-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "ungetc.tmp"
|
||||
#endif
|
||||
|
||||
void test(int buffering) {
|
||||
FILE *f = fopen(TEST_FILE, "w");
|
||||
for(int c = '0'; c <= '9'; c++) {
|
||||
fputc(c, f);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
f = fopen(TEST_FILE, "r");
|
||||
if (!buffering) {
|
||||
setbuf(f, NULL);
|
||||
}
|
||||
|
||||
assert(ungetc('x', f) == 'x');
|
||||
assert(fgetc(f) == 'x');
|
||||
|
||||
// Test pushing back the same character
|
||||
for (int c = '0'; c <= '9'; c++) {
|
||||
assert(fgetc(f) == c);
|
||||
assert(ungetc(c, f) == c);
|
||||
assert(fgetc(f) == c);
|
||||
}
|
||||
assert(fgetc(f) == EOF);
|
||||
assert(ungetc(EOF, f) == EOF);
|
||||
|
||||
// Even though the spec does not guarantee it, we should be able to
|
||||
// ungetc more than one character.
|
||||
assert(ungetc('x', f) == 'x');
|
||||
assert(ungetc('y', f) == 'y');
|
||||
assert(fgetc(f) == 'y');
|
||||
assert(fgetc(f) == 'x');
|
||||
|
||||
// Seeking should discard the effects of ungetc.
|
||||
assert(ungetc('x', f) == 'x');
|
||||
rewind(f);
|
||||
|
||||
// Test pushing back a different character
|
||||
for (int c = '0'; c <= '9'; c++) {
|
||||
assert(fgetc(f) == c);
|
||||
assert(ungetc(c - '0' + 'a', f) == c - '0' + 'a');
|
||||
assert(fgetc(f) == c - '0' + 'a');
|
||||
}
|
||||
|
||||
#ifndef USE_HOST_LIBC
|
||||
// Too many ungetcs should fail.
|
||||
int eof = 0;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (ungetc('x', f) == EOF) {
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(eof);
|
||||
#endif
|
||||
|
||||
fclose(f);
|
||||
|
||||
// TODO: Test with other operations, like fread.
|
||||
}
|
||||
|
||||
int main() {
|
||||
fprintf(stderr, "with buffering...\n");
|
||||
test(1);
|
||||
fprintf(stderr, "without buffering...\n");
|
||||
test(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <locale.h>
|
||||
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
#define WCHAR_SPEC ""
|
||||
#else
|
||||
#define WCHAR_SPEC "l"
|
||||
#endif
|
||||
|
||||
#define EXPECT(func) ({ \
|
||||
if(res != expected_ret) { \
|
||||
printf(#func " decoded %d bytes (expected %d bytes), at %s:%d\n", \
|
||||
res, expected_ret, __FILE__, line); \
|
||||
fflush(stdout); \
|
||||
abort(); \
|
||||
} \
|
||||
if(wc != expected) { \
|
||||
printf(#func " output cp %" WCHAR_SPEC "x (expected cp %" WCHAR_SPEC "x), at %s:%d\n", wc, \
|
||||
expected, __FILE__, line); \
|
||||
fflush(stdout); \
|
||||
abort(); \
|
||||
} \
|
||||
})
|
||||
|
||||
void verify_decode(const char *input, wchar_t expected, int line) {
|
||||
wchar_t wc;
|
||||
int bytes = *input ? strlen(input) : 1;
|
||||
int expected_ret = *input ? strlen(input) : 0;
|
||||
|
||||
// Check mbrtowc().
|
||||
mbstate_t state;
|
||||
memset(&state, 0, sizeof(state));
|
||||
assert(mbrtowc(NULL, NULL, -1, &state) == 0);
|
||||
int res = mbrtowc(&wc, input, bytes, &state);
|
||||
EXPECT("mbrtowc");
|
||||
res = mbrtowc(NULL, input, bytes, &state);
|
||||
EXPECT("mbrtowc (pwc == NULL)");
|
||||
|
||||
// Check mbtowc().
|
||||
assert(mbtowc(NULL, NULL, -1) == 0);
|
||||
res = mbtowc(&wc, input, bytes);
|
||||
EXPECT("mbtowc");
|
||||
res = mbtowc(NULL, input, bytes);
|
||||
EXPECT("mbtowc (pwc == NULL)");
|
||||
}
|
||||
|
||||
int main() {
|
||||
setlocale(LC_ALL, "C.UTF-8");
|
||||
|
||||
#define verify_decode(in, out) verify_decode(in, out, __LINE__)
|
||||
verify_decode("\x24", 0x24);
|
||||
verify_decode("\xC2\xA2", 0xA2);
|
||||
verify_decode("\xE0\xA4\xB9", 0x939);
|
||||
verify_decode("\xE2\x82\xAC", 0x20AC);
|
||||
verify_decode("\xED\x95\x9C", 0xD55C);
|
||||
verify_decode("\xF0\x90\x8D\x88", 0x10348);
|
||||
verify_decode("", L'\0');
|
||||
|
||||
// Check wcrtomb.
|
||||
char representation[MB_CUR_MAX];
|
||||
representation[0] = '\0';
|
||||
mbstate_t state;
|
||||
memset(&state, 0, sizeof(state));
|
||||
assert(wcrtomb(representation, L'1', &state) == 1);
|
||||
assert(wcrtomb(representation, L'ß', &state) == 2);
|
||||
assert(!strncmp(representation, "\xC3\x9F", 2));
|
||||
assert(wcrtomb(representation, L'ࠑ', &state) == 3);
|
||||
assert(!strncmp(representation, "\xE0\xA0\x91", 3));
|
||||
assert(wcrtomb(representation, L'𒂲', &state) == 4);
|
||||
assert(!strncmp(representation, "\xF0\x92\x82\xB2", 4));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
int main() {
|
||||
wchar_t *wide_string = L"test string\n";
|
||||
wchar_t *dup_string = wcsdup(wide_string);
|
||||
assert(!memcmp(wide_string, dup_string, (wcslen(wide_string) + 1) * sizeof(wchar_t)));
|
||||
free(dup_string);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <assert.h>
|
||||
#include <wchar.h>
|
||||
|
||||
int main() {
|
||||
assert(!wcsncasecmp(L"foo", L"foo", 3));
|
||||
assert(!wcsncasecmp(L"foo", L"FOO", 3));
|
||||
assert(!wcsncasecmp(L"fooa", L"FOOB", 3));
|
||||
assert(wcsncasecmp(L"foo", L"bar", 3));
|
||||
assert(!wcsncasecmp(L"fooa", L"FOOA", 4));
|
||||
assert(!wcsncasecmp(L"123abc", L"123AbC", 6));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
const wchar_t str[] = L"wcsrtombs";
|
||||
const wchar_t *p = str;
|
||||
int ret = wcsrtombs(NULL, &p, 343245234, NULL);
|
||||
assert(ret == 9);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <assert.h>
|
||||
#include <wchar.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void){
|
||||
wchar_t *ws1 = calloc(10, sizeof(wchar_t));
|
||||
wchar_t *ws2 = calloc(10, sizeof(wchar_t));
|
||||
|
||||
mbstowcs(ws1, "Test 1", 10);
|
||||
mbstowcs(ws2, "Tester 2", 10);
|
||||
|
||||
assert(wmemcmp(ws1, ws2, 10) < 0);
|
||||
assert(wmemcmp(ws2, ws1, 10) > 0);
|
||||
assert(wmemcmp(ws2, ws2, 10) == 0);
|
||||
|
||||
free(ws1);
|
||||
free(ws2);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
double samples[3];
|
||||
assert(getloadavg(samples, 3) != 0);
|
||||
printf("%f %f %f\n", samples[0], samples[1], samples[2]);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <assert.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int main() {
|
||||
uint8_t *buf = malloc(256);
|
||||
uint16_t original16 = 4891;
|
||||
uint32_t original32 = 4861984;
|
||||
memset(buf, 0x0, sizeof(*buf));
|
||||
ns_put16(original16, buf);
|
||||
uint16_t result16 = ns_get16(buf);
|
||||
assert(result16 == original16);
|
||||
memset(buf, 0x0, sizeof(*buf));
|
||||
ns_put32(original32, buf);
|
||||
uint32_t result32 = ns_get32(buf);
|
||||
assert(result32 == original32);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
void *ret = reallocarray(NULL, 69, 0xCB7);
|
||||
free(ret);
|
||||
return !ret;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
void *ret = sbrk(0);
|
||||
assert(ret != (void *) -1);
|
||||
assert(ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
char buf[256];
|
||||
|
||||
/* Test copy to 0-sized buffer . */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
assert(strlcpy(buf, "xyz", 0) == 3);
|
||||
assert(strcmp(buf, "") == 0);
|
||||
|
||||
/* Test normal copy. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
assert(strlcpy(buf, "xyz", sizeof(buf)) == 3);
|
||||
assert(strcmp(buf, "xyz") == 0);
|
||||
|
||||
/* Test truncated copy. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
assert(strlcpy(buf, "abcdefabcdef", 10) == 12);
|
||||
assert(strcmp(buf, "abcdefabc") == 0);
|
||||
|
||||
/* Test concat to 0-sized buffer. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
assert(strlcat(buf, "abc", 0) == 3);
|
||||
assert(strcmp(buf, "") == 0);
|
||||
|
||||
/* Test concat to full buffer. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
assert(strlcat(buf, "abcde", 6) == 5);
|
||||
assert(strcmp(buf, "abcde") == 0);
|
||||
assert(strlcat(buf, "xyz", 5) == 8);
|
||||
assert(strcmp(buf, "abcde") == 0);
|
||||
|
||||
/* Test normal concat. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
assert(strlcat(buf, "abc", sizeof(buf)) == 3);
|
||||
assert(strcmp(buf, "abc") == 0);
|
||||
assert(strlcat(buf, "xyz", sizeof(buf)) == 6);
|
||||
assert(strcmp(buf, "abcxyz") == 0);
|
||||
|
||||
/* Test truncated concat. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
assert(strlcat(buf, "abcabc", 10) == 6);
|
||||
assert(strcmp(buf, "abcabc") == 0);
|
||||
assert(strlcat(buf, "xyzxyz", 10) == 12);
|
||||
assert(strcmp(buf, "abcabcxyz") == 0);
|
||||
|
||||
/* Test truncated concat w/ truncated dst. */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
assert(strlcat(buf, "abcabc", 10) == 6);
|
||||
assert(strcmp(buf, "abcabc") == 0);
|
||||
assert(strlcat(buf, "xyz", 4) == 7);
|
||||
assert(strcmp(buf, "abcabc") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
|
||||
int main() {
|
||||
error(0, EINVAL, "test: %s", "error");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from pyexpect import expect
|
||||
|
||||
wrapper = os.getenv("MESON_EXE_WRAPPER")
|
||||
wrapper = [x for x in (wrapper,) if x]
|
||||
|
||||
output = subprocess.check_output(wrapper + [sys.argv[1]], stderr=subprocess.STDOUT)
|
||||
|
||||
expect(bytes(sys.argv[1], 'utf-8') + b': test: error: Invalid argument (EINVAL)\n').to_equal(output)
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
|
||||
int main() {
|
||||
error_at_line(0, EINVAL, "error_at_line", 5, "test: %s", "error");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from pyexpect import expect
|
||||
|
||||
wrapper = os.getenv("MESON_EXE_WRAPPER")
|
||||
wrapper = [x for x in (wrapper,) if x]
|
||||
|
||||
output = subprocess.check_output(wrapper + [sys.argv[1]], stderr=subprocess.STDOUT)
|
||||
|
||||
expect(bytes(sys.argv[1], 'utf-8') + b':error_at_line:5: test: error: Invalid argument (EINVAL)\n').to_equal(output)
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
|
||||
int main() {
|
||||
error(1, EINVAL, "test error #1");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
|
||||
int main() {
|
||||
assert(error_message_count == 0);
|
||||
error(0, EINVAL, "test error #1");
|
||||
assert(error_message_count == 1);
|
||||
error_at_line(0, EINVAL, __FILE__, __LINE__, "test error #2");
|
||||
assert(error_message_count == 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
|
||||
int main() {
|
||||
assert(error_one_per_line == 0);
|
||||
assert(error_message_count == 0);
|
||||
error_one_per_line = 1;
|
||||
error_at_line(0, EINVAL, __FILE__, 0, "test error #1");
|
||||
assert(error_message_count == 1);
|
||||
error_at_line(0, EINVAL, __FILE__, 0, "test error #2");
|
||||
assert(error_message_count == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
|
||||
bool ran = false;
|
||||
|
||||
void test_progname(void) {
|
||||
ran = true;
|
||||
fprintf(stderr, "progname test");
|
||||
}
|
||||
|
||||
int main() {
|
||||
assert(error_print_progname == NULL);
|
||||
error_print_progname = &test_progname;
|
||||
error(0, EINVAL, "test error #1");
|
||||
assert(ran == true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
int main(void){
|
||||
// ffsl
|
||||
assert(ffsl(0x8000) == 16);
|
||||
assert(ffsl(0) == 0);
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
assert(ffsl(LLONG_MAX - 1) == 2);
|
||||
assert(ffsl(LLONG_MAX) == 1);
|
||||
#endif
|
||||
assert(ffsl(LONG_MIN) == (long)(sizeof(long) * CHAR_BIT));
|
||||
assert(ffsl(LONG_MIN + 1) == 1);
|
||||
|
||||
for (int i = 1; i < 0x1000; i++) {
|
||||
assert(ffsl(i) - 1 == __builtin_ctz(i));
|
||||
}
|
||||
|
||||
// ffsll
|
||||
assert(ffsll(0x8000) == 16);
|
||||
assert(ffsll(0) == 0);
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
assert(ffsll(LLONG_MAX - 1) == 2);
|
||||
assert(ffsll(LLONG_MAX) == 1);
|
||||
#endif
|
||||
assert(ffsll(LLONG_MIN) == (long long)(sizeof(long long) * CHAR_BIT));
|
||||
assert(ffsll(LLONG_MIN + 1) == 1);
|
||||
|
||||
for (int i = 1; i < 0x1000; i++) {
|
||||
assert(ffsll(i) - 1 == __builtin_ctz(i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
int ngroups = 100;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
gid_t *groups;
|
||||
bool gid_checked = false;
|
||||
int e = 0;
|
||||
|
||||
groups = malloc(sizeof(*groups) * ngroups);
|
||||
if(groups == NULL) {
|
||||
perror("malloc");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Fetch passwd structure */
|
||||
pw = getpwuid(geteuid());
|
||||
if(pw == NULL) {
|
||||
perror("getpwnam");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Retrieve group list */
|
||||
e = getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
|
||||
assert(e > 0);
|
||||
if(e == -1) {
|
||||
fprintf(stderr, "getgrouplist() returned -1 (%s); ngroups = %d\n", strerror(errno), ngroups);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Display list of retrieved groups, along with group names */
|
||||
fprintf(stderr, "ngroups = %d\n", ngroups);
|
||||
for(int j = 0; j < ngroups; j++) {
|
||||
if(groups[j] == pw->pw_gid)
|
||||
gid_checked = true;
|
||||
printf("%d", groups[j]);
|
||||
gr = getgrgid(groups[j]);
|
||||
if(gr != NULL)
|
||||
printf(" (%s)", gr->gr_name);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
assert(gid_checked);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@@ -0,0 +1,884 @@
|
||||
#include <assert.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||
#define dump(x) fprintf(stderr, "getopt c '%c' (%d), optind %d ('%s'), optarg '%s', optopt '%c' (%d)\n", \
|
||||
(x), (x), optind, (size_t)optind >= COUNT_OF(test_argv) ? "out of range" : test_argv[optind], optarg, optopt, optopt);
|
||||
|
||||
#define dumpargv(argv) do { \
|
||||
fprintf(stderr, "args(%zu) {\n", COUNT_OF(argv)); \
|
||||
for (size_t i = 0; i < COUNT_OF(argv); i++) { \
|
||||
fprintf(stderr, "\targv[%zu] = '%s'\n", i, argv[i]); \
|
||||
} \
|
||||
fprintf(stderr, "}\n"); \
|
||||
} while (0)
|
||||
|
||||
void test1() {
|
||||
const char *shortopts = "b:cdef";
|
||||
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, NULL, 'f'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
int test_argc = 7;
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"--foo",
|
||||
"abc",
|
||||
"-b",
|
||||
"abc",
|
||||
"abc",
|
||||
"abc"
|
||||
};
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(test_argc, test_argv, shortopts, longopts, NULL);
|
||||
dump(c)
|
||||
assert(c == 'f');
|
||||
|
||||
c = getopt_long(test_argc, test_argv, shortopts, longopts, NULL);
|
||||
dump(c)
|
||||
assert(optarg && !strcmp(optarg, "abc"));
|
||||
assert(c == 'b');
|
||||
|
||||
c = getopt_long(test_argc, test_argv, shortopts, longopts, NULL);
|
||||
dump(c);
|
||||
assert(c == -1);
|
||||
assert(optarg == NULL);
|
||||
|
||||
// we have 2 non-option arguments
|
||||
assert((optind + 2) == test_argc);
|
||||
}
|
||||
|
||||
void test2() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, NULL, 'f'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-c",
|
||||
};
|
||||
|
||||
fputs("Situation: we pass a non-existant short option in argv\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:", longopts, NULL);
|
||||
// Expected result: return '?', optopt is set to the offender
|
||||
assert(c == '?');
|
||||
assert(optopt == 'c');
|
||||
|
||||
fputs("Situation: we pass a non-existant short option in argv, while passing a leading colon in optstring\n", stderr);
|
||||
optind = 0;
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, ":ab:", longopts, NULL);
|
||||
// Expected result: return '?', optopt is set to the offender
|
||||
assert(c == '?');
|
||||
assert(optopt == 'c');
|
||||
|
||||
fputs("Situation: we omit the required arg to a short option\n", stderr);
|
||||
optind = 0;
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:c:", longopts, NULL);
|
||||
// Expected result: return '?', optopt is set to the offender
|
||||
assert(c == '?');
|
||||
assert(optopt == 'c');
|
||||
|
||||
fputs("Situation: we omit the required arg to a short option, while passing a leading colon in optstring\n", stderr);
|
||||
optind = 0;
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, ":ab:c:", longopts, NULL);
|
||||
// Expected result: return ':', optopt is set to the offender
|
||||
assert(c == ':');
|
||||
assert(optopt == 'c');
|
||||
}
|
||||
|
||||
void test3() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, NULL, 'f'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-cmanagarm",
|
||||
};
|
||||
|
||||
fputs("Situation: we pass a concatenated argument to a short option\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:c:", longopts, NULL);
|
||||
dump(c);
|
||||
// Expected result:
|
||||
assert(c == 'c');
|
||||
assert(!strcmp(optarg, "managarm"));
|
||||
}
|
||||
|
||||
void test4() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, NULL, 'f'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-acmanagarm",
|
||||
};
|
||||
|
||||
fputs("Situation: we pass concatenated short options to getopt\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:c:", longopts, NULL);
|
||||
assert(c == 'a');
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:c:", longopts, NULL);
|
||||
// Expected result:
|
||||
assert(c == 'c');
|
||||
assert(!strcmp(optarg, "managarm"));
|
||||
}
|
||||
|
||||
void test5() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, NULL, 'f'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"su",
|
||||
"-",
|
||||
"managarm",
|
||||
0
|
||||
};
|
||||
|
||||
int test_argc = 3;
|
||||
|
||||
fputs("Situation: testing `su - managarm`\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(test_argc, test_argv, "ab:", longopts, NULL);
|
||||
dump(c);
|
||||
assert(c == -1);
|
||||
|
||||
if (optind < test_argc && !strcmp(test_argv[optind], "-")) {
|
||||
++optind;
|
||||
}
|
||||
|
||||
assert(optind < test_argc);
|
||||
assert(!strcmp(test_argv[optind++], "managarm"));
|
||||
assert(optind == test_argc);
|
||||
}
|
||||
|
||||
void test6() {
|
||||
char *test_argv[] = {
|
||||
"telescope",
|
||||
"gemini://electrode.codes",
|
||||
"-S",
|
||||
0
|
||||
};
|
||||
|
||||
int test_argc = 3;
|
||||
optind = 0;
|
||||
|
||||
const struct option longopts[] = {
|
||||
{"colors", no_argument, NULL, 'C'},
|
||||
{"colours", no_argument, NULL, 'C'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"safe", no_argument, NULL, 'S'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
|
||||
int c = getopt_long(test_argc, test_argv, "Cc:hnST:v", longopts, NULL);
|
||||
dump(c);
|
||||
dumpargv(test_argv);
|
||||
assert(c == 'S');
|
||||
c = getopt_long(test_argc, test_argv, "Cc:hnST:v", longopts, NULL);
|
||||
dump(c);
|
||||
dumpargv(test_argv);
|
||||
assert(optind == 2);
|
||||
assert(!optarg);
|
||||
}
|
||||
|
||||
void test7() {
|
||||
int c;
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "debug", no_argument, NULL, 'd' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{}
|
||||
};
|
||||
const char *command;
|
||||
|
||||
char *test_argv[] = {
|
||||
"udevadm",
|
||||
"hwdb",
|
||||
"--update",
|
||||
0
|
||||
};
|
||||
|
||||
int test_argc = 3;
|
||||
setenv("POSIXLY_CORRECT", "1", 1);
|
||||
optind = 0;
|
||||
|
||||
while ((c = getopt_long(test_argc, test_argv, "+dhV", options, NULL)) >= 0) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
break;
|
||||
case 'h':
|
||||
break;
|
||||
case 'V':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dump(c);
|
||||
command = test_argv[optind];
|
||||
assert(command);
|
||||
assert(!strcmp(command, "hwdb"));
|
||||
unsetenv("POSIXLY_CORRECT");
|
||||
}
|
||||
|
||||
void test8() {
|
||||
const char *shortopts = "b:cde";
|
||||
|
||||
int foo = false;
|
||||
int bar = false;
|
||||
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, &foo, 'x'},
|
||||
{"bar", required_argument, &bar, 'y'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
int test_argc = 6;
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-foo",
|
||||
"abc",
|
||||
"-bar=def",
|
||||
"ghi",
|
||||
"jkl"
|
||||
};
|
||||
|
||||
#ifdef __GLIBC__
|
||||
optind = 0;
|
||||
#else
|
||||
optreset = 1;
|
||||
#endif
|
||||
optopt = 0;
|
||||
int c = getopt_long_only(test_argc, test_argv, shortopts, longopts, NULL);
|
||||
dump(c);
|
||||
assert(foo && !c);
|
||||
assert(optind == 3);
|
||||
|
||||
c = getopt_long_only(test_argc, test_argv, shortopts, longopts, NULL);
|
||||
dump(c);
|
||||
assert(bar && !c);
|
||||
assert(optind == 4);
|
||||
}
|
||||
|
||||
void test9() {
|
||||
char *test_argv[] = {
|
||||
"foo",
|
||||
};
|
||||
struct option opts[] = { {0} };
|
||||
optind = 0;
|
||||
int c = getopt_long(1, test_argv, "abc", opts, NULL);
|
||||
dump(c);
|
||||
assert(c == -1);
|
||||
}
|
||||
|
||||
void test10() {
|
||||
char *test_argv[] = {
|
||||
"foo",
|
||||
"nonoption",
|
||||
"-a",
|
||||
"nonoption2",
|
||||
"nonoption3",
|
||||
"-b",
|
||||
"-c",
|
||||
};
|
||||
struct option opts[] = { {0} };
|
||||
optind = 2;
|
||||
dump(0);
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "abc", opts, NULL);
|
||||
dump(c);
|
||||
dumpargv(test_argv);
|
||||
assert(c == 'a');
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "abc", opts, NULL);
|
||||
dump(c);
|
||||
dumpargv(test_argv);
|
||||
assert(c == 'b');
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "abc", opts, NULL);
|
||||
dump(c);
|
||||
dumpargv(test_argv);
|
||||
assert(c == 'c');
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "abc", opts, NULL);
|
||||
dump(c);
|
||||
dumpargv(test_argv);
|
||||
assert(c == -1);
|
||||
|
||||
assert(!strcmp(test_argv[0], "foo"));
|
||||
assert(!strcmp(test_argv[1], "nonoption"));
|
||||
assert(!strcmp(test_argv[2], "-a"));
|
||||
assert(!strcmp(test_argv[3], "-b"));
|
||||
assert(!strcmp(test_argv[4], "-c"));
|
||||
assert(!strcmp(test_argv[5], "nonoption2"));
|
||||
assert(!strcmp(test_argv[6], "nonoption3"));
|
||||
}
|
||||
|
||||
void test11() {
|
||||
const struct option longopts[] = {
|
||||
{"op", optional_argument, NULL, 'o'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"--op",
|
||||
"--op=arg",
|
||||
"non-option",
|
||||
"--op"
|
||||
};
|
||||
|
||||
fputs("Situation: optional argument to long option\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == 'o');
|
||||
assert(optarg == NULL);
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == 'o');
|
||||
assert(!strcmp(optarg, "arg"));
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == 'o');
|
||||
assert(optarg == NULL);
|
||||
}
|
||||
|
||||
void test12() {
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-a",
|
||||
"-b",
|
||||
"arg",
|
||||
"-carg",
|
||||
"arg",
|
||||
};
|
||||
|
||||
fputs("Situation: optional argument to short option\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "ab::c::", NULL, NULL);
|
||||
assert(c == 'a');
|
||||
assert(optarg == NULL);
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "ab::c::", NULL, NULL);
|
||||
assert(c == 'b');
|
||||
assert(!optarg);
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "ab::c::", NULL, NULL);
|
||||
assert(c == 'c');
|
||||
assert(!strcmp(optarg, "arg"));
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "ab::c::", NULL, NULL);
|
||||
assert(c == -1);
|
||||
assert(optind == 4);
|
||||
assert(!strcmp(test_argv[optind], "arg"));
|
||||
}
|
||||
|
||||
void test13() {
|
||||
const struct option longopts[] = {
|
||||
{"ambiguous-opt", no_argument, NULL, 0},
|
||||
{"ambiguous-option", no_argument, NULL, 1},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"--ambiguous-o"
|
||||
};
|
||||
|
||||
fputs("Situation: ambiguous long option\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == '?');
|
||||
}
|
||||
|
||||
void test14() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, NULL, 'f'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-Wfoo=bar",
|
||||
};
|
||||
|
||||
fputs("Situation: -W for long options\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "W;", longopts, NULL);
|
||||
assert(c == 'f');
|
||||
assert(!strcmp(optarg, "bar"));
|
||||
}
|
||||
|
||||
void test15() {
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-c",
|
||||
"-a",
|
||||
"--",
|
||||
"-b"
|
||||
};
|
||||
|
||||
fputs("Situation: -- to stop option processing\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt(COUNT_OF(test_argv), test_argv, "+ab");
|
||||
assert(c == '?');
|
||||
assert(optind == 2);
|
||||
|
||||
c = getopt(COUNT_OF(test_argv), test_argv, "+ab");
|
||||
assert(c == 'a');
|
||||
assert(optind == 3);
|
||||
|
||||
c = getopt(COUNT_OF(test_argv), test_argv, "+ab");
|
||||
assert(c == -1);
|
||||
assert(optind == 4);
|
||||
assert(!strcmp(test_argv[optind], "-b"));
|
||||
}
|
||||
|
||||
void test16() {
|
||||
const struct option longopts[] = {
|
||||
{"add", required_argument, NULL, 'a'},
|
||||
{"append", no_argument, NULL, 'p'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"--ad=foo",
|
||||
"--appe"
|
||||
};
|
||||
|
||||
fputs("Situation: non-ambiguous long option prefix\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == 'a');
|
||||
assert(!strcmp(optarg, "foo"));
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == 'p');
|
||||
assert(optarg == NULL);
|
||||
}
|
||||
|
||||
void test17() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", no_argument, NULL, 'l'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-foo"
|
||||
};
|
||||
|
||||
fputs("Situation: getopt_long_only with what could be short opts or a long opt\n", stderr);
|
||||
|
||||
// Case 1: long option "foo" exists, so "-foo" should be treated as "--foo"
|
||||
optind = 0;
|
||||
int c = getopt_long_only(COUNT_OF(test_argv), test_argv, "f:o", longopts, NULL);
|
||||
assert(c == 'l');
|
||||
|
||||
// Case 2: long option "foo" does not exist.
|
||||
const struct option longopts2[] = {
|
||||
{"bar", no_argument, NULL, 'b'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
optind = 0;
|
||||
c = getopt_long_only(COUNT_OF(test_argv), test_argv, "f:o", longopts2, NULL);
|
||||
assert(c == 'f');
|
||||
assert(!strcmp(optarg, "oo"));
|
||||
}
|
||||
|
||||
void test18() {
|
||||
const struct option longopts[] = {
|
||||
{"op", optional_argument, NULL, 'o'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-Wop=val",
|
||||
};
|
||||
|
||||
fputs("Situation: -W with a long option with an optional argument (with value)\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "W;", longopts, NULL);
|
||||
assert(c == 'o');
|
||||
assert(!strcmp(optarg, "val"));
|
||||
|
||||
char *test_argv2[] = {
|
||||
"dummy",
|
||||
"-Wop",
|
||||
};
|
||||
|
||||
fputs("Situation: -W with a long option with an optional argument (no value)\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
c = getopt_long(COUNT_OF(test_argv2), test_argv2, "W;", longopts, NULL);
|
||||
assert(c == 'o');
|
||||
assert(optarg == NULL);
|
||||
}
|
||||
|
||||
void test19() {
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-a",
|
||||
"non-option",
|
||||
"-b",
|
||||
};
|
||||
|
||||
fputs("Situation: POSIXLY_CORRECT behavior with '+'\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt(COUNT_OF(test_argv), test_argv, "+ab");
|
||||
assert(c == 'a');
|
||||
|
||||
c = getopt(COUNT_OF(test_argv), test_argv, "+ab");
|
||||
assert(c == -1);
|
||||
assert(optind == 2);
|
||||
assert(!strcmp(test_argv[optind], "non-option"));
|
||||
}
|
||||
|
||||
void test20() {
|
||||
const struct option longopts[] = {
|
||||
{"option", required_argument, NULL, 'o'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"--option",
|
||||
"-x",
|
||||
};
|
||||
|
||||
fputs("Situation: long option with argument that looks like an option\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "x", longopts, NULL);
|
||||
assert(c == 'o');
|
||||
assert(!strcmp(optarg, "-x"));
|
||||
assert(optind == 3);
|
||||
}
|
||||
|
||||
void test21() {
|
||||
const struct option longopts[] = {
|
||||
{"ambig-one", no_argument, NULL, '1'},
|
||||
{"ambig-two", no_argument, NULL, '2'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-ambig",
|
||||
};
|
||||
|
||||
fputs("Situation: ambiguous long option with getopt_long_only\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
int c = getopt_long_only(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == '?');
|
||||
}
|
||||
|
||||
void test22() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", no_argument, NULL, 'f'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-Wbar",
|
||||
};
|
||||
|
||||
fputs("Situation: -W with non-existent long option\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "W;", longopts, NULL);
|
||||
assert(c == '?');
|
||||
assert(optind == 2);
|
||||
}
|
||||
|
||||
void test23() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, NULL, 'f'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-foo",
|
||||
"val1",
|
||||
"-foo=val2",
|
||||
};
|
||||
|
||||
fputs("Situation: getopt_long_only with required argument\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long_only(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == 'f');
|
||||
assert(!strcmp(optarg, "val1"));
|
||||
assert(optind == 3);
|
||||
|
||||
c = getopt_long_only(COUNT_OF(test_argv), test_argv, "", longopts, NULL);
|
||||
assert(c == 'f');
|
||||
assert(!strcmp(optarg, "val2"));
|
||||
assert(optind == 4);
|
||||
}
|
||||
|
||||
void test24() {
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-W",
|
||||
};
|
||||
|
||||
fputs("Situation: -W as a short option, not for passing long options\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt(COUNT_OF(test_argv), test_argv, "W");
|
||||
assert(c == 'W');
|
||||
assert(optind == 2);
|
||||
}
|
||||
|
||||
void test25() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", required_argument, NULL, 'f'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-Wfoo",
|
||||
};
|
||||
|
||||
fputs("Situation: -W with missing argument for a long option, with ':' in optstring\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, ":W;", longopts, NULL);
|
||||
assert(c == ':');
|
||||
assert(optopt == 'f');
|
||||
assert(optind == 2);
|
||||
}
|
||||
|
||||
void test26() {
|
||||
const struct option longopts[] = {
|
||||
{"foo", no_argument, NULL, 0},
|
||||
{"ambig-one", no_argument, NULL, 1},
|
||||
{"ambig-two", no_argument, NULL, 2},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-W",
|
||||
};
|
||||
|
||||
fputs("Situation: -W without an argument\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
opterr = 1;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, ":W;", longopts, NULL);
|
||||
assert(c == ':');
|
||||
assert(optopt == 'W');
|
||||
assert(optind == 2);
|
||||
}
|
||||
|
||||
void test27() {
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-Wambig",
|
||||
};
|
||||
|
||||
const struct option longopts[] = {
|
||||
{"foo", no_argument, NULL, 0},
|
||||
{"ambig-one", no_argument, NULL, 1},
|
||||
{"ambig-two", no_argument, NULL, 2},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
fputs("Situation: -W with an ambiguous long option\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "W;", longopts, NULL);
|
||||
assert(c == '?');
|
||||
assert(optind == 2);
|
||||
}
|
||||
|
||||
void test28() {
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"-Wfoo=bar",
|
||||
"-Wfoo=",
|
||||
};
|
||||
|
||||
const struct option longopts[] = {
|
||||
{"foo", no_argument, NULL, 0},
|
||||
{"ambig-one", no_argument, NULL, 1},
|
||||
{"ambig-two", no_argument, NULL, 2},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
fputs("Situation: -W with an argument to a long option that does not take one\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "W;", longopts, NULL);
|
||||
assert(c == '?');
|
||||
assert(optind == 2);
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "W;", longopts, NULL);
|
||||
assert(c == '?');
|
||||
assert(optind == 3);
|
||||
|
||||
c = getopt_long(COUNT_OF(test_argv), test_argv, "W;", longopts, NULL);
|
||||
assert(c == -1);
|
||||
}
|
||||
|
||||
void test29() {
|
||||
char *test_argv[] = {
|
||||
"dummy",
|
||||
"--a",
|
||||
};
|
||||
|
||||
const struct option longopts[] = {
|
||||
{"load-credentials", no_argument, NULL, 0x103},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
|
||||
optind = 0;
|
||||
opterr = 1;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "el:sSRp:m:t:Vh", longopts, NULL);
|
||||
dump(c);
|
||||
assert(c == '?');
|
||||
assert(optind == 2);
|
||||
}
|
||||
|
||||
void test30() {
|
||||
const struct option longopts[] = {
|
||||
{"long-opt", required_argument, NULL, 'l'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *test_argv[] = {
|
||||
"getopt_test",
|
||||
"non-arg1",
|
||||
"--long-opt",
|
||||
"val",
|
||||
"non-arg2"
|
||||
};
|
||||
|
||||
fputs("Situation: non-arguments before valid long arguments\n", stderr);
|
||||
|
||||
optind = 0;
|
||||
int c = getopt_long(COUNT_OF(test_argv), test_argv, "+", longopts, NULL);
|
||||
assert(c == -1);
|
||||
assert(optind == 1);
|
||||
assert(!strcmp(test_argv[0], "getopt_test"));
|
||||
assert(!strcmp(test_argv[1], "non-arg1"));
|
||||
assert(!strcmp(test_argv[2], "--long-opt"));
|
||||
assert(!strcmp(test_argv[3], "val"));
|
||||
assert(!strcmp(test_argv[4], "non-arg2"));
|
||||
|
||||
optind = 2;
|
||||
while ((c = getopt_long(COUNT_OF(test_argv), test_argv, "+", longopts, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'l':
|
||||
assert(!strcmp(optarg, "val"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(c == -1);
|
||||
assert(optind == 4);
|
||||
|
||||
optind = 0;
|
||||
while ((c = getopt_long(COUNT_OF(test_argv), test_argv, "", longopts, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'l':
|
||||
assert(!strcmp(optarg, "val"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(optind == 3);
|
||||
assert(!strcmp(test_argv[0], "getopt_test"));
|
||||
assert(!strcmp(test_argv[1], "--long-opt"));
|
||||
assert(!strcmp(test_argv[2], "val"));
|
||||
assert(!strcmp(test_argv[3], "non-arg1"));
|
||||
assert(!strcmp(test_argv[4], "non-arg2"));
|
||||
}
|
||||
|
||||
int main() {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
test7();
|
||||
test8();
|
||||
test9();
|
||||
test10();
|
||||
test11();
|
||||
test12();
|
||||
test13();
|
||||
test14();
|
||||
test15();
|
||||
test16();
|
||||
test17();
|
||||
test18();
|
||||
test19();
|
||||
test20();
|
||||
test21();
|
||||
test22();
|
||||
test23();
|
||||
test24();
|
||||
test25();
|
||||
test26();
|
||||
test27();
|
||||
test28();
|
||||
test29();
|
||||
test30();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define test_string(x, expectval) assert(strcmp(basename(x), expectval) == 0)
|
||||
|
||||
int main() {
|
||||
test_string("/usr/lib", "lib");
|
||||
test_string("/usr/", "");
|
||||
test_string("/", "");
|
||||
test_string(".", ".");
|
||||
test_string("..", "..");
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
char *data = "hello mlibc\n";
|
||||
long ret = syscall(SYS_write, 1, data, strlen(data));
|
||||
assert(ret == (long)strlen(data));
|
||||
|
||||
syscall(SYS_exit, 0);
|
||||
abort();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <assert.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
assert(rpmatch("y") == 1);
|
||||
assert(rpmatch("Y") == 1);
|
||||
assert(rpmatch("n") == 0);
|
||||
assert(rpmatch("N") == 0);
|
||||
assert(rpmatch("yno") == 1);
|
||||
assert(rpmatch("no") == 0);
|
||||
assert(rpmatch("NO") == 0);
|
||||
assert(rpmatch("YES") == 1);
|
||||
assert(rpmatch("mlibc") == -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <sched.h>
|
||||
|
||||
#define SET_SIZE 15
|
||||
|
||||
int main() {
|
||||
cpu_set_t *set = CPU_ALLOC(SET_SIZE);
|
||||
size_t setsize = CPU_ALLOC_SIZE(SET_SIZE);
|
||||
|
||||
CPU_ZERO_S(setsize, set);
|
||||
|
||||
assert(!CPU_ISSET_S(11, setsize, set));
|
||||
|
||||
CPU_SET_S(11, setsize, set);
|
||||
assert(CPU_ISSET_S(11, setsize, set));
|
||||
assert(CPU_COUNT_S(setsize, set) == 1);
|
||||
|
||||
assert(!CPU_ISSET_S(CPU_SETSIZE - 1, setsize, set));
|
||||
|
||||
CPU_CLR_S(11, setsize, set);
|
||||
assert(!CPU_ISSET_S(11, setsize, set));
|
||||
|
||||
CPU_FREE(set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
struct ifaddrs *ifaddr = 0;
|
||||
char host[NI_MAXHOST];
|
||||
bool loopback_found = false;
|
||||
|
||||
if(getifaddrs(&ifaddr)) {
|
||||
perror("getifaddrs");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for(struct ifaddrs *ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
|
||||
if(ifa->ifa_addr == NULL)
|
||||
continue;
|
||||
|
||||
int family = ifa->ifa_addr->sa_family;
|
||||
|
||||
if(family == AF_INET && !strcmp("lo", ifa->ifa_name)) {
|
||||
loopback_found = true;
|
||||
|
||||
printf("%-10s %s (%d)\n", ifa->ifa_name,
|
||||
(family == AF_INET) ? "AF_INET" : (family == AF_INET6) ? "AF_INET6" : "???",
|
||||
family
|
||||
);
|
||||
|
||||
int s = getnameinfo(ifa->ifa_addr,
|
||||
(family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
|
||||
host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
|
||||
assert(!s);
|
||||
|
||||
printf("\t\taddress: <%s>\n", host);
|
||||
if(ifa->ifa_netmask)
|
||||
printf("\t\tnetmask: <%s>\n", inet_ntoa(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr));
|
||||
|
||||
if(ifa->ifa_flags & IFF_BROADCAST) {
|
||||
assert(ifa->ifa_broadaddr);
|
||||
printf("\t\tbroadcast: <%s>\n", inet_ntoa(((struct sockaddr_in *) ifa->ifa_broadaddr)->sin_addr));
|
||||
}
|
||||
|
||||
if(ifa->ifa_flags & IFF_POINTOPOINT) {
|
||||
assert(ifa->ifa_dstaddr);
|
||||
printf("\t\tdest addr: <%s>\n", inet_ntoa(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
|
||||
exit(loopback_found ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
void *p1 = malloc(1023);
|
||||
fprintf(stderr, "size: %zu\n", malloc_usable_size(p1));
|
||||
assert(malloc_usable_size(p1) >= 1023);
|
||||
free(p1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/pidfd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
int child = fork();
|
||||
|
||||
if(!child) {
|
||||
sleep(1);
|
||||
exit(42);
|
||||
}
|
||||
|
||||
int pidfd = pidfd_open(child, 0);
|
||||
assert(pidfd > 0);
|
||||
|
||||
int ret = lseek(pidfd, 0, SEEK_SET);
|
||||
assert(ret == -1);
|
||||
assert(errno == ESPIPE);
|
||||
|
||||
pid_t outpid = pidfd_getpid(pidfd);
|
||||
assert(outpid == child);
|
||||
|
||||
struct pollfd pollfd;
|
||||
pollfd.fd = pidfd;
|
||||
pollfd.events = POLLIN;
|
||||
|
||||
int ready = poll(&pollfd, 1, 0);
|
||||
assert(ready == 0);
|
||||
|
||||
ready = poll(&pollfd, 1, 2000);
|
||||
if(ready == -1) {
|
||||
perror("poll");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
assert(ready == 1);
|
||||
assert(pollfd.revents == POLLIN);
|
||||
|
||||
siginfo_t info = {};
|
||||
ret = waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG);
|
||||
assert(ret == 0);
|
||||
assert(info.si_code == CLD_EXITED);
|
||||
assert(info.si_pid == child);
|
||||
assert(info.si_status == 42);
|
||||
|
||||
close(pidfd);
|
||||
|
||||
child = fork();
|
||||
|
||||
if(!child) {
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
pidfd = pidfd_open(child, 0);
|
||||
assert(pidfd > 0);
|
||||
|
||||
ret = pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
|
||||
assert(ret == 0);
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
ret = waitid(P_PIDFD, pidfd, &info, WEXITED);
|
||||
assert(ret == 0);
|
||||
assert(info.si_code == CLD_KILLED);
|
||||
assert(info.si_pid == child);
|
||||
assert(info.si_status == SIGKILL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void sig_handler(int sig) {
|
||||
(void)sig;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int fds[2];
|
||||
int ret = pipe(fds);
|
||||
assert(ret == 0);
|
||||
|
||||
struct pollfd poll_fds[1];
|
||||
poll_fds[0].fd = fds[0];
|
||||
poll_fds[0].events = POLLIN;
|
||||
|
||||
struct timespec timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 1000000; // 1 ms
|
||||
|
||||
// Test that ppoll times out correctly.
|
||||
ret = ppoll(poll_fds, 1, &timeout, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
// Test that ppoll returns 1 if there is an event.
|
||||
char buf[1];
|
||||
ret = write(fds[1], "a", 1);
|
||||
assert(ret == 1);
|
||||
|
||||
ret = ppoll(poll_fds, 1, &timeout, NULL);
|
||||
assert(ret == 1);
|
||||
assert(poll_fds[0].revents & POLLIN);
|
||||
|
||||
// Test that ppoll returns 0 if there are no events and timeout is 0.
|
||||
ret = read(fds[0], buf, 1);
|
||||
assert(ret == 1);
|
||||
|
||||
timeout.tv_nsec = 0;
|
||||
ret = ppoll(poll_fds, 1, &timeout, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
// Test that ppoll returns immediately if there is an event and timeout is 0.
|
||||
ret = write(fds[1], "a", 1);
|
||||
assert(ret == 1);
|
||||
|
||||
ret = ppoll(poll_fds, 1, &timeout, NULL);
|
||||
assert(ret == 1);
|
||||
assert(poll_fds[0].revents & POLLIN);
|
||||
|
||||
char recvbuf[2];
|
||||
ret = read(fds[0], &recvbuf, 2);
|
||||
assert(ret == 1);
|
||||
|
||||
// Test that ppoll is interrupted by a signal.
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = sig_handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
ret = sigaction(SIGUSR1, &sa, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
pid_t pid = fork();
|
||||
assert(pid >= 0);
|
||||
|
||||
if (pid == 0) {
|
||||
// Child process.
|
||||
usleep(100000); // 100 ms
|
||||
ret = kill(getppid(), SIGUSR1);
|
||||
assert(ret == 0);
|
||||
exit(0);
|
||||
} else {
|
||||
// Parent process.
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_nsec = 0;
|
||||
ret = ppoll(poll_fds, 1, &timeout, NULL);
|
||||
assert(ret == -1);
|
||||
assert(errno == EINTR);
|
||||
|
||||
int status;
|
||||
ret = waitpid(pid, &status, 0);
|
||||
assert(ret == pid);
|
||||
assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);
|
||||
}
|
||||
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Test variable to read and write
|
||||
static int test = 42;
|
||||
|
||||
int main() {
|
||||
// Read the variable using process_vm_readv
|
||||
int temp;
|
||||
struct iovec local_iov = {
|
||||
.iov_base = &temp,
|
||||
.iov_len = sizeof(temp),
|
||||
};
|
||||
struct iovec remote_iov = {
|
||||
.iov_base = &test,
|
||||
.iov_len = sizeof(test),
|
||||
};
|
||||
ssize_t bytes_read = process_vm_readv(getpid(), &local_iov, 1, &remote_iov, 1, 0);
|
||||
assert(bytes_read == sizeof(test));
|
||||
assert(temp == 42);
|
||||
|
||||
// Write a new value to the variable using process_vm_writev
|
||||
int new_value = 1337;
|
||||
struct iovec new_local_iov = {
|
||||
.iov_base = &new_value,
|
||||
.iov_len = sizeof(new_value),
|
||||
};
|
||||
ssize_t bytes_written = process_vm_writev(getpid(), &new_local_iov, 1, &remote_iov, 1, 0);
|
||||
assert(bytes_written == sizeof(new_value));
|
||||
assert(test == 1337);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
static void test_affinity() {
|
||||
pthread_attr_t attr;
|
||||
cpu_set_t set = {0};
|
||||
assert(!pthread_attr_init(&attr));
|
||||
assert(!pthread_attr_setaffinity_np(&attr, 1, &set));
|
||||
|
||||
cpu_set_t other_set = {0};
|
||||
assert(!pthread_attr_getaffinity_np(&attr, 1, &set));
|
||||
|
||||
assert(!memcmp(&set, &other_set, sizeof(cpu_set_t)));
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
|
||||
#if !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32)
|
||||
static void test_sigmask() {
|
||||
pthread_attr_t attr;
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGUSR1);
|
||||
#ifndef USE_HOST_LIBC
|
||||
sigaddset(&set, SIGCANCEL);
|
||||
#endif
|
||||
|
||||
assert(!pthread_attr_init(&attr));
|
||||
assert(!pthread_attr_setsigmask_np(&attr, &set));
|
||||
|
||||
sigset_t other_set;
|
||||
sigemptyset(&other_set);
|
||||
|
||||
assert(!pthread_attr_getsigmask_np(&attr, &other_set));
|
||||
|
||||
assert(sigismember(&other_set, SIGUSR1));
|
||||
#ifndef USE_HOST_LIBC
|
||||
// Test whether internal signals get filtered properly.
|
||||
assert(!sigismember(&other_set, SIGCANCEL));
|
||||
#endif
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
|
||||
static void *getattr_worker(void *arg) {
|
||||
(void)arg;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void test_getattrnp() {
|
||||
pthread_attr_t attr;
|
||||
size_t stacksize = PTHREAD_STACK_MIN;
|
||||
assert(!pthread_attr_init(&attr));
|
||||
assert(!pthread_attr_setstacksize(&attr, stacksize));
|
||||
|
||||
pthread_t thread;
|
||||
assert(!pthread_create(&thread, &attr, getattr_worker, NULL));
|
||||
assert(!pthread_getattr_np(thread, &attr));
|
||||
size_t other_stacksize;
|
||||
assert(!pthread_attr_getstacksize(&attr, &other_stacksize));
|
||||
assert(other_stacksize == stacksize);
|
||||
assert(!pthread_join(thread, NULL));
|
||||
|
||||
pthread_t own_thread = pthread_self();
|
||||
void *stack;
|
||||
assert(!pthread_getattr_np(own_thread, &attr));
|
||||
assert(!pthread_attr_getstack(&attr, &stack, &other_stacksize));
|
||||
assert(stack);
|
||||
assert(other_stacksize);
|
||||
// Check that we can read from the highest byte returned.
|
||||
// pthread_getattr_np() should return the lowest byte
|
||||
// of the stack.
|
||||
printf("highest byte: %hhu\n", *(char *)(stack + other_stacksize - 1));
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
#endif // !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32)
|
||||
|
||||
int main() {
|
||||
test_affinity();
|
||||
#if !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32)
|
||||
test_sigmask();
|
||||
test_getattrnp();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int main() {
|
||||
int ret = pthread_setname_np(pthread_self(), "mlibc-test-123");
|
||||
assert(!ret);
|
||||
|
||||
char buf[16];
|
||||
ret = pthread_getname_np(pthread_self(), buf, 16);
|
||||
assert(!ret);
|
||||
assert(!strcmp("mlibc-test-123", buf));
|
||||
|
||||
ret = pthread_setname_np(pthread_self(), "mlibc-test-123-too-long");
|
||||
assert(ret == ERANGE);
|
||||
|
||||
ret = pthread_getname_np(pthread_self(), buf, 1);
|
||||
assert(ret == ERANGE);
|
||||
|
||||
ret = pthread_getname_np(pthread_self(), buf, 15);
|
||||
assert(ret == ERANGE);
|
||||
|
||||
ret = pthread_getname_np(pthread_self(), buf, 16);
|
||||
assert(!ret);
|
||||
assert(!strcmp("mlibc-test-123", buf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
int t = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||
assert(t > 0);
|
||||
|
||||
struct itimerspec its;
|
||||
int ret = timerfd_gettime(t, &its);
|
||||
assert(ret == 0);
|
||||
assert(!its.it_value.tv_sec);
|
||||
assert(!its.it_value.tv_nsec);
|
||||
assert(!its.it_interval.tv_sec);
|
||||
assert(!its.it_interval.tv_nsec);
|
||||
|
||||
struct itimerspec new_its = {
|
||||
.it_interval = {0, 0},
|
||||
.it_value = {0, 100000000},
|
||||
};
|
||||
ret = timerfd_settime(t, 0, &new_its, &its);
|
||||
assert(ret == 0);
|
||||
assert(!its.it_value.tv_sec);
|
||||
assert(!its.it_value.tv_nsec);
|
||||
assert(!its.it_interval.tv_sec);
|
||||
assert(!its.it_interval.tv_nsec);
|
||||
|
||||
ret = timerfd_gettime(t, &its);
|
||||
assert(ret == 0);
|
||||
assert(!its.it_value.tv_sec);
|
||||
assert(its.it_value.tv_nsec);
|
||||
assert(!its.it_interval.tv_sec);
|
||||
assert(!its.it_interval.tv_nsec);
|
||||
|
||||
struct timeval before;
|
||||
gettimeofday(&before, NULL);
|
||||
assert(ret == 0);
|
||||
uint64_t ev = 0;
|
||||
ret = read(t, &ev, sizeof(ev));
|
||||
struct timeval after;
|
||||
gettimeofday(&after, NULL);
|
||||
|
||||
assert(ret == sizeof(ev));
|
||||
assert(ev == 1);
|
||||
|
||||
struct timeval diff = {};
|
||||
timersub(&after, &before, &diff);
|
||||
assert(diff.tv_sec || diff.tv_usec);
|
||||
|
||||
fcntl(t, F_SETFL, fcntl(t, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
ret = timerfd_settime(t, 0, &new_its, &its);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = read(t, &ev, sizeof(ev));
|
||||
assert(ret == -1);
|
||||
assert(errno == EAGAIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
int main() {
|
||||
char path[] = "/tmp/mlibc-utmp-test-XXXXXX";
|
||||
int fd = mkstemp(path);
|
||||
assert(fd != -1);
|
||||
close(fd);
|
||||
|
||||
int ret = utmpname(path);
|
||||
assert(!ret);
|
||||
|
||||
// Test writing to the utmp file.
|
||||
struct utmp entry1;
|
||||
memset(&entry1, 0, sizeof(struct utmp));
|
||||
entry1.ut_type = USER_PROCESS;
|
||||
entry1.ut_pid = 1234;
|
||||
strcpy(entry1.ut_line, "pts/1");
|
||||
strcpy(entry1.ut_id, "id1");
|
||||
strcpy(entry1.ut_user, "user1");
|
||||
strcpy(entry1.ut_host, "host1");
|
||||
entry1.ut_tv.tv_sec = 1;
|
||||
entry1.ut_tv.tv_usec = 1;
|
||||
|
||||
setutent();
|
||||
struct utmp *res = pututline(&entry1);
|
||||
assert(res);
|
||||
endutent();
|
||||
|
||||
// Test reading from the utmp file.
|
||||
setutent();
|
||||
struct utmp *read_entry = getutent();
|
||||
assert(read_entry);
|
||||
assert(read_entry->ut_type == USER_PROCESS);
|
||||
assert(read_entry->ut_pid == 1234);
|
||||
assert(strcmp(read_entry->ut_line, "pts/1") == 0);
|
||||
assert(strcmp(read_entry->ut_id, "id1") == 0);
|
||||
assert(strcmp(read_entry->ut_user, "user1") == 0);
|
||||
assert(strcmp(read_entry->ut_host, "host1") == 0);
|
||||
assert(read_entry->ut_tv.tv_sec == 1);
|
||||
assert(read_entry->ut_tv.tv_usec == 1);
|
||||
|
||||
read_entry = getutent();
|
||||
assert(!read_entry);
|
||||
assert(errno == ESRCH);
|
||||
endutent();
|
||||
|
||||
// Test getutid
|
||||
struct utmp id_entry;
|
||||
memset(&id_entry, 0, sizeof(struct utmp));
|
||||
id_entry.ut_type = USER_PROCESS;
|
||||
strcpy(id_entry.ut_id, "id1");
|
||||
|
||||
setutent();
|
||||
struct utmp *id_read_entry = getutid(&id_entry);
|
||||
assert(id_read_entry);
|
||||
assert(id_read_entry->ut_pid == 1234);
|
||||
|
||||
read_entry = getutent();
|
||||
assert(!read_entry);
|
||||
assert(errno == ESRCH);
|
||||
endutent();
|
||||
|
||||
// Test getutline
|
||||
struct utmp line_entry;
|
||||
memset(&line_entry, 0, sizeof(struct utmp));
|
||||
line_entry.ut_type = USER_PROCESS;
|
||||
strcpy(line_entry.ut_line, "pts/1");
|
||||
|
||||
setutent();
|
||||
struct utmp *line_read_entry = getutline(&line_entry);
|
||||
assert(line_read_entry);
|
||||
assert(line_read_entry->ut_pid == 1234);
|
||||
endutent();
|
||||
|
||||
// Test getutent_r
|
||||
struct utmp buf;
|
||||
struct utmp *res_r;
|
||||
setutent();
|
||||
int ret_r = getutent_r(&buf, &res_r);
|
||||
assert(!ret_r);
|
||||
assert(res_r == &buf);
|
||||
assert(buf.ut_pid == 1234);
|
||||
endutent();
|
||||
|
||||
// Test updwtmp.
|
||||
char wtmp_path[] = "/tmp/mlibc-wtmp-test-XXXXXX";
|
||||
int wtmp_fd = mkstemp(wtmp_path);
|
||||
assert(wtmp_fd != -1);
|
||||
close(wtmp_fd);
|
||||
|
||||
struct utmp entry2;
|
||||
memset(&entry2, 0, sizeof(struct utmp));
|
||||
entry2.ut_type = USER_PROCESS;
|
||||
entry2.ut_pid = 5678;
|
||||
strcpy(entry2.ut_line, "pts/2");
|
||||
strcpy(entry2.ut_id, "id2");
|
||||
strcpy(entry2.ut_user, "user2");
|
||||
strcpy(entry2.ut_host, "host2");
|
||||
entry2.ut_tv.tv_sec = 2;
|
||||
entry2.ut_tv.tv_usec = 2;
|
||||
|
||||
updwtmp(wtmp_path, &entry2);
|
||||
|
||||
// Verify the wtmp file.
|
||||
FILE *f = fopen(wtmp_path, "r");
|
||||
assert(f);
|
||||
struct utmp wtmp_entry;
|
||||
ret = fread(&wtmp_entry, sizeof(struct utmp), 1, f);
|
||||
assert(ret == 1);
|
||||
fclose(f);
|
||||
|
||||
assert(wtmp_entry.ut_type == USER_PROCESS);
|
||||
assert(wtmp_entry.ut_pid == 5678);
|
||||
assert(strcmp(wtmp_entry.ut_line, "pts/2") == 0);
|
||||
assert(strcmp(wtmp_entry.ut_id, "id2") == 0);
|
||||
assert(strcmp(wtmp_entry.ut_user, "user2") == 0);
|
||||
assert(strcmp(wtmp_entry.ut_host, "host2") == 0);
|
||||
assert(wtmp_entry.ut_tv.tv_sec == 2);
|
||||
assert(wtmp_entry.ut_tv.tv_usec == 2);
|
||||
|
||||
unlink(wtmp_path);
|
||||
unlink(path);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utmpx.h>
|
||||
|
||||
int main() {
|
||||
char path[] = "/tmp/mlibc-utmpx-test-XXXXXX";
|
||||
int fd = mkstemp(path);
|
||||
assert(fd != -1);
|
||||
close(fd);
|
||||
|
||||
int ret = utmpxname(path);
|
||||
assert(!ret);
|
||||
|
||||
struct utmpx entry;
|
||||
memset(&entry, 0, sizeof(struct utmpx));
|
||||
|
||||
// Test an empty file.
|
||||
setutxent();
|
||||
struct utmpx *read_entry = getutxent();
|
||||
assert(!read_entry);
|
||||
endutxent();
|
||||
|
||||
// Test writing a new entry.
|
||||
entry.ut_type = USER_PROCESS;
|
||||
entry.ut_pid = getpid();
|
||||
strncpy(entry.ut_line, "tty1", sizeof(entry.ut_line));
|
||||
strncpy(entry.ut_id, "t1", sizeof(entry.ut_id));
|
||||
strncpy(entry.ut_user, "root", sizeof(entry.ut_user));
|
||||
strncpy(entry.ut_host, "localhost", sizeof(entry.ut_host));
|
||||
entry.ut_tv.tv_sec = 1234567890;
|
||||
entry.ut_tv.tv_usec = 0;
|
||||
setutxent();
|
||||
assert(pututxline(&entry));
|
||||
endutxent();
|
||||
|
||||
// Test reading the entry back.
|
||||
setutxent();
|
||||
read_entry = getutxent();
|
||||
assert(read_entry);
|
||||
assert(read_entry->ut_type == USER_PROCESS);
|
||||
assert(read_entry->ut_pid == getpid());
|
||||
assert(!strcmp(read_entry->ut_line, "tty1"));
|
||||
assert(!strcmp(read_entry->ut_id, "t1"));
|
||||
assert(!strcmp(read_entry->ut_user, "root"));
|
||||
assert(!strcmp(read_entry->ut_host, "localhost"));
|
||||
assert(read_entry->ut_tv.tv_sec == 1234567890);
|
||||
read_entry = getutxent();
|
||||
assert(!read_entry);
|
||||
endutxent();
|
||||
|
||||
// Test getutxid().
|
||||
struct utmpx id_entry;
|
||||
memset(&id_entry, 0, sizeof(struct utmpx));
|
||||
id_entry.ut_type = USER_PROCESS;
|
||||
strncpy(id_entry.ut_id, "t1", sizeof(id_entry.ut_id));
|
||||
setutxent();
|
||||
struct utmpx *id_read_entry = getutxid(&id_entry);
|
||||
assert(id_read_entry);
|
||||
assert(id_read_entry->ut_pid == getpid());
|
||||
endutxent();
|
||||
|
||||
// Test getutxline().
|
||||
struct utmpx line_entry;
|
||||
memset(&line_entry, 0, sizeof(struct utmpx));
|
||||
line_entry.ut_type = USER_PROCESS;
|
||||
strncpy(line_entry.ut_line, "tty1", sizeof(line_entry.ut_line));
|
||||
setutxent();
|
||||
struct utmpx *line_read_entry = getutxline(&line_entry);
|
||||
assert(line_read_entry);
|
||||
assert(line_read_entry->ut_pid == getpid());
|
||||
endutxent();
|
||||
|
||||
// Test updwtmpx.
|
||||
char wtmpx_path[] = "/tmp/mlibc-wtmpx-test-XXXXXX";
|
||||
int wtmpx_fd = mkstemp(wtmpx_path);
|
||||
assert(wtmpx_fd != -1);
|
||||
close(wtmpx_fd);
|
||||
|
||||
struct utmpx entry2;
|
||||
memset(&entry2, 0, sizeof(struct utmpx));
|
||||
entry2.ut_type = USER_PROCESS;
|
||||
entry2.ut_pid = 5678;
|
||||
strcpy(entry2.ut_line, "pts/2");
|
||||
strcpy(entry2.ut_id, "id2");
|
||||
strcpy(entry2.ut_user, "user2");
|
||||
strcpy(entry2.ut_host, "host2");
|
||||
entry2.ut_tv.tv_sec = 2;
|
||||
entry2.ut_tv.tv_usec = 2;
|
||||
|
||||
updwtmpx(wtmpx_path, &entry2);
|
||||
|
||||
// Verify the wtmpx file.
|
||||
FILE *f = fopen(wtmpx_path, "r");
|
||||
assert(f);
|
||||
struct utmpx wtmpx_entry;
|
||||
ret = fread(&wtmpx_entry, sizeof(struct utmpx), 1, f);
|
||||
assert(ret == 1);
|
||||
fclose(f);
|
||||
|
||||
assert(wtmpx_entry.ut_type == USER_PROCESS);
|
||||
assert(wtmpx_entry.ut_pid == 5678);
|
||||
assert(strcmp(wtmpx_entry.ut_line, "pts/2") == 0);
|
||||
assert(strcmp(wtmpx_entry.ut_id, "id2") == 0);
|
||||
assert(strcmp(wtmpx_entry.ut_user, "user2") == 0);
|
||||
assert(strcmp(wtmpx_entry.ut_host, "host2") == 0);
|
||||
assert(wtmpx_entry.ut_tv.tv_sec == 2);
|
||||
assert(wtmpx_entry.ut_tv.tv_usec == 2);
|
||||
|
||||
unlink(wtmpx_path);
|
||||
unlink(path);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/xattr.h>
|
||||
|
||||
#define assert_perror(x) \
|
||||
({ \
|
||||
int res = (x); \
|
||||
if (res < 0) { \
|
||||
perror(#x); \
|
||||
return 1; \
|
||||
} \
|
||||
res; \
|
||||
})
|
||||
|
||||
#define soft_assert(x, m) \
|
||||
({ \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "cond \"%s\" failed: %s\n", #x, m); \
|
||||
return 1; \
|
||||
} \
|
||||
})
|
||||
|
||||
void remove_tmp(const char (*fname)[]) {
|
||||
unlink(&(*fname)[0]);
|
||||
}
|
||||
#define _cleanup_file_ __attribute__((cleanup(remove_tmp)))
|
||||
|
||||
int main(void) {
|
||||
int ret;
|
||||
char buf[32] = { 0 };
|
||||
_cleanup_file_ char filename[] = "xattr_test.XXXXXX";
|
||||
_cleanup_file_ char filename2[] = "xattr_test.XXXXXX.2";
|
||||
|
||||
int tmpfile = assert_perror(mkstemp(filename));
|
||||
memcpy(filename2, filename, sizeof(filename) - 1);
|
||||
assert_perror(symlink(filename, filename2));
|
||||
|
||||
assert_perror(setxattr(filename, "user.T1", "ABC", 3, XATTR_CREATE));
|
||||
assert_perror(fsetxattr(tmpfile, "user.T2", "DEF", 3, XATTR_CREATE));
|
||||
|
||||
// for testing remove
|
||||
assert_perror(fsetxattr(tmpfile, "user.T3", "DEF", 3, XATTR_CREATE));
|
||||
|
||||
if ((ret = getxattr(filename, "user.T1", buf, 3)) != 3) {
|
||||
if (ret < 0) {
|
||||
perror("getxattr");
|
||||
return 1;
|
||||
}
|
||||
|
||||
soft_assert(memcmp(buf, "ABC", 3) == 0, "xattr read wrong");
|
||||
}
|
||||
|
||||
ret = lgetxattr(filename2, "user.T1", buf, 3);
|
||||
soft_assert(ret < 0 && errno == ENODATA, "lgetxattr deref'd");
|
||||
|
||||
if ((ret = fgetxattr(tmpfile, "user.T3", buf, 3)) != 3) {
|
||||
if (ret < 0) {
|
||||
perror("fgetxattr");
|
||||
return 1;
|
||||
}
|
||||
|
||||
soft_assert(memcmp(buf, "DEF", 3) == 0, "xattr read wrong");
|
||||
}
|
||||
|
||||
assert_perror(removexattr(filename, "user.T2"));
|
||||
assert_perror(fremovexattr(tmpfile, "user.T3"));
|
||||
|
||||
ret = assert_perror(listxattr(filename, buf, sizeof(buf) - 1));
|
||||
soft_assert(memmem(buf, ret, "user.T1", 7), "user.T1 not found");
|
||||
soft_assert(!memmem(buf, ret, "user.T2", 7), "user.T2 found");
|
||||
soft_assert(!memmem(buf, ret, "user.T3", 7), "user.T3 found");
|
||||
|
||||
ret = assert_perror(flistxattr(tmpfile, buf, sizeof(buf) - 1));
|
||||
soft_assert(memmem(buf, ret, "user.T1", 7), "user.T1 not found");
|
||||
soft_assert(!memmem(buf, ret, "user.T2", 7), "user.T2 found");
|
||||
soft_assert(!memmem(buf, ret, "user.T3", 7), "user.T3 found");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
timeout_sec = 10
|
||||
|
||||
all_test_cases = [
|
||||
'ansi/alloc',
|
||||
'ansi/sscanf',
|
||||
'ansi/sprintf',
|
||||
'ansi/snprintf',
|
||||
'ansi/utf8',
|
||||
'ansi/strtol',
|
||||
'ansi/strtof',
|
||||
'ansi/abs',
|
||||
'ansi/longjmp',
|
||||
'ansi/mbrtoc32',
|
||||
'ansi/strverscmp',
|
||||
'ansi/strftime',
|
||||
'ansi/strchr',
|
||||
'ansi/strrchr',
|
||||
'ansi/wcsrtombs',
|
||||
'ansi/wmemcmp',
|
||||
'ansi/timegm',
|
||||
'ansi/tz',
|
||||
'ansi/ungetc',
|
||||
'ansi/wcsdup',
|
||||
'ansi/wcsncasecmp',
|
||||
'ansi/fopen',
|
||||
'ansi/memmem',
|
||||
'ansi/creal-cimag',
|
||||
'ansi/fenv',
|
||||
'ansi/qsort',
|
||||
'ansi/freopen',
|
||||
'ansi/strxfrm',
|
||||
'ansi/calloc',
|
||||
'ansi/fgetpos',
|
||||
'ansi/fputs',
|
||||
'ansi/ftell',
|
||||
'bsd/ns_get_put',
|
||||
'bsd/reallocarray',
|
||||
'bsd/strl',
|
||||
'bsd/sbrk',
|
||||
'bsd/getloadavg',
|
||||
'posix/inet_ntop',
|
||||
'posix/inet_pton',
|
||||
'posix/access',
|
||||
'posix/pthread_barrier',
|
||||
'posix/pthread_rwlock',
|
||||
'posix/pthread_cond',
|
||||
'posix/pthread_create',
|
||||
'posix/pthread_cancel',
|
||||
'posix/pthread_atfork',
|
||||
'posix/pthread_cleanup',
|
||||
'posix/pthread_kill',
|
||||
'posix/pthread_mutex',
|
||||
'posix/pthread_key',
|
||||
'posix/pthread_thread_local',
|
||||
'posix/pthread_attr',
|
||||
'posix/pthread_schedparam',
|
||||
'posix/pwd',
|
||||
'posix/fdopen',
|
||||
'posix/fopencookie',
|
||||
'posix/fmemopen',
|
||||
'posix/getaddrinfo',
|
||||
'posix/getdelim',
|
||||
'posix/getnameinfo',
|
||||
'posix/getparam',
|
||||
'posix/getservbyname',
|
||||
'posix/getservbyport',
|
||||
'posix/grp',
|
||||
'posix/dprintf',
|
||||
'posix/posix_memalign',
|
||||
'posix/posix_spawn',
|
||||
'posix/index',
|
||||
'posix/rindex',
|
||||
'posix/search',
|
||||
'posix/semaphore',
|
||||
'posix/open_memstream',
|
||||
'posix/popen',
|
||||
'posix/system', # This test should be in the ANSI tests, but it depends on sys/wait.h
|
||||
'posix/sigsuspend',
|
||||
'posix/sigaltstack',
|
||||
'posix/time',
|
||||
'posix/realpath',
|
||||
'posix/ffs',
|
||||
'posix/getcwd',
|
||||
'posix/memrchr',
|
||||
'posix/wordexp',
|
||||
'posix/rlimits',
|
||||
'posix/accept4',
|
||||
'posix/setpriority',
|
||||
'posix/nice',
|
||||
'posix/alarm',
|
||||
'posix/abort', # This test should be in the ANSI tests, but it depends on sigaction
|
||||
'posix/timer',
|
||||
'posix/vfork',
|
||||
'posix/wcwidth',
|
||||
'posix/pause',
|
||||
'posix/flockfile',
|
||||
'posix/basename',
|
||||
'posix/regex',
|
||||
'posix/sigtimedwait',
|
||||
'posix/if_indextoname',
|
||||
'posix/readv-writev',
|
||||
'posix/posix-timer',
|
||||
'posix/strdupa',
|
||||
'posix/mkstemp',
|
||||
'posix/waitid',
|
||||
'posix/usershell',
|
||||
'posix/shm',
|
||||
'posix/swab',
|
||||
'glibc/getopt',
|
||||
'glibc/ffsl-ffsll',
|
||||
'glibc/error_message_count',
|
||||
'glibc/error_one_per_line',
|
||||
'glibc/error_print_progname',
|
||||
'glibc/error_expect_fail',
|
||||
'glibc/error',
|
||||
'glibc/error_at_line',
|
||||
'glibc/getgrouplist',
|
||||
'glibc/rpmatch',
|
||||
'linux/xattr',
|
||||
'linux/pthread_setname_np',
|
||||
'linux/pthread_attr',
|
||||
'linux/cpuset',
|
||||
'linux/malloc-usable-size',
|
||||
'linux/getifaddrs',
|
||||
'linux/pidfd',
|
||||
'linux/timerfd',
|
||||
'linux/ppoll',
|
||||
'linux/utmp',
|
||||
'linux/utmpx',
|
||||
]
|
||||
|
||||
if host_machine.system() == 'linux'
|
||||
all_test_cases += 'glibc/linux-syscall'
|
||||
endif
|
||||
|
||||
# We only add some tests if the target is the same as the build machine.
|
||||
if build_machine.cpu_family() == target_machine.cpu_family()
|
||||
# process_vm_readv_writev can only run natively beacuse qemu-user doesn't support these syscalls.
|
||||
all_test_cases += 'linux/process_vm_readv_writev'
|
||||
endif
|
||||
|
||||
fail_test_cases = [
|
||||
'posix/abort',
|
||||
'glibc/error_expect_fail',
|
||||
]
|
||||
|
||||
wrapped_test_cases = [
|
||||
'ansi/tz',
|
||||
'glibc/error',
|
||||
'glibc/error_at_line',
|
||||
]
|
||||
|
||||
host_libc_excluded_test_cases = [
|
||||
'bsd/strl', # These functions do not exist on Linux.
|
||||
'glibc/error', # These tests depend on mlibc error messages.
|
||||
'glibc/error_at_line', # These tests depend on mlibc error messages.
|
||||
'rtld/search-order', # See rtld/search-order/meson.build.
|
||||
]
|
||||
host_libc_noasan_test_cases = [
|
||||
'posix/pthread_cancel',
|
||||
'posix/pthread_attr', # does some stack overflowing to check stack size
|
||||
'posix/posix_memalign',
|
||||
'posix/search', # requires tdelete (#351)
|
||||
'ansi/calloc', # does some overflowing
|
||||
'linux/pthread_attr', # encounters memory leaks
|
||||
]
|
||||
|
||||
extra_cflags_test_cases = {
|
||||
'ansi/calloc': ['-Wno-alloc-size-larger-than'],
|
||||
}
|
||||
|
||||
test_sources = []
|
||||
test_objects = []
|
||||
test_link_args = []
|
||||
test_c_args = ['-D_GNU_SOURCE', '-U__MLIBC_DEBUG', '-U__MLIBC_BUILDING_MLIBC', '-fhosted', '-fno-builtin']
|
||||
use_pie = false
|
||||
|
||||
host_test_c_args = ['-fno-builtin']
|
||||
|
||||
c_compiler = meson.get_compiler('c')
|
||||
|
||||
if c_compiler.get_id() == 'gcc'
|
||||
test_c_args += []
|
||||
host_test_c_args += []
|
||||
elif c_compiler.get_id() == 'clang'
|
||||
test_c_args += ['-Wno-unknown-warning-option']
|
||||
host_test_c_args += ['-Wno-unknown-warning-option']
|
||||
endif
|
||||
|
||||
# Our ubsan implementation can't be used by the tests themselves,
|
||||
# since it is internal to libc.so and ld.so.
|
||||
test_override_options = ['b_sanitize=none']
|
||||
|
||||
if library_type == 'static'
|
||||
c_compiler = meson.get_compiler('c')
|
||||
searchdirs = run_command(c_compiler.cmd_array(), '-print-search-dirs',
|
||||
check: true).stdout()
|
||||
searchdirs_arr = searchdirs.split('\n')
|
||||
searchline = 'libraries: ='
|
||||
searchpaths = ''
|
||||
|
||||
foreach line : searchdirs_arr
|
||||
if line.startswith(searchline)
|
||||
searchpaths = line.strip(searchline)
|
||||
break
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if searchpaths == ''
|
||||
error('could not find compiler-specific library directory')
|
||||
endif
|
||||
|
||||
searchpaths_arr = searchpaths.split(':')
|
||||
crtpath = ''
|
||||
fs = import('fs')
|
||||
foreach path : searchpaths_arr
|
||||
if fs.exists(path / 'crtbegin.o')
|
||||
crtpath = path
|
||||
break
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if crtpath == ''
|
||||
error('could not find crtbegin.o/crtend.o')
|
||||
endif
|
||||
test_objects += [crtpath / 'crtbegin.o', crtpath / 'crtend.o']
|
||||
|
||||
libc_dep = declare_dependency(
|
||||
include_directories: libc_include_dirs,
|
||||
link_with: libc_static,
|
||||
dependencies: [libc_deps, rtlib_deps]
|
||||
)
|
||||
use_pie = false
|
||||
test_c_args += '-no-pie'
|
||||
test_link_args += ['-no-pie', '-static']
|
||||
test_sources += crt
|
||||
else
|
||||
libc_dep = declare_dependency(
|
||||
include_directories: libc_include_dirs,
|
||||
link_with: libc_shared,
|
||||
dependencies: [libc_deps, rtlib_deps]
|
||||
)
|
||||
test_link_args += ['-Wl,--dynamic-linker=' + meson.global_build_root() + '/ld.so']
|
||||
|
||||
if host_machine.system() in ['linux']
|
||||
use_pie = true
|
||||
test_sources += crt_pie
|
||||
else
|
||||
use_pie = false
|
||||
test_sources += crt
|
||||
|
||||
# Meson doesn't set these for us (issue #4651).
|
||||
test_c_args += '-no-pie'
|
||||
test_link_args += '-no-pie'
|
||||
endif
|
||||
|
||||
# Add the rtld tests.
|
||||
if posix_option
|
||||
subdir('rtld')
|
||||
endif
|
||||
endif
|
||||
|
||||
py = import('python').find_installation('python3')
|
||||
|
||||
foreach test_name : all_test_cases
|
||||
test_subdir = test_name.split('/')[0]
|
||||
test_short_name = test_name.split('/')[1]
|
||||
test_exec_name = test_name.replace('/', '-')
|
||||
|
||||
if test_subdir == 'bsd' and not bsd_option
|
||||
continue
|
||||
elif test_subdir == 'glibc' and not glibc_option
|
||||
continue
|
||||
elif test_subdir == 'posix' and not posix_option
|
||||
continue
|
||||
elif test_subdir == 'linux' and not linux_option
|
||||
continue
|
||||
endif
|
||||
|
||||
should_fail = fail_test_cases.contains(test_name)
|
||||
exec = executable(test_exec_name, [test_name + '.c', test_sources],
|
||||
dependencies: libc_dep,
|
||||
objects: test_objects,
|
||||
build_rpath: meson.global_build_root(),
|
||||
override_options: test_override_options,
|
||||
c_args: test_c_args,
|
||||
link_args: test_link_args,
|
||||
pie: use_pie,
|
||||
)
|
||||
|
||||
if wrapped_test_cases.contains(test_name)
|
||||
test(test_short_name,
|
||||
py,
|
||||
suite: test_subdir,
|
||||
should_fail: should_fail,
|
||||
args: [
|
||||
meson.global_source_root() + '/tests/' + test_name + '.py',
|
||||
exec
|
||||
],
|
||||
timeout: timeout_sec,
|
||||
)
|
||||
else
|
||||
test(test_short_name, exec, suite: test_subdir, should_fail: should_fail, timeout: timeout_sec)
|
||||
endif
|
||||
|
||||
if build_tests_host_libc and not host_libc_excluded_test_cases.contains(test_name)
|
||||
if test_name in host_libc_noasan_test_cases
|
||||
host_libc_sanitize_options = 'b_sanitize=undefined'
|
||||
else
|
||||
host_libc_sanitize_options = 'b_sanitize=address,undefined'
|
||||
endif
|
||||
|
||||
if test_name in extra_cflags_test_cases
|
||||
extra_cflags = extra_cflags_test_cases[test_name]
|
||||
else
|
||||
extra_cflags = []
|
||||
endif
|
||||
|
||||
exec = executable('host-libc-' + test_exec_name, test_name + '.c',
|
||||
build_rpath: meson.global_build_root(),
|
||||
override_options: host_libc_sanitize_options,
|
||||
c_args: [host_test_c_args + '-D_GNU_SOURCE', '-DUSE_HOST_LIBC', '-pthread', extra_cflags],
|
||||
link_args: ['-lresolv', '-ldl', '-pthread', '-lm', '-lrt'],
|
||||
native: true,
|
||||
)
|
||||
|
||||
if wrapped_test_cases.contains(test_name)
|
||||
test(test_short_name,
|
||||
py,
|
||||
suite: ['host-libc', test_subdir],
|
||||
should_fail: should_fail,
|
||||
args: [
|
||||
meson.source_root() + '/tests/' + test_name + '.py',
|
||||
exec
|
||||
],
|
||||
timeout: timeout_sec,
|
||||
)
|
||||
else
|
||||
test(test_short_name, exec, suite: ['host-libc', test_subdir], should_fail: should_fail, timeout: timeout_sec)
|
||||
endif
|
||||
endif
|
||||
endforeach
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void handler(int sig, siginfo_t *info, void *ctx) {
|
||||
(void)sig;
|
||||
(void)info;
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
int main() {
|
||||
struct sigaction sa;
|
||||
sa.sa_sigaction = handler;
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
int ret = sigaction(SIGABRT, &sa, NULL);
|
||||
assert(!ret);
|
||||
|
||||
abort();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_PORT 31337
|
||||
#else
|
||||
#define TEST_PORT 42069
|
||||
#endif
|
||||
|
||||
static struct sockaddr_in connect_addr, accept_addr;
|
||||
static int listen_fd;
|
||||
|
||||
int permutations[] = {
|
||||
0,
|
||||
SOCK_CLOEXEC,
|
||||
SOCK_NONBLOCK,
|
||||
SOCK_CLOEXEC | SOCK_NONBLOCK,
|
||||
};
|
||||
|
||||
static bool run_test(int flags)
|
||||
{
|
||||
int connect_fd;
|
||||
int fd_flags, access;
|
||||
socklen_t addrlen;
|
||||
|
||||
connect_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
connect(connect_fd, (struct sockaddr *)&connect_addr, sizeof(connect_addr));
|
||||
addrlen = sizeof(accept_addr);
|
||||
|
||||
int accept_fd = accept4(listen_fd, (struct sockaddr *)&accept_addr, &addrlen, flags);
|
||||
|
||||
if(accept_fd == -1) {
|
||||
fprintf(stderr, "accept4 failed: %s\n", strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
fd_flags = fcntl(accept_fd, F_GETFD);
|
||||
if(!(!!(fd_flags & FD_CLOEXEC) == !!(flags & SOCK_CLOEXEC))) {
|
||||
fprintf(stderr, "CLOEXEC mismatch, got %d instead of %d\n", !!(fd_flags & FD_CLOEXEC), !!(flags & SOCK_CLOEXEC));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
access = fcntl(accept_fd, F_GETFL);
|
||||
if(!(!!(access & O_NONBLOCK) == !!(flags & SOCK_NONBLOCK))) {
|
||||
fprintf(stderr, "NONBLOCK flag mismatch, %d vs %d\n", !!(access & O_NONBLOCK), !!(flags & SOCK_NONBLOCK));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
close(accept_fd);
|
||||
close(connect_fd);
|
||||
|
||||
fprintf(stderr, "tested CLOEXEC %d, NONBLOCK %d\n", !!(flags & SOCK_CLOEXEC), !!(flags & SOCK_NONBLOCK));
|
||||
return true;
|
||||
|
||||
cleanup:
|
||||
close(accept_fd);
|
||||
close(connect_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int socket_setup(void)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int reuseaddr;
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addr.sin_port = htons(TEST_PORT);
|
||||
|
||||
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if(socket_fd == -1) {
|
||||
fprintf(stderr, "socket failed: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
reuseaddr = 1;
|
||||
int ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
|
||||
|
||||
if(ret == -1) {
|
||||
fprintf(stderr, "setsockopt failed: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = bind(socket_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
|
||||
|
||||
if(ret == -1) {
|
||||
fprintf(stderr, "bind failed: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = listen(socket_fd, 5);
|
||||
|
||||
if(ret == -1) {
|
||||
fprintf(stderr, "listen failed: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return socket_fd;
|
||||
}
|
||||
|
||||
int main() {
|
||||
memset(&connect_addr, 0, sizeof(connect_addr));
|
||||
connect_addr.sin_family = AF_INET;
|
||||
connect_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
connect_addr.sin_port = htons(TEST_PORT);
|
||||
|
||||
for(size_t i = 0; i < 4; i++) {
|
||||
listen_fd = socket_setup();
|
||||
if(!run_test(permutations[i])) {
|
||||
exit(1);
|
||||
}
|
||||
close(listen_fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "access-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "access.tmp"
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
// Make sure that it wasn't created by a previous test run
|
||||
unlink(TEST_FILE);
|
||||
|
||||
assert(access(TEST_FILE, F_OK) == -1);
|
||||
assert(access(TEST_FILE, W_OK) == -1);
|
||||
assert(access(TEST_FILE, R_OK) == -1);
|
||||
assert(access(TEST_FILE, X_OK) == -1);
|
||||
|
||||
close(open(TEST_FILE, O_CREAT | O_RDWR, 0666));
|
||||
|
||||
assert(access(TEST_FILE, F_OK) == 0);
|
||||
assert(access(TEST_FILE, W_OK) == 0);
|
||||
assert(access(TEST_FILE, R_OK) == 0);
|
||||
assert(access(TEST_FILE, X_OK) == -1);
|
||||
|
||||
unlink(TEST_FILE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static volatile int alarms_fired = 0;
|
||||
|
||||
static void sigalrm_handler(int signal) {
|
||||
if(signal == SIGALRM)
|
||||
alarms_fired++;
|
||||
}
|
||||
|
||||
int main() {
|
||||
signal(SIGALRM, sigalrm_handler);
|
||||
|
||||
alarms_fired = 0;
|
||||
|
||||
unsigned int ret = alarm(10);
|
||||
assert(!ret);
|
||||
|
||||
sleep(1);
|
||||
|
||||
ret = alarm(1);
|
||||
assert(ret == 9);
|
||||
|
||||
sleep(2);
|
||||
|
||||
if(alarms_fired != 1) {
|
||||
fprintf(stderr, "alarm handler fired %u times instead of 1\n", alarms_fired);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <assert.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
/* intentionally a macro: basename modifies its argument */
|
||||
#define test_string(x, expectval) do { \
|
||||
char str[] = x; \
|
||||
assert(strcmp(basename(str), expectval) == 0); \
|
||||
} while (0)
|
||||
|
||||
test_string("/usr/lib", "lib");
|
||||
test_string("/usr/", "usr");
|
||||
test_string("/", "/");
|
||||
test_string(".", ".");
|
||||
test_string("..", "..");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "dprintf-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "dprintf.tmp"
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
int fd = open(TEST_FILE, O_RDWR | O_CREAT, 0666);
|
||||
assert(fd > -1);
|
||||
|
||||
int ret = dprintf(fd, "aaa");
|
||||
assert(ret == 3);
|
||||
|
||||
// Check if we can read back the same things.
|
||||
// Also checks to see if the fd is still open,
|
||||
// which is issue #199.
|
||||
|
||||
off_t seek = lseek(fd, 0, SEEK_SET);
|
||||
assert(seek == 0);
|
||||
|
||||
char buf[3];
|
||||
ssize_t num_read = read(fd, buf, 3);
|
||||
|
||||
assert(num_read == 3);
|
||||
assert(buf[0] == 'a'
|
||||
&& buf[1] == 'a'
|
||||
&& buf[2] == 'a');
|
||||
|
||||
// All the tests pass, now we can unlink the file.
|
||||
ret = unlink(TEST_FILE);
|
||||
assert(ret == 0);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define TEST_FILE "fdopen.tmp"
|
||||
|
||||
int main() {
|
||||
int fd = open(TEST_FILE, O_CREAT | O_RDWR, 0666);
|
||||
assert(fd >= 0);
|
||||
|
||||
char *str = "mlibc fdopen test";
|
||||
assert(write(fd, str, strlen(str)));
|
||||
|
||||
// Seek to the beginning, then reopen with fdopen in append mode.
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
FILE *file = fdopen(fd, "a");
|
||||
assert(file);
|
||||
|
||||
// Append and close.
|
||||
str = " appended";
|
||||
fwrite(str, strlen(str), 1, file);
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
|
||||
// Open it again and check that the append succeeded.
|
||||
fd = open(TEST_FILE, O_RDONLY);
|
||||
assert(fd >= 0);
|
||||
file = fdopen(fd, "r");
|
||||
assert(file);
|
||||
str = "mlibc fdopen test appended";
|
||||
char buf[100] = {0};
|
||||
assert(fread(buf, 1, strlen(str), file));
|
||||
assert(!strcmp(buf, str));
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <assert.h>
|
||||
#include <strings.h>
|
||||
#include <limits.h>
|
||||
|
||||
int main(void){
|
||||
assert(ffs(0x8000) == 16);
|
||||
assert(ffs(0) == 0);
|
||||
assert(ffs(INT_MAX - 1) == 2);
|
||||
assert(ffs(INT_MAX) == 1);
|
||||
assert(ffs(INT_MIN) == (int)(sizeof(int) * CHAR_BIT));
|
||||
assert(ffs(INT_MIN + 1) == 1);
|
||||
|
||||
for (int i = 1; i < 0x1000; i++) {
|
||||
assert(ffs(i) - 1 == __builtin_ctz(i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void *worker(void *arg) {
|
||||
(void)arg;
|
||||
flockfile(stdout);
|
||||
fputs_unlocked("hello from worker", stdout);
|
||||
funlockfile(stdout);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Check that recursive locking works.
|
||||
assert(!ftrylockfile(stdout));
|
||||
flockfile(stdout);
|
||||
flockfile(stdout);
|
||||
funlockfile(stdout);
|
||||
funlockfile(stdout);
|
||||
funlockfile(stdout);
|
||||
|
||||
assert(!ftrylockfile(stdout));
|
||||
|
||||
pthread_t thread;
|
||||
int ret = pthread_create(&thread, NULL, &worker, NULL);
|
||||
assert(!ret);
|
||||
|
||||
sleep(1);
|
||||
funlockfile(stdout);
|
||||
|
||||
assert(!pthread_join(thread, NULL));
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUFFER0_SIZE 0x1000
|
||||
#define BUFFER1 "Hello world"
|
||||
#define BUFFER1_SIZE (sizeof(BUFFER1))
|
||||
|
||||
int main() {
|
||||
// test seek with mode "r"
|
||||
FILE *f = fmemopen(NULL, BUFFER0_SIZE, "r");
|
||||
assert(f);
|
||||
|
||||
int ret = fseek(f, 0, SEEK_END);
|
||||
assert(!ret);
|
||||
long pos = ftell(f);
|
||||
fprintf(stderr, "pos = %ld\n", pos);
|
||||
// Despite the fact that this is correct behavior (see below),
|
||||
// this sometimes fails on glibc; newlib seems to get this wrong, too.
|
||||
// to quote what posix says about it:
|
||||
// > The stream shall also maintain the size of the current buffer contents;
|
||||
// > use of fseek() or fseeko() on the stream with SEEK_END shall seek relative to this size.
|
||||
// > For modes r and r+ the size shall be set to the value given by the size argument.
|
||||
#if !defined(__GLIBC__)
|
||||
assert(pos == BUFFER0_SIZE);
|
||||
#endif
|
||||
|
||||
fclose(f);
|
||||
|
||||
// test seek with mode "w"
|
||||
f = fmemopen(NULL, BUFFER0_SIZE, "w");
|
||||
assert(f);
|
||||
|
||||
ret = fseek(f, 0, SEEK_END);
|
||||
assert(!ret);
|
||||
pos = ftell(f);
|
||||
assert(pos == 0);
|
||||
|
||||
fclose(f);
|
||||
|
||||
// test seek with mode "a" and a NULL buffer
|
||||
f = fmemopen(NULL, BUFFER0_SIZE, "a");
|
||||
assert(f);
|
||||
|
||||
ret = fseek(f, 0, SEEK_END);
|
||||
assert(!ret);
|
||||
pos = ftell(f);
|
||||
assert(pos == 0);
|
||||
|
||||
fclose(f);
|
||||
|
||||
// test seek with mode "a" and a buffer containing a '\0'
|
||||
f = fmemopen(BUFFER1, BUFFER1_SIZE + 2, "a");
|
||||
assert(f);
|
||||
|
||||
pos = ftell(f);
|
||||
assert(pos == (long) (BUFFER1_SIZE - 1));
|
||||
|
||||
ret = fseek(f, 0, SEEK_SET);
|
||||
assert(!ret);
|
||||
pos = ftell(f);
|
||||
assert(!pos);
|
||||
|
||||
ret = fseek(f, 0, SEEK_END);
|
||||
assert(!ret);
|
||||
pos = ftell(f);
|
||||
assert(pos == (long) (BUFFER1_SIZE - 1));
|
||||
|
||||
fclose(f);
|
||||
|
||||
// test seek with mode "a" and a buffer not containing a '\0'
|
||||
f = fmemopen(BUFFER1, BUFFER1_SIZE - 2, "a");
|
||||
assert(f);
|
||||
|
||||
ret = fseek(f, 0, SEEK_END);
|
||||
assert(!ret);
|
||||
pos = ftell(f);
|
||||
assert(pos == (long) (BUFFER1_SIZE - 2));
|
||||
|
||||
fclose(f);
|
||||
|
||||
f = fmemopen(BUFFER1, BUFFER1_SIZE, "r");
|
||||
assert(f);
|
||||
|
||||
ret = fseek(f, 0, SEEK_SET);
|
||||
assert(!ret);
|
||||
|
||||
char buf[BUFFER1_SIZE];
|
||||
int read = fread(buf, 1, BUFFER1_SIZE - 2, f);
|
||||
assert(read == BUFFER1_SIZE - 2);
|
||||
assert(!strncmp(BUFFER1, buf, BUFFER1_SIZE - 2));
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
|
||||
read = fread(buf, 1, 2, f);
|
||||
assert(read == 0);
|
||||
assert(feof(f));
|
||||
|
||||
fclose(f);
|
||||
|
||||
// Open a buffer for read+write
|
||||
char *buf1 = strdup(BUFFER1);
|
||||
f = fmemopen(buf1, BUFFER1_SIZE, "w+");
|
||||
assert(f);
|
||||
assert(strlen(BUFFER1) == BUFFER1_SIZE - 1);
|
||||
|
||||
// seek to somewhere in the middle of the buffer
|
||||
fseek(f, BUFFER1_SIZE - 5, SEEK_SET);
|
||||
// write as much data to it as possible
|
||||
read = fwrite(BUFFER1, 1, 9, f);
|
||||
rewind(f);
|
||||
|
||||
// seek the the same position in the middle of the buffer
|
||||
ret = fseek(f, BUFFER1_SIZE - 5, SEEK_SET);
|
||||
assert(!ret);
|
||||
memset(buf, 0, BUFFER1_SIZE);
|
||||
// read what we just wrote
|
||||
read = fread(buf, 1, 5, f);
|
||||
// check that the write got correctly truncated
|
||||
fprintf(stderr, "buf '%s' (%zu)\n", buf, strlen(buf));
|
||||
assert(!strncmp(BUFFER1, buf, 4) && strlen(buf) == 4);
|
||||
|
||||
fclose(f);
|
||||
free(buf1);
|
||||
|
||||
char *buf2 = strdup(BUFFER1);
|
||||
f = fmemopen(buf2, 0, "r");
|
||||
assert(f || errno == EINVAL);
|
||||
|
||||
if(f) {
|
||||
memset(buf, 0, BUFFER1_SIZE);
|
||||
read = fread(buf, 10, 1, f);
|
||||
assert(!read);
|
||||
rewind(f);
|
||||
|
||||
read = fwrite(BUFFER1, 1, 12, f);
|
||||
assert(read == 0);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
free(buf2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct testcookie {
|
||||
bool read;
|
||||
bool write;
|
||||
bool seek;
|
||||
bool close;
|
||||
};
|
||||
|
||||
ssize_t cookie_read(void *c, char *buf, size_t size) {
|
||||
(void) buf;
|
||||
struct testcookie *cookie = c;
|
||||
cookie->read = true;
|
||||
return size;
|
||||
}
|
||||
|
||||
ssize_t cookie_write(void *c, const char *buf, size_t size) {
|
||||
(void) buf;
|
||||
struct testcookie *cookie = c;
|
||||
cookie->write = true;
|
||||
return size;
|
||||
}
|
||||
|
||||
int cookie_seek(void *c, off64_t *offset, int whence) {
|
||||
(void) offset;
|
||||
(void) whence;
|
||||
struct testcookie *cookie = c;
|
||||
cookie->seek = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cookie_close(void *c) {
|
||||
struct testcookie *cookie = c;
|
||||
cookie->close = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
struct testcookie cookie = { false, false, false, false };
|
||||
|
||||
cookie_io_functions_t funcs = {
|
||||
.read = cookie_read,
|
||||
.write = cookie_write,
|
||||
.seek = cookie_seek,
|
||||
.close = cookie_close,
|
||||
};
|
||||
|
||||
FILE *stream = fopencookie(&cookie, "w+", funcs);
|
||||
assert(stream);
|
||||
|
||||
unsigned char buf[1];
|
||||
int ret = fread(buf, 1, 1, stream);
|
||||
assert(ret == 1);
|
||||
ret = fwrite(buf, 1, 1, stream);
|
||||
assert(ret == 1);
|
||||
ret = fseek(stream, 0, SEEK_SET);
|
||||
assert(!ret);
|
||||
|
||||
ret = fclose(stream);
|
||||
assert(!ret);
|
||||
|
||||
assert(cookie.read && cookie.write && cookie.seek && cookie.close);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
#if !defined(USE_HOST_LIBC)
|
||||
#include <mlibc-config.h>
|
||||
#endif
|
||||
|
||||
#include <netdb.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if __MLIBC_LINUX_OPTION || defined(USE_HOST_LIBC)
|
||||
#include <ifaddrs.h>
|
||||
|
||||
static bool has_ipv4_addr(void) {
|
||||
struct ifaddrs *addrs;
|
||||
if (getifaddrs(&addrs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int found = 0;
|
||||
for (struct ifaddrs *cur = addrs; cur; cur = cur->ifa_next) {
|
||||
if (cur->ifa_addr && (cur->ifa_flags & IFF_UP) && cur->ifa_addr->sa_family == AF_INET && strncmp(cur->ifa_name, "lo", IF_NAMESIZE)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(addrs);
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool has_ipv6_addr(void) {
|
||||
struct ifaddrs *addrs;
|
||||
if (getifaddrs(&addrs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int found = 0;
|
||||
for (struct ifaddrs *cur = addrs; cur; cur = cur->ifa_next) {
|
||||
if (cur->ifa_addr && (cur->ifa_flags & IFF_UP) && cur->ifa_addr->sa_family == AF_INET6 && strncmp(cur->ifa_name, "lo", IF_NAMESIZE)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(addrs);
|
||||
return found;
|
||||
}
|
||||
#endif // __MLIBC_LINUX_OPTION || defined(USE_HOST_LIBC)
|
||||
|
||||
int main() {
|
||||
struct addrinfo *res = NULL;
|
||||
struct addrinfo hints = {0};
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
int ret = getaddrinfo(NULL, "443", &hints, &res);
|
||||
assert(ret == 0);
|
||||
|
||||
struct sockaddr_in *addr = (struct sockaddr_in*)(res[0].ai_addr);
|
||||
assert(addr->sin_port == htons(443));
|
||||
assert(res[0].ai_socktype == SOCK_STREAM);
|
||||
assert(res[0].ai_protocol == IPPROTO_TCP);
|
||||
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
/* check we can resolve any domain */
|
||||
ret = getaddrinfo("example.net", NULL, &hints, &res);
|
||||
assert(ret == 0);
|
||||
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
ret = getaddrinfo("10.10.10.10", NULL, &hints, &res);
|
||||
assert(ret == 0);
|
||||
|
||||
addr = (struct sockaddr_in*)res[0].ai_addr;
|
||||
assert((addr->sin_addr.s_addr & 0xFF) == 10);
|
||||
assert(((addr->sin_addr.s_addr >> 8) & 0xFF) == 10);
|
||||
assert(((addr->sin_addr.s_addr >> 16) & 0xFF) == 10);
|
||||
assert(((addr->sin_addr.s_addr >> 24) & 0xFF) == 10);
|
||||
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
ret = getaddrinfo("example.net", NULL, &hints, &res);
|
||||
assert(ret == EAI_NONAME);
|
||||
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
hints.ai_family = AF_INET6;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
ret = getaddrinfo("::1", "1234", &hints, &res);
|
||||
assert(ret == 0);
|
||||
|
||||
assert(res[0].ai_family == AF_INET6);
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6*) res[0].ai_addr;
|
||||
assert(addr6->sin6_port == htons(1234));
|
||||
assert(addr6->sin6_addr.s6_addr[15] == 1);
|
||||
for (int i = 0; i < 15; i++) {
|
||||
assert(addr6->sin6_addr.s6_addr[i] == 0);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
hints.ai_family = AF_INET6;
|
||||
hints.ai_flags = 0;
|
||||
ret = getaddrinfo("example.net", "443", &hints, &res);
|
||||
assert(ret == 0);
|
||||
|
||||
assert(res[0].ai_family == AF_INET6);
|
||||
addr6 = (struct sockaddr_in6*)res[0].ai_addr;
|
||||
assert(addr6->sin6_port == htons(443));
|
||||
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
#if __MLIBC_LINUX_OPTION || defined(USE_HOST_LIBC)
|
||||
// Test with AF_INET
|
||||
hints.ai_family = AF_INET;
|
||||
ret = getaddrinfo("localhost", NULL, &hints, &res);
|
||||
if (has_ipv4_addr()) {
|
||||
assert(ret == 0);
|
||||
for(struct addrinfo *p = res; p != NULL; p = p->ai_next) {
|
||||
assert(p->ai_family == AF_INET);
|
||||
}
|
||||
} else {
|
||||
assert(ret != 0);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
// Test with AF_INET6
|
||||
hints.ai_family = AF_INET6;
|
||||
ret = getaddrinfo("localhost", NULL, &hints, &res);
|
||||
assert(ret == 0);
|
||||
for(struct addrinfo *p = res; p != NULL; p = p->ai_next) {
|
||||
assert(p->ai_family == AF_INET6);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
// Test AI_ADDRCONFIG
|
||||
hints = (struct addrinfo){0};
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
||||
ret = getaddrinfo("localhost", NULL, &hints, &res);
|
||||
|
||||
if (ret == 0) {
|
||||
int found_ipv4 = 0;
|
||||
int found_ipv6 = 0;
|
||||
for(struct addrinfo *p = res; p != NULL; p = p->ai_next) {
|
||||
if (p->ai_family == AF_INET)
|
||||
found_ipv4 = 1;
|
||||
else if (p->ai_family == AF_INET6)
|
||||
found_ipv6 = 1;
|
||||
}
|
||||
|
||||
if (has_ipv4_addr())
|
||||
assert(found_ipv4);
|
||||
else
|
||||
assert(!found_ipv4);
|
||||
|
||||
if (has_ipv6_addr())
|
||||
assert(found_ipv6);
|
||||
else
|
||||
assert(!found_ipv6);
|
||||
} else {
|
||||
// If getaddrinfo fails, it should be because no addresses are configured.
|
||||
assert(!has_ipv4_addr() && !has_ipv6_addr());
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
#endif // __MLIBC_LINUX_OPTION || defined(USE_HOST_LIBC)
|
||||
|
||||
// Test AI_NUMERICSERV.
|
||||
hints = (struct addrinfo){0};
|
||||
hints.ai_flags = AI_NUMERICSERV;
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
ret = getaddrinfo(NULL, "8080", &hints, &res);
|
||||
assert(ret == 0);
|
||||
assert(res->ai_family == AF_INET);
|
||||
struct sockaddr_in *addr_in = (struct sockaddr_in *)res->ai_addr;
|
||||
assert(addr_in->sin_port == htons(8080));
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
ret = getaddrinfo(NULL, "http", &hints, &res);
|
||||
assert(ret == EAI_NONAME);
|
||||
assert(res == NULL);
|
||||
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
ret = getaddrinfo(NULL, "9090", &hints, &res);
|
||||
assert(ret == 0);
|
||||
assert(res->ai_family == AF_INET6);
|
||||
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res->ai_addr;
|
||||
assert(addr_in6->sin6_port == htons(9090));
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
ret = getaddrinfo(NULL, "https", &hints, &res);
|
||||
assert(ret == EAI_NONAME);
|
||||
assert(res == NULL);
|
||||
|
||||
// Test for NXDOMAIN
|
||||
hints = (struct addrinfo){0};
|
||||
ret = getaddrinfo("this-domain-should-not-exist.nxdomain", NULL, &hints, &res);
|
||||
assert(ret == EAI_NONAME);
|
||||
assert(res == NULL);
|
||||
|
||||
// Test AI_CANONNAME.
|
||||
hints = (struct addrinfo){0};
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
ret = getaddrinfo("localhost.localdomain", NULL, &hints, &res);
|
||||
assert(ret == 0);
|
||||
assert(res->ai_canonname);
|
||||
freeaddrinfo(res);
|
||||
res = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
char buf[PATH_MAX];
|
||||
char *ret = getcwd(buf, PATH_MAX);
|
||||
|
||||
assert(ret);
|
||||
assert((strlen(ret) == strlen(buf)) && strlen(ret));
|
||||
assert(!strcmp(ret, buf));
|
||||
|
||||
char *ret2 = getcwd(NULL, 0);
|
||||
assert(ret2);
|
||||
assert(strlen(ret2));
|
||||
assert(!strcmp(ret, ret2));
|
||||
free(ret2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "getdelim-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "getdelim.tmp"
|
||||
#endif
|
||||
|
||||
int main(void) {
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
// We have to open the file for writing and then reading separately,
|
||||
// as mlibc doesn't allow us to do both at the same time (yet).
|
||||
fp = fopen(TEST_FILE, "w");
|
||||
assert(fp);
|
||||
fputs("foo\nbar\nbaz\nquux\n", fp);
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen(TEST_FILE, "r");
|
||||
assert(fp);
|
||||
while ((read = getline(&line, &len, fp)) != -1) {
|
||||
printf("read line of length %zd, capacity %zu\n", read, len);
|
||||
}
|
||||
assert(!ferror(fp));
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
size_t nchars = 10000;
|
||||
fp = fopen(TEST_FILE, "w");
|
||||
assert(fp);
|
||||
for (size_t i = 0; i < nchars; i++)
|
||||
fputc('a', fp);
|
||||
fputc('b', fp);
|
||||
fclose(fp);
|
||||
|
||||
line = NULL;
|
||||
len = 0;
|
||||
fp = fopen(TEST_FILE, "r");
|
||||
assert(fp);
|
||||
while ((read = getdelim(&line, &len, 'b', fp)) != -1) {
|
||||
printf("read line of length %zd, capacity %zu\n", read, len);
|
||||
assert((size_t)read == nchars + 1);
|
||||
}
|
||||
|
||||
assert(len > nchars + 1);
|
||||
assert(!ferror(fp));
|
||||
assert(feof(fp));
|
||||
|
||||
assert(getdelim(&line, &len, 'b', fp) == -1);
|
||||
assert(feof(fp));
|
||||
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen(TEST_FILE, "w");
|
||||
assert(fp);
|
||||
assert(fwrite("1234ef\0f", 1, 8, fp) == 8);
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen(TEST_FILE, "r");
|
||||
assert(fp);
|
||||
|
||||
/* test with line = NULL and large len */
|
||||
line = NULL;
|
||||
len = (size_t) ~0;
|
||||
assert(getdelim(&line, &len, 'e', fp) == 5);
|
||||
assert(!memcmp(line, "1234e", 6));
|
||||
assert(5 < len);
|
||||
|
||||
/* test handling of internal nulls */
|
||||
assert(getdelim(&line, &len, 'e', fp) == 3);
|
||||
assert(!memcmp(line, "f\0f", 4));
|
||||
assert(3 < len);
|
||||
|
||||
/* test handling of EOF */
|
||||
assert(getdelim(&line, &len, 'e', fp) == -1);
|
||||
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
// Delete the file
|
||||
unlink(TEST_FILE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <netdb.h>
|
||||
#include <assert.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
assert(inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr));
|
||||
|
||||
char host[64];
|
||||
assert(!getnameinfo((struct sockaddr*)&addr, sizeof(addr), host,
|
||||
sizeof(host), NULL, 0, 0));
|
||||
|
||||
assert(inet_pton(AF_INET, "8.8.8.8", &addr.sin_addr));
|
||||
|
||||
assert(!getnameinfo((struct sockaddr*)&addr, sizeof(addr), host,
|
||||
sizeof(host), NULL, 0, 0));
|
||||
assert(!strcmp(host, "dns.google"));
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
struct sched_param param = {
|
||||
.sched_priority = 100,
|
||||
};
|
||||
|
||||
int ret = sched_getparam(getpid(), ¶m);
|
||||
assert(!ret);
|
||||
|
||||
ret = sched_setparam(getpid(), ¶m);
|
||||
assert(ret == 0);
|
||||
|
||||
param.sched_priority = 0xD00DFEED;
|
||||
|
||||
ret = sched_setparam(getpid(), ¶m);
|
||||
assert(ret == -1 && errno == EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <assert.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
int main() {
|
||||
struct servent *ret = getservbyname("http", "tcp");
|
||||
assert(ret);
|
||||
assert(!strcmp("http", ret->s_name));
|
||||
assert(ret->s_port == htons(80));
|
||||
assert(!strcmp("tcp", ret->s_proto));
|
||||
|
||||
ret = getservbyname("http", NULL);
|
||||
assert(ret);
|
||||
assert(!strcmp("http", ret->s_name));
|
||||
assert(ret->s_port == htons(80));
|
||||
assert(!strcmp("tcp", ret->s_proto));
|
||||
|
||||
ret = getservbyname("babel", "udp");
|
||||
assert(ret);
|
||||
ret = getservbyname("babel", "tcp");
|
||||
assert(!ret);
|
||||
|
||||
ret = getservbyname("", NULL);
|
||||
assert(!ret);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
struct servent *ret = getservbyport(htons(80), "tcp");
|
||||
assert(ret);
|
||||
assert(!strcmp("http", ret->s_name));
|
||||
assert(ret->s_port == htons(80));
|
||||
assert(!strcmp("tcp", ret->s_proto));
|
||||
|
||||
ret = getservbyport(htons(80), NULL);
|
||||
assert(ret);
|
||||
assert(!strcmp("http", ret->s_name));
|
||||
assert(ret->s_port == htons(80));
|
||||
assert(!strcmp("tcp", ret->s_proto));
|
||||
|
||||
ret = getservbyport(htons(6696), "udp");
|
||||
assert(ret);
|
||||
ret = getservbyport(htons(6696), "tcp");
|
||||
assert(!ret);
|
||||
|
||||
ret = getservbyport(htons(0), NULL);
|
||||
assert(!ret);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <grp.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void check_root_group(struct group *grp) {
|
||||
assert(grp);
|
||||
|
||||
printf("group name: %s\n", grp->gr_name);
|
||||
fflush(stdout);
|
||||
|
||||
assert(grp->gr_gid == 0);
|
||||
assert(!strcmp(grp->gr_name, "root"));
|
||||
|
||||
// Depending on your system, the root group may or may not contain the root user.
|
||||
if (grp->gr_mem[0] != NULL) {
|
||||
bool found = false;
|
||||
for (size_t i = 0; grp->gr_mem[i] != NULL; i++) {
|
||||
printf("group member: %s\n", grp->gr_mem[i]);
|
||||
fflush(stdout);
|
||||
|
||||
if (!strcmp(grp->gr_mem[i], "root")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(found);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct group grp, *result = NULL;
|
||||
char *buf;
|
||||
size_t bufsize;
|
||||
int s;
|
||||
bool password = false;
|
||||
char *members[3];
|
||||
char filename[] = "grpXXXXXX";
|
||||
int tmpfd;
|
||||
FILE *tmp;
|
||||
char *expected = "managarm:passwordhash:12345:managarm,mlibc\n";
|
||||
size_t readsize;
|
||||
|
||||
bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||
assert(bufsize > 0 && bufsize < 0x100000);
|
||||
|
||||
buf = malloc(bufsize);
|
||||
assert(buf);
|
||||
|
||||
s = getgrnam_r("root", &grp, buf, bufsize, &result);
|
||||
assert(!s);
|
||||
check_root_group(result);
|
||||
|
||||
s = getgrgid_r(0, &grp, buf, bufsize, &result);
|
||||
assert(!s);
|
||||
check_root_group(result);
|
||||
|
||||
result = getgrnam("root");
|
||||
check_root_group(result);
|
||||
|
||||
result = getgrgid(0);
|
||||
check_root_group(result);
|
||||
|
||||
result = getgrnam("this_group_doesnt_exist");
|
||||
assert(!result);
|
||||
#ifndef USE_HOST_LIBC
|
||||
// This is not guaranteed.
|
||||
assert(errno == ESRCH);
|
||||
#endif
|
||||
|
||||
s = getgrnam_r("this_group_doesnt_exist", &grp, buf, bufsize, &result);
|
||||
assert(!result);
|
||||
#ifndef USE_HOST_LIBC
|
||||
// This is not guaranteed.
|
||||
assert(s == ESRCH);
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
setgrent();
|
||||
assert(errno == 0);
|
||||
|
||||
result = getgrent();
|
||||
assert(result);
|
||||
grp.gr_name = strdup(result->gr_name);
|
||||
if(result->gr_passwd) {
|
||||
password = true;
|
||||
}
|
||||
grp.gr_passwd = strdup(result->gr_passwd);
|
||||
grp.gr_gid = result->gr_gid;
|
||||
assert(grp.gr_name);
|
||||
if(password)
|
||||
assert(grp.gr_passwd);
|
||||
|
||||
assert(grp.gr_name);
|
||||
if(password)
|
||||
assert(grp.gr_passwd);
|
||||
|
||||
endgrent();
|
||||
|
||||
result = getgrent();
|
||||
assert(result);
|
||||
assert(strcmp(result->gr_name, grp.gr_name) == 0);
|
||||
if(password)
|
||||
assert(strcmp(result->gr_passwd, grp.gr_passwd) == 0);
|
||||
assert(result->gr_gid == grp.gr_gid);
|
||||
|
||||
free(grp.gr_name);
|
||||
if(password)
|
||||
free(grp.gr_passwd);
|
||||
|
||||
grp.gr_name = "managarm";
|
||||
grp.gr_passwd = "passwordhash";
|
||||
grp.gr_gid = 12345;
|
||||
members[0] = "managarm";
|
||||
members[1] = "mli:bc";
|
||||
members[2] = NULL;
|
||||
grp.gr_mem = members;
|
||||
|
||||
// tmpfile() cannot be used because its unimplemented in mlibc.
|
||||
tmpfd = mkstemp(filename);
|
||||
assert(tmpfd);
|
||||
tmp = fdopen(tmpfd, "w+");
|
||||
assert(tmp);
|
||||
|
||||
assert(putgrent(NULL, tmp) < 0);
|
||||
assert(putgrent(&grp, tmp) < 0);
|
||||
|
||||
members[1] = "mlibc";
|
||||
|
||||
grp.gr_name = "mana:garm";
|
||||
assert(putgrent(&grp, tmp) < 0);
|
||||
grp.gr_name = "managarm";
|
||||
|
||||
grp.gr_passwd = "passwordhash\n";
|
||||
assert(putgrent(&grp, tmp) < 0);
|
||||
grp.gr_passwd = "passwordhash";
|
||||
|
||||
assert(putgrent(&grp, tmp) == 0);
|
||||
rewind(tmp);
|
||||
|
||||
readsize = fread(buf, 1, bufsize, tmp);
|
||||
assert(readsize == strlen(expected));
|
||||
assert(strncmp(expected, buf, strlen(expected)) == 0);
|
||||
|
||||
fclose(tmp);
|
||||
unlink(filename);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <assert.h>
|
||||
#include <net/if.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
char name[IF_NAMESIZE];
|
||||
|
||||
assert(name == if_indextoname(1, name));
|
||||
printf("test: name '%s'\n", name);
|
||||
assert(1 == if_nametoindex(name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <assert.h>
|
||||
#include <strings.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int main() {
|
||||
char str[] = "This is a sample string";
|
||||
char *pch;
|
||||
// The character 's' is at position 4, 7, 11 and 18
|
||||
pch = index(str, 's');
|
||||
assert(pch - str + 1 == 4);
|
||||
pch = index(pch + 1, 's');
|
||||
assert(pch - str + 1 == 7);
|
||||
pch = index(pch + 1, 's');
|
||||
assert(pch - str + 1 == 11);
|
||||
pch = index(pch + 1, 's');
|
||||
assert(pch - str + 1 == 18);
|
||||
pch = index(pch + 1, 's');
|
||||
assert(pch == NULL);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
struct in_addr addr;
|
||||
addr.s_addr = (1 << 24) |
|
||||
(1 << 16) | (1 << 8) | 1;
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
assert(inet_ntop(AF_INET, &addr, buf, INET_ADDRSTRLEN) != NULL);
|
||||
assert(strncmp("1.1.1.1", buf, INET_ADDRSTRLEN) == 0);
|
||||
|
||||
struct in6_addr addr2 = { .s6_addr = {0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1} };
|
||||
char buf2[INET6_ADDRSTRLEN];
|
||||
assert(inet_ntop(AF_INET6, &addr2, buf2, INET6_ADDRSTRLEN) != NULL);
|
||||
assert(strncmp("2001:db8::1:0:0:1", buf2, INET6_ADDRSTRLEN) == 0);
|
||||
|
||||
struct in6_addr addr3 = { .s6_addr = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} };
|
||||
char buf3[INET6_ADDRSTRLEN];
|
||||
assert(inet_ntop(AF_INET6, &addr3, buf3, INET6_ADDRSTRLEN) != NULL);
|
||||
assert(strncmp("::1", buf3, INET6_ADDRSTRLEN) == 0);
|
||||
|
||||
struct in6_addr addr4 = { .s6_addr = {0x20, 0x1, 0xd, 0xb8, 00, 00, 00, 0x1, 00, 0x1, 00, 0x1, 00, 0x1, 00, 0x1} };
|
||||
char buf4[INET6_ADDRSTRLEN];
|
||||
assert(inet_ntop(AF_INET6, &addr4, buf4, INET6_ADDRSTRLEN) != NULL);
|
||||
assert(strncmp("2001:db8:0:1:1:1:1:1", buf4, INET6_ADDRSTRLEN) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
int main() {
|
||||
struct in_addr addr;
|
||||
assert(inet_pton(AF_INET, "1.1.1.1", &addr));
|
||||
assert((addr.s_addr & 0xFF) == 1);
|
||||
assert(((addr.s_addr >> 8) & 0xFF) == 1);
|
||||
assert(((addr.s_addr >> 16) & 0xFF) == 1);
|
||||
assert(((addr.s_addr >> 24) & 0xFF) == 1);
|
||||
|
||||
assert(!inet_pton(AF_INET, "256.999.1234.555", &addr));
|
||||
assert(!inet_pton(AF_INET, "a.b.c.d", &addr));
|
||||
|
||||
struct in6_addr test6;
|
||||
{
|
||||
struct in6_addr addr6 = {
|
||||
.s6_addr = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
|
||||
},
|
||||
};
|
||||
int ret = inet_pton(AF_INET6, "::1", &test6);
|
||||
assert(ret == 1);
|
||||
assert(!memcmp(&addr6, &test6, sizeof(addr6)));
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
struct in6_addr addr6 = {
|
||||
.s6_addr16 = {
|
||||
htons(0x2606), htons(0x4700), htons(0x4700), htons(0x00), htons(0x00), htons(0x00), htons(0x00), htons(0x1111)
|
||||
},
|
||||
};
|
||||
int ret = inet_pton(AF_INET6, "2606:4700:4700::1111", &test6);
|
||||
assert(ret == 1);
|
||||
assert(!memcmp(&addr6, &test6, sizeof(addr6)));
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
struct in6_addr addr6 = {
|
||||
.s6_addr16 = {
|
||||
htons(0x2606), htons(0x4700), htons(0x4700), htons(0x00), htons(0x00), htons(0x00), htons(0x00), htons(0x1111)
|
||||
},
|
||||
};
|
||||
int ret = inet_pton(AF_INET6, "2606:4700:4700:0000:0000:0000:0000:1111", &test6);
|
||||
assert(ret == 1);
|
||||
assert(!memcmp(&addr6, &test6, sizeof(addr6)));
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
struct in6_addr addr6 = {
|
||||
.s6_addr16 = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
},
|
||||
};
|
||||
int ret = inet_pton(AF_INET6, "::", &test6);
|
||||
assert(ret == 1);
|
||||
assert(!memcmp(&addr6, &test6, sizeof(addr6)));
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
int ret = inet_pton(AF_INET6, "mlibc::", &test6);
|
||||
assert(!ret);
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
struct in6_addr addr6 = {
|
||||
.s6_addr = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0xFF, 0xFF, 204, 152, 189, 116,
|
||||
},
|
||||
};
|
||||
int ret = inet_pton(AF_INET6, "::FFFF:204.152.189.116", &test6);
|
||||
assert(ret == 1);
|
||||
assert(!memcmp(&addr6, &test6, sizeof(addr6)));
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
int ret = inet_pton(AF_INET6, "::FFFF:204.152.189.", &test6);
|
||||
assert(!ret);
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
int ret = inet_pton(AF_INET6, "::FFFF:204.152.189.420", &test6);
|
||||
assert(!ret);
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
int ret = inet_pton(AF_INET6, "::FFFF:204.152.420.69", &test6);
|
||||
assert(!ret);
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
int ret = inet_pton(AF_INET6, "1100::FFFF:204.152.189.116", &test6);
|
||||
(void) ret;
|
||||
#if !defined(USE_HOST_LIBC)
|
||||
assert(!ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
memset(&test6, 0, sizeof(test6));
|
||||
|
||||
{
|
||||
struct in6_addr addr6 = {
|
||||
.s6_addr = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0xFF, 0xFF, 204, 152, 189, 116,
|
||||
},
|
||||
};
|
||||
int ret = inet_pton(AF_INET6, "0000:0000:0000:0000:0000:FFFF:204.152.189.116", &test6);
|
||||
assert(ret == 1);
|
||||
assert(!memcmp(&addr6, &test6, sizeof(addr6)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main () {
|
||||
char str[] = "The Last Supper by Leonardo da Vinci";
|
||||
char *str_temp;
|
||||
|
||||
// Test strstr
|
||||
str_temp = strstr(str, "Supper"); /* Find a substring in the string */
|
||||
assert(!strcmp(str_temp, "Supper by Leonardo da Vinci"));
|
||||
|
||||
/* Following calls use memory APIs for the above tasks */
|
||||
// Test memchr
|
||||
str_temp = (char *)memchr((void *)str, 'L', strlen(str));
|
||||
assert(!strcmp(str_temp, "Last Supper by Leonardo da Vinci"));
|
||||
|
||||
// Test memrchr
|
||||
str_temp = (char *)memrchr((void *)str, 'L', strlen(str));
|
||||
assert(!strcmp(str_temp, "Leonardo da Vinci"));
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
void validate_pattern(char *p) {
|
||||
assert(memcmp(p, "XXXXXX", 6));
|
||||
assert(memchr(p, 0, 6) == NULL);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
assert(isalnum(p[i]));
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int ret;
|
||||
|
||||
// Make sure the patterns themselves cannot be chosen. This
|
||||
// *could* happen on glibc, or if we widen the character set
|
||||
// used for generating random names. Odds are 1 in 60 billion,
|
||||
// but I'd rather not worry about this.
|
||||
ret = open("prefixXXXXXX", O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
assert(ret >= 0 || (ret == -1 && errno == EEXIST));
|
||||
ret = open("longprefixXXXXXXlongsuffix", O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
assert(ret >= 0 || (ret == -1 && errno == EEXIST));
|
||||
|
||||
ret = mkstemp("short");
|
||||
assert(ret == -1);
|
||||
assert(errno == EINVAL);
|
||||
|
||||
ret = mkstemp("lessthan6XXX");
|
||||
assert(ret == -1);
|
||||
assert(errno == EINVAL);
|
||||
|
||||
ret = mkstemps("lessthan6XXXswithsuffix", 11);
|
||||
assert(ret == -1);
|
||||
assert(errno == EINVAL);
|
||||
|
||||
char *p = strdup("prefixXXXXXX");
|
||||
ret = mkstemp(p);
|
||||
// We can't really protect against EEXIST...
|
||||
assert(ret >= 0 || (ret == -1 && errno == EEXIST));
|
||||
assert(!memcmp(p, "prefix", 6));
|
||||
assert(p[12] == 0);
|
||||
validate_pattern(p + 6);
|
||||
|
||||
if (ret >= 0) {
|
||||
ret = close(ret);
|
||||
assert(!ret);
|
||||
}
|
||||
free(p);
|
||||
|
||||
p = strdup("longprefixXXXXXXlongsuffix");
|
||||
ret = mkstemps(p, 10);
|
||||
// We can't really protect against EEXIST...
|
||||
assert(ret >= 0 || (ret == -1 && errno == EEXIST));
|
||||
assert(!memcmp(p, "longprefix", 10));
|
||||
assert(!memcmp(p + 16, "longsuffix", 10));
|
||||
assert(p[26] == 0);
|
||||
validate_pattern(p + 10);
|
||||
|
||||
if (ret >= 0) {
|
||||
ret = close(ret);
|
||||
assert(!ret);
|
||||
}
|
||||
free(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
int main() {
|
||||
errno = 0;
|
||||
int original_priority = nice(0);
|
||||
|
||||
assert(original_priority != -1 || !errno);
|
||||
|
||||
errno = 0;
|
||||
int ret = nice(1);
|
||||
|
||||
if(ret == -1 && errno) {
|
||||
fprintf(stderr, "%s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
int new_priority = nice(0);
|
||||
|
||||
assert(new_priority != -1 || !errno);
|
||||
assert(new_priority == original_priority + 1);
|
||||
|
||||
errno = 0;
|
||||
new_priority = nice(INT_MAX - new_priority);
|
||||
|
||||
assert(new_priority != -1 || !errno);
|
||||
assert(new_priority != INT_MAX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define WRITE_NO 1024
|
||||
|
||||
int main() {
|
||||
size_t size;
|
||||
char *buf;
|
||||
|
||||
FILE *fp = open_memstream(&buf, &size);
|
||||
assert(fp);
|
||||
|
||||
char c = 'A';
|
||||
for (size_t i = 0; i < WRITE_NO; i++)
|
||||
assert(fwrite(&c, sizeof(char), 1, fp) == 1);
|
||||
|
||||
// Flush the file to update the pointers.
|
||||
assert(!fflush(fp));
|
||||
|
||||
assert(size == WRITE_NO);
|
||||
for (size_t i = 0; i < size; i++)
|
||||
assert(buf[i] == c);
|
||||
|
||||
// Check if the stream maintains a null-bye at the end.
|
||||
assert(buf[size] == '\0');
|
||||
|
||||
// Stream should be expanded, size should be == 2*WRITE_NO.
|
||||
assert(!fseek(fp, WRITE_NO, SEEK_END));
|
||||
assert(!fflush(fp));
|
||||
assert(size == 2*WRITE_NO);
|
||||
assert(buf[size] == '\0');
|
||||
|
||||
// Check if it's filled with zero's.
|
||||
for (size_t i = WRITE_NO; i < size; i++)
|
||||
assert(buf[i] == '\0');
|
||||
|
||||
// Go back and overwrite the 0's with 'B'.
|
||||
assert(!fseek(fp, -WRITE_NO, SEEK_CUR));
|
||||
c = 'B';
|
||||
for (size_t i = 0; i < WRITE_NO; i++)
|
||||
assert(fwrite(&c, sizeof(char), 1, fp) == 1);
|
||||
|
||||
// Check if that happened.
|
||||
assert(size == 2*WRITE_NO);
|
||||
for (size_t i = WRITE_NO; i < size; i++)
|
||||
assert(buf[i] == c);
|
||||
assert(buf[size] == '\0');
|
||||
|
||||
// Go to the front and write 'B'.
|
||||
assert(!fseek(fp, 0, SEEK_SET));
|
||||
for (size_t i = 0; i < WRITE_NO; i++)
|
||||
assert(fwrite(&c, sizeof(char), 1, fp) == 1);
|
||||
|
||||
// Check if that happened.
|
||||
assert(size == 2*WRITE_NO);
|
||||
for (size_t i = 0; i < size; i++)
|
||||
assert(buf[i] == c);
|
||||
assert(buf[size] == '\0');
|
||||
|
||||
// Close the file, we have tested everything.
|
||||
assert(!fclose(fp));
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static void noop(int x) {
|
||||
(void)x;
|
||||
}
|
||||
|
||||
int main() {
|
||||
signal(SIGUSR1, &noop);
|
||||
|
||||
int pid;
|
||||
switch(pid = fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
abort();
|
||||
case 0:
|
||||
pause();
|
||||
assert(errno == EINTR);
|
||||
return 0;
|
||||
default:
|
||||
while (1) {
|
||||
usleep(100);
|
||||
kill(pid, SIGUSR1);
|
||||
usleep(100);
|
||||
int status;
|
||||
|
||||
errno = 0;
|
||||
if (waitpid(-1, &status, WNOHANG) <= 0) {
|
||||
if (errno && errno != EAGAIN) {
|
||||
perror("wait");
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!WIFEXITED(status)) {
|
||||
printf("wait returned %x\n", status);
|
||||
abort();
|
||||
}
|
||||
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef USE_HOST_LIBC
|
||||
#define TEST_FILE "popen-host-libc.tmp"
|
||||
#else
|
||||
#define TEST_FILE "popen.tmp"
|
||||
#endif
|
||||
|
||||
#define TEST_STRING1 "the quick brown fox jumps over the lazy dog"
|
||||
#define TEST_STRING1_LEN 43
|
||||
#define TEST_STRING2 "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
|
||||
#define TEST_STRING2_LEN 55
|
||||
|
||||
int main() {
|
||||
// Test reading
|
||||
FILE *f1 = popen("echo -n '" TEST_STRING1 "'", "r");
|
||||
assert(f1);
|
||||
char buf1[TEST_STRING1_LEN];
|
||||
assert(fread(buf1, 1, TEST_STRING1_LEN, f1) == TEST_STRING1_LEN);
|
||||
assert(memcmp(buf1, TEST_STRING1, TEST_STRING1_LEN) == 0);
|
||||
pclose(f1);
|
||||
|
||||
// Test writing
|
||||
FILE *f2 = popen("cat - > " TEST_FILE, "w");
|
||||
assert(f2);
|
||||
assert(fwrite(TEST_STRING2, 1, TEST_STRING2_LEN, f2) == TEST_STRING2_LEN);
|
||||
pclose(f2);
|
||||
|
||||
// Read test file back
|
||||
FILE *test_file = fopen(TEST_FILE, "r");
|
||||
assert(test_file);
|
||||
char buf2[TEST_STRING2_LEN];
|
||||
assert(fread(buf2, 1, TEST_STRING2_LEN, test_file) == TEST_STRING2_LEN);
|
||||
assert(memcmp(buf2, TEST_STRING2, TEST_STRING2_LEN) == 0);
|
||||
fclose(test_file);
|
||||
assert(unlink(TEST_FILE) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
size_t COUNTER_EXPIRATIONS = 3;
|
||||
|
||||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
size_t count = 0;
|
||||
|
||||
void timer_handler(union sigval val) {
|
||||
(void) val;
|
||||
pthread_mutex_lock(&mutex);
|
||||
count++;
|
||||
fprintf(stderr, "new count %zu\n", count);
|
||||
if(count >= COUNTER_EXPIRATIONS) {
|
||||
pthread_cond_signal(&cond);
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
static void test_thread_notify() {
|
||||
timer_t timer;
|
||||
struct sigevent sev = {
|
||||
.sigev_value = {
|
||||
.sival_ptr = &timer,
|
||||
},
|
||||
.sigev_notify = SIGEV_THREAD,
|
||||
};
|
||||
sev.sigev_notify_function = timer_handler;
|
||||
sev.sigev_notify_attributes = NULL;
|
||||
|
||||
int ret = timer_create(CLOCK_MONOTONIC, &sev, &timer);
|
||||
assert(ret == 0);
|
||||
|
||||
struct itimerspec its = {
|
||||
.it_interval = {
|
||||
.tv_sec = 1,
|
||||
.tv_nsec = 0,
|
||||
},
|
||||
.it_value = {
|
||||
.tv_sec = 1,
|
||||
.tv_nsec = 0,
|
||||
},
|
||||
};
|
||||
ret = timer_settime(timer, 0, &its, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
while(count < COUNTER_EXPIRATIONS)
|
||||
pthread_cond_wait(&cond, &mutex);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
ret = timer_delete(timer);
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
struct sigevent evp;
|
||||
memset(&evp, 0, sizeof(evp));
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGUSR1);
|
||||
sigprocmask(SIG_BLOCK, &set, 0);
|
||||
evp.sigev_notify = SIGEV_SIGNAL;
|
||||
evp.sigev_signo = SIGUSR1;
|
||||
|
||||
struct timeval start;
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
timer_t timer;
|
||||
if (timer_create(CLOCK_MONOTONIC, &evp, &timer)) {
|
||||
perror("timer_create");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct itimerspec spec;
|
||||
memset(&spec, 0, sizeof(spec));
|
||||
spec.it_value.tv_sec = 1;
|
||||
spec.it_value.tv_nsec = 0;
|
||||
|
||||
int sig;
|
||||
timer_settime(timer, 0, &spec, NULL);
|
||||
|
||||
struct itimerspec its = {};
|
||||
int ret = timer_gettime(timer, &its);
|
||||
assert(ret == 0);
|
||||
assert(its.it_value.tv_sec || its.it_value.tv_nsec);
|
||||
|
||||
sigwait(&set, &sig);
|
||||
|
||||
struct timeval end;
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
double diff = end.tv_sec - start.tv_sec;
|
||||
diff += (end.tv_usec - start.tv_usec) / 1000000.0;
|
||||
assert(diff >= 1.0);
|
||||
|
||||
#if defined(__linux__)
|
||||
test_thread_notify();
|
||||
#endif
|
||||
|
||||
timer_delete(timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main() {
|
||||
void *p = NULL;
|
||||
|
||||
// align must be a power of two
|
||||
assert(posix_memalign(&p, 3, 1) == EINVAL && p == NULL);
|
||||
|
||||
// align must be a multiple of sizeof(void *)
|
||||
assert(posix_memalign(&p, sizeof(void *) / 2, 8) == EINVAL && p == NULL);
|
||||
|
||||
assert(posix_memalign(&p, sizeof(void *), sizeof(void *)) == 0 && p != NULL && (uintptr_t)p % sizeof(void *) == 0);
|
||||
free(p);
|
||||
assert(posix_memalign(&p, 256, 1) == 0 && p != NULL && (uintptr_t)p % 256 == 0);
|
||||
free(p);
|
||||
assert(posix_memalign(&p, 256, 256) == 0 && p != NULL && (uintptr_t)p % 256 == 0);
|
||||
free(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <spawn.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
extern char **environ;
|
||||
|
||||
void run_cmd(char *cmd)
|
||||
{
|
||||
pid_t pid;
|
||||
char *argv[] = {"sh", "-c", cmd, NULL};
|
||||
int status;
|
||||
printf("Run command: %s\n", cmd);
|
||||
status = posix_spawn(&pid, "/bin/sh", NULL, NULL, argv, environ);
|
||||
if(status == 0) {
|
||||
printf("Child pid: %i\n", pid);
|
||||
if(waitpid(pid, &status, 0) != -1) {
|
||||
printf("Child exited with status %i\n", status);
|
||||
printf("Child exit status: %i\n", WEXITSTATUS(status));
|
||||
assert(WEXITSTATUS(status) == 0);
|
||||
} else {
|
||||
perror("waitpid");
|
||||
assert(0 == 1);
|
||||
}
|
||||
} else {
|
||||
printf("posix_spawn: %s\n", strerror(status));
|
||||
assert(0 == 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
run_cmd(":");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
_Atomic int prepare_order = 0;
|
||||
_Atomic int parent_order = 0;
|
||||
_Atomic int child_order = 0;
|
||||
|
||||
static void prepare1() { prepare_order = 1; }
|
||||
static void prepare2() { prepare_order = 2; }
|
||||
|
||||
static void parent1() { parent_order = 1; }
|
||||
static void parent2() { parent_order = 2; }
|
||||
|
||||
static void child1() { child_order = 1; }
|
||||
static void child2() { child_order = 2; }
|
||||
|
||||
int main() {
|
||||
assert(!pthread_atfork(prepare1, parent1, child1));
|
||||
assert(!pthread_atfork(prepare2, parent2, child2));
|
||||
|
||||
pid_t pid = fork();
|
||||
assert(pid >= 0);
|
||||
|
||||
if (!pid) {
|
||||
assert(child_order == 2);
|
||||
exit(0);
|
||||
} else {
|
||||
assert(prepare_order == 1);
|
||||
assert(parent_order == 2);
|
||||
|
||||
while (1) {
|
||||
int status = 0;
|
||||
|
||||
int ret = waitpid(pid, &status, 0);
|
||||
|
||||
if (ret == -1 && errno == EINTR)
|
||||
continue;
|
||||
|
||||
assert(ret > 0);
|
||||
|
||||
if (WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT)
|
||||
return 1;
|
||||
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <alloca.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <signal.h>
|
||||
|
||||
static void test_detachstate() {
|
||||
pthread_attr_t attr;
|
||||
assert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
|
||||
int detachstate;
|
||||
assert(!pthread_attr_getdetachstate(&attr, &detachstate));
|
||||
assert(detachstate == PTHREAD_CREATE_DETACHED);
|
||||
assert(pthread_attr_setdetachstate(&attr, 2* (PTHREAD_CREATE_DETACHED +
|
||||
PTHREAD_CREATE_JOINABLE)) == EINVAL);
|
||||
}
|
||||
|
||||
static void *stacksize_worker(void *arg) {
|
||||
size_t default_stacksize = (*(size_t*)arg);
|
||||
size_t alloc_size = default_stacksize + default_stacksize/2;
|
||||
void *area = alloca(alloc_size);
|
||||
// If the allocated stack was not enough this will crash.
|
||||
// Trample both the start and end of the area so it works on both upwards-
|
||||
// and downwards-growing stacks.
|
||||
*(volatile char*)area = 1;
|
||||
*(volatile char*)(area + alloc_size - 1) = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void test_stacksize() {
|
||||
pthread_attr_t attr;
|
||||
assert(!pthread_attr_init(&attr));
|
||||
size_t stacksize;
|
||||
assert(!pthread_attr_getstacksize(&attr, &stacksize));
|
||||
assert(!pthread_attr_setstacksize(&attr, stacksize * 2));
|
||||
pthread_t thread;
|
||||
assert(!pthread_create(&thread, &attr, stacksize_worker, &stacksize));
|
||||
assert(!pthread_join(thread, NULL));
|
||||
}
|
||||
|
||||
static void test_guardsize() {
|
||||
pthread_attr_t attr;
|
||||
assert(!pthread_attr_init(&attr));
|
||||
assert(!pthread_attr_setguardsize(&attr, 0));
|
||||
size_t guardsize;
|
||||
assert(!pthread_attr_getguardsize(&attr, &guardsize));
|
||||
assert(!guardsize);
|
||||
}
|
||||
|
||||
static void test_scope() {
|
||||
pthread_attr_t attr;
|
||||
assert(!pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM));
|
||||
int scope;
|
||||
assert(!pthread_attr_getscope(&attr, &scope));
|
||||
assert(scope == PTHREAD_SCOPE_SYSTEM);
|
||||
assert(pthread_attr_setscope(&attr, 2* (PTHREAD_SCOPE_SYSTEM +
|
||||
PTHREAD_SCOPE_PROCESS)) == EINVAL);
|
||||
}
|
||||
|
||||
static void test_inheritsched() {
|
||||
pthread_attr_t attr;
|
||||
assert(!pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED));
|
||||
int inheritsched;
|
||||
assert(!pthread_attr_getinheritsched(&attr, &inheritsched));
|
||||
assert(inheritsched == PTHREAD_INHERIT_SCHED);
|
||||
assert(pthread_attr_setinheritsched(&attr, 2* (PTHREAD_INHERIT_SCHED +
|
||||
PTHREAD_EXPLICIT_SCHED)) == EINVAL);
|
||||
}
|
||||
|
||||
static void test_schedparam() {
|
||||
pthread_attr_t attr;
|
||||
struct sched_param init_param = {0};
|
||||
assert(!pthread_attr_setschedparam(&attr, &init_param));
|
||||
struct sched_param param = {1};
|
||||
assert(!pthread_attr_getschedparam(&attr, ¶m));
|
||||
assert(param.sched_priority == init_param.sched_priority);
|
||||
}
|
||||
|
||||
static void test_schedpolicy() {
|
||||
pthread_attr_t attr;
|
||||
assert(!pthread_attr_setschedpolicy(&attr, SCHED_FIFO));
|
||||
int policy;
|
||||
assert(!pthread_attr_getschedpolicy(&attr, &policy));
|
||||
assert(policy == SCHED_FIFO);
|
||||
assert(pthread_attr_setinheritsched(&attr, 2* (SCHED_FIFO + SCHED_RR +
|
||||
SCHED_OTHER)) == EINVAL);
|
||||
}
|
||||
|
||||
static void *stackaddr_worker(void *arg) {
|
||||
void *addr = *(void**)arg;
|
||||
|
||||
void *sp;
|
||||
#if defined(__x86_64__)
|
||||
asm volatile ("mov %%rsp, %0" : "=r"(sp));
|
||||
#elif defined(__i386__)
|
||||
asm volatile ("mov %%esp, %0" : "=r"(sp));
|
||||
#elif defined(__aarch64__)
|
||||
asm volatile ("mov %0, sp" : "=r"(sp));
|
||||
#elif defined (__riscv)
|
||||
asm volatile ("mv %0, sp" : "=r"(sp));
|
||||
#elif defined(__m68k__)
|
||||
asm volatile ("move.l %%sp, %0" : "=r"(sp));
|
||||
#elif defined (__loongarch64)
|
||||
asm volatile ("move %0, $sp" : "=r"(sp));
|
||||
#else
|
||||
# error Unknown architecture
|
||||
#endif
|
||||
|
||||
// Check if our stack pointer is in a sane range.
|
||||
assert(sp > addr);
|
||||
return NULL;
|
||||
}
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
static void test_stackaddr() {
|
||||
pthread_attr_t attr;
|
||||
assert(!pthread_attr_init(&attr));
|
||||
size_t size;
|
||||
assert(!pthread_attr_getstacksize(&attr, &size));
|
||||
void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
assert(!pthread_attr_setstack(&attr, addr, size));
|
||||
assert(!pthread_attr_setguardsize(&attr, 0));
|
||||
void *new_addr;
|
||||
size_t new_size;
|
||||
assert(!pthread_attr_getstack(&attr, &new_addr, &new_size));
|
||||
assert(new_addr == addr);
|
||||
assert(new_size == size);
|
||||
|
||||
pthread_t thread;
|
||||
assert(!pthread_create(&thread, &attr, stackaddr_worker, &addr));
|
||||
assert(!pthread_join(thread, NULL));
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#if !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32)
|
||||
static void test_stack() {
|
||||
pthread_attr_t attr;
|
||||
void *stackaddr = (void*)1;
|
||||
size_t stacksize = PTHREAD_STACK_MIN;
|
||||
|
||||
assert(!pthread_attr_setstack(&attr, stackaddr, stacksize));
|
||||
void *new_addr;
|
||||
size_t new_size;
|
||||
assert(!pthread_attr_getstack(&attr, &new_addr, &new_size));
|
||||
assert(new_addr == stackaddr);
|
||||
assert(new_size == stacksize);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
test_detachstate();
|
||||
test_stacksize();
|
||||
test_guardsize();
|
||||
test_scope();
|
||||
test_inheritsched();
|
||||
test_schedparam();
|
||||
test_schedpolicy();
|
||||
test_stackaddr();
|
||||
#if !defined(USE_HOST_LIBC) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32)
|
||||
test_stack();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user