U
    #ºcL>  ã                   @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	m
Z
mZ d dlZejdd„ ƒZdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zejjdd„ ƒZejjejjdkddej ddd dg¡d!d"„ ƒƒZ d#d$„ Z!dS )%é    N)ÚextbuildÚassert_warnsÚIS_WASMc                 C   s|   t j d¡rt d¡ tr$t d¡ dddddd	g}d
}d}zddl}|W S  tk
r^   Y nX tj	d||t
 ¡ g| |dS )a   Add a memory policy that returns a false pointer 64 bytes into the
    actual allocation, and fill the prefix with some text. Then check at each
    memory manipulation that the prefix exists, to make sure all alloc/realloc/
    free/calloc go via the functions here.
    Úcygwinzlink fails on cygwinzCan't build module inside Wasm)Úget_default_policyÚMETH_NOARGSzj
             Py_INCREF(PyDataMem_DefaultHandler);
             return PyDataMem_DefaultHandler;
         )Úset_secret_data_policyr   aM  
             PyObject *secret_data =
                 PyCapsule_New(&secret_data_handler, "mem_handler", NULL);
             if (secret_data == NULL) {
                 return NULL;
             }
             PyObject *old = PyDataMem_SetHandler(secret_data);
             Py_DECREF(secret_data);
             return old;
         )Úset_old_policyÚMETH_Oa  
             PyObject *old;
             if (args != NULL && PyCapsule_CheckExact(args)) {
                 old = PyDataMem_SetHandler(args);
             }
             else {
                 old = PyDataMem_SetHandler(NULL);
             }
             return old;
         )Ú	get_arrayr   aM  
            char *buf = (char *)malloc(20);
            npy_intp dims[1];
            dims[0] = 20;
            PyArray_Descr *descr =  PyArray_DescrNewFromType(NPY_UINT8);
            return PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims, NULL,
                                        buf, NPY_ARRAY_WRITEABLE, NULL);
         )Úset_ownr
   aƒ  
            if (!PyArray_Check(args)) {
                PyErr_SetString(PyExc_ValueError,
                             "need an ndarray");
                return NULL;
            }
            PyArray_ENABLEFLAGS((PyArrayObject*)args, NPY_ARRAY_OWNDATA);
            // Maybe try this too?
            // PyArray_BASE(PyArrayObject *)args) = NULL;
            Py_RETURN_NONE;
         )Úget_array_with_baser   a~  
            char *buf = (char *)malloc(20);
            npy_intp dims[1];
            dims[0] = 20;
            PyArray_Descr *descr =  PyArray_DescrNewFromType(NPY_UINT8);
            PyObject *arr = PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims,
                                                 NULL, buf,
                                                 NPY_ARRAY_WRITEABLE, NULL);
            if (arr == NULL) return NULL;
            PyObject *obj = PyCapsule_New(buf, "buf capsule",
                                          (PyCapsule_Destructor)&warn_on_free);
            if (obj == NULL) {
                Py_DECREF(arr);
                return NULL;
            }
            if (PyArray_SetBaseObject((PyArrayObject *)arr, obj) < 0) {
                Py_DECREF(arr);
                Py_DECREF(obj);
                return NULL;
            }
            return arr;

         a  
        #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
        #include <numpy/arrayobject.h>
        /*
         * This struct allows the dynamic configuration of the allocator funcs
         * of the `secret_data_allocator`. It is provided here for
         * demonstration purposes, as a valid `ctx` use-case scenario.
         */
        typedef struct {
            void *(*malloc)(size_t);
            void *(*calloc)(size_t, size_t);
            void *(*realloc)(void *, size_t);
            void (*free)(void *);
        } SecretDataAllocatorFuncs;

        NPY_NO_EXPORT void *
        shift_alloc(void *ctx, size_t sz) {
            SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx;
            char *real = (char *)funcs->malloc(sz + 64);
            if (real == NULL) {
                return NULL;
            }
            snprintf(real, 64, "originally allocated %ld", (unsigned long)sz);
            return (void *)(real + 64);
        }
        NPY_NO_EXPORT void *
        shift_zero(void *ctx, size_t sz, size_t cnt) {
            SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx;
            char *real = (char *)funcs->calloc(sz + 64, cnt);
            if (real == NULL) {
                return NULL;
            }
            snprintf(real, 64, "originally allocated %ld via zero",
                     (unsigned long)sz);
            return (void *)(real + 64);
        }
        NPY_NO_EXPORT void
        shift_free(void *ctx, void * p, npy_uintp sz) {
            SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx;
            if (p == NULL) {
                return ;
            }
            char *real = (char *)p - 64;
            if (strncmp(real, "originally allocated", 20) != 0) {
                fprintf(stdout, "uh-oh, unmatched shift_free, "
                        "no appropriate prefix\n");
                /* Make C runtime crash by calling free on the wrong address */
                funcs->free((char *)p + 10);
                /* funcs->free(real); */
            }
            else {
                npy_uintp i = (npy_uintp)atoi(real +20);
                if (i != sz) {
                    fprintf(stderr, "uh-oh, unmatched shift_free"
                            "(ptr, %ld) but allocated %ld\n", sz, i);
                    /* This happens in some places, only print */
                    funcs->free(real);
                }
                else {
                    funcs->free(real);
                }
            }
        }
        NPY_NO_EXPORT void *
        shift_realloc(void *ctx, void * p, npy_uintp sz) {
            SecretDataAllocatorFuncs *funcs = (SecretDataAllocatorFuncs *)ctx;
            if (p != NULL) {
                char *real = (char *)p - 64;
                if (strncmp(real, "originally allocated", 20) != 0) {
                    fprintf(stdout, "uh-oh, unmatched shift_realloc\n");
                    return realloc(p, sz);
                }
                return (void *)((char *)funcs->realloc(real, sz + 64) + 64);
            }
            else {
                char *real = (char *)funcs->realloc(p, sz + 64);
                if (real == NULL) {
                    return NULL;
                }
                snprintf(real, 64, "originally allocated "
                         "%ld  via realloc", (unsigned long)sz);
                return (void *)(real + 64);
            }
        }
        /* As an example, we use the standard {m|c|re}alloc/free funcs. */
        static SecretDataAllocatorFuncs secret_data_handler_ctx = {
            malloc,
            calloc,
            realloc,
            free
        };
        static PyDataMem_Handler secret_data_handler = {
            "secret_data_allocator",
            1,
            {
                &secret_data_handler_ctx, /* ctx */
                shift_alloc,              /* malloc */
                shift_zero,               /* calloc */
                shift_realloc,            /* realloc */
                shift_free                /* free */
            }
        };
        void warn_on_free(void *capsule) {
            PyErr_WarnEx(PyExc_UserWarning, "in warn_on_free", 1);
            void * obj = PyCapsule_GetPointer(capsule,
                                              PyCapsule_GetName(capsule));
            free(obj);
        };
        zimport_array();r   NÚ
