1# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com 2# 3# Python tests originally created or extracted from other peoples work. The 4# parts were too small to be protected. 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18""" Reference counting tests for Python3.6 or higher. 19 20These contain functions that do specific things, where we have a suspect 21that references may be lost or corrupted. Executing them repeatedly and 22checking the reference count is how they are used. 23 24These are Python3.6 specific constructs, that will give a SyntaxError or 25not be relevant on older versions. 26""" 27 28import os 29import sys 30 31# While we use that for comparison code, no need to compile that. 32# nuitka-project: --nofollow-import-to=nuitka 33 34# Find nuitka package relative to us. 35sys.path.insert( 36 0, 37 os.path.normpath( 38 os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") 39 ), 40) 41 42# isort:start 43 44import asyncio 45import types 46 47from nuitka.tools.testing.Common import ( 48 async_iterate, 49 executeReferenceChecked, 50 run_async, 51) 52 53 54class AwaitException(Exception): 55 pass 56 57 58def run_until_complete(coro): 59 exc = False 60 while True: 61 try: 62 if exc: 63 exc = False 64 fut = coro.throw(AwaitException) 65 else: 66 fut = coro.send(None) 67 except StopIteration as ex: 68 return ex.args[0] 69 70 if fut == ("throw",): 71 exc = True 72 73 74def simpleFunction1(): 75 async def gen1(): 76 try: 77 yield 78 except: # pylint: disable=bare-except 79 pass 80 81 async def run(): 82 g = gen1() 83 await g.asend(None) 84 await g.asend(None) 85 86 try: 87 run_async(run()) 88 except StopAsyncIteration: 89 pass 90 91 92def simpleFunction2(): 93 async def async_gen(): 94 try: 95 yield 1 96 yield 1.1 97 1 / 0 # pylint: disable=pointless-statement 98 finally: 99 yield 2 100 yield 3 101 102 yield 100 103 104 async_iterate(async_gen()) 105 106 107@types.coroutine 108def awaitable(*, throw=False): 109 if throw: 110 yield ("throw",) 111 else: 112 yield ("result",) 113 114 115async def gen2(): 116 await awaitable() 117 a = yield 123 118 assert a is None 119 await awaitable() 120 yield 456 121 await awaitable() 122 yield 789 123 124 125def simpleFunction3(): 126 def to_list(gen): 127 async def iterate(): 128 res = [] 129 async for i in gen: 130 res.append(i) 131 return res 132 133 return run_until_complete(iterate()) 134 135 async def run2(): 136 return to_list(gen2()) 137 138 run_async(run2()) 139 140 141def simpleFunction4(): 142 g = gen2() 143 ai = g.__aiter__() 144 an = ai.__anext__() 145 an.__next__() 146 147 try: 148 ai.__anext__().__next__() 149 except StopIteration as _ex: 150 pass 151 except RuntimeError: 152 # Python 3.8 doesn't like this anymore 153 assert sys.version_info >= (3, 8) 154 155 try: 156 ai.__anext__().__next__() 157 except RuntimeError: 158 # Python 3.8 doesn't like this anymore 159 assert sys.version_info >= (3, 8) 160 161 162def simpleFunction5(): 163 t = 2 164 165 class C: # pylint: disable=invalid-name 166 exec("u=2") # pylint: disable=exec-used 167 x: int = 2 168 y: float = 2.0 169 170 z = x + y + t * u # pylint: disable=undefined-variable 171 172 rawdata = b"The quick brown fox jumps over the lazy dog.\r\n" 173 # Be slow so we don't depend on other modules 174 rawdata += bytes(range(256)) 175 176 return C() 177 178 179# This refleaks big time, but the construct is rare enough to not bother 180# as this proves hard to find. 181def disabled_simpleFunction6(): 182 loop = asyncio.new_event_loop() 183 asyncio.set_event_loop(None) 184 185 async def waiter(timeout): 186 await asyncio.sleep(timeout) 187 yield 1 188 189 async def wait(): 190 async for _ in waiter(1): 191 pass 192 193 t1 = loop.create_task(wait()) 194 t2 = loop.create_task(wait()) 195 196 loop.run_until_complete(asyncio.sleep(0.01)) 197 198 t1.cancel() 199 t2.cancel() 200 201 try: 202 loop.run_until_complete(t1) 203 except asyncio.CancelledError: 204 pass 205 try: 206 loop.run_until_complete(t2) 207 except asyncio.CancelledError: 208 pass 209 210 loop.run_until_complete(loop.shutdown_asyncgens()) 211 212 loop.close() 213 214 215# These need stderr to be wrapped. 216tests_stderr = () 217 218# Disabled tests 219tests_skipped = {} 220 221result = executeReferenceChecked( 222 prefix="simpleFunction", 223 names=globals(), 224 tests_skipped=tests_skipped, 225 tests_stderr=tests_stderr, 226) 227 228sys.exit(0 if result else 1) 229