1// Copyright 2014 The Android Open Source Project 2// 3// This software is licensed under the terms of the GNU General Public 4// License version 2, as published by the Free Software Foundation, and 5// may be copied, distributed, and modified under those terms. 6// 7// This program is distributed in the hope that it will be useful, 8// but WITHOUT ANY WARRANTY; without even the implied warranty of 9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10// GNU General Public License for more details. 11 12// Forces debug mode 13#define EINTR_WRAPPER_DEBUG 1 14 15#include "android/utils/eintr_wrapper.h" 16 17#include <stdarg.h> 18#include <setjmp.h> 19 20#include "android/utils/panic.h" 21 22#include <gtest/gtest.h> 23 24// Loop counter used by several functions below. 25static int loop_count = 0; 26 27// This function returns the first time it is called, or -1/EINVAL 28// otherwise. 29static int return_einval_after_first_call(void) { 30 if (++loop_count == 1) 31 return 0; 32 33 errno = EINVAL; 34 return -1; 35} 36 37TEST(eintr_wrapper,NoLoopOnSuccess) { 38 loop_count = 0; 39 EXPECT_EQ(0, HANDLE_EINTR(return_einval_after_first_call())); 40 EXPECT_EQ(1, loop_count); 41} 42 43TEST(eintr_wrapper,NoLoopOnRegularError) { 44 loop_count = 0; 45 EXPECT_EQ(0, HANDLE_EINTR(return_einval_after_first_call())); 46 EXPECT_EQ(-1, HANDLE_EINTR(return_einval_after_first_call())); 47 EXPECT_EQ(EINVAL, errno); 48 EXPECT_EQ(2, loop_count); 49} 50 51static int always_return_eintr(void) { 52 loop_count++; 53#ifdef _WIN32 54 // Win32 cannot generate EINTR. 55 return 0; 56#else 57 errno = EINTR; 58 return -1; 59#endif 60} 61 62TEST(eintr_wrapper,IgnoreEintr) { 63 loop_count = 0; 64 EXPECT_EQ(0, IGNORE_EINTR(always_return_eintr())); 65 EXPECT_EQ(1, loop_count); 66} 67 68#ifndef _WIN32 69 70// This function loops 10 times around |loop_count|, while returning 71// -1/errno. 72static int loop_eintr_10(void) { 73 if (++loop_count < 10) { 74 errno = EINTR; 75 return -1; 76 } 77 return 0; 78} 79 80TEST(eintr_wrapper,LoopOnEintr) { 81 loop_count = 0; 82 EXPECT_EQ(0, HANDLE_EINTR(loop_eintr_10())); 83 EXPECT_EQ(10, loop_count); 84} 85 86// Implementation of a custom panic function used to detect that 87// HANDLE_EINTR() called panic after too many loop iterations. 88// Uses setjmp()/longjmp() since the panic handler must be 89// __attribute__((noreturn)). 90static jmp_buf panic_jumper; 91static bool panic_called = false; 92 93static void __attribute__((noreturn)) 94 my_panic_handler(const char*, va_list); 95 96static void my_panic_handler(const char* fmt, va_list args) { 97 panic_called = true; 98 longjmp(panic_jumper, 1); 99} 100 101static int loop_eintr_200(void) { 102 if (++loop_count < 200) { 103 errno = EINTR; 104 return -1; 105 } 106 return 0; 107} 108 109TEST(eintr_wrapper,PanicOnTooManyLoops) { 110 loop_count = 0; 111 android_panic_registerHandler(my_panic_handler); 112 if (setjmp(panic_jumper) == 0) { 113 HANDLE_EINTR(loop_eintr_200()); 114 ASSERT_TRUE(0) << "HANDLE_EINTR() didn't panic!"; 115 } else { 116 EXPECT_EQ(true, panic_called); 117 EXPECT_EQ(MAX_EINTR_LOOP_COUNT, loop_count); 118 } 119} 120 121#endif // !_WIN32 122