mem_policy)ÚprologueÚinclude_dirsÚ	build_dirÚ	more_init)ÚsysÚplatformÚ
startswithÚpytestÚskipr   r   ÚImportErrorr   Zbuild_and_import_extensionÚnpZget_include)Ztmp_pathZ	functionsr   r   r   © r   úD/tmp/pip-unpacked-wheel-b2rbor69/numpy/core/tests/test_mem_policy.pyÚ
get_module   s2    



ÔDmûr   c                 C   s
  t jjj}t jjj}|ƒ }t  d¡ d¡}||ƒd ks:t‚||ƒd ksJt‚||jƒ|ks\t‚||jƒdksnt‚|  	¡ }t  d¡ d¡}||ƒd ks–t‚||ƒd ks¦t‚||jƒdks¸t‚||jƒdksÊt‚|dkrì|  
d ¡ |ƒ dksêt‚n|  
|¡ |ƒ |kst‚d S )Né
   ©é   é   é   Úsecret_data_allocatorÚdefault_allocator)r   ÚcoreÚ
multiarrayÚget_handler_nameÚget_handler_versionÚarangeÚreshapeÚAssertionErrorÚbaser   r	   )r   r&   r'   Úorig_policy_nameÚaÚorig_policyÚbr   r   r   Útest_set_policy×   s&    



r0   c                 C   sf   t jjj}|  d ¡}|ƒ dks"t‚|  d ¡}|ƒ dks:t‚|  |¡}||  kr\|  ¡ ksbn t‚d S ©Nr#   )r   r$   r%   r&   r	   r*   r   )r   r&   r.   Zdef_policy_1Zdef_policy_2r   r   r   Útest_default_policy_singletonó   s    



