Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Feedback Pool Allocator tests
0003  *
0004  * @file test_nstd_fpa.c
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037 #include <cgreen/cgreen.h>
0038 #include <ubf.h>
0039 #include <ndrstandard.h>
0040 #include <string.h>
0041 #include <errno.h>
0042 #include <ndebug.h>
0043 #include <exbase64.h>
0044 #include <nstdutil.h>
0045 #include "test.fd.h"
0046 #include "ubfunit1.h"
0047 #include "xatmi.h"
0048 #include "nstopwatch.h"
0049 #include <nstd_int.h>
0050 #include <fpalloc.h>
0051 
0052 /*---------------------------Externs------------------------------------*/
0053 /*---------------------------Macros-------------------------------------*/
0054 /*---------------------------Enums--------------------------------------*/
0055 /*---------------------------Typedefs-----------------------------------*/
0056 /*---------------------------Globals------------------------------------*/
0057 /*---------------------------Statics------------------------------------*/
0058 /*---------------------------Prototypes---------------------------------*/
0059 
0060 /**
0061  * Check dynamic blocks
0062  */
0063 Ensure(test_nstd_fpa_dyn)
0064 {
0065     char *ptr[1];
0066     char *ptr2[1];
0067     ndrx_fpablock_t *hdr[1];
0068     
0069     unsetenv(CONF_NDRX_FPAOPTS);
0070 
0071     ptr[0] = ndrx_fpmalloc(NDRX_FPA_0_SIZE, 0);
0072     hdr[0] = (ndrx_fpablock_t *)(ptr[0] - sizeof(ndrx_fpablock_t));
0073     assert_not_equal(ptr[0], NULL);
0074     /* 0 block */
0075     assert_equal(hdr[0]->poolno, 0);
0076     ndrx_fpfree(ptr[0]);
0077     
0078     /* alloc again, block shall be re-used */
0079     ptr2[0] = ndrx_fpmalloc(NDRX_FPA_0_SIZE, 0);
0080     assert_equal(ptr2[0], ptr[0]);
0081     
0082     /* check the boundries -> if any problem addr sanitizer will check */
0083     memset(ptr2[0], 0, NDRX_FPA_0_SIZE);
0084     
0085     
0086     /* add to stack.. -> free up ? */
0087     ndrx_fpfree(ptr2[0]);
0088     
0089     /* check pool 1 size */
0090     ptr[0] = ndrx_fpmalloc(NDRX_FPA_0_SIZE+1, 0);
0091     hdr[0] = (ndrx_fpablock_t *)(ptr[0] - sizeof(ndrx_fpablock_t));
0092     assert_not_equal(ptr[0], NULL);
0093     assert_equal(hdr[0]->poolno, 1); /* next pool */
0094     ndrx_fpfree(ptr[0]);
0095     
0096     /* check pool 4 */
0097     ptr[0] = ndrx_fpmalloc(NDRX_FPA_4_SIZE, 0);
0098     hdr[0] = (ndrx_fpablock_t *)(ptr[0] - sizeof(ndrx_fpablock_t));
0099     assert_not_equal(ptr[0], NULL);
0100     assert_equal(hdr[0]->poolno, 4);
0101     ndrx_fpfree(ptr[0]);
0102     
0103     /* alloc sysbuf... */
0104     ptr[0] = ndrx_fpmalloc(NDRX_MSGSIZEMAX, NDRX_FPSYSBUF);
0105     hdr[0] = (ndrx_fpablock_t *)(ptr[0] - sizeof(ndrx_fpablock_t));
0106     assert_not_equal(ptr[0], NULL);
0107     assert_equal(hdr[0]->poolno, NDRX_FPA_SYSBUF_POOLNO);
0108     ndrx_fpfree(ptr[0]);
0109     
0110     /* get arbsize... */
0111     ptr[0] = ndrx_fpmalloc(NDRX_FPA_SIZE_MAX+1, 0);
0112     hdr[0] = (ndrx_fpablock_t *)(ptr[0] - sizeof(ndrx_fpablock_t));
0113     assert_not_equal(ptr[0], NULL);
0114     assert_equal(hdr[0]->flags, NDRX_FPABRSIZE);
0115     assert_equal(hdr[0]->poolno, EXFAIL);
0116     ndrx_fpfree(ptr[0]);
0117     
0118     /* deinit the pool */
0119     ndrx_fpuninit();
0120     
0121 }
0122 
0123 /**
0124  * Pool limits tests
0125  */
0126 Ensure(test_nstd_fpa_limits)
0127 {
0128     char *ptr[NDRX_FPA_4_DNUM+1];
0129     char *ptr2[NDRX_FPA_4_DNUM+1];
0130     int i;
0131     ndrx_fpapool_t stats;    
0132     
0133     unsetenv(CONF_NDRX_FPAOPTS);
0134 
0135     /* load the bmin blocks */
0136     for (i=0; i<NDRX_FPA_4_DNUM; i++)
0137     {
0138         ptr2[i] = ptr[i] = ndrx_fpmalloc(NDRX_FPA_4_SIZE, 0);
0139         
0140         /* use the memory. */
0141         memset(ptr[i], i, NDRX_FPA_4_SIZE);
0142         
0143         /* check that we alloc'd something */
0144         assert_not_equal(ptr[i], NULL);
0145     }
0146 
0147     /* free up the pool, in reverse order, so that latest goes to the stack.. */
0148     for (i=NDRX_FPA_4_DNUM-1; i>=0; i--)
0149     {
0150         ndrx_fpfree(ptr[i]);
0151     }
0152     
0153     /* get pool stats, shall be NDRX_FPA_BNUM allocations */
0154     ndrx_fpstats(4, &stats);
0155     
0156     assert_equal(stats.cur_blocks, NDRX_FPA_4_DNUM);
0157     
0158     /* alloc again, pointer shall match */
0159     
0160     for (i=0; i<NDRX_FPA_4_DNUM; i++)
0161     {
0162         ptr2[i] = ndrx_fpmalloc(NDRX_FPA_4_SIZE, 0);
0163         
0164         /* check that we alloc'd something */
0165         assert_not_equal(ptr2[i], NULL);
0166         
0167         /* blocks are the same as on first alloc... */
0168         assert_equal(ptr[i][0], i);
0169         
0170         /* ptrs match ... */
0171         assert_equal(ptr2[i], ptr[i]);
0172     }
0173     
0174     /* extra alloc over the pool limits */
0175     ptr2[NDRX_FPA_4_DNUM] = ndrx_fpmalloc(NDRX_FPA_4_SIZE, 0);
0176     assert_not_equal(ptr2[NDRX_FPA_4_DNUM], NULL);
0177     
0178     /* free stuff up... check the blocks ... */
0179     for (i=0; i<NDRX_FPA_4_DNUM; i++)
0180     {
0181         ndrx_fpstats(4, &stats);
0182         assert_equal(stats.cur_blocks, i);
0183         ndrx_fpfree(ptr2[i]);
0184     }
0185     
0186     ndrx_fpstats(4, &stats);
0187     assert_equal(stats.cur_blocks, NDRX_FPA_4_DNUM);
0188     
0189     /* free up that one extra... should have the same max blocks.. */
0190     ndrx_fpfree(ptr2[NDRX_FPA_4_DNUM]);
0191     ndrx_fpstats(4, &stats);
0192     assert_equal(stats.cur_blocks, NDRX_FPA_4_DNUM);
0193     
0194     /* deinit the pool */
0195     ndrx_fpuninit();
0196 }
0197 
0198 
0199 #define CHK_LOOPS   5
0200 /**
0201  * Dynamic work with some blocks
0202  */
0203 static void * thread_start(void *arg)
0204 {
0205     int i, j;
0206     char *ptr[NDRX_FPA_SYSBUF_DNUM+1];
0207     ndrx_fpapool_t stats;
0208     
0209     ndrx_fpstats(NDRX_FPA_SYSBUF_POOLNO, &stats);
0210     
0211     for (j=0; j<1000; j++)
0212     {
0213         
0214         for (i=0; i<CHK_LOOPS; i++)
0215         {
0216             ptr[i] = ndrx_fpmalloc(NDRX_MSGSIZEMAX, NDRX_FPSYSBUF);
0217         }
0218 
0219         for (i=0; i<CHK_LOOPS; i++)
0220         {
0221             ndrx_fpfree(ptr[i]);
0222         }
0223     }
0224     
0225     return NULL;
0226 }
0227  
0228 /**
0229  * Init the pool. Run two threads.
0230  * The pool size shall stay in the boundries of alloc'd size
0231  * due to negative feedback (went bellow bmin)
0232  */
0233 Ensure(test_nstd_fpa_threaded)
0234 {
0235     char *ptr[NDRX_FPA_SYSBUF_DNUM];
0236     int i;
0237     ndrx_fpapool_t stats;
0238     pthread_t th1;
0239     pthread_t th2;
0240     int ret;
0241     
0242     unsetenv(CONF_NDRX_FPAOPTS);
0243 
0244     /* build up the pool */
0245     for (i=0; i<NDRX_FPA_SYSBUF_DNUM; i++)
0246     {
0247         ptr[i] = ndrx_fpmalloc(NDRX_MSGSIZEMAX, NDRX_FPSYSBUF);
0248     }
0249     
0250     /* load blocks in the pool */
0251     for (i=0; i<NDRX_FPA_SYSBUF_DNUM; i++)
0252     {
0253         ndrx_fpfree(ptr[i]);
0254     }
0255     
0256     ret=pthread_create(&th1, NULL, thread_start, NULL);
0257     assert_equal(ret, EXSUCCEED);
0258     
0259     ret=pthread_create(&th2, NULL, thread_start, NULL);
0260     assert_equal(ret, EXSUCCEED);
0261     
0262     pthread_join(th1, NULL);
0263     pthread_join(th2, NULL);
0264     
0265     ndrx_fpstats(NDRX_FPA_SYSBUF_POOLNO, &stats);
0266     assert_equal(stats.cur_blocks, NDRX_FPA_SYSBUF_DNUM);
0267  
0268     /* deinit the pool */
0269     ndrx_fpuninit();
0270     
0271 }
0272 
0273 /**
0274  * Load some config...
0275  */
0276 Ensure(test_nstd_fpa_config_memall)
0277 {
0278     char *ptr;
0279     int i;
0280     
0281     /* use malloc only... */
0282     setenv(CONF_NDRX_FPAOPTS, "D:M", EXTRUE);
0283     
0284     for (i=0;i<10;i++)
0285     {
0286         ptr=ndrx_fpmalloc(777, 0);
0287         assert_not_equal(ptr, NULL);
0288         ndrx_fpfree(ptr);
0289     }
0290     
0291     /* deinit the pool */
0292     ndrx_fpuninit();
0293     
0294 }
0295 
0296 /**
0297  * Configure limits and verify...
0298  */
0299 Ensure(test_nstd_fpa_config_limits)
0300 {    
0301     char *ptr;
0302     ndrx_fpapool_t stats;
0303     
0304     /* use malloc only... */
0305     setenv(CONF_NDRX_FPAOPTS, "256:5,2K:3,S:20,4K:M", EXTRUE);
0306     
0307     /* pull in the init... */
0308     ptr=ndrx_fpmalloc(777, 0);
0309     assert_not_equal(ptr, NULL);
0310     ndrx_fpfree(ptr);
0311     
0312     /* check the settings applied... */
0313     ndrx_fpstats(0, &stats);
0314     assert_equal(stats.num_blocks, 5);
0315     
0316     /* check the settings applied... */
0317     ndrx_fpstats(3, &stats);
0318     assert_equal(stats.num_blocks, 3);
0319     
0320     /* check the settings applied... */
0321     ndrx_fpstats(NDRX_FPA_SYSBUF_POOLNO, &stats);
0322     assert_equal(stats.num_blocks, 20);
0323     
0324     ndrx_fpstats(4, &stats);
0325     assert_equal(stats.flags, NDRX_FPNOPOOL);
0326     
0327     /* deinit the pool */
0328     ndrx_fpuninit();
0329     
0330 }
0331 
0332 /**
0333  * Check invalid config
0334  */
0335 Ensure(test_nstd_fpa_config_inval)
0336 {
0337     char *ptr;
0338     ndrx_fpapool_t stats;
0339     /* use malloc only... */
0340     setenv(CONF_NDRX_FPAOPTS, "1:5:3:4:6", EXTRUE);
0341     /* pull in the init... */
0342     assert_equal(ndrx_fpmalloc(777, 0), NULL);
0343     assert_equal(errno, EINVAL);
0344     
0345     setenv(CONF_NDRX_FPAOPTS, "X", EXTRUE);
0346     assert_equal(ndrx_fpmalloc(777, 0), NULL);
0347     assert_equal(errno, EINVAL);
0348     
0349     setenv(CONF_NDRX_FPAOPTS, "1:5, 4:5", EXTRUE);
0350     assert_equal(ndrx_fpmalloc(777, 0), NULL);
0351     assert_equal(errno, EINVAL);
0352     
0353     setenv(CONF_NDRX_FPAOPTS, "4M:4", EXTRUE);
0354     assert_equal(ndrx_fpmalloc(777, 0), NULL);
0355     assert_equal(errno, EINVAL);
0356     
0357     setenv(CONF_NDRX_FPAOPTS, "4K:99", EXTRUE);
0358     assert_not_equal((ptr=ndrx_fpmalloc(777, 0)), NULL);
0359     ndrx_fpstats(4, &stats);
0360     assert_equal(stats.num_blocks, 99);
0361     ndrx_fpfree(ptr);
0362     
0363     /* check the settings applied... */
0364     ndrx_fpstats(NDRX_FPA_SYSBUF_POOLNO, &stats);
0365     assert_equal(stats.num_blocks, NDRX_FPA_SYSBUF_DNUM);
0366     assert_equal(stats.flags, NDRX_FPSYSBUF);
0367     
0368 }
0369 
0370 /**
0371  * Do some realloc tests
0372  */
0373 Ensure(test_nstd_fpa_realloc)
0374 {
0375     ndrx_fpapool_t stats;
0376     ndrx_fpablock_t *hdr;
0377     char *ptr, *ptr2;
0378     
0379     unsetenv(CONF_NDRX_FPAOPTS);
0380 
0381     ptr = ndrx_fpmalloc(NDRX_FPA_0_SIZE-100, 0);
0382     
0383     NDRX_STRCPY_SAFE_DST(ptr, "HELLO WORLD", (NDRX_FPA_0_SIZE-100));
0384     
0385     hdr = (ndrx_fpablock_t *)(ptr - sizeof(ndrx_fpablock_t));
0386     assert_equal(hdr->poolno, 0);
0387     
0388     /* check that it is still first pool, no pointer change */
0389     ptr2 = ndrx_fprealloc(ptr, NDRX_FPA_0_SIZE);
0390     assert_equal(ptr, ptr2);
0391     hdr = (ndrx_fpablock_t *)(ptr - sizeof(ndrx_fpablock_t));
0392     assert_equal(hdr->poolno, 0);
0393     assert_string_equal(ptr, "HELLO WORLD");
0394     
0395     
0396     /* check that it is second poll */
0397     ptr = ndrx_fprealloc(ptr, NDRX_FPA_1_SIZE);
0398     hdr = (ndrx_fpablock_t *)(ptr - sizeof(ndrx_fpablock_t));
0399     assert_equal(hdr->poolno, 1);
0400     assert_string_equal(ptr, "HELLO WORLD");
0401     
0402     /* check that it is free style pool */
0403     ptr = ndrx_fprealloc(ptr, NDRX_FPA_5_SIZE+100);
0404     hdr = (ndrx_fpablock_t *)(ptr - sizeof(ndrx_fpablock_t));
0405     assert_equal(hdr->flags, NDRX_FPABRSIZE);
0406     assert_string_equal(ptr, "HELLO WORLD");
0407     
0408     /* check that it is first pool */
0409     ptr = ndrx_fprealloc(ptr, 1);
0410     hdr = (ndrx_fpablock_t *)(ptr - sizeof(ndrx_fpablock_t));
0411     assert_equal(hdr->poolno, 0);
0412     /* block stays the same... */
0413     assert_string_equal(ptr, "HELLO WORLD");
0414     
0415     ndrx_fpfree(ptr);
0416     
0417     ndrx_fpstats(0, &stats);
0418     
0419     assert_equal(stats.cur_blocks, 1);
0420     
0421     
0422 }
0423 
0424 /**
0425  * Standard library tests
0426  * @return
0427  */
0428 TestSuite *ubf_nstd_fpa(void)
0429 {
0430     TestSuite *suite = create_test_suite();
0431 
0432     add_test(suite, test_nstd_fpa_dyn);
0433     add_test(suite, test_nstd_fpa_limits);
0434     add_test(suite, test_nstd_fpa_threaded);
0435     add_test(suite, test_nstd_fpa_config_memall);
0436     add_test(suite, test_nstd_fpa_config_limits);
0437     add_test(suite, test_nstd_fpa_config_inval);
0438     add_test(suite, test_nstd_fpa_realloc);
0439     
0440     return suite;
0441 }
0442 /* vim: set ts=4 sw=4 et smartindent: */