$search
00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of the Willow Garage nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *********************************************************************/ 00034 00035 #include <gtest/gtest.h> 00036 00037 #include "rosrt/malloc_wrappers.h" 00038 #include "ros/atomic.h" 00039 #include <ros/time.h> 00040 #include <ros/console.h> 00041 00042 #include <boost/thread.hpp> 00043 00044 #if __unix__ && !APPLE 00045 #include <dlfcn.h> 00046 #endif 00047 00048 using namespace rosrt; 00049 using namespace ros; 00050 00051 void allocateThread(const atomic<bool>& done) 00052 { 00053 while (!done.load()) 00054 { 00055 void* mem = malloc(500); 00056 free(mem); 00057 ros::WallDuration(0.001).sleep(); 00058 } 00059 } 00060 00061 TEST(MallocWrappers, statsMainThread) 00062 { 00063 atomic<bool> done(false); 00064 boost::thread t(boost::bind(allocateThread, boost::ref(done))); 00065 00066 resetThreadAllocInfo(); 00067 00068 for (uint32_t i = 1; i <= 1000; ++i) 00069 { 00070 void* mem = malloc(500); 00071 free(mem); 00072 ros::WallDuration(0.001).sleep(); 00073 00074 AllocInfo info = getThreadAllocInfo(); 00075 ASSERT_EQ(info.mallocs, i); 00076 ASSERT_EQ(info.frees, i); 00077 ASSERT_EQ(info.total_ops, i * 2); 00078 } 00079 00080 done.store(true); 00081 t.join(); 00082 } 00083 00084 void statsThread(atomic<bool>& failed) 00085 { 00086 resetThreadAllocInfo(); 00087 00088 for (uint32_t i = 1; i <= 1000; ++i) 00089 { 00090 void* mem = malloc(500); 00091 free(mem); 00092 ros::WallDuration(0.001).sleep(); 00093 00094 AllocInfo info = getThreadAllocInfo(); 00095 if (info.mallocs != i) 00096 { 00097 ROS_ERROR_STREAM("mallocs is " << info.mallocs << " should be " << i); 00098 failed.store(true); 00099 return; 00100 } 00101 00102 if (info.frees != i) 00103 { 00104 ROS_ERROR_STREAM("mallocs is " << info.frees << " should be " << i); 00105 failed.store(true); 00106 return; 00107 } 00108 } 00109 } 00110 00111 TEST(MallocWrappers, statsNewThread) 00112 { 00113 atomic<bool> failed(false); 00114 boost::thread t(boost::bind(statsThread, boost::ref(failed))); 00115 t.join(); 00116 00117 ASSERT_FALSE(failed.load()); 00118 } 00119 00120 // TODO: once we have a low-level dynamic library wrapper, use it and allow testing on non-unix platforms 00121 #if __unix__ && !APPLE 00122 TEST(MallocWrappers, sharedObjectDynamicallyOpened) 00123 { 00124 void* handle = dlopen("libtest_malloc_wrappers_so.so", RTLD_LAZY|RTLD_GLOBAL); 00125 ASSERT_TRUE(handle); 00126 void*(*alloc_func)(size_t) = (void*(*)(size_t))dlsym(handle, "myTestMalloc"); 00127 ASSERT_TRUE(handle); 00128 void(*free_func)(void*) = (void(*)(void*))dlsym(handle, "myTestFree"); 00129 ASSERT_TRUE(free_func); 00130 00131 resetThreadAllocInfo(); 00132 void* mem = alloc_func(500); 00133 free_func(mem); 00134 00135 AllocInfo info = getThreadAllocInfo(); 00136 ASSERT_EQ(info.mallocs, 1U); 00137 ASSERT_EQ(info.frees, 1U); 00138 00139 dlclose(handle); 00140 } 00141 #endif 00142 00143 void doBreakOnMalloc() 00144 { 00145 setThreadBreakOnAllocOrFree(true); 00146 void* mem = malloc(500); 00147 mem = 0; 00148 setThreadBreakOnAllocOrFree(false); 00149 } 00150 00151 TEST(MallocWrappersDeathTest, breakOnAllocFree) 00152 { 00153 resetThreadAllocInfo(); 00154 00155 // TODO: Re-enable once ROS 1.1 goes out with the updated version of gtest 00156 //ASSERT_DEATH_IF_SUPPORTED(doBreakOnMalloc(), "Issuing break due to break_on_alloc_or_free being set"); 00157 } 00158 00159 int main(int argc, char** argv) 00160 { 00161 testing::InitGoogleTest(&argc, argv); 00162 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 00163 return RUN_ALL_TESTS(); 00164 } 00165