Home | History | Annotate | Download | only in utils
      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.
     25 static int loop_count = 0;
     26 
     27 // This function returns the first time it is called, or -1/EINVAL
     28 // otherwise.
     29 static int return_einval_after_first_call(void) {
     30     if (++loop_count == 1)
     31         return 0;
     32 
     33     errno = EINVAL;
     34     return -1;
     35 }
     36 
     37 TEST(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 
     43 TEST(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 
     51 static 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 
     62 TEST(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.
     72 static int loop_eintr_10(void) {
     73     if (++loop_count < 10) {
     74         errno = EINTR;
     75         return -1;
     76     }
     77     return 0;
     78 }
     79 
     80 TEST(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)).
     90 static jmp_buf panic_jumper;
     91 static bool panic_called = false;
     92 
     93 static void __attribute__((noreturn))
     94         my_panic_handler(const char*, va_list);
     95 
     96 static void my_panic_handler(const char* fmt, va_list args) {
     97     panic_called = true;
     98     longjmp(panic_jumper, 1);
     99 }
    100 
    101 static int loop_eintr_200(void) {
    102     if (++loop_count < 200) {
    103         errno = EINTR;
    104         return -1;
    105     }
    106     return 0;
    107 }
    108 
    109 TEST(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