r2   c                 C   s¨   G dd„ dt jƒ}t jjj}|ƒ }t  d¡ |¡ d¡}||ƒd ksHt‚|j	j
dksXt‚||jƒd ksjt‚|jj	j
dks|t‚||jjƒ|kst‚|jjj	j
dks¤t‚d S )Nc                   @   s   e Zd ZdS )z&test_policy_propagation.<locals>.MyArrN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   ÚMyArr  s   r6   r   r   FT)r   Zndarrayr$   r%   r&   r(   Úviewr)   r*   ÚflagsZowndatar+   )r   r6   r&   r,   r-   r   r   r   Útest_policy_propagation  s    
r9   c                 Ã   sP   |dkr&|   ¡  tjj ¡ dksDt‚n|  d ¡ tjj ¡ dksDt‚| ¡  d S ©Nr#   r"   )r   r   r$   r%   r&   r*   r	   Úset©r   r,   Úeventr   r   r   Úconcurrent_context1  s    
r>   c                 Ã   sj   |  ¡ I d H  tjj ¡ |ks"t‚|dkrH|  ¡  tjj ¡ dksft‚n|  d ¡ tjj ¡ dksft‚d S r:   )Úwaitr   r$   r%   r&   r*   r   r	   r<   r   r   r   Úconcurrent_context2%  s    
r@   c                 Ã   sd   t jj ¡ }t ¡ }t t| ||ƒ¡}t t| ||ƒ¡}|I d H  |I d H  t jj ¡ |ks`t	‚d S )N)
r   r$   r%   r&   ÚasyncioÚEventZcreate_taskr>   r@   r*   ©r   r,   r=   Zconcurrent_task1Zconcurrent_task2r   r   r   Úasync_test_context_locality2  s    
ÿ
ÿ

rD   c                 C   s:   t jjdkr(t jd d… dk r(t d¡ t t| ƒ¡ d S )NÚpypyé   )é   rF   é   z+no context-locality support in PyPy < 7.3.6)	r   ÚimplementationÚnameÚpypy_version_infor   r   rA   ÚrunrD   )r   r   r   r   Útest_context_localityB  s
    ÿ
rM   c                 C   s(   |   ¡  tjj ¡ dkst‚| ¡  d S )Nr"   )r   r   r$   r%   r&   r*   r;   ©r   r=   r   r   r   Úconcurrent_thread1I  s    rO   c                 C   s(   |  ¡  tjj ¡ dkst‚|  ¡  d S r1   )r?   r   r$   r%   r&   r*   r   rN   r   r   r   Úconcurrent_thread2O  s    rP   c                 C   sp   t jj ¡ }t ¡ }tjt| |fd}tjt| |fd}| 	¡  | 	¡  | 
¡  | 
¡  t jj ¡ |kslt‚d S )N)ÚtargetÚargs)r   r$   r%   r&   Ú	threadingrB   ÚThreadrO   rP   ÚstartÚjoinr*   rC   r   r   r   Útest_thread_localityW  s    ÿÿrW   c                 C   s¦   t  d¡}t jj |¡}|  ¡ }t  d¡}t jj |¡dks@t‚|dkrxt jjdddgds`t‚t jjdddgdsxt‚|  	|¡ t  d¡}t jj |¡|ks¢t‚d S )Nr   r"   r#   Úfullr   z-vv)ÚverboseZ
extra_argv)
r   r(   r$   r%   r&   r   r*   ÚtestÚmar	   )r   r-   r,   r.   r/   Úcr   r   r   Útest_new_policyi  s    



r]   rE   z;bad interaction between getenv and os.environ inside pytest)ÚreasonÚpolicyÚ0Ú1c              	   C   sÈ   |   ¡ }tjj |¡d kst‚|  |¡ tj 	dd ¡}|d krVdtjkr`tj 
d¡ n
|tjd< z6|dkrŠttƒ}~t ¡  W 5 Q R X n
~t ¡  W 5 |d kr¸dtjkrÂtj 
d¡ n
|tjd< X d S )NZNUMPY_WARN_IF_NO_MEM_POLICYra   )r   r   r$   r%   r&   r*   r   ÚosÚenvironÚgetÚpopr   ÚRuntimeWarningÚgcÚcollect)r   r_   r-   ZoldvalÚwr   r   r   Útest_switch_owner…  s&    




rj   c              	   C   s0   |   ¡ }tjtdd ~t ¡  W 5 Q R X d S )NZwarn_on_free)Úmatch)r   r   ZwarnsÚUserWarningrg   rh   )r   r-   r   r   r   Útest_owner_is_base¥  s    rm   )"rA   rg   rb   r   Znumpyr   rS   ÚwarningsZnumpy.testingr   r   r   r   Zfixturer   r0   r2   r9   r>   r@   rD   rM   rO   rP   rW   ÚmarkZslowr]   ZxfailrI   rJ   Zparametrizerj   rm   r   r   r   r   Ú<module>   s:   
 K

ÿ