o
    1ήc=                     @   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
 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g dd d! Zd"d# Z dS )$    N)extbuildassert_warnsc                 C   sd   t jdrtd g d}d}d}zddl}|W S  ty#   Y nw 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 cygwin))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   ImportErrorr   build_and_import_extensionnpget_include)tmp_path	functionsr   r   r    r   G/tmp/pip-target-vg8gfxp4/lib/python/numpy/core/tests/test_mem_policy.py
get_module   s$   
Dmr   c                 C   s
  t jjj}t jjj}| }t dd}||d u sJ ||d u s%J ||j|ks.J ||jdks7J |  }t dd}||d u sKJ ||d u sSJ ||jdks\J ||jdkseJ |dkrw| 	d  | dksuJ d S | 	| | |ksJ d S )N
            secret_data_allocatordefault_allocator)
r   core
multiarrayget_handler_nameget_handler_versionarangereshapebaser   r   )r   r)   r*   orig_policy_nameaorig_policybr   r   r   test_set_policy   s&   



r2   c                 C   sh   t jjj}| d }| dksJ | d }| dksJ | |}||  u r/|  u s2J  J d S Nr&   )r   r'   r(   r)   r   r   )r   r)   r0   def_policy_1def_policy_2r   r   r   test_default_policy_singleton   s   



$r6   c                 C   s   G dd dt j}t jjj}| }t d|d}||d u s$J |jj	du s,J ||j
d u s5J |j
jj	du s>J ||j
j
|ksHJ |j
j
jj	du sRJ 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    r:   r    r!   FT)r   ndarrayr'   r(   r)   r+   viewr,   flagsowndatar-   )r   r:   r)   r.   r/   r   r   r   test_policy_propagation  s   
r?   c                    sR   |dkr|    tjj dksJ n| d  tjj dks#J |  d S Nr&   r%   )r   r   r'   r(   r)   r   setr   r.   eventr   r   r   concurrent_context1  s   
rD   c                    sn   |  I d H  tjj |ksJ |dkr&|   tjj dks$J d S | d  tjj dks5J d S r@   )waitr   r'   r(   r)   r   r   rB   r   r   r   concurrent_context2#  s   
rF   c                    sf   t jj }t }tt| ||}tt| ||}|I d H  |I d H  t jj |ks1J d S )N)	r   r'   r(   r)   asyncioEventcreate_taskrD   rF   r   r.   rC   concurrent_task1concurrent_task2r   r   r   async_test_context_locality0  s   



rM   c                 C   s:   t jjdkrt jd d dk rtd tt|  d S )Npypy   )   rO      z+no context-locality support in PyPy < 7.3.6)	r   implementationnamepypy_version_infor   r   rG   runrM   )r   r   r   r   test_context_locality@  s
   
rV   c                 C   s(   |    tjj dksJ |  d S )Nr%   )r   r   r'   r(   r)   rA   r   rC   r   r   r   concurrent_thread1G  s   rX   c                 C   s(   |   tjj dksJ |   d S r3   )rE   r   r'   r(   r)   r   rW   r   r   r   concurrent_thread2M  s   rY   c                 C   sp   t jj }t }tjt| |fd}tjt| |fd}|	  |	  |
  |
  t jj |ks6J d S )N)targetargs)r   r'   r(   r)   	threadingrH   ThreadrX   rY   startjoinrJ   r   r   r   test_thread_localityU  s   r`   c                 C   s   t d}t jj|}|  }t d}t jj|dks J |dkr<t jjdddgds0J t jjdddgds<J | | t d}t jj||ksQJ d S )Nr    r%   r&   fullr"   z-vv)verbose
extra_argv)	r   r+   r'   r(   r)   r   testmar   )r   r/   r.   r0   r1   cr   r   r   test_new_policyg  s   



rg   rN   z;bad interaction between getenv and os.environ inside pytest)reasonpolicy)01Nc              	   C   s
  |   }tjj|d u sJ | | tjdd }|d u r+dtjv r*tj	d n|tjd< z>|dkrOt
t}~t  W d    n1 sIw   Y  n~t  W |d u rhdtjv rftj	d d S d S |tjd< d S |d u rdtjv r~tj	d w |tjd< w )NNUMPY_WARN_IF_NO_MEM_POLICYrk   )r
   r   r'   r(   r)   r   osenvirongetpopr   RuntimeWarninggccollect)r   ri   r/   oldvalwr   r   r   test_switch_owner  s8   






rv   c                 C   sF   |   }tjtdd ~t  W d    d S 1 sw   Y  d S )Nwarn_on_free)match)r   r   warnsUserWarningrr   rs   )r   r/   r   r   r   test_owner_is_base  s
   
"r{   )!rG   rr   rm   r   numpyr   r\   warningsnumpy.testingr   r   r   fixturer   r2   r6   r?   rD   rF   rM   rV   rX   rY   r`   markslowrg   xfailrR   rS   parametrizerv   r{   r   r   r   r   <module>   s<    
 I

