text: /*
   * Copyright (c) 2017 Intel Corporation
   *
   * SPDX-License-Identifier: Apache-2.0
   */
  
  /*
   * @file test dynamic memory allocation using C libraries
   *
   * This module verifies that the various dynamic memory allocation functions
   * works fine with minimal C library and newlib C library.
   *
   * IMPORTANT: The module only ensures that each supported library is present,
   * and that a bare minimum of its functionality is operating correctly. It does
   * NOT guarantee that ALL standards-defined functionality is present, nor does
   * it guarantee that ALL functionality provided is working correctly.
   */
  
  #include <zephyr.h>
  #include <ztest.h>
  #include <stdlib.h>
  #include <errno.h>
  #include <kernel_internal.h>
  
  #define BUF_LEN 10
  
  #ifdef CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE
  #define MAX_HEAP_SIZE CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE
  #endif
  
  /**
   * @brief Test dynamic memory allocation using malloc
   *
   * @see malloc(), free()
   */
  void test_malloc(void)
  {
  	/* Initialize error number to avoid garbage value, in case of SUCCESS */
  	int *iptr = NULL;
  
  	iptr = malloc(BUF_LEN * sizeof(int));
  	zassert_not_null((iptr), "malloc failed, errno: %d", errno);
  	free(iptr);
  	iptr = NULL;
  }
  
  /**
   * @brief Test dynamic memory allocation free function
   *
   * @see free()
   */
  void test_free(void)
  {
  /*
   * In free, if ptr is passed as NULL, no operation is performed
   * Just make sure, no exception occurs and test pass
   */
  	free(NULL);
  }
  
  /**
   * @brief Test dynamic memory allocation using calloc
   *
   * @see calloc(), free()
   */
  #define CALLOC_BUFLEN (200)
  static unsigned char zerobuf[CALLOC_BUFLEN];
  
  void test_calloc(void)
  {
  	char *cptr = NULL;
  
  	cptr =  calloc(CALLOC_BUFLEN, sizeof(char));
  	zassert_not_null((cptr), "calloc failed, errno: %d", errno);
  	zassert_true(((memcmp(cptr, zerobuf, CALLOC_BUFLEN)) == 0),
  			"calloc failed to set zero value, errno: %d", errno);
  	free(cptr);
  	cptr = NULL;
  }
  
  /**
   * @brief Test dynamic memory allocation using realloc
   *
   * @see malloc(), realloc(), free()
   */
  unsigned char filled_buf[BUF_LEN];
  
  void test_realloc(void)
  {
  	char orig_size = BUF_LEN;
  	char new_size = BUF_LEN + BUF_LEN;
  	char *ptr = NULL;
  	char *reloc_ptr = NULL;
  
  	ptr = malloc(orig_size);
  
  	zassert_not_null((ptr), "malloc failed, errno: %d", errno);
  	(void)memset(ptr, 'p', orig_size);
  
  	reloc_ptr = realloc(ptr, new_size);
  
  	zassert_not_null(reloc_ptr, "realloc failed, errno: %d", errno);
  	zassert_not_null((ptr), "malloc/realloc failed, errno: %d", errno);
  	ptr = reloc_ptr;
  
  	(void)memset(filled_buf, 'p', BUF_LEN);
  	zassert_true(((memcmp(ptr, filled_buf, BUF_LEN)) == 0),
  			"realloc failed to copy malloc data, errno: %d", errno);
  
  	free(ptr);
  	ptr = NULL;
  }
  
  /**
   * @brief Test dynamic memory allocation using reallocarray
   *
   * @see malloc(), reallocarray(), free()
   */
  #ifdef CONFIG_NEWLIB_LIBC
  void test_reallocarray(void)
  {
  	/* reallocarray not implemented for newlib */
  	ztest_test_skip();
  }
  #else
  void test_reallocarray(void)
  {
  	char orig_size = BUF_LEN;
  	char *ptr = NULL;
  
  	ptr = malloc(orig_size);
  
  	zassert_not_null((ptr), "malloc failed, errno: %d", errno);
  	(void)memset(ptr, 'p', orig_size);
  
  	char *reloc_ptr = reallocarray(ptr, 2, orig_size);
  
  	zassert_not_null(reloc_ptr, "reallocarray failed");
  	zassert_not_null((ptr), "malloc/reallocarray failed, errno: %d", errno);
  	ptr = reloc_ptr;
  
  	(void)memset(filled_buf, 'p', BUF_LEN);
  	zassert_true(((memcmp(ptr, filled_buf, BUF_LEN)) == 0),
  			"realloc failed to copy malloc data, errno: %d", errno);
  
  	free(ptr);
  	ptr = NULL;
  }
  #endif
  
  
  #define MAX_LEN (10 * BUF_LEN)
  
  /**
   * @brief Test dynamic memory allocation functions
   *
   * @see malloc(), calloc(), realloc(), free()
   */
  void test_memalloc_all(void)
  {
  	char *mlc_ptr = NULL;
  	char *clc_ptr = NULL;
  	char *reloc_ptr = NULL;
  	int orig_size = BUF_LEN;
  	int new_size = MAX_LEN;
  
  	mlc_ptr = malloc(orig_size);
  	zassert_not_null((mlc_ptr), "malloc failed, errno: %d", errno);
  
  	clc_ptr = calloc(100, sizeof(char));
  	zassert_not_null((clc_ptr), "calloc failed, errno: %d", errno);
  
  	reloc_ptr = realloc(mlc_ptr, new_size);
  	zassert_not_null(reloc_ptr, "realloc failed, errno: %d", errno);
  	zassert_not_null((mlc_ptr), "malloc/realloc failed, errno: %d", errno);
  	mlc_ptr = reloc_ptr;
  
  	free(mlc_ptr);
  	free(clc_ptr);
  	mlc_ptr = NULL;
  	clc_ptr = NULL;
  	reloc_ptr = NULL;
  }
  
  /**
   *
   * @brief Test dynamic memory allocation upto maximum size
   * Negative test case
   *
   */
  
  void test_memalloc_max(void)
  {
  	size_t max_heap_size = 0;
  	char *ptr = NULL;
  
  #ifdef CONFIG_NEWLIB_LIBC
  	void *heap_base = NULL;
  
  	z_newlib_get_heap_bounds(&heap_base, &max_heap_size);
  #else
  	max_heap_size = MAX_HEAP_SIZE;
  #endif
  	ptr = malloc(max_heap_size + 1);
  	zassert_is_null(ptr, "malloc passed unexpectedly");
  	free(ptr);
  	ptr = NULL;
  }
  
  void test_main(void)
  {
  	ztest_test_suite(test_c_lib_dynamic_memalloc,
  			 ztest_unit_test(test_malloc),
  			 ztest_unit_test(test_free),
  			 ztest_unit_test(test_calloc),
  			 ztest_unit_test(test_realloc),
  			 ztest_unit_test(test_reallocarray),
  			 ztest_unit_test(test_memalloc_all),
  			 ztest_unit_test(test_memalloc_max)
  			 );
  	ztest_run_test_suite(test_c_lib_dynamic_memalloc);
  }
  