| /* Copyright 2013-2015 IBM Corp. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define BUFSZ 50 |
| |
| #include <stdlib.h> |
| #include <assert.h> |
| #include <string.h> |
| #include <stdio.h> |
| |
| int test1(void); |
| int skiboot_snprintf(char *buf, size_t bufsz, size_t l, const char* format, ...); |
| |
| static void test_printf_0u(int n) |
| { |
| char *buf, *buf2; |
| int blen; |
| unsigned int i; |
| |
| for(i=1; i<10; i++) |
| { |
| blen = i+1; |
| if (n<0) |
| blen++; |
| |
| buf = (char*)malloc(blen); |
| buf2 = (char*)malloc(blen); |
| skiboot_snprintf(buf, blen, blen, "%08u", n); |
| snprintf(buf2, blen, "%08u", n); |
| n = n * 10; |
| assert(0 == strncmp(buf, buf2, blen)); |
| free(buf); |
| free(buf2); |
| } |
| } |
| |
| static void test_printf_u(int n) |
| { |
| char *buf, *buf2; |
| int blen; |
| unsigned int r; |
| unsigned int i; |
| |
| for(i=1; i<10; i++) |
| { |
| blen = i+1; |
| if (n<0) |
| blen++; |
| |
| buf = (char*)malloc(blen); |
| buf2 = (char*)malloc(blen); |
| r = skiboot_snprintf(buf, blen, blen, "%u", n); |
| snprintf(buf2, blen, "%u", n); |
| n = n * 10; |
| if (n<0) |
| assert(i+1 == r); |
| else |
| assert(i == r); |
| assert(0 == strncmp(buf, buf2, blen)); |
| free(buf); |
| free(buf2); |
| } |
| } |
| |
| static void test_printf_d(int n) |
| { |
| char *buf, *buf2; |
| int blen; |
| int r; |
| int i; |
| |
| for(i=1; i<10; i++) |
| { |
| blen = i+1; |
| if (n<0) |
| blen++; |
| |
| buf = (char*)malloc(blen); |
| buf2 = (char*)malloc(blen); |
| r = skiboot_snprintf(buf, blen, blen, "%d", n); |
| snprintf(buf2, blen, "%d", n); |
| n = n * 10; |
| if (n<0) |
| assert(i+1 == r); |
| else |
| assert(i == r); |
| assert(0 == strncmp(buf, buf2, blen)); |
| free(buf); |
| free(buf2); |
| } |
| } |
| |
| static void test_printf_x(const char* f) |
| { |
| char *buf, *buf2; |
| int blen; |
| int i, r; |
| unsigned int n=0x1; |
| |
| for (i=0; i<8; i++) |
| { |
| blen = i+2; |
| buf = (char*)malloc(blen); |
| buf2 = (char*)malloc(blen); |
| r = skiboot_snprintf(buf, blen, blen, f, n); |
| snprintf(buf2, blen, f, n); |
| assert(i+1 == r); |
| assert(0 == strncmp(buf, buf2, blen)); |
| free(buf); |
| free(buf2); |
| n = n << 4; |
| } |
| } |
| |
| static void test_printf_c(void) |
| { |
| char *buf= (char*)malloc(2); |
| char buf2[2]; |
| unsigned char i= 0xff; |
| int r; |
| while(i) |
| { |
| r = skiboot_snprintf(buf, 2, 2, "%c", i); |
| snprintf(buf2, 2, "%c", i); |
| assert(r==1); |
| assert(0 == strncmp(buf, buf2, 2)); |
| i--; |
| } |
| free(buf); |
| } |
| |
| static void test_printf_p(void) |
| { |
| char *buf= (char*)malloc(32); |
| char buf2[32]; |
| skiboot_snprintf(buf, 32, 32, "%p", buf); |
| snprintf(buf2, 32, "%p", buf); |
| assert(0 == strncmp(buf, buf2, 32)); |
| free(buf); |
| } |
| |
| static void test_printf_o(void) |
| { |
| char *buf= (char*)malloc(32); |
| char buf2[32]; |
| skiboot_snprintf(buf, 32, 32, "%o", 0x12345678); |
| snprintf(buf2, 32, "%o", 0x12345678); |
| assert(0 == strncmp(buf, buf2, 32)); |
| free(buf); |
| } |
| |
| static void test_printf_h(short i) |
| { |
| char *buf= (char*)malloc(32); |
| char buf2[32]; |
| skiboot_snprintf(buf, 32, 32, "%hd", i); |
| snprintf(buf2, 32, "%hd", i); |
| assert(0 == strncmp(buf, buf2, 32)); |
| free(buf); |
| } |
| |
| static void test_printf_z(size_t i) |
| { |
| char *buf= (char*)malloc(32); |
| char buf2[32]; |
| skiboot_snprintf(buf, 32, 32, "%zu", i); |
| snprintf(buf2, 32, "%zu", i); |
| assert(0 == strncmp(buf, buf2, 32)); |
| free(buf); |
| } |
| |
| int main(void) |
| { |
| char *buf; |
| int r; |
| |
| buf = (char*)malloc(BUFSZ); |
| memset(buf, 0, BUFSZ); |
| |
| assert(-1 == test1()); |
| |
| r = skiboot_snprintf(buf, BUFSZ, 2, "%%"); |
| assert(r==1); |
| assert(buf[0] == '%' && buf[1] == 0); |
| |
| r = skiboot_snprintf(buf, BUFSZ, 2, "%d", 137); |
| /* BUG/FIXME: |
| * skiboot libc does NOT return the length of the buffer you'd need |
| * Instead, it'll return something random, possibly zero (as here) |
| * but as you'll see in test_in_buf_len2, sometimes not. |
| * |
| * Basically, we're not POSIX printf and this is some day going to |
| * cause things to be awful. |
| */ |
| assert(0 == r); // BUG, should be 3 |
| assert(0 == strncmp(buf, "", 3)); |
| |
| r = skiboot_snprintf(buf, BUFSZ, 4, "%d", 137); |
| assert(3 == r); |
| assert(0 == strncmp(buf, "137", 3)); |
| assert(buf[3] == 0); |
| |
| /* Now we test the strange behaviour of our printf. |
| * For strings, we get partial prints going, but if we whack an |
| * integer on the end, we may or may not get that integer, depending |
| * on if we have enough size. We should test that though */ |
| |
| r = skiboot_snprintf(buf, BUFSZ, 4, "Hello %d", 137); |
| assert(3 == r); |
| assert(0 == strncmp(buf, "Hel", 3)); |
| assert(buf[3] == 0); |
| r = skiboot_snprintf(buf, BUFSZ, 7, "Hello %d", 137); |
| assert(6 == r); |
| assert(0 == strncmp(buf, "Hello ", 6)); |
| assert(buf[6] == 0); |
| r = skiboot_snprintf(buf, BUFSZ, 10, "Hello %d", 137); |
| assert(9 == r); |
| assert(0 == strncmp(buf, "Hello 137", 10)); |
| assert(buf[9] == 0); |
| free(buf); |
| |
| test_printf_u(1); |
| test_printf_0u(1); |
| test_printf_d(1); |
| test_printf_d(-1); |
| test_printf_x("%x"); |
| test_printf_x("%X"); |
| test_printf_c(); |
| test_printf_p(); |
| test_printf_o(); |
| test_printf_h(0); |
| test_printf_h(128); |
| test_printf_h(256); |
| test_printf_h(-1); |
| test_printf_h(32767); |
| test_printf_h(32768); |
| test_printf_h(65535); |
| test_printf_z(0); |
| test_printf_z(-1); |
| test_printf_z(12345); |
| test_printf_z(128000000); |
| |
| return 0; |
| } |