coreutils / tests /expr /tests_for_printv.c
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
#include "../../unity/unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
/* Unity fixtures */
void setUp(void) {
/* No setup required */
}
void tearDown(void) {
/* No teardown required */
}
/* Helper: capture stdout from printv(v) into *out.
Returns NULL on success, or a malloc'd error message on failure.
This function must not use Unity asserts while stdout is redirected. */
static char *capture_printv_output(VALUE *v, char **out)
{
int saved_stdout = dup(STDOUT_FILENO);
if (saved_stdout < 0)
return strdup("dup(STDOUT_FILENO) failed");
FILE *tmp = tmpfile();
if (!tmp) {
int e = errno;
close(saved_stdout);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "tmpfile() failed: errno=%d", e);
return msg ? msg : strdup("tmpfile() failed");
}
int tmpfd = fileno(tmp);
if (tmpfd < 0) {
int e = errno;
fclose(tmp);
close(saved_stdout);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "fileno(tmp) failed: errno=%d", e);
return msg ? msg : strdup("fileno(tmp) failed");
}
if (fflush(stdout) != 0) {
int e = errno;
fclose(tmp);
close(saved_stdout);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "fflush(stdout) before dup2 failed: errno=%d", e);
return msg ? msg : strdup("fflush(stdout) failed");
}
if (dup2(tmpfd, STDOUT_FILENO) < 0) {
int e = errno;
fclose(tmp);
close(saved_stdout);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "dup2(tmpfd, STDOUT_FILENO) failed: errno=%d", e);
return msg ? msg : strdup("dup2 failed");
}
/* Call the function under test while stdout is redirected. */
printv(v);
if (fflush(stdout) != 0) {
/* Attempt to restore stdout even on error */
int e = errno;
dup2(saved_stdout, STDOUT_FILENO);
close(saved_stdout);
fclose(tmp);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "fflush(stdout) after printv failed: errno=%d", e);
return msg ? msg : strdup("fflush(stdout) failed after printv");
}
/* Read back the content */
if (fseek(tmp, 0, SEEK_END) != 0) {
int e = errno;
dup2(saved_stdout, STDOUT_FILENO);
close(saved_stdout);
fclose(tmp);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "fseek(tmp, SEEK_END) failed: errno=%d", e);
return msg ? msg : strdup("fseek failed");
}
long len = ftell(tmp);
if (len < 0) {
int e = errno;
dup2(saved_stdout, STDOUT_FILENO);
close(saved_stdout);
fclose(tmp);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "ftell(tmp) failed: errno=%d", e);
return msg ? msg : strdup("ftell failed");
}
if (fseek(tmp, 0, SEEK_SET) != 0) {
int e = errno;
dup2(saved_stdout, STDOUT_FILENO);
close(saved_stdout);
fclose(tmp);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "fseek(tmp, SEEK_SET) failed: errno=%d", e);
return msg ? msg : strdup("fseek reset failed");
}
char *buf = (char*)malloc((size_t)len + 1);
if (!buf) {
dup2(saved_stdout, STDOUT_FILENO);
close(saved_stdout);
fclose(tmp);
return strdup("malloc for output buffer failed");
}
size_t rd = fread(buf, 1, (size_t)len, tmp);
buf[rd] = '\0';
/* Restore stdout and clean up */
if (dup2(saved_stdout, STDOUT_FILENO) < 0) {
int e = errno;
close(saved_stdout);
fclose(tmp);
free(buf);
char *msg = (char*)malloc(128);
if (msg) snprintf(msg, 128, "dup2(saved_stdout, STDOUT_FILENO) restore failed: errno=%d", e);
return msg ? msg : strdup("dup2 restore failed");
}
close(saved_stdout);
fclose(tmp);
*out = buf;
return NULL;
}
/* Convenience: build an integer VALUE from a base-10 C string using mpz_set_str. */
static VALUE *int_value_from_str(const char *s)
{
VALUE *v = int_value(0);
/* mpz_set_str returns 0 on success. We use valid inputs in tests. */
(void) mpz_set_str(v->u.i, s, 10);
return v;
}
/* Tests */
static void test_printv_integer_zero(void)
{
VALUE *v = int_value(0);
char *out = NULL;
char *err = capture_printv_output(v, &out);
TEST_ASSERT_NULL_MESSAGE(err, err ? err : "unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("0\n", out);
free(out);
freev(v);
}
static void test_printv_integer_positive_small(void)
{
VALUE *v = int_value(12345UL);
char *out = NULL;
char *err = capture_printv_output(v, &out);
TEST_ASSERT_NULL_MESSAGE(err, err ? err : "unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("12345\n", out);
free(out);
freev(v);
}
static void test_printv_integer_negative(void)
{
VALUE *v = int_value(0);
mpz_set_si(v->u.i, -42);
char *out = NULL;
char *err = capture_printv_output(v, &out);
TEST_ASSERT_NULL_MESSAGE(err, err ? err : "unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("-42\n", out);
free(out);
freev(v);
}
static void test_printv_integer_large(void)
{
/* Larger than 64-bit integer */
const char *big = "1234567890123456789012345678901234567890";
VALUE *v = int_value_from_str(big);
char *out = NULL;
char *err = capture_printv_output(v, &out);
TEST_ASSERT_NULL_MESSAGE(err, err ? err : "unexpected error");
TEST_ASSERT_NOT_NULL(out);
size_t need = strlen(big) + 2;
char *expected = (char*)malloc(need);
TEST_ASSERT_NOT_NULL(expected);
snprintf(expected, need, "%s\n", big);
TEST_ASSERT_EQUAL_STRING(expected, out);
free(expected);
free(out);
freev(v);
}
static void test_printv_string_simple(void)
{
VALUE *v = str_value("hello");
char *out = NULL;
char *err = capture_printv_output(v, &out);
TEST_ASSERT_NULL_MESSAGE(err, err ? err : "unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("hello\n", out);
free(out);
freev(v);
}
static void test_printv_string_empty(void)
{
VALUE *v = str_value("");
char *out = NULL;
char *err = capture_printv_output(v, &out);
TEST_ASSERT_NULL_MESSAGE(err, err ? err : "unexpected error");
TEST_ASSERT_NOT_NULL(out);
TEST_ASSERT_EQUAL_STRING("\n", out); /* puts("") emits a newline */
free(out);
freev(v);
}
static void test_printv_string_multibyte_utf8(void)
{
/* Greek alpha (UTF-8) followed by ASCII */
const char *s = "\xCE\xB1bc"; /* "αbc" */
VALUE *v = str_value(s);
char *out = NULL;
char *err = capture_printv_output(v, &out);
TEST_ASSERT_NULL_MESSAGE(err, err ? err : "unexpected error");
TEST_ASSERT_NOT_NULL(out);
size_t need = strlen(s) + 2;
char *expected = (char*)malloc(need);
TEST_ASSERT_NOT_NULL(expected);
snprintf(expected, need, "%s\n", s);
TEST_ASSERT_EQUAL_STRING(expected, out);
free(expected);
free(out);
freev(v);
}
static void test_printv_string_with_embedded_newline(void)
{
const char *s = "hi\nthere";
VALUE *v = str_value(s);
char *out = NULL;
char *err = capture_printv_output(v, &out);
TEST_ASSERT_NULL_MESSAGE(err, err ? err : "unexpected error");
TEST_ASSERT_NOT_NULL(out);
size_t need = strlen(s) + 2;
char *expected = (char*)malloc(need);
TEST_ASSERT_NOT_NULL(expected);
snprintf(expected, need, "%s\n", s);
TEST_ASSERT_EQUAL_STRING(expected, out);
free(expected);
free(out);
freev(v);
}
/* Unity runner */
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_printv_integer_zero);
RUN_TEST(test_printv_integer_positive_small);
RUN_TEST(test_printv_integer_negative);
RUN_TEST(test_printv_integer_large);
RUN_TEST(test_printv_string_simple);
RUN_TEST(test_printv_string_empty);
RUN_TEST(test_printv_string_multibyte_utf8);
RUN_TEST(test_printv_string_with_embedded_newline);
return UNITY_END();
}