// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. #if defined(GB_MEASURE_MEMORY_FOR_THIS) #undef GB_MEASURE_MEMORY_FOR_THIS #endif #ifdef __cplusplus #include #else #include #endif #include "azure_macro_utils/macro_utils.h" #include "azure_c_shared_utility/optimize_size.h" #include "azure_c_shared_utility/gballoc.h" #include "testrunnerswitcher.h" #include "azure_c_shared_utility/lock.h" #ifndef SIZE_MAX #define SIZE_MAX ((size_t)~(size_t)0) #endif static TEST_MUTEX_HANDLE g_testByTest; static void* TEST_ALLOC_PTR1 = (void*)0x4242; static void* TEST_ALLOC_PTR2 = (void*)0x4243; static void* TEST_REALLOC_PTR = (void*)0x4245; #define OVERHEAD_SIZE 4096 static const LOCK_HANDLE TEST_LOCK_HANDLE = (LOCK_HANDLE)0x4244; #define ENABLE_MOCKS #include "umock_c/umock_c.h" #include "umock_c/umock_c_prod.h" IMPLEMENT_UMOCK_C_ENUM_TYPE(LOCK_RESULT, LOCK_RESULT_VALUES); #ifdef __cplusplus extern "C" { #endif MOCKABLE_FUNCTION(, void*, mock_malloc, size_t, size); MOCKABLE_FUNCTION(, void*, mock_calloc, size_t, nmemb, size_t, size); MOCKABLE_FUNCTION(, void*, mock_realloc, void*, ptr, size_t, size); MOCKABLE_FUNCTION(, void, mock_free, void*, ptr); MOCKABLE_FUNCTION(, LOCK_HANDLE, Lock_Init); MOCKABLE_FUNCTION(, LOCK_RESULT, Lock_Deinit, LOCK_HANDLE, handle); MOCKABLE_FUNCTION(, LOCK_RESULT, Lock, LOCK_HANDLE, handle); MOCKABLE_FUNCTION(, LOCK_RESULT, Unlock, LOCK_HANDLE, handle); #ifdef __cplusplus } #endif MU_DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES) static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code) { ASSERT_FAIL("umock_c reported error :%" PRI_MU_ENUM "", MU_ENUM_VALUE(UMOCK_C_ERROR_CODE, error_code)); } BEGIN_TEST_SUITE(GBAlloc_UnitTests) TEST_SUITE_INITIALIZE(TestClassInitialize) { int result; g_testByTest = TEST_MUTEX_CREATE(); ASSERT_IS_NOT_NULL(g_testByTest); result = umock_c_init(on_umock_c_error); ASSERT_ARE_EQUAL(int, 0, result); REGISTER_UMOCK_ALIAS_TYPE(LOCK_HANDLE, void*); REGISTER_TYPE(LOCK_RESULT, LOCK_RESULT); REGISTER_GLOBAL_MOCK_RETURN(mock_malloc, TEST_ALLOC_PTR1); REGISTER_GLOBAL_MOCK_RETURN(mock_realloc, TEST_ALLOC_PTR1); REGISTER_GLOBAL_MOCK_RETURN(mock_calloc, TEST_ALLOC_PTR1); REGISTER_GLOBAL_MOCK_RETURN(Lock_Init, TEST_LOCK_HANDLE); REGISTER_GLOBAL_MOCK_RETURN(Lock, LOCK_OK); REGISTER_GLOBAL_MOCK_RETURN(Unlock, LOCK_OK); } TEST_SUITE_CLEANUP(TestClassCleanup) { umock_c_deinit(); TEST_MUTEX_DESTROY(g_testByTest); } TEST_FUNCTION_INITIALIZE(TestMethodInitialize) { if (TEST_MUTEX_ACQUIRE(g_testByTest)) { ASSERT_FAIL("our mutex is ABANDONED. Failure in test framework"); } umock_c_reset_all_calls(); } TEST_FUNCTION_CLEANUP(TestMethodCleanup) { gballoc_deinit(); TEST_MUTEX_RELEASE(g_testByTest); } /* gballoc_init */ /* Tests_SRS_GBALLOC_01_002: [Upon initialization the total memory used and maximum total memory used tracked by the module shall be set to 0.] */ TEST_FUNCTION(gballoc_init_resets_memory_used) { //arrange void* allocation; gballoc_init(); allocation = malloc(OVERHEAD_SIZE); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); gballoc_free(gballoc_malloc(1)); gballoc_deinit(); // act gballoc_init(); // assert ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getCurrentMemoryUsed()); ///cleanup free(allocation); } /* Tests_SRS_GBALLOC_01_024: [gballoc_init shall initialize the gballoc module and return 0 upon success.] */ /* Tests_SRS_GBALLOC_01_026: [gballoc_Init shall create a lock handle that will be used to make the other gballoc APIs thread-safe.] */ TEST_FUNCTION(when_gballoc_init_calls_lock_init_and_it_succeeds_then_gballoc_init_succeeds) { // arrange int result; STRICT_EXPECTED_CALL(Lock_Init()); // act result = gballoc_init(); // assert ASSERT_ARE_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_027: [If the Lock creation fails, gballoc_init shall return a non-zero value.] */ TEST_FUNCTION(when_lock_init_fails_gballoc_init_fails) { // arrange int result; STRICT_EXPECTED_CALL(Lock_Init()) .SetReturn((LOCK_HANDLE)NULL); // act result = gballoc_init(); // assert ASSERT_ARE_NOT_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_025: [Init after Init shall fail and return a non-zero value.] */ TEST_FUNCTION(gballoc_init_after_gballoc_init_fails) { // arrange int result; STRICT_EXPECTED_CALL(Lock_Init()); gballoc_init(); //act result = gballoc_init(); // assert ASSERT_ARE_NOT_EQUAL(int, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* gballoc_deinit */ /* Tests_SRS_GBALLOC_01_028: [gballoc_deinit shall free all resources allocated by gballoc_init.] */ TEST_FUNCTION(gballoc_deinit_frees_the_lock_when_the_module_was_initialized) { // arrange gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock_Deinit(TEST_LOCK_HANDLE)); // act gballoc_deinit(); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_029: [if gballoc is not initialized gballoc_deinit shall do nothing.] */ TEST_FUNCTION(gballoc_deinit_after_gballoc_deinit_doesnot_free_lock) { //arrange // act gballoc_deinit(); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* gballoc_malloc */ /* Tests_SRS_GBALLOC_01_048: [If acquiring the lock fails, gballoc_malloc shall return NULL.] */ TEST_FUNCTION(when_acquiring_the_lock_fails_gballoc_malloc_fails) { // arrange void* result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)) .SetReturn(LOCK_ERROR); // act result = gballoc_malloc(1); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_003: [gballoc_malloc shall call the C99 malloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_004: [If the underlying malloc call is successful, gballoc_malloc shall increment the total memory used with the amount indicated by size.] */ /* Tests_SRS_GBALLOC_01_030: [gballoc_malloc shall ensure thread safety by using the lock created by gballoc_Init.] */ TEST_FUNCTION(gballoc_malloc_with_0_Size_Calls_Underlying_malloc) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_malloc(0)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_malloc(0); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_003: [gballoc_malloc shall call the C99 malloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_004: [If the underlying malloc call is successful, gballoc_malloc shall increment the total memory used with the amount indicated by size.] */ TEST_FUNCTION(gballoc_malloc_with_1_Size_Calls_Underlying_malloc_And_Increases_Max_Used) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_malloc(1); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 1, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_012: [When the underlying malloc call fails, gballoc_malloc shall return NULL and size should not be counted towards total memory used.] */ TEST_FUNCTION(When_malloc_Fails_Then_gballoc_malloc_fails_too) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_malloc(1)) .SetReturn((void*)NULL); STRICT_EXPECTED_CALL(mock_free(allocation)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_malloc(1); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); // cleanup free(allocation); } /* Tests_SRS_GBALLOC_01_013: [When gballoc_malloc fails allocating memory for its internal use, gballoc_malloc shall return NULL.] */ TEST_FUNCTION(When_allocating_memory_for_tracking_information_fails_Then_gballoc_malloc_fails_too) { // arrange void* result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn((void*)NULL); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_malloc(1); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); } /* Tests_SRS_GBALLOC_01_039: [If gballoc was not initialized gballoc_malloc shall simply call malloc without any memory tracking being performed.] */ TEST_FUNCTION(gballoc_malloc_after_deinit_calls_crt_malloc) { // arrange void* result; STRICT_EXPECTED_CALL(mock_malloc(1)); //act result = gballoc_malloc(1); //assert ASSERT_IS_NOT_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* gballoc_calloc */ /* Tests_SRS_GBALLOC_01_046: [If acquiring the lock fails, gballoc_calloc shall return NULL.] */ TEST_FUNCTION(when_acquiring_the_lock_fails_gballoc_calloc_fails) { // arrange void* result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)) .SetReturn(LOCK_ERROR); // act result = gballoc_calloc(1,1); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_020: [gballoc_calloc shall call the C99 calloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_021: [If the underlying calloc call is successful, gballoc_calloc shall increment the total memory used with nmemb*size.] */ /* Tests_SRS_GBALLOC_01_031: [gballoc_calloc shall ensure thread safety by using the lock created by gballoc_Init] */ TEST_FUNCTION(gballoc_calloc_with_0_Size_And_ItemCount_Calls_Underlying_calloc) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_calloc(0, 0)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_calloc(0, 0); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_020: [gballoc_calloc shall call the C99 calloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_021: [If the underlying calloc call is successful, gballoc_calloc shall increment the total memory used with nmemb*size.] */ TEST_FUNCTION(gballoc_calloc_with_1_Item_Of_1_Size_Calls_Underlying_malloc_And_Increases_Max_Used) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_calloc(1, 1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_calloc(1, 1); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 1, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_020: [gballoc_calloc shall call the C99 calloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_021: [If the underlying calloc call is successful, gballoc_calloc shall increment the total memory used with nmemb*size.] */ TEST_FUNCTION(gballoc_calloc_with_1_Item_Of_0_Size_Calls_Underlying_malloc_And_Does_Not_Increase_Max_Used) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_calloc(1, 0)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_calloc(1, 0); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_020: [gballoc_calloc shall call the C99 calloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_021: [If the underlying calloc call is successful, gballoc_calloc shall increment the total memory used with nmemb*size.] */ TEST_FUNCTION(gballoc_calloc_with_0_Items_Of_1_Size_Calls_Underlying_malloc_And_Does_Not_Increase_Max_Used) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_calloc(0, 1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_calloc(0, 1); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_020: [gballoc_calloc shall call the C99 calloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_021: [If the underlying calloc call is successful, gballoc_calloc shall increment the total memory used with nmemb*size.] */ TEST_FUNCTION(gballoc_calloc_with_42_Items_Of_2_Size_Calls_Underlying_malloc_And_Increases_Max_Size) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_calloc(42, 2)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_calloc(42, 2); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 84, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_022: [When the underlying calloc call fails, gballoc_calloc shall return NULL and size should not be counted towards total memory used.] */ TEST_FUNCTION(When_calloc_Fails_Then_gballoc_calloc_fails_too) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_calloc(1, 1)) .SetReturn((void*)NULL); STRICT_EXPECTED_CALL(mock_free(allocation)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_calloc(1, 1); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); // cleanup free(allocation); } /* Tests_SRS_GBALLOC_01_023: [When gballoc_calloc fails allocating memory for its internal use, gballoc_calloc shall return NULL.] */ TEST_FUNCTION(When_allocating_memory_for_tracking_information_fails_Then_gballoc_calloc_fails_too) { // arrange void* result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn((void*)NULL); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_calloc(1, 1); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); } /* Tests_SRS_GBALLOC_01_040: [If gballoc was not initialized gballoc_calloc shall simply call calloc without any memory tracking being performed.] */ TEST_FUNCTION(gballoc_calloc_after_deinit_calls_crt_calloc) { // arrange void* result; STRICT_EXPECTED_CALL(mock_calloc(1, 1)); // act result = gballoc_calloc(1, 1); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NOT_NULL(result); } /* gballoc_realloc */ /* Tests_SRS_GBALLOC_01_047: [If acquiring the lock fails, gballoc_realloc shall return NULL.]*/ TEST_FUNCTION(when_acquiring_the_lock_fails_gballoc_realloc_fails) { // arrange void* result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)) .SetReturn(LOCK_ERROR); // act result = gballoc_realloc(NULL, 1); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NULL(result); } /* Tests_SRS_GBALLOC_01_041: [If gballoc was not initialized gballoc_realloc shall shall simply call realloc without any memory tracking being performed.] */ TEST_FUNCTION(gballoc_realloc_after_deinit_fails) { // arrange void* result; STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)); // act result = gballoc_realloc(NULL, 1); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_IS_NOT_NULL(result); } /* Tests_SRS_GBALLOC_01_005: [gballoc_realloc shall call the C99 realloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_017: [When ptr is NULL, gballoc_realloc shall call the underlying realloc with ptr being NULL and the realloc result shall be tracked by gballoc.] */ /* Tests_SRS_GBALLOC_01_032: [gballoc_realloc shall ensure thread safety by using the lock created by gballoc_Init.] */ TEST_FUNCTION(gballoc_realloc_with_NULL_Arg_And_0_Size_Calls_Underlying_realloc) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_realloc(NULL, 0)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_realloc(NULL, 0); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_005: [gballoc_realloc shall call the C99 realloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_017: [When ptr is NULL, gballoc_realloc shall call the underlying realloc with ptr being NULL and the realloc result shall be tracked by gballoc.] */ TEST_FUNCTION(gballoc_realloc_with_NULL_Arg_And_1_Size_Calls_Underlying_realloc) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_realloc(NULL, 1); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 1, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_005: [gballoc_realloc shall call the C99 realloc function and return its result.] */ /* Tests_SRS_GBALLOC_01_006: [If the underlying realloc call is successful, gballoc_realloc shall look up the size associated with the pointer ptr and decrease the total memory used with that size.] */ TEST_FUNCTION(gballoc_realloc_with_Previous_1_Byte_Block_Ptr_And_2_Size_Calls_Underlying_realloc_And_Increases_Max_Used_Memory) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(mock_realloc(TEST_ALLOC_PTR1, 2)) .SetReturn(TEST_ALLOC_PTR2); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); result = gballoc_realloc(NULL, 1); // act result = gballoc_realloc(result, 2); // assert ASSERT_ARE_EQUAL(void_ptr, TEST_ALLOC_PTR2, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 2, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result); free(allocation); } /* Tests_SRS_GBALLOC_01_014: [When the underlying realloc call fails, gballoc_realloc shall return NULL and no change should be made to the counted total memory usage.] */ TEST_FUNCTION(When_realloc_fails_then_gballoc_realloc_Fails_Too_And_No_Change_Is_Made_To_Memory_Counters) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(mock_realloc(TEST_ALLOC_PTR1, 2)) .SetReturn((void*)NULL); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); result = gballoc_realloc(NULL, 1); // act result = gballoc_realloc(result, 2); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 1, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(TEST_ALLOC_PTR1); free(allocation); } /* Tests_SRS_GBALLOC_01_015: [When allocating memory used for tracking by gballoc_realloc fails, gballoc_realloc shall return NULL and no change should be made to the counted total memory usage.] */ TEST_FUNCTION(When_Allocating_Memory_For_tracking_fails_gballoc_realloc_fails) { // arrange void* result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn((void*)NULL); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_realloc(NULL, 1); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); } /* Tests_SRS_GBALLOC_01_016: [When the ptr pointer cannot be found in the pointers tracked by gballoc, gballoc_realloc shall return NULL and the underlying realloc shall not be called.] */ TEST_FUNCTION(When_The_Pointer_Is_Not_Tracked_gballoc_realloc_Returns_NULL) { // arrange void* result1; void* result2; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); result1 = gballoc_realloc(NULL, 1); // act result2 = gballoc_realloc(TEST_REALLOC_PTR, 2); // assert ASSERT_IS_NULL(result2); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 1, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(result1); free(allocation); } /* Tests_SRS_GBALLOC_01_014: [When the underlying realloc call fails, gballoc_realloc shall return NULL and no change should be made to the counted total memory usage.] */ TEST_FUNCTION(When_ptr_is_null_and_the_underlying_realloc_fails_then_the_memory_used_for_tracking_is_freed) { // arrange void* result; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)) .SetReturn((void*)NULL); STRICT_EXPECTED_CALL(mock_free(allocation)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_realloc(NULL, 1); // assert ASSERT_IS_NULL(result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 0, gballoc_getMaximumMemoryUsed()); // cleanup free(allocation); } /* gballoc_free */ /* Tests_SRS_GBALLOC_01_042: [If gballoc was not initialized gballoc_free shall shall simply call free.] */ TEST_FUNCTION(gballoc_free_after_deinit_calls_crt_free) { // arrange STRICT_EXPECTED_CALL(mock_free((void*)0x4242)); // act gballoc_free((void*)0x4242); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_049: [If acquiring the lock fails, gballoc_free shall do nothing.] */ TEST_FUNCTION(when_acquiring_the_lock_fails_then_gballoc_free_does_nothing) { // arrange void* block; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)); block = gballoc_realloc(NULL, 1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)) .SetReturn(LOCK_ERROR); // act gballoc_free(block); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // cleanup gballoc_free(block); free(allocation); } /* Tests_SRS_GBALLOC_01_008: [gballoc_free shall call the C99 free function.] */ /* Tests_SRS_GBALLOC_01_009: [gballoc_free shall also look up the size associated with the ptr pointer and decrease the total memory used with the associated size amount.] */ /* Tests_SRS_GBALLOC_01_010: [gballoc_getMaximumMemoryUsed shall return the maximum amount of total memory used recorded since the module initialization.] */ /* Tests_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */ /* Tests_SRS_GBALLOC_01_033: [gballoc_free shall ensure thread safety by using the lock created by gballoc_Init.] */ TEST_FUNCTION(gballoc_free_calls_the_underlying_free) { // arrange void* block; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); /* This is the call to the underlying malloc with the size we want to allocate */ STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)); block = gballoc_realloc(NULL, 1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(mock_free(TEST_ALLOC_PTR1)); STRICT_EXPECTED_CALL(mock_free(allocation)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act gballoc_free(block); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 1, gballoc_getMaximumMemoryUsed()); // cleanup free(allocation); } /* Tests_SRS_GBALLOC_01_008: [gballoc_free shall call the C99 free function.] */ /* Tests_SRS_GBALLOC_01_009: [gballoc_free shall also look up the size associated with the ptr pointer and decrease the total memory used with the associated size amount.] */ /* Tests_SRS_GBALLOC_01_010: [gballoc_getMaximumMemoryUsed shall return the maximum amount of total memory used recorded since the module initialization.] */ /* Tests_SRS_GBALLOC_01_010: [gballoc_getMaximumMemoryUsed shall return the maximum amount of total memory used recorded since the module initialization.] */ /* Tests_SRS_GBALLOC_01_011: [The maximum total memory used shall be the maximum of the total memory used at any point.] */ TEST_FUNCTION(gballoc_malloc_free_2_times_with_1_byte_yields_1_byte_as_max) { // arrange void* block; void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); STRICT_EXPECTED_CALL(mock_realloc(NULL, 1)); block = gballoc_realloc(NULL, 1); gballoc_free(block); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); block = gballoc_realloc(NULL, 1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(mock_free(TEST_ALLOC_PTR1)); STRICT_EXPECTED_CALL(mock_free(allocation)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act gballoc_free(block); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, 1, gballoc_getMaximumMemoryUsed()); // cleanup free(allocation); } /* Tests_SRS_GBALLOC_01_019:[When the ptr pointer cannot be found in the pointers tracked by gballoc, gballoc_free shall not free any memory.] */ TEST_FUNCTION(gballoc_free_with_an_untracked_pointer_does_not_alter_total_memory_used) { // arrange void* allocation; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); /* don't quite like this, but I'm unsure I want to invest more in this memory counting */ STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); gballoc_realloc(NULL, 1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act gballoc_free(TEST_REALLOC_PTR); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); gballoc_realloc(TEST_ALLOC_PTR1, 2); ASSERT_ARE_EQUAL(size_t, 2, gballoc_getMaximumMemoryUsed()); // cleanup gballoc_free(TEST_ALLOC_PTR1); free(allocation); } /* gballoc_getMaximumMemoryUsed */ /* Tests_SRS_GBALLOC_01_034: [gballoc_getMaximumMemoryUsed shall ensure thread safety by using the lock created by gballoc_Init.] */ TEST_FUNCTION(when_gballoc_getMaximumMemoryUsed_called_It_Shall_Lock_And_Unlock) { // arrange gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act (void)gballoc_getMaximumMemoryUsed(); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_050: [If the lock cannot be acquired, gballoc_getMaximumMemoryUsed shall return SIZE_MAX.] */ TEST_FUNCTION(when_acquiring_the_lock_fails_then_gballoc_getMaximumMemoryUsed_fails) { // arrange size_t result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)) .SetReturn(LOCK_ERROR); // act result = gballoc_getMaximumMemoryUsed(); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ASSERT_ARE_EQUAL(size_t, SIZE_MAX, result); } /* Tests_SRS_GBALLOC_01_038: [If gballoc was not initialized gballoc_getMaximumMemoryUsed shall return MAX_INT_SIZE.] */ TEST_FUNCTION(gballoc_getMaximumMemoryUsed_after_deinit_fails) { // arrange // act size_t result = gballoc_getMaximumMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, SIZE_MAX, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* gballoc_getCurrentMemoryUsed */ /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_1_byte_malloc_returns_1) { // arrange void* allocation; void* toBeFreed; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); STRICT_EXPECTED_CALL(mock_malloc(1)); toBeFreed = gballoc_malloc(1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup gballoc_free(toBeFreed); free(allocation); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_2x3_byte_calloc_returns_6) { // arrange void* allocation; void* toBeFreed; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); toBeFreed = gballoc_calloc(2, 3); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 6, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup gballoc_free(toBeFreed); free(allocation); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_1_byte_malloc_and_3_bytes_realloc_returns_3) { // arrange void* allocation; void* toBeFreed; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed = gballoc_malloc(1); toBeFreed = gballoc_realloc(toBeFreed, 3); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 3, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup gballoc_free(toBeFreed); free(allocation); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_1_byte_malloc_and_free_returns_0) { // arrange void* allocation; void* toBeFreed; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed = gballoc_malloc(1); gballoc_free(toBeFreed); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup free(allocation); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_2x3_byte_calloc_and_free_returns_0) { // arrange void* allocation; void* toBeFreed; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed = gballoc_calloc(2, 3); gballoc_free(toBeFreed); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup free(allocation); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_realloc_and_free_returns_0) { // arrange void* allocation; void* toBeFreed; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed = gballoc_malloc(1); toBeFreed = gballoc_realloc(toBeFreed, 3); gballoc_free(toBeFreed); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup free(allocation); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_1_byte_malloc_and_1_byte_malloc_returns_2) { // arrange void* allocation1; void* allocation2; void* toBeFreed1; void* toBeFreed2; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation1 = malloc(OVERHEAD_SIZE); allocation2 = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation1); STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation2); STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed1 = gballoc_malloc(1); toBeFreed2 = gballoc_malloc(1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 2, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup gballoc_free(toBeFreed1); gballoc_free(toBeFreed2); free(allocation1); free(allocation2); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_1_byte_malloc_and_1_byte_malloc_and_3_realloc_returns_4) { // arrange void* allocation1; void* allocation2; void* toBeFreed1; void* toBeFreed2; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation1 = malloc(OVERHEAD_SIZE); allocation2 = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation1); STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation2); STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed1 = gballoc_malloc(1); toBeFreed2 = gballoc_malloc(1); toBeFreed2 = gballoc_realloc(toBeFreed2, 3); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 4, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup gballoc_free(toBeFreed1); gballoc_free(toBeFreed2); free(allocation1); free(allocation2); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_1_byte_malloc_and_6_byte_calloc_returns_7) { // arrange void* allocation1; void* allocation2; void* toBeFreed1; void* toBeFreed2; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation1 = malloc(OVERHEAD_SIZE); allocation2 = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation1); STRICT_EXPECTED_CALL(mock_malloc(1)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation2); STRICT_EXPECTED_CALL(mock_calloc(2, 3)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed1 = gballoc_malloc(1); toBeFreed2 = gballoc_calloc(2, 3); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 7, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup gballoc_free(toBeFreed1); gballoc_free(toBeFreed2); free(allocation1); free(allocation2); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_1_byte_malloc_and_6_byte_calloc_and_free_returns_6) { // arrange void* allocation1; void* allocation2; void* toBeFreed1; void* toBeFreed2; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation1 = malloc(OVERHEAD_SIZE); allocation2 = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation1); STRICT_EXPECTED_CALL(mock_malloc(1)) .SetReturn((char*)allocation1 + OVERHEAD_SIZE / 2); /*somewhere in the middle of allocation*/ STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation2); STRICT_EXPECTED_CALL(mock_calloc(2, 3)) .SetReturn((char*)allocation2 + OVERHEAD_SIZE / 2); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed1 = gballoc_malloc(1); toBeFreed2 = gballoc_calloc(2, 3); gballoc_free(toBeFreed1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 6, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup gballoc_free(toBeFreed2); free(allocation1); free(allocation2); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /*Tests_SRS_GBALLOC_02_001: [gballoc_getCurrentMemoryUsed shall return the currently used memory size.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_1_byte_malloc_and_1_byte_malloc_and_3_realloc_and_free_returns_3) { // arrange void* allocation1; void* allocation2; void* toBeFreed1; void* toBeFreed2; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation1 = malloc(OVERHEAD_SIZE); allocation2 = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation1); STRICT_EXPECTED_CALL(mock_malloc(1)) .SetReturn((char*)allocation1 + OVERHEAD_SIZE / 2); /*somewhere in the middle of allocation*/ STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation2); STRICT_EXPECTED_CALL(mock_realloc(IGNORED_PTR_ARG, 3)) .IgnoreArgument(1) .SetReturn((char*)allocation2 + OVERHEAD_SIZE / 2); /*somewhere in the middle of allocation*/ STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); toBeFreed1 = gballoc_malloc(1); toBeFreed2 = gballoc_malloc(1); toBeFreed2 = gballoc_realloc(toBeFreed2, 3); gballoc_free(toBeFreed1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 3, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); ///cleanup gballoc_free(toBeFreed2); free(allocation1); free(allocation2); umock_c_reset_all_calls(); //this is just for mathematics, not for functionality } /* Tests_SRS_GBALLOC_01_036: [gballoc_getCurrentMemoryUsed shall ensure thread safety by using the lock created by gballoc_Init.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_locks_and_unlocks) { // assert size_t result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_044: [If gballoc was not initialized gballoc_getCurrentMemoryUsed shall return SIZE_MAX.] */ TEST_FUNCTION(gballoc_getCurrentMemoryUsed_after_deinit_fails) { // arrange // act size_t result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, SIZE_MAX, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_01_051: [If the lock cannot be acquired, gballoc_getCurrentMemoryUsed shall return SIZE_MAX.] */ TEST_FUNCTION(when_acquiring_the_lock_fails_gballoc_getCurrentMemoryUsed_fails) { // arrange size_t result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)) .SetReturn(LOCK_ERROR); // act result = gballoc_getCurrentMemoryUsed(); // assert ASSERT_ARE_EQUAL(size_t, SIZE_MAX, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_07_001: [ If gballoc was not initialized gballoc_getAllocationCount shall return SIZE_MAX. ] */ TEST_FUNCTION(gballoc_getAllocationCount_without_init_fail) { // arrange size_t result; // act result = gballoc_getAllocationCount(); // assert ASSERT_ARE_EQUAL(size_t, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_07_003: [ If the lock cannot be acquired, gballoc_getAllocationCount shall return SIZE_MAX. ] */ TEST_FUNCTION(gballoc_getAllocationCount_lock_fail) { // arrange size_t result; gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)) .SetReturn(LOCK_ERROR); // act result = gballoc_getAllocationCount(); // assert ASSERT_ARE_EQUAL(size_t, 0, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_07_004: [ gballoc_getAllocationCount shall return the currently number of allocations. ] */ /* Tests_SRS_GBALLOC_07_002: [ gballoc_getAllocationCount shall ensure thread safety by using the lock created by gballoc_Init ] */ TEST_FUNCTION(gballoc_getAllocationCount_success) { // arrange void* allocation; void* toBeFreed; size_t result; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); STRICT_EXPECTED_CALL(mock_malloc(1)); toBeFreed = gballoc_malloc(1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act result = gballoc_getAllocationCount(); // assert ASSERT_ARE_EQUAL(size_t, 1, result); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // Cleanup gballoc_free(toBeFreed); free(allocation); } TEST_FUNCTION(gballoc_resetMetrics_without_init_fail) { // arrange // act gballoc_resetMetrics(); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_07_003: [ If the lock cannot be acquired, gballoc_getAllocationCount shall return SIZE_MAX. ] */ TEST_FUNCTION(gballoc_resetMetrics_lock_fail) { // arrange gballoc_init(); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)) .SetReturn(LOCK_ERROR); // act gballoc_resetMetrics(); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* Tests_SRS_GBALLOC_07_004: [ gballoc_getAllocationCount shall return the currently number of allocations. ] */ /* Tests_SRS_GBALLOC_07_002: [ gballoc_getAllocationCount shall ensure thread safety by using the lock created by gballoc_Init ] */ TEST_FUNCTION(gballoc_resetMetrics_success) { // arrange void* allocation; void* toBeFreed; size_t mem_used; size_t alloc_count; gballoc_init(); umock_c_reset_all_calls(); allocation = malloc(OVERHEAD_SIZE); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); EXPECTED_CALL(mock_calloc(1, 0)) .SetReturn(allocation); STRICT_EXPECTED_CALL(mock_malloc(1)); toBeFreed = gballoc_malloc(1); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); alloc_count = gballoc_getAllocationCount(); ASSERT_ARE_EQUAL(size_t, 1, alloc_count); umock_c_reset_all_calls(); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Lock(TEST_LOCK_HANDLE)); STRICT_EXPECTED_CALL(Unlock(TEST_LOCK_HANDLE)); // act gballoc_resetMetrics(); mem_used = gballoc_getCurrentMemoryUsed(); alloc_count = gballoc_getAllocationCount(); // assert ASSERT_ARE_EQUAL(size_t, 0, mem_used); ASSERT_ARE_EQUAL(size_t, 0, alloc_count); ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); // Cleanup gballoc_free(toBeFreed); free(allocation); } END_TEST_SUITE(GBAlloc_UnitTests)