diff options
author | Damien George <damien.p.george@gmail.com> | 2017-08-14 16:37:13 +1000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2017-08-14 16:37:13 +1000 |
commit | 545354cb2a428bd844878a7c8cfd6e67a415e699 (patch) | |
tree | bd04f76b577cf50d45490981cac316484df0d28f /tests | |
parent | 76b564ca4701460a2ad72ef26076c2e339ada506 (diff) | |
parent | 5653e3c72fc8555c6a060acf6447ac694a036053 (diff) |
Merge tag 'v1.8.7' into parse-bytecode
Support for Xtensa emitter and assembler, and upgraded F4 and F7 STM HAL
This release adds support for the Xtensa architecture as a target for the
native emitter, as well as Xtensa inline assembler. The int.from_bytes
and int.to_bytes methods now require a second argument (the byte order)
per CPython (only "little" is supported at this time). The "readall"
method has been removed from all stream classes that used it; "read" with
no arguments should be used instead. There is now support for importing
packages from compiled .mpy files. Test coverage is increased to 96%.
The generic I2C driver has improvements: configurable clock stretching
timeout, "stop" argument added to readfrom/writeto methods, "nack"
argument added to readinto, and write[to] now returns num of ACKs
received. The framebuf module now handles 16-bit depth (generic colour
format) and has hline, vline, rect, line methods. A new utimeq module is
added for efficient queue ordering defined by modulo time (to be
compatible with time.ticks_xxx functions). The pyboard.py script has been
modified so that the target board is not reset between scripts or commands
that are given on a single command line.
For the stmhal port the STM Cube HAL has been upgraded: Cube F4 HAL to
v1.13.1 (CMSIS 2.5.1, HAL v1.5.2) and Cube F7 HAL to v1.1.2. There is a
more robust pyb.I2C implementation (DMA is now disabled by default, can be
enabled via an option), and there is an implementation of machine.I2C with
robust error handling and hardware acceleration on F4 MCUs. It is now
recommended to use machine.I2C instead of pyb.I2C. The UART class is now
more robust with better handling of errors/timeouts. There is also more
accurate VBAT and VREFINT measurements for the ADC. New boards that are
supported include: NUCLEO_F767ZI, STM32F769DISC and NUCLEO_L476RG.
For the esp8266 port select/poll is now supported for sockets using the
uselect module. There is support for native and viper emitters, as well
as an inline assembler (with limited iRAM for storage of native functions,
or the option to store code to flash). There is improved software I2C
with a slight API change: scl/sda pins can be specified as positional only
when "-1" is passed as the first argument to indicate the use of software
I2C. It is recommended to use keyword arguments for scl/sda. There is
very early support for over-the-air (OTA) updates using the yaota8266
project.
A detailed list of changes follows.
py core:
- emitnative: fix native import emitter when in viper mode
- remove readall() method, which is equivalent to read() w/o args
- objexcept: allow clearing traceback with 'exc.__traceback__ = None'
- runtime: mp_resume: handle exceptions in Python __next__()
- mkrules.mk: rework find command so it works on OSX
- *.mk: replace uses of 'sed' with $(SED)
- parse: move function to check for const parse node to parse.[ch]
- parse: make mp_parse_node_new_leaf an inline function
- parse: add code to fold logical constants in or/and/not operations
- factor persistent code load/save funcs into persistentcode.[ch]
- factor out persistent-code reader into separate files
- lexer: rewrite mp_lexer_new_from_str_len in terms of mp_reader_mem
- lexer: provide generic mp_lexer_new_from_file based on mp_reader
- lexer: rewrite mp_lexer_new_from_fd in terms of mp_reader
- lexer: make lexer use an mp_reader as its source
- objtype: implement __call__ handling for an instance w/o heap alloc
- factor out common code from assemblers into asmbase.[ch]
- stream: move ad-hoc ioctl constants to stream.h and rename them
- compile: simplify configuration of native emitter
- emit.h: remove long-obsolete declarations for cpython emitter
- move arch-specific assembler macros from emitnative to asmXXX.h
- asmbase: add MP_PLAT_COMMIT_EXEC option for handling exec code
- asmxtensa: add low-level Xtensa assembler
- integrate Xtensa assembler into native emitter
- allow inline-assembler emitter to be generic
- add inline Xtensa assembler
- emitinline: embed entire asm struct instead of a pointer to it
- emitinline: move inline-asm align and data methods to compiler
- emitinline: move common code for end of final pass to compiler
- asm: remove need for dummy_data when doing initial assembler passes
- objint: from_bytes, to_bytes: require byteorder arg, require "little"
- binary: do zero extension when storing a value larger than word size
- builtinimport: support importing packages from compiled .mpy files
- mpz: remove unreachable code in mpn_or_neg functions
- runtime: zero out fs_user_mount array in mp_init
- mpconfig.h: enable MICROPY_PY_SYS_EXIT by default
- add MICROPY_KBD_EXCEPTION config option to provide mp_kbd_exception
- compile: add an extra pass for Xtensa inline assembler
- modbuiltins: remove unreachable code
- objint: rename mp_obj_int_as_float to mp_obj_int_as_float_impl
- emitglue: refactor to remove assert(0), to improve coverage
- lexer: remove unreachable code in string tokeniser
- lexer: remove unnecessary check for EOF in lexer's next_char func
- lexer: permanently disable the mp_lexer_show_token function
- parsenum: simplify and generalise decoding of digit values
- mpz: fix assertion in mpz_set_from_str which checks value of base
- mpprint: add assertion for, and comment about, valid base values
- objint: simplify mp_int_format_size and remove unreachable code
- unicode: comment-out unused function unichar_isprint
- consistently update signatures of .make_new and .call methods
- mkrules.mk: add MPY_CROSS_FLAGS option to pass flags to mpy-cross
- builtinimport: fix bug when importing names from frozen packages
extmod:
- machine_i2c: make the clock stretching timeout configurable
- machine_i2c: raise an error when clock stretching times out
- machine_i2c: release SDA on bus error
- machine_i2c: add a C-level I2C-protocol, refactoring soft I2C
- machine_i2c: add argument to C funcs to control stop generation
- machine_i2c: rewrite i2c.scan in terms of C-level protocol
- machine_i2c: rewrite mem xfer funcs in terms of C-level protocol
- machine_i2c: remove unneeded i2c_write_mem/i2c_read_mem funcs
- machine_i2c: make C-level functions return -errno on I2C error
- machine_i2c: add 'nack' argument to i2c.readinto
- machine_i2c: make i2c.write[to] methods return num of ACKs recvd
- machine_i2c: add 'stop' argument to i2c readfrom/writeto meths
- machine_i2c: remove trivial function wrappers
- machine_i2c: expose soft I2C obj and readfrom/writeto funcs
- machine_i2c: add hook to constructor to call port-specific code
- modurandom: allow to build with float disabled
- modframebuf: make FrameBuffer handle 16bit depth
- modframebuf: add back legacy FrameBuffer1 "class"
- modframebuf: optimise fill and fill_rect methods
- vfs_fat: implement POSIX behaviour of rename, allow to overwrite
- moduselect: use stream helper function instead of ad-hoc code
- moduselect: use configurable EVENT_POLL_HOOK instead of WFI
- modlwip: add ioctl method to socket, with poll implementation
- vfs_fat_file: allow file obj to respond to ioctl flush request
- modbtree: add method to sync the database
- modbtree: rename "sync" method to "flush" for consistency
- modframebuf: add hline, vline, rect and line methods
- machine_spi: provide reusable software SPI class
- modframebuf: make framebuf implement the buffer protocol
- modframebuf: store underlying buffer object to prevent GC free
- modutimeq: copy of current moduheapq with timeq support for refactoring
- modutimeq: refactor into optimized class
- modutimeq: make time_less_than be actually "less than", not less/eq
lib:
- utils/interrupt_char: use core-provided mp_kbd_exception if enabled
drivers:
- display/ssd1306.py: update to use FrameBuffer not FrameBuffer1
- onewire: enable pull up on data pin
- onewire/ds18x20: fix negative temperature calc for DS18B20
tools:
- tinytest-codegen: blacklist recently added uheapq_timeq test (qemu-arm)
- pyboard.py: refactor so target is not reset between scripts/cmd
- mpy-tool.py: add support for OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
tests:
- micropython: add test for import from within viper function
- use read() instead of readall()
- basics: add test for logical constant folding
- micropython: add test for creating traceback without allocation
- micropython: move alloc-less traceback test to separate test file
- extmod: improve ujson coverage
- basics: improve user class coverage
- basics: add test for dict.fromkeys where arg is a generator
- basics: add tests for if-expressions
- basics: change dict_fromkeys test so it doesn't use generators
- basics: enable tests for list slice getting with 3rd arg
- extmod/vfs_fat_fileio: add test for constructor of FileIO type
- extmod/btree1: exercise btree.flush()
- extmod/framebuf1: add basics tests for hline, vline, rect, line
- update for required byteorder arg for int.from_bytes()/to_bytes()
- extmod: improve moductypes test coverage
- extmod: improve modframebuf test coverage
- micropython: get heapalloc_traceback test running on baremetal
- struct*: make skippable
- basics: improve mpz test coverage
- float/builtin_float_round: test round() with second arg
- basics/builtin_dir: add test for dir() of a type
- basics: add test for builtin locals()
- basics/set_pop: improve coverage of set functions
- run-tests: for REPL tests make sure the REPL is exited at the end
- basics: improve test coverage for generators
- import: add a test which uses ... in from-import statement
- add tests to improve coverage of runtime.c
- add tests to improve coverage of objarray.c
- extmod: add test for utimeq module
- basics/lexer: add a test for newline-escaping within a string
- add a coverage test for printing the parse-tree
- utimeq_stable: test for partial stability of utimeq queuing
- heapalloc_inst_call: test for no alloc for simple object calls
- basics: add tests for parsing of ints with base 36
- basics: add tests to improve coverage of binary.c
- micropython: add test for micropython.stack_use() function
- extmod: improve ubinascii.c test coverage
- thread: improve modthread.c test coverage
- cmdline: improve repl.c autocomplete test coverage
- unix: improve runtime_utils.c test coverage
- pyb/uart: update test to match recent change to UART timeout_char
- run-tests: allow to skip set tests
- improve warning.c test coverage
- float: improve formatfloat.c test coverage using Python
- unix: improve formatfloat.c test coverage using C
- unix/extra_coverage: add basic tests to import frozen str and mpy
- types1: split out set type test to set_types
- array: allow to skip test if "array" is unavailable
- unix/extra_coverage: add tests for importing frozen packages
unix port:
- rename define for unix moduselect to MICROPY_PY_USELECT_POSIX
- Makefile: update freedos target for change of USELECT config name
- enable utimeq module
- main: allow to print the parse tree in coverage build
- Makefile: make "coverage_test" target mirror Travis test actions
- moduselect: if file object passed to .register(), return it in .poll()
- Makefile: split long line for coverage target, easier to modify
- enable and add basic frozen str and frozen mpy in coverage build
- Makefile: allow cache-map-lookup optimisation with frozen bytecode
windows port:
- enable READER_POSIX to get access to lexer_new_from_file
stmhal port:
- dma: de-init the DMA peripheral properly before initialising
- i2c: add option to I2C to enable/disable use of DMA transfers
- i2c: reset the I2C peripheral if there was an error on the bus
- rename mp_hal_pin_set_af to _config_alt, to simplify alt config
- upgrade to STM32CubeF4 v1.13.0 - CMSIS/Device 2.5.1
- upgrade to STM32CubeF4 v1.13.0 - HAL v1.5.1
- apply STM32CubeF4 v1.13.1 patch - upgrade HAL driver to v1.5.2
- hal/i2c: reapply HAL commit ea040a4 for f4
- hal/sd: reapply HAL commit 1d7fb82 for f4
- hal: reapply HAL commit 9db719b for f4
- hal/rcc: reapply HAL commit c568a2b for f4
- hal/sd: reapply HAL commit 09de030 for f4
- boards: configure all F4 boards to work with new HAL
- make-stmconst.py: fix regex's to work with current CMSIS
- i2c: handle I2C IRQs
- dma: precalculate register base and bitshift on handle init
- dma: mark DMA sate as READY even if HAL_DMA_Init is skipped
- can: clear FIFO flags in IRQ handler
- i2c: provide custom IRQ handlers
- hal: do not include <stdio.h> in HAL headers
- mphalport.h: use single GPIOx->BSRR register
- make-stmconst.py: add support for files with invalid utf8 bytes
- update HALCOMMITS due to change to hal
- make-stmconst.py: restore Python 2 compatibility
- update HALCOMMITS due to change to hal
- moduselect: move to extmod/ for reuse by other ports
- i2c: use the HAL's I2C IRQ handler for F7 and L4 MCUs
- updates to get F411 MCUs compiling with latest ST HAL
- i2c: remove use of legacy I2C_NOSTRETCH_DISABLED option
- add beginnings of port-specific machine.I2C implementation
- i2c: add support for I2C4 hardware block on F7 MCUs
- i2c: expose the pyb_i2c_obj_t struct and some relevant functions
- machine_i2c: provide HW implementation of I2C peripherals for F4
- add support for flash storage on STM32F415
- add back GPIO_BSRRL and GPIO_BSRRH constants to stm module
- add OpenOCD configuration for STM32L4
- add address parameters to openocd config files
- adc: add "mask" selection parameter to pyb.ADCAll constructor
- adc: provide more accurate measure of VBAT and VREFINT
- adc: make ADCAll.read_core_temp return accurate float value
- adc: add ADCAll.read_vref method, returning "3.3v" value
- adc: add support for F767 MCU
- adc: make channel "16" always map to the temperature sensor
- sdcard: clean/invalidate cache before DMA transfers with SD card
- moduos: implement POSIX behaviour of rename, allow to overwrite
- adc: use constants from new HAL version
- refactor UART configuration to use pin objects
- uart: add support for UART7 and UART8 on F7 MCUs
- uart: add check that UART id is valid for the given board
- cmsis: update STM32F7 CMSIS device include files to V1.1.2
- hal: update ST32CubeF7 HAL files to V1.1.2
- port of f4 hal commit c568a2b to updated f7 hal
- port of f4 hal commit 09de030 to updated f7 hal
- port of f4 hal commit 1d7fb82 to updated f7 hal
- declare and initialise PrescTables for F7 MCUs
- boards/STM32F7DISC: define LSE_STARTUP_TIMEOUT
- hal: update HALCOMMITS due to change in f7 hal files
- refactor to use extmod implementation of software SPI class
- cmsis: add CMSIS file stm32f767xx.h, V1.1.2
- add NUCLEO_F767ZI board, with openocd config for stm32f7
- cmsis: add CMSIS file stm32f769xx.h, V1.1.2
- add STM32F769DISC board files
- move PY_SYS_PLATFORM config from board to general config file
- mpconfigport: add weak-module links for io, collections, random
- rename mp_const_vcp_interrupt to mp_kbd_exception
- usb: always use the mp_kbd_exception object for VCP interrupt
- use core-provided keyboard exception object
- led: properly initialise timer handle to zero before using it
- mphalport.h: explicitly use HAL's GPIO constants for pull modes
- usrsw: use mp_hal_pin_config function instead of HAL_GPIO_Init
- led: use mp_hal_pin_config function instead of HAL_GPIO_Init
- sdcard: use mp_hal_pin_config function instead of HAL_GPIO_Init
- add support for STM32 Nucleo64 L476RG
- uart: provide a custom function to transmit over UART
- uart: increase inter-character timeout by 1ms
- enable utimeq module
cc3200 port:
- tools/smoke.py: change readall() to read()
- pybspi: remove static mode=SPI.MASTER parameter for latest HW API
- mods/pybspi: remove SPI.MASTER constant, it's no longer needed
- update for moduselect moved to extmod/
- re-add support for UART REPL (MICROPY_STDIO_UART setting)
- enable UART REPL by default
- README: (re)add information about accessing REPL on serial
- make: rename "deploy" target to "deploy-ota"
- add targets to erase flash, deploy firmware using cc3200tool
- README: reorganize and update to the current state of affairs
- modwlan: add network.WLAN.print_ver() diagnostic function
esp8266 port:
- enable uselect module
- move websocket_helper.py from scripts to modules for frozen BC
- refactor to use extmod implementation of software SPI class
- mpconfigport_512k: disable framebuf module for 512k build
- enable native emitter for Xtensa arch
- enable inline Xtensa assembler
- add "ota" target to produce firmware binary for use with yaota8266
- use core-provided keyboard exception object
- add "erase" target to Makefile, to erase entire flash
- when doing GC be sure to trace the memory holding native code
- modesp: flash_user_start(): support configuration with yaota8266
- force relinking OTA firmware image if built after normal one
- scripts/inisetup: dump FS starting sector/size on error
- Makefile: produce OTA firmware as firmware-ota.bin
- modesp: make check_fw() work with OTA firmware
- enable utimeq module
- Makefile: put firmware-ota.bin in build/, for consistency
- modules/flashbdev: add RESERVED_SECS before the filesystem
- modules/flashbdev: remove code to patch bootloader flash size
- modules/flashbdev: remove now-unused function set_bl_flash_size
- modules/flashbdev: change RESERVED_SECS to 0
zephyr port:
- add .gitignore to ignore Zephyr's "outdir" directory
- zephyr_getchar: update to Zephyr 1.6 unified kernel API
- switch to Zephyr 1.6 unified kernel API
- support raw REPL
- implement soft reset feature
- main: initialize sys.path and sys.argv
- use core-provided keyboard exception object
- uart_core: access console UART directly instead of printk() hack
- enable slice subscription
docs:
- remove references to readall() and update stream read() docs
- library/index: elaborate on u-modules
- library/machine.I2C: refine definitions of I2C methods
- library/pyb.Accel: add hardware note about pins used by accel
- library/pyb.UART: added clarification about timeouts
- library/pyb.UART: moved writechar doc to sit with other writes
- esp8266/tutorial: update intro to add Getting the firmware section
- library/machine.I2C: fix I2C constructor docs to match impl
- esp8266/tutorial: close socket after reading page content
- esp8266/general: add "Scarcity of runtime resources" section
- library/esp: document esp.set_native_code_location() function
- library/esp: remove para and add further warning about flash
- usocket: clarify that socket timeout raises OSError exception
travis:
- build STM32 F7 and L4 boards under Travis CI
- include persistent bytecode with floats in coverage tests
examples:
- hwapi: button_led: Add GPIO pin read example
- hwapi: add soft_pwm example converted to uasyncio
- http_client: use read() instead of readall()
- hwapi: add uasyncio example of fading 2 LEDs in parallel
- hwapi: add example for machine.time_pulse_us()
- hwapi: add hwconfig for console tracing of LED operations
- accellog.py: change 1: to /sd/, and update comment about FS
- hwapi/hwconfig_console: don't alloc memory in value()
Diffstat (limited to 'tests')
110 files changed, 1152 insertions, 33 deletions
diff --git a/tests/basics/array1.py b/tests/basics/array1.py index c45b883c9..43f775b79 100644 --- a/tests/basics/array1.py +++ b/tests/basics/array1.py @@ -1,4 +1,9 @@ -import array +try: + import array +except ImportError: + import sys + print("SKIP") + sys.exit() a = array.array('B', [1, 2, 3]) print(a, len(a)) diff --git a/tests/basics/array_add.py b/tests/basics/array_add.py index 1dba8a3bc..41cd77b42 100644 --- a/tests/basics/array_add.py +++ b/tests/basics/array_add.py @@ -1,5 +1,10 @@ # test array + array -import array +try: + import array +except ImportError: + import sys + print("SKIP") + sys.exit() a1 = array.array('I', [1]) a2 = array.array('I', [2]) diff --git a/tests/basics/array_construct.py b/tests/basics/array_construct.py index 0625111c9..cafa57784 100644 --- a/tests/basics/array_construct.py +++ b/tests/basics/array_construct.py @@ -1,6 +1,11 @@ # test construction of array.array from different objects -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() # tuple, list print(array('b', (1, 2))) diff --git a/tests/basics/array_construct2.py b/tests/basics/array_construct2.py index 0013a0aa7..d1c1a6c70 100644 --- a/tests/basics/array_construct2.py +++ b/tests/basics/array_construct2.py @@ -1,4 +1,9 @@ -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() # construct from something with unknown length (requires generators) print(array('i', (i for i in range(10)))) diff --git a/tests/basics/array_construct_endian.py b/tests/basics/array_construct_endian.py index 1ea823053..bf34b05d1 100644 --- a/tests/basics/array_construct_endian.py +++ b/tests/basics/array_construct_endian.py @@ -1,6 +1,11 @@ # test construction of array.array from different objects -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() # raw copy from bytes, bytearray print(array('h', b'12')) diff --git a/tests/basics/array_micropython.py b/tests/basics/array_micropython.py new file mode 100644 index 000000000..8e904bdfe --- /dev/null +++ b/tests/basics/array_micropython.py @@ -0,0 +1,12 @@ +# test MicroPython-specific features of array.array +import array + +# arrays of objects +a = array.array('O') +a.append(1) +print(a[0]) + +# arrays of pointers +a = array.array('P') +a.append(1) +print(a[0]) diff --git a/tests/basics/array_micropython.py.exp b/tests/basics/array_micropython.py.exp new file mode 100644 index 000000000..6ed281c75 --- /dev/null +++ b/tests/basics/array_micropython.py.exp @@ -0,0 +1,2 @@ +1 +1 diff --git a/tests/basics/array_q.py b/tests/basics/array_q.py index a52c9895c..2975cd385 100644 --- a/tests/basics/array_q.py +++ b/tests/basics/array_q.py @@ -1,6 +1,11 @@ # test array('q') and array('Q') -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() print(array('q')) print(array('Q')) diff --git a/tests/basics/builtin_dir.py b/tests/basics/builtin_dir.py index 70ab24960..843467e78 100644 --- a/tests/basics/builtin_dir.py +++ b/tests/basics/builtin_dir.py @@ -7,6 +7,9 @@ print('__name__' in dir()) import sys print('platform' in dir(sys)) +# dir of type +print('append' in dir(list)) + class Foo: def __init__(self): self.x = 1 diff --git a/tests/basics/builtin_locals.py b/tests/basics/builtin_locals.py new file mode 100644 index 000000000..3689216ef --- /dev/null +++ b/tests/basics/builtin_locals.py @@ -0,0 +1,4 @@ +# test builtin locals() + +x = 123 +print(locals()['x']) diff --git a/tests/basics/class_item.py b/tests/basics/class_item.py index a96817462..1d9488bde 100644 --- a/tests/basics/class_item.py +++ b/tests/basics/class_item.py @@ -15,3 +15,12 @@ c = C() print(c[1]) c[1] = 2 del c[3] + +# index not supported +class A: + pass +a = A() +try: + a[1] +except TypeError: + print('TypeError') diff --git a/tests/basics/class_misc.py b/tests/basics/class_misc.py new file mode 100644 index 000000000..82b9b3479 --- /dev/null +++ b/tests/basics/class_misc.py @@ -0,0 +1,9 @@ +# converting user instance to buffer +class C: + pass + +c = C() +try: + d = bytearray(c) +except TypeError: + print('TypeError') diff --git a/tests/basics/dict_fromkeys.py b/tests/basics/dict_fromkeys.py index d03f6ae9d..bfad347c8 100644 --- a/tests/basics/dict_fromkeys.py +++ b/tests/basics/dict_fromkeys.py @@ -8,3 +8,6 @@ l = list(d.values()) l.sort() print(l) +# argument to fromkeys has no __len__ +d = dict.fromkeys(reversed(range(1))) +print(d) diff --git a/tests/basics/gen_yield_from_close.py b/tests/basics/gen_yield_from_close.py index 7982d5c99..d66691ff9 100644 --- a/tests/basics/gen_yield_from_close.py +++ b/tests/basics/gen_yield_from_close.py @@ -85,3 +85,39 @@ try: print(next(g)) except StopIteration: print("StopIteration") + +# case where generator ignores the close request and yields instead +def gen7(): + try: + yield 123 + except GeneratorExit: + yield 456 + +g = gen7() +print(next(g)) +try: + g.close() +except RuntimeError: + print('RuntimeError') + +# case where close is propagated up to a built-in iterator +def gen8(): + g = reversed([2, 1]) + yield from g +g = gen8() +print(next(g)) +g.close() + +# case with a user-defined close method +class Iter: + def __iter__(self): + return self + def __next__(self): + return 1 + def close(self): + print('close') +def gen9(): + yield from Iter() +g = gen9() +print(next(g)) +g.close() diff --git a/tests/basics/gen_yield_from_throw.py b/tests/basics/gen_yield_from_throw.py index 30960fb9c..829bf0f3b 100644 --- a/tests/basics/gen_yield_from_throw.py +++ b/tests/basics/gen_yield_from_throw.py @@ -17,3 +17,14 @@ try: except TypeError: print("got TypeError from downstream!") +# case where generator doesn't intercept the thrown/injected exception +def gen3(): + yield 123 + yield 456 + +g3 = gen3() +print(next(g3)) +try: + g3.throw(StopIteration) +except StopIteration: + print('got StopIteration from downstream!') diff --git a/tests/basics/gen_yield_from_throw2.py b/tests/basics/gen_yield_from_throw2.py new file mode 100644 index 000000000..2cff9e08b --- /dev/null +++ b/tests/basics/gen_yield_from_throw2.py @@ -0,0 +1,15 @@ +# uPy differs from CPython for this test +# generator ignored GeneratorExit +def gen(): + try: + yield 123 + except GeneratorExit: + print('GeneratorExit') + yield 456 + +g = gen() +print(next(g)) +try: + g.throw(GeneratorExit) +except RuntimeError: + print('RuntimeError') diff --git a/tests/basics/gen_yield_from_throw2.py.exp b/tests/basics/gen_yield_from_throw2.py.exp new file mode 100644 index 000000000..d5805b494 --- /dev/null +++ b/tests/basics/gen_yield_from_throw2.py.exp @@ -0,0 +1,3 @@ +123 +GeneratorExit +RuntimeError diff --git a/tests/basics/generator1.py b/tests/basics/generator1.py index d4028b0ce..ea1d3b38b 100644 --- a/tests/basics/generator1.py +++ b/tests/basics/generator1.py @@ -20,3 +20,6 @@ for val in f(3): #print(gen.__next__()) #print(gen.__next__()) #print(gen.__next__()) + +# test printing, but only the first chars that match CPython +print(repr(f(0))[0:17]) diff --git a/tests/basics/ifexpr.py b/tests/basics/ifexpr.py new file mode 100644 index 000000000..66f94f95c --- /dev/null +++ b/tests/basics/ifexpr.py @@ -0,0 +1,9 @@ +# test if-expressions + +print(1 if 0 else 2) +print(3 if 1 else 4) + +def f(x): + print('a' if x else 'b') +f([]) +f([1]) diff --git a/tests/basics/int1.py b/tests/basics/int1.py index aea72b7dd..2d92105c7 100644 --- a/tests/basics/int1.py +++ b/tests/basics/int1.py @@ -36,6 +36,7 @@ print(int('11', 16)) print(int('11', 8)) print(int('11', 2)) print(int('11', 36)) +print(int('xyz', 36)) print(int('0o123', 0)) print(int('8388607')) print(int('0x123', 16)) diff --git a/tests/basics/int_big_add.py b/tests/basics/int_big_add.py new file mode 100644 index 000000000..f0c3336d0 --- /dev/null +++ b/tests/basics/int_big_add.py @@ -0,0 +1,11 @@ +# tests transition from small to large int representation by addition + +# 31-bit overflow +i = 0x3fffffff +print(i + i) +print(-i + -i) + +# 63-bit overflow +i = 0x3fffffffffffffff +print(i + i) +print(-i + -i) diff --git a/tests/basics/int_big_rshift.py b/tests/basics/int_big_rshift.py index 6055e95b9..b2fecb36c 100644 --- a/tests/basics/int_big_rshift.py +++ b/tests/basics/int_big_rshift.py @@ -4,3 +4,4 @@ print(i >> 1000) # result needs rounding up print(-(1<<70) >> 80) +print(-0xffffffffffffffff >> 32) diff --git a/tests/basics/int_big_xor.py b/tests/basics/int_big_xor.py index 943d1ac15..318db45e6 100644 --- a/tests/basics/int_big_xor.py +++ b/tests/basics/int_big_xor.py @@ -19,6 +19,7 @@ print((-a) ^ (1 << 100)) print((-a) ^ (1 << 200)) print((-a) ^ a == 0) print(bool((-a) ^ a)) +print(-1 ^ 0xffffffffffffffff) # carry overflows to higher digit # test + - diff --git a/tests/basics/int_bytes_notimpl.py b/tests/basics/int_bytes_notimpl.py new file mode 100644 index 000000000..b47d6ab58 --- /dev/null +++ b/tests/basics/int_bytes_notimpl.py @@ -0,0 +1,9 @@ +try: + print((10).to_bytes(1, "big")) +except Exception as e: + print(type(e)) + +try: + print(int.from_bytes(b"\0", "big")) +except Exception as e: + print(type(e)) diff --git a/tests/basics/int_bytes_notimpl.py.exp b/tests/basics/int_bytes_notimpl.py.exp new file mode 100644 index 000000000..d1bf338eb --- /dev/null +++ b/tests/basics/int_bytes_notimpl.py.exp @@ -0,0 +1,2 @@ +<class 'NotImplementedError'> +<class 'NotImplementedError'> diff --git a/tests/basics/int_mpz.py b/tests/basics/int_mpz.py index 05aec95ce..425bc21b6 100644 --- a/tests/basics/int_mpz.py +++ b/tests/basics/int_mpz.py @@ -7,6 +7,8 @@ y = 2000000000000000000000000000000 # printing print(x) print(y) +print('%#X' % (x - x)) # print prefix +print('{:#,}'.format(x)) # print with commas # addition print(x + 1) @@ -66,6 +68,13 @@ print(int("123456789012345678901234567890")) print(int("-123456789012345678901234567890")) print(int("123456789012345678901234567890abcdef", 16)) print(int("123456789012345678901234567890ABCDEF", 16)) +print(int("1234567890abcdefghijklmnopqrstuvwxyz", 36)) + +# invalid characters in string +try: + print(int("123456789012345678901234567890abcdef")) +except ValueError: + print('ValueError'); # test constant integer with more than 255 chars x = 0x84ce72aa8699df436059f052ac51b6398d2511e49631bcb7e71f89c499b9ee425dfbc13a5f6d408471b054f2655617cbbaf7937b7c80cd8865cf02c8487d30d2b0fbd8b2c4e102e16d828374bbc47b93852f212d5043c3ea720f086178ff798cc4f63f787b9c2e419efa033e7644ea7936f54462dc21a6c4580725f7f0e7d1aaaaaaa diff --git a/tests/basics/iter1.py b/tests/basics/iter1.py index 5bd7f5090..9117dfd2b 100644 --- a/tests/basics/iter1.py +++ b/tests/basics/iter1.py @@ -9,6 +9,15 @@ try: except TypeError: print('TypeError') +# this class has no __next__ implementation +class NotIterable: + def __iter__(self): + return self +try: + print(all(NotIterable())) +except TypeError: + print('TypeError') + class MyStopIteration(StopIteration): pass diff --git a/tests/basics/lexer.py b/tests/basics/lexer.py index 70a9cce99..5f12afa70 100644 --- a/tests/basics/lexer.py +++ b/tests/basics/lexer.py @@ -19,6 +19,10 @@ print(eval("1\r")) print(eval("12\r")) print(eval("123\r")) +# backslash used to escape a line-break in a string +print('a\ +b') + # lots of indentation def a(x): if x: diff --git a/tests/basics/list_slice.py b/tests/basics/list_slice.py index 3a9a1e05e..fc08e580a 100644 --- a/tests/basics/list_slice.py +++ b/tests/basics/list_slice.py @@ -1,22 +1,28 @@ -# test slices; only 2 argument version supported by Micro Python at the moment +# test list slices, getting values + x = list(range(10)) a = 2 b = 4 c = 3 print(x[:]) print(x[::]) -#print(x[::c]) +print(x[::c]) print(x[:b]) print(x[:b:]) -#print(x[:b:c]) +print(x[:b:c]) print(x[a]) print(x[a:]) print(x[a::]) -#print(x[a::c]) +print(x[a::c]) print(x[a:b]) print(x[a:b:]) -#print(x[a:b:c]) +print(x[a:b:c]) # these should not raise IndexError print([][1:]) print([][-1:]) + +try: + [][::0] +except ValueError: + print('ValueError') diff --git a/tests/basics/logic_constfolding.py b/tests/basics/logic_constfolding.py new file mode 100644 index 000000000..14afe6111 --- /dev/null +++ b/tests/basics/logic_constfolding.py @@ -0,0 +1,26 @@ +# tests logical constant folding in parser + +def f_true(): + print('f_true') + return True + +def f_false(): + print('f_false') + return False + +print(0 or False) +print(1 or foo) +print(f_false() or 1 or foo) +print(f_false() or 1 or f_true()) + +print(0 and foo) +print(1 and True) +print(f_true() and 0 and foo) +print(f_true() and 1 and f_false()) + +print(not 0) +print(not False) +print(not 1) +print(not True) +print(not not 0) +print(not not 1) diff --git a/tests/basics/memoryview1.py b/tests/basics/memoryview1.py index 862a573e8..1cd411195 100644 --- a/tests/basics/memoryview1.py +++ b/tests/basics/memoryview1.py @@ -28,6 +28,7 @@ print(list(m[1:-1])) # this tests get_buffer of memoryview m = memoryview(bytearray(2)) print(bytearray(m)) +print(list(memoryview(memoryview(b'1234')))) # read-only memoryview import array a = array.array('i', [1, 2, 3, 4]) @@ -78,3 +79,9 @@ try: m4[1:3] = m2[1:3] except ValueError: print("ValueError") + +# invalid assignment on RHS +try: + memoryview(array.array('i'))[0:2] = b'1234' +except ValueError: + print('ValueError') diff --git a/tests/basics/set1.py b/tests/basics/set_basic.py index 6ea69e4f0..6ea69e4f0 100644 --- a/tests/basics/set1.py +++ b/tests/basics/set_basic.py diff --git a/tests/basics/set_pop.py b/tests/basics/set_pop.py index 0cd478ce2..5e1196c9f 100644 --- a/tests/basics/set_pop.py +++ b/tests/basics/set_pop.py @@ -7,3 +7,12 @@ except KeyError: else: print("Failed to raise KeyError") +# this tests an optimisation in mp_set_remove_first +# N must not be equal to one of the values in hash_allocation_sizes +N = 11 +s = set(range(N)) +while s: + print(s.pop()) # last pop() should trigger the optimisation +for i in range(N): + s.add(i) # check that we can add the numbers back to the set +print(list(s)) diff --git a/tests/basics/set_type.py b/tests/basics/set_type.py new file mode 100644 index 000000000..d790fa062 --- /dev/null +++ b/tests/basics/set_type.py @@ -0,0 +1,16 @@ +# set type + +# This doesn't really work as expected, because {None} +# leads SyntaxError during parsing. +try: + set +except NameError: + import sys + print("SKIP") + sys.exit() + +print(set) + +print(type(set()) == set) + +print(type({None}) == set) diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py index b53a9c8bc..d89519a2f 100644 --- a/tests/basics/struct1.py +++ b/tests/basics/struct1.py @@ -1,7 +1,13 @@ try: import ustruct as struct except: - import struct + try: + import struct + except ImportError: + import sys + print("SKIP") + sys.exit() + print(struct.calcsize("<bI")) print(struct.unpack("<bI", b"\x80\0\0\x01\0")) print(struct.calcsize(">bI")) @@ -55,6 +61,10 @@ print(struct.unpack(">q", b"\xf2\x34\x56\x78\x90\x12\x34\x56")) print(struct.unpack("<I", b"\xff\xff\xff\xff")) print(struct.unpack("<Q", b"\xff\xff\xff\xff\xff\xff\xff\xff")) +# check small int overflow +print(struct.unpack("<i", b'\xff\xff\xff\x7f')) +print(struct.unpack("<q", b'\xff\xff\xff\xff\xff\xff\xff\x7f')) + # network byte order print(struct.pack('!i', 123)) diff --git a/tests/basics/struct2.py b/tests/basics/struct2.py index f438bb55d..6dd963260 100644 --- a/tests/basics/struct2.py +++ b/tests/basics/struct2.py @@ -3,7 +3,12 @@ try: import ustruct as struct except: - import struct + try: + import struct + except ImportError: + import sys + print("SKIP") + sys.exit() print(struct.calcsize('0s')) print(struct.unpack('0s', b'')) diff --git a/tests/basics/struct_micropython.py b/tests/basics/struct_micropython.py new file mode 100644 index 000000000..e3b0ea508 --- /dev/null +++ b/tests/basics/struct_micropython.py @@ -0,0 +1,20 @@ +# test MicroPython-specific features of struct + +try: + import ustruct as struct +except: + try: + import struct + except ImportError: + import sys + print("SKIP") + sys.exit() + +class A(): + pass + +# pack and unpack objects +o = A() +s = struct.pack("<O", o) +o2 = struct.unpack("<O", s) +print(o is o2[0]) diff --git a/tests/basics/struct_micropython.py.exp b/tests/basics/struct_micropython.py.exp new file mode 100644 index 000000000..0ca95142b --- /dev/null +++ b/tests/basics/struct_micropython.py.exp @@ -0,0 +1 @@ +True diff --git a/tests/basics/try2.py b/tests/basics/try2.py index 5827699e9..11e60b3c2 100644 --- a/tests/basics/try2.py +++ b/tests/basics/try2.py @@ -22,6 +22,15 @@ try: except NameError: print("except 1") +# raised exception not contained in except tuple +try: + try: + raise Exception + except (RuntimeError, SyntaxError): + print('except 2') +except Exception: + print('except 1') + # Check that exceptions across function boundaries work as expected def func1(): try: diff --git a/tests/basics/types1.py b/tests/basics/types1.py index 38a20d680..e098abe8b 100644 --- a/tests/basics/types1.py +++ b/tests/basics/types1.py @@ -1,24 +1,22 @@ # basic types +# similar test for set type is done in set_type.py print(bool) print(int) print(tuple) print(list) -print(set) print(dict) print(type(bool()) == bool) print(type(int()) == int) print(type(tuple()) == tuple) print(type(list()) == list) -print(type(set()) == set) print(type(dict()) == dict) print(type(False) == bool) print(type(0) == int) print(type(()) == tuple) print(type([]) == list) -print(type({None}) == set) print(type({}) == dict) try: diff --git a/tests/cmdline/cmd_parsetree.py b/tests/cmdline/cmd_parsetree.py new file mode 100644 index 000000000..5f698eeae --- /dev/null +++ b/tests/cmdline/cmd_parsetree.py @@ -0,0 +1,11 @@ +# cmdline: -v -v -v +# test printing of the parse-tree + +for i in (): + pass +a = None +b = 'str' +c = 'a very long str that will not be interned' +d = b'bytes' +e = b'a very long bytes that will not be interned' +f = 123456789012345678901234567890 diff --git a/tests/cmdline/cmd_parsetree.py.exp b/tests/cmdline/cmd_parsetree.py.exp new file mode 100644 index 000000000..06fbeadfc --- /dev/null +++ b/tests/cmdline/cmd_parsetree.py.exp @@ -0,0 +1,67 @@ +---------------- +[ 4] rule(2) (n=8) + tok(5) +[ 4] rule(78) (n=4) + id(i) +[ 4] rule(131) (n=1) + NULL +[ 5] rule(42) (n=0) + NULL +[ 6] rule(32) (n=2) + id(a) + tok(15) +[ 7] rule(32) (n=2) + id(b) + str(str) +[ 8] rule(32) (n=2) + id(c) +[ 8] literal str(a very long str that will not be interned) +[ 9] rule(32) (n=2) + id(d) + bytes(bytes) +[ 10] rule(32) (n=2) + id(e) +[ 10] literal bytes(a very long bytes that will not be interned) +[ 11] rule(32) (n=2) + id(f) +[ 11] literal \.\+ +---------------- +File cmdline/cmd_parsetree.py, code block '<module>' (descriptor: \.\+, bytecode @\.\+ bytes) +Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): +######## +\.\+5b +arg names: +(N_STATE 2) +(N_EXC_STACK 0) + bc=-1 line=1 + bc=0 line=4 + bc=9 line=5 + bc=12 line=6 + bc=16 line=7 + bc=22 line=8 + bc=27 line=9 + bc=32 line=10 + bc=37 line=11 +00 BUILD_TUPLE 0 +02 GET_ITER +03 FOR_ITER 12 +06 STORE_NAME i +09 JUMP 3 +12 LOAD_CONST_NONE +13 STORE_NAME a +16 LOAD_CONST_STRING 'str' +19 STORE_NAME b +22 LOAD_CONST_OBJ \.\+ +24 STORE_NAME c +27 LOAD_CONST_OBJ \.\+ +29 STORE_NAME d +32 LOAD_CONST_OBJ \.\+ +34 STORE_NAME e +37 LOAD_CONST_OBJ \.\+ +39 STORE_NAME f +42 LOAD_CONST_NONE +43 RETURN_VALUE +mem: total=\\d\+, current=\\d\+, peak=\\d\+ +stack: \\d\+ out of \\d\+ +GC: total: \\d\+, used: \\d\+, free: \\d\+ + No. of 1-blocks: \\d\+, 2-blocks: \\d\+, max blk sz: \\d\+, max free sz: \\d\+ diff --git a/tests/cmdline/repl_autocomplete.py b/tests/cmdline/repl_autocomplete.py new file mode 100644 index 000000000..a848cab0f --- /dev/null +++ b/tests/cmdline/repl_autocomplete.py @@ -0,0 +1,10 @@ +# tests for autocompletion +impo sys +not_exist. +not_exist +x = '123' +1, x.isdi () +i = str +i.lowe ('ABC') +j = None +j. diff --git a/tests/cmdline/repl_autocomplete.py.exp b/tests/cmdline/repl_autocomplete.py.exp new file mode 100644 index 000000000..dfb998ff6 --- /dev/null +++ b/tests/cmdline/repl_autocomplete.py.exp @@ -0,0 +1,15 @@ +MicroPython \.\+ version +Use \.\+ +>>> # tests for autocompletion +>>> import sys +>>> not_exist.[K[K[K[K[K[K[K[K[K[K +>>> not_exist[K[K[K[K[K[K[K[K[K +>>> x = '123' +>>> 1, x.isdigit() +(1, True) +>>> i = str +>>> i.lower('ABC') +'abc' +>>> j = None +>>> j.[K[K +>>> diff --git a/tests/extmod/btree1.py b/tests/extmod/btree1.py index 715f62824..2127554db 100644 --- a/tests/extmod/btree1.py +++ b/tests/extmod/btree1.py @@ -85,5 +85,6 @@ try: except TypeError: print("TypeError") +db.flush() db.close() f.close() diff --git a/tests/extmod/framebuf1.py b/tests/extmod/framebuf1.py index 52899028c..cdc7e5b18 100644 --- a/tests/extmod/framebuf1.py +++ b/tests/extmod/framebuf1.py @@ -8,7 +8,10 @@ except ImportError: w = 5 h = 16 buf = bytearray(w * h // 8) -fbuf = framebuf.FrameBuffer1(buf, w, h, w) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.MVLSB) + +# access as buffer +print(memoryview(fbuf)[0]) # fill fbuf.fill(1) @@ -30,6 +33,36 @@ print(buf) # get pixel print(fbuf.pixel(0, 0), fbuf.pixel(1, 1)) +# hline +fbuf.fill(0) +fbuf.hline(0, 1, w, 1) +print('hline', buf) + +# vline +fbuf.fill(0) +fbuf.vline(1, 0, h, 1) +print('vline', buf) + +# rect +fbuf.fill(0) +fbuf.rect(1, 1, 3, 3, 1) +print('rect', buf) + +#fill rect +fbuf.fill(0) +fbuf.fill_rect(1, 1, 3, 3, 1) +print('fill_rect', buf) + +# line +fbuf.fill(0) +fbuf.line(1, 1, 3, 3, 1) +print('line', buf) + +# line steep negative gradient +fbuf.fill(0) +fbuf.line(3, 3, 2, 1, 1) +print('line', buf) + # scroll fbuf.fill(0) fbuf.pixel(2, 7, 1) @@ -54,3 +87,13 @@ print(buf) # char out of font range set to chr(127) fbuf.text(str(chr(31)), 0, 0) print(buf) + +# test invalid constructor +try: + fbuf = framebuf.FrameBuffer(buf, w, h, 2, framebuf.MVLSB) +except ValueError: + print("ValueError") + +# test legacy constructor +fbuf = framebuf.FrameBuffer1(buf, w, h) +fbuf = framebuf.FrameBuffer1(buf, w, h, w) diff --git a/tests/extmod/framebuf1.py.exp b/tests/extmod/framebuf1.py.exp index 1577faac8..83d775d3c 100644 --- a/tests/extmod/framebuf1.py.exp +++ b/tests/extmod/framebuf1.py.exp @@ -1,8 +1,15 @@ +0 bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x01\x00\x00\x00\x01\x80\x00\x00\x00\x80') bytearray(b'\x01\x00\x00\x00\x01\x80\x00\x00\x00\x00') 1 0 +hline bytearray(b'\x02\x02\x02\x02\x02\x00\x00\x00\x00\x00') +vline bytearray(b'\x00\xff\x00\x00\x00\x00\xff\x00\x00\x00') +rect bytearray(b'\x00\x0e\n\x0e\x00\x00\x00\x00\x00\x00') +fill_rect bytearray(b'\x00\x0e\x0e\x0e\x00\x00\x00\x00\x00\x00') +line bytearray(b'\x00\x02\x04\x08\x00\x00\x00\x00\x00\x00') +line bytearray(b'\x00\x00\x06\x08\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00') bytearray(b'\x00\x00@\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00@\x00\x00\x00\x00\x00\x00') @@ -11,3 +18,4 @@ bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01') bytearray(b'\x00\x7f\x7f\x04\x04\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\xaaU\xaaU\xaa\x00\x00\x00\x00\x00') +ValueError diff --git a/tests/extmod/framebuf16.py b/tests/extmod/framebuf16.py new file mode 100644 index 000000000..3aa1d34de --- /dev/null +++ b/tests/extmod/framebuf16.py @@ -0,0 +1,60 @@ +try: + import framebuf +except ImportError: + print("SKIP") + import sys + sys.exit() + +def printbuf(): + print("--8<--") + for y in range(h): + print(buf[y * w * 2:(y + 1) * w * 2]) + print("-->8--") + +w = 4 +h = 5 +buf = bytearray(w * h * 2) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.RGB565) + +# fill +fbuf.fill(0xffff) +printbuf() +fbuf.fill(0x0000) +printbuf() + +# put pixel +fbuf.pixel(0, 0, 0xeeee) +fbuf.pixel(3, 0, 0xee00) +fbuf.pixel(0, 4, 0x00ee) +fbuf.pixel(3, 4, 0x0ee0) +printbuf() + +# get pixel +print(fbuf.pixel(0, 4), fbuf.pixel(1, 1)) + +# scroll +fbuf.fill(0x0000) +fbuf.pixel(2, 2, 0xffff) +printbuf() +fbuf.scroll(0, 1) +printbuf() +fbuf.scroll(1, 0) +printbuf() +fbuf.scroll(-1, -2) +printbuf() + +w2 = 2 +h2 = 3 +buf2 = bytearray(w2 * h2 * 2) +fbuf2 = framebuf.FrameBuffer(buf2, w2, h2, framebuf.RGB565) + +fbuf2.fill(0x0000) +fbuf2.pixel(0, 0, 0x0ee0) +fbuf2.pixel(0, 2, 0xee00) +fbuf2.pixel(1, 0, 0x00ee) +fbuf2.pixel(1, 2, 0xe00e) +fbuf.fill(0xffff) +fbuf.blit(fbuf2, 3, 3, 0x0000) +fbuf.blit(fbuf2, -1, -1, 0x0000) +fbuf.blit(fbuf2, 16, 16, 0x0000) +printbuf() diff --git a/tests/extmod/framebuf16.py.exp b/tests/extmod/framebuf16.py.exp new file mode 100644 index 000000000..c41dc19d0 --- /dev/null +++ b/tests/extmod/framebuf16.py.exp @@ -0,0 +1,57 @@ +--8<-- +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +-->8-- +--8<-- +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\xee\xee\x00\x00\x00\x00\x00\xee') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\xee\x00\x00\x00\x00\x00\xe0\x0e') +-->8-- +238 0 +--8<-- +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\xff\xff') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\xff\xff') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\x0e\xe0\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xe0\x0e') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +-->8-- diff --git a/tests/extmod/ubinascii_a2b_base64.py b/tests/extmod/ubinascii_a2b_base64.py index 25986b7c0..97c451950 100644 --- a/tests/extmod/ubinascii_a2b_base64.py +++ b/tests/extmod/ubinascii_a2b_base64.py @@ -14,6 +14,7 @@ print(binascii.a2b_base64(b'Zm9vYmFy')) print(binascii.a2b_base64(b'AAECAwQFBgc=')) print(binascii.a2b_base64(b'CAkKCwwNDg8=')) print(binascii.a2b_base64(b'f4D/')) +print(binascii.a2b_base64(b'f4D+')) # convert '+' print(binascii.a2b_base64(b'MTIzNEFCQ0RhYmNk')) try: diff --git a/tests/extmod/ubinascii_b2a_base64.py b/tests/extmod/ubinascii_b2a_base64.py index 343c28da2..fdcaf32dd 100644 --- a/tests/extmod/ubinascii_b2a_base64.py +++ b/tests/extmod/ubinascii_b2a_base64.py @@ -15,3 +15,4 @@ print(binascii.b2a_base64(b'\x00\x01\x02\x03\x04\x05\x06\x07')) print(binascii.b2a_base64(b'\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f')) print(binascii.b2a_base64(b'\x7f\x80\xff')) print(binascii.b2a_base64(b'1234ABCDabcd')) +print(binascii.b2a_base64(b'\x00\x00>')) # convert into '+' diff --git a/tests/extmod/ubinascii_micropython.py b/tests/extmod/ubinascii_micropython.py new file mode 100644 index 000000000..d68da3205 --- /dev/null +++ b/tests/extmod/ubinascii_micropython.py @@ -0,0 +1,8 @@ +try: + import ubinascii as binascii +except ImportError: + import binascii + +# two arguments supported in uPy but not CPython +a = binascii.hexlify(b'123', ':') +print(a) diff --git a/tests/extmod/ubinascii_micropython.py.exp b/tests/extmod/ubinascii_micropython.py.exp new file mode 100644 index 000000000..0ae3d768e --- /dev/null +++ b/tests/extmod/ubinascii_micropython.py.exp @@ -0,0 +1 @@ +b'31:32:33' diff --git a/tests/extmod/ubinascii_unhexlify.py b/tests/extmod/ubinascii_unhexlify.py index 1ec6972c5..99c2c0208 100644 --- a/tests/extmod/ubinascii_unhexlify.py +++ b/tests/extmod/ubinascii_unhexlify.py @@ -7,3 +7,13 @@ print(binascii.unhexlify(b'0001020304050607')) print(binascii.unhexlify(b'08090a0b0c0d0e0f')) print(binascii.unhexlify(b'7f80ff')) print(binascii.unhexlify(b'313233344142434461626364')) + +try: + a = binascii.unhexlify(b'0') # odd buffer length +except ValueError: + print('ValueError') + +try: + a = binascii.unhexlify(b'gg') # digit not hex +except ValueError: + print('ValueError') diff --git a/tests/extmod/uctypes_array_assign_native_le.py b/tests/extmod/uctypes_array_assign_native_le.py index 6901654dd..632c4d252 100644 --- a/tests/extmod/uctypes_array_assign_native_le.py +++ b/tests/extmod/uctypes_array_assign_native_le.py @@ -15,9 +15,16 @@ desc = { # aligned "arr5": (uctypes.ARRAY | 0, uctypes.UINT32 | 1), "arr7": (uctypes.ARRAY | 0, 1, {"l": uctypes.UINT32 | 0}), + + "arr8": (uctypes.ARRAY | 0, uctypes.INT8 | 1), + "arr9": (uctypes.ARRAY | 0, uctypes.INT16 | 1), + "arr10": (uctypes.ARRAY | 0, uctypes.INT32 | 1), + "arr11": (uctypes.ARRAY | 0, uctypes.INT64 | 1), + "arr12": (uctypes.ARRAY | 0, uctypes.UINT64| 1), + "arr13": (uctypes.ARRAY | 1, 1, {"l": {}}), } -data = bytearray(5) +data = bytearray(8) S = uctypes.struct(uctypes.addressof(data), desc) @@ -44,3 +51,45 @@ assert hex(S.arr5[0]) == "0x66778899" print(S.arr5[0] == S.arr7[0].l) assert S.arr5[0] == S.arr7[0].l +# assign int8 +S.arr8[0] = 0x11 +print(hex(S.arr8[0])) +assert hex(S.arr8[0]) == "0x11" + +# assign int16 +S.arr9[0] = 0x1122 +print(hex(S.arr9[0])) +assert hex(S.arr9[0]) == "0x1122" + +# assign int32 +S.arr10[0] = 0x11223344 +print(hex(S.arr10[0])) +assert hex(S.arr10[0]) == "0x11223344" + +# assign int64 +S.arr11[0] = 0x11223344 +print(hex(S.arr11[0])) +assert hex(S.arr11[0]) == "0x11223344" + +# assign uint64 +S.arr12[0] = 0x11223344 +print(hex(S.arr12[0])) +assert hex(S.arr12[0]) == "0x11223344" + +# index out of range +try: + print(S.arr8[2]) +except IndexError: + print("IndexError") + +# syntax error in descriptor +try: + S.arr13[0].l = 0x11 +except TypeError: + print("TypeError") + +# operation not supported +try: + S.arr13[0] = 0x11 +except TypeError: + print("TypeError") diff --git a/tests/extmod/uctypes_array_assign_native_le.py.exp b/tests/extmod/uctypes_array_assign_native_le.py.exp index 0c3dc50fb..4efcdec66 100644 --- a/tests/extmod/uctypes_array_assign_native_le.py.exp +++ b/tests/extmod/uctypes_array_assign_native_le.py.exp @@ -3,3 +3,11 @@ 0x4455 0x66778899 True +0x11 +0x1122 +0x11223344 +0x11223344 +0x11223344 +IndexError +TypeError +TypeError diff --git a/tests/extmod/uctypes_le.py b/tests/extmod/uctypes_le.py index ff499476f..5ae410b01 100644 --- a/tests/extmod/uctypes_le.py +++ b/tests/extmod/uctypes_le.py @@ -66,3 +66,22 @@ assert bytes(data) == b"21" S.bf3 = 5 print(data) assert bytes(data) == b"2Q" + +desc2 = { + "bf8": uctypes.BFUINT8 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN, + "bf32": uctypes.BFUINT32 | 0 | 20 << uctypes.BF_POS | 4 << uctypes.BF_LEN +} + +data2 = bytearray(b"0123") + +S2 = uctypes.struct(uctypes.addressof(data2), desc2, uctypes.LITTLE_ENDIAN) + +# bitfield using uint8 as base type +S2.bf8 = 5 +print(data2) +assert bytes(data2) == b"5123" + +# bitfield using uint32 as base type +S2.bf32 = 5 +print(data2) +assert bytes(data2) == b"51R3" diff --git a/tests/extmod/uctypes_le.py.exp b/tests/extmod/uctypes_le.py.exp index 8efd7a6ea..2598b4eab 100644 --- a/tests/extmod/uctypes_le.py.exp +++ b/tests/extmod/uctypes_le.py.exp @@ -8,3 +8,5 @@ bf: 48 49 bf 4bit: 3 1 3 0 bytearray(b'21') bytearray(b'2Q') +bytearray(b'5123') +bytearray(b'51R3') diff --git a/tests/extmod/uctypes_native_le.py b/tests/extmod/uctypes_native_le.py index a053b68d5..ef0f9f5e9 100644 --- a/tests/extmod/uctypes_native_le.py +++ b/tests/extmod/uctypes_native_le.py @@ -74,3 +74,22 @@ assert bytes(data) == b"21" S.bf3 = 5 print(data) assert bytes(data) == b"2Q" + +desc2 = { + "bf8": uctypes.BFUINT8 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN, + "bf32": uctypes.BFUINT32 | 0 | 20 << uctypes.BF_POS | 4 << uctypes.BF_LEN +} + +data2 = bytearray(b"0123") + +S2 = uctypes.struct(uctypes.addressof(data2), desc2, uctypes.NATIVE) + +# bitfield using uint8 as base type +S2.bf8 = 5 +print(data2) +assert bytes(data2) == b"5123" + +# bitfield using uint32 as base type +S2.bf32 = 5 +print(data2) +assert bytes(data2) == b"51R3" diff --git a/tests/extmod/uctypes_native_le.py.exp b/tests/extmod/uctypes_native_le.py.exp index 8efd7a6ea..2598b4eab 100644 --- a/tests/extmod/uctypes_native_le.py.exp +++ b/tests/extmod/uctypes_native_le.py.exp @@ -8,3 +8,5 @@ bf: 48 49 bf 4bit: 3 1 3 0 bytearray(b'21') bytearray(b'2Q') +bytearray(b'5123') +bytearray(b'51R3') diff --git a/tests/extmod/uctypes_print.py b/tests/extmod/uctypes_print.py new file mode 100644 index 000000000..71981ce7e --- /dev/null +++ b/tests/extmod/uctypes_print.py @@ -0,0 +1,22 @@ +# test printing of uctypes objects + +import uctypes + +# we use an address of "0" because we just want to print something deterministic +# and don't actually need to set/get any values in the struct + +desc = {"arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 1)} +S = uctypes.struct(0, desc) +print(S) + +desc2 = [(uctypes.ARRAY | 0, uctypes.UINT8 | 1)] +S2 = uctypes.struct(0, desc2) +print(S2) + +desc3 = ((uctypes.ARRAY | 0, uctypes.UINT8 | 1)) +S3 = uctypes.struct(0, desc3) +print(S3) + +desc4 = ((uctypes.PTR | 0, uctypes.UINT8 | 1)) +S4 = uctypes.struct(0, desc4) +print(S4) diff --git a/tests/extmod/uctypes_print.py.exp b/tests/extmod/uctypes_print.py.exp new file mode 100644 index 000000000..63daefc84 --- /dev/null +++ b/tests/extmod/uctypes_print.py.exp @@ -0,0 +1,4 @@ +<struct STRUCT 0> +<struct ERROR 0> +<struct ARRAY 0> +<struct PTR 0> diff --git a/tests/extmod/uctypes_ptr_le.py b/tests/extmod/uctypes_ptr_le.py index 4bff58517..d0216dfb8 100644 --- a/tests/extmod/uctypes_ptr_le.py +++ b/tests/extmod/uctypes_ptr_le.py @@ -14,7 +14,7 @@ desc = { bytes = b"01" addr = uctypes.addressof(bytes) -buf = addr.to_bytes(uctypes.sizeof(desc)) +buf = addr.to_bytes(uctypes.sizeof(desc), "little") S = uctypes.struct(uctypes.addressof(buf), desc, uctypes.LITTLE_ENDIAN) diff --git a/tests/extmod/uctypes_ptr_native_le.py b/tests/extmod/uctypes_ptr_native_le.py index 0d02cfdc8..6f011c3c2 100644 --- a/tests/extmod/uctypes_ptr_native_le.py +++ b/tests/extmod/uctypes_ptr_native_le.py @@ -15,7 +15,7 @@ desc = { bytes = b"01" addr = uctypes.addressof(bytes) -buf = addr.to_bytes(uctypes.sizeof(desc)) +buf = addr.to_bytes(uctypes.sizeof(desc), "little") S = uctypes.struct(uctypes.addressof(buf), desc, uctypes.NATIVE) diff --git a/tests/extmod/ujson_loads.py b/tests/extmod/ujson_loads.py index 22f4a02c4..37576e6ae 100644 --- a/tests/extmod/ujson_loads.py +++ b/tests/extmod/ujson_loads.py @@ -23,6 +23,12 @@ my_print(json.loads('{}')) my_print(json.loads('{"a":true}')) my_print(json.loads('{"a":null, "b":false, "c":true}')) my_print(json.loads('{"a":[], "b":[1], "c":{"3":4}}')) +my_print(json.loads('"abc\\bdef"')) +my_print(json.loads('"abc\\fdef"')) +my_print(json.loads('"abc\\ndef"')) +my_print(json.loads('"abc\\rdef"')) +my_print(json.loads('"abc\\tdef"')) +my_print(json.loads('"abc\\uabcd"')) # whitespace handling my_print(json.loads('{\n\t"a":[]\r\n, "b":[1], "c":{"3":4} \n\r\t\r\r\r\n}')) @@ -32,3 +38,33 @@ try: json.loads('') except ValueError: print('ValueError') + +# string which is not closed +try: + my_print(json.loads('"abc')) +except ValueError: + print('ValueError') + +# unaccompanied closing brace +try: + my_print(json.loads(']')) +except ValueError: + print('ValueError') + +# unspecified object type +try: + my_print(json.loads('a')) +except ValueError: + print('ValueError') + +# bad property name +try: + my_print(json.loads('{{}:"abc"}')) +except ValueError: + print('ValueError') + +# unexpected characters after white space +try: + my_print(json.loads('[null] a')) +except ValueError: + print('ValueError') diff --git a/tests/extmod/utimeq1.py b/tests/extmod/utimeq1.py new file mode 100644 index 000000000..9af723674 --- /dev/null +++ b/tests/extmod/utimeq1.py @@ -0,0 +1,103 @@ +# Test for utimeq module which implements task queue with support for +# wraparound time (utime.ticks_ms() style). +try: + from utime import ticks_add, ticks_diff + from utimeq import utimeq +except ImportError: + print("SKIP") + import sys + sys.exit() + +DEBUG = 0 + +MAX = ticks_add(0, -1) +MODULO_HALF = MAX // 2 + 1 + +if DEBUG: + def dprint(*v): + print(*v) +else: + def dprint(*v): + pass + +# Try not to crash on invalid data +h = utimeq(10) +try: + h.push(1) + assert False +except TypeError: + pass + +try: + h.pop(1) + assert False +except IndexError: + pass + + +def pop_all(h): + l = [] + while h: + item = [0, 0, 0] + h.pop(item) + #print("!", item) + l.append(tuple(item)) + dprint(l) + return l + +def add(h, v): + h.push(v, 0, 0) + dprint("-----") + #h.dump() + dprint("-----") + +h = utimeq(10) +add(h, 0) +add(h, MAX) +add(h, MAX - 1) +add(h, 101) +add(h, 100) +add(h, MAX - 2) +dprint(h) +l = pop_all(h) +for i in range(len(l) - 1): + diff = ticks_diff(l[i + 1][0], l[i][0]) + assert diff > 0 + +def edge_case(edge, offset): + h = utimeq(10) + add(h, ticks_add(0, offset)) + add(h, ticks_add(edge, offset)) + dprint(h) + l = pop_all(h) + diff = ticks_diff(l[1][0], l[0][0]) + dprint(diff, diff > 0) + return diff + +dprint("===") +diff = edge_case(MODULO_HALF - 1, 0) +assert diff == MODULO_HALF - 1 +assert edge_case(MODULO_HALF - 1, 100) == diff +assert edge_case(MODULO_HALF - 1, -100) == diff + +# We expect diff to be always positive, per the definition of heappop() which should return +# the smallest value. +# This is the edge case where this invariant breaks, due to assymetry of two's-complement +# range - there's one more negative integer than positive, so heappushing values like below +# will then make ticks_diff() return the minimum negative value. We could make heappop +# return them in a different order, but ticks_diff() result would be the same. Conclusion: +# never add to a heap values where (a - b) == MODULO_HALF (and which are >= MODULO_HALF +# ticks apart in real time of course). +dprint("===") +diff = edge_case(MODULO_HALF, 0) +assert diff == -MODULO_HALF +assert edge_case(MODULO_HALF, 100) == diff +assert edge_case(MODULO_HALF, -100) == diff + +dprint("===") +diff = edge_case(MODULO_HALF + 1, 0) +assert diff == MODULO_HALF - 1 +assert edge_case(MODULO_HALF + 1, 100) == diff +assert edge_case(MODULO_HALF + 1, -100) == diff + +print("OK") diff --git a/tests/extmod/utimeq1.py.exp b/tests/extmod/utimeq1.py.exp new file mode 100644 index 000000000..d86bac9de --- /dev/null +++ b/tests/extmod/utimeq1.py.exp @@ -0,0 +1 @@ +OK diff --git a/tests/extmod/utimeq_stable.py b/tests/extmod/utimeq_stable.py new file mode 100644 index 000000000..9f6ba76d4 --- /dev/null +++ b/tests/extmod/utimeq_stable.py @@ -0,0 +1,23 @@ +try: + from utimeq import utimeq +except ImportError: + print("SKIP") + import sys + sys.exit() + +h = utimeq(10) + +# Check that for 2 same-key items, the queue is stable (pops items +# in the same order they were pushed). Unfortunately, this no longer +# holds for more same-key values, as the underlying heap structure +# is not stable itself. +h.push(100, 20, 0) +h.push(100, 10, 0) + +res = [0, 0, 0] +h.pop(res) +assert res == [100, 20, 0] +h.pop(res) +assert res == [100, 10, 0] + +print("OK") diff --git a/tests/extmod/utimeq_stable.py.exp b/tests/extmod/utimeq_stable.py.exp new file mode 100644 index 000000000..d86bac9de --- /dev/null +++ b/tests/extmod/utimeq_stable.py.exp @@ -0,0 +1 @@ +OK diff --git a/tests/extmod/vfs_fat_fileio.py b/tests/extmod/vfs_fat_fileio.py index de8d4953c..f050d94e2 100644 --- a/tests/extmod/vfs_fat_fileio.py +++ b/tests/extmod/vfs_fat_fileio.py @@ -89,6 +89,11 @@ with vfs.open("foo_file.txt") as f2: f2.seek(-2, 2) # SEEK_END print(f2.read(1)) +# using constructor of FileIO type to open a file +FileIO = type(f) +with FileIO("foo_file.txt") as f: + print(f.read()) + # dirs vfs.mkdir("foo_dir") @@ -140,6 +145,14 @@ print(vfs.listdir("foo_dir")) vfs.rename("foo_dir/file.txt", "moved-to-root.txt") print(vfs.listdir()) +# check that renaming to existing file will overwrite it +with vfs.open("temp", "w") as f: + f.write("new text") +vfs.rename("temp", "moved-to-root.txt") +print(vfs.listdir()) +with vfs.open("moved-to-root.txt") as f: + print(f.read()) + # valid removes vfs.remove("foo_dir/sub_file.txt") vfs.remove("foo_file.txt") diff --git a/tests/extmod/vfs_fat_fileio.py.exp b/tests/extmod/vfs_fat_fileio.py.exp index c438bc850..a09442ae8 100644 --- a/tests/extmod/vfs_fat_fileio.py.exp +++ b/tests/extmod/vfs_fat_fileio.py.exp @@ -9,6 +9,7 @@ h e True d +hello!world! True True True @@ -18,5 +19,7 @@ b'data in file' True ['sub_file.txt', 'file.txt'] ['foo_file.txt', 'foo_dir', 'moved-to-root.txt'] +['foo_file.txt', 'foo_dir', 'moved-to-root.txt'] +new text ['moved-to-root.txt'] ENOSPC: True diff --git a/tests/feature_check/coverage.py b/tests/feature_check/coverage.py new file mode 100644 index 000000000..dcda53eae --- /dev/null +++ b/tests/feature_check/coverage.py @@ -0,0 +1,5 @@ +try: + extra_coverage + print('coverage') +except NameError: + print('no') diff --git a/tests/feature_check/coverage.py.exp b/tests/feature_check/coverage.py.exp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/feature_check/coverage.py.exp diff --git a/tests/feature_check/set_check.py b/tests/feature_check/set_check.py new file mode 100644 index 000000000..ec186cc5b --- /dev/null +++ b/tests/feature_check/set_check.py @@ -0,0 +1,2 @@ +# check if set literal syntax is supported +{1} diff --git a/tests/feature_check/set_check.py.exp b/tests/feature_check/set_check.py.exp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/feature_check/set_check.py.exp diff --git a/tests/float/builtin_float_round.py b/tests/float/builtin_float_round.py index 4419b744b..de72514db 100644 --- a/tests/float/builtin_float_round.py +++ b/tests/float/builtin_float_round.py @@ -13,5 +13,5 @@ for i in range(11): print(round((i - 5) / 2)) # test second arg -# TODO uPy currently only supports second arg being 0 -print(round(1.4, 0)) +for i in range(-1, 3): + print(round(1.47, i)) diff --git a/tests/float/complex1.py b/tests/float/complex1.py index ebe4b0f37..027d12583 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -75,6 +75,12 @@ try: except TypeError: print("TypeError") +#small int on LHS, complex on RHS, unsupported op +try: + print(1 | 1j) +except TypeError: + print('TypeError') + # zero division try: 1j / 0 diff --git a/tests/float/float1.py b/tests/float/float1.py index f21f5bcdd..0e115032b 100644 --- a/tests/float/float1.py +++ b/tests/float/float1.py @@ -87,6 +87,12 @@ try: except TypeError: print("TypeError") +# small int on LHS, float on RHS, unsupported op +try: + print(1 | 1.0) +except TypeError: + print('TypeError') + # can't convert list to float try: float([]) diff --git a/tests/float/string_format_modulo.py b/tests/float/string_format_modulo.py index 681e9eb80..03c8dd00a 100644 --- a/tests/float/string_format_modulo.py +++ b/tests/float/string_format_modulo.py @@ -42,3 +42,5 @@ print(('%.40g' % 1e-1)[:2]) print(('%.40g' % 1e-2)[:2]) print(('%.40g' % 1e-3)[:2]) print(('%.40g' % 1e-4)[:2]) + +print("%.0g" % 1) # 0 precision 'g' diff --git a/tests/float/string_format_modulo3.py b/tests/float/string_format_modulo3.py new file mode 100644 index 000000000..563964786 --- /dev/null +++ b/tests/float/string_format_modulo3.py @@ -0,0 +1,4 @@ +# uPy and CPython outputs differ for the following +print("%.1g" % -9.9) # round up 'g' with '-' sign +print("%.1e" % 9.99) # round up with positive exponent +print("%.1e" % 0.999) # round up with negative exponent diff --git a/tests/float/string_format_modulo3.py.exp b/tests/float/string_format_modulo3.py.exp new file mode 100644 index 000000000..b158c7d7f --- /dev/null +++ b/tests/float/string_format_modulo3.py.exp @@ -0,0 +1,3 @@ +-10 +1.00e+01 +1.00e-00 diff --git a/tests/import/import_pkg7.py b/tests/import/import_pkg7.py new file mode 100644 index 000000000..be8564ef6 --- /dev/null +++ b/tests/import/import_pkg7.py @@ -0,0 +1,2 @@ +# This tests ... relative imports as used in pkg7 +import pkg7.subpkg1.subpkg2.mod3 diff --git a/tests/import/pkg7/__init__.py b/tests/import/pkg7/__init__.py new file mode 100644 index 000000000..8b92fa996 --- /dev/null +++ b/tests/import/pkg7/__init__.py @@ -0,0 +1 @@ +print("pkg __name__:", __name__) diff --git a/tests/import/pkg7/mod1.py b/tests/import/pkg7/mod1.py new file mode 100644 index 000000000..6b574114d --- /dev/null +++ b/tests/import/pkg7/mod1.py @@ -0,0 +1,2 @@ +print('mod1') +foo = 'mod1.foo' diff --git a/tests/import/pkg7/mod2.py b/tests/import/pkg7/mod2.py new file mode 100644 index 000000000..039a5d174 --- /dev/null +++ b/tests/import/pkg7/mod2.py @@ -0,0 +1,2 @@ +print('mod2') +bar = 'mod2.bar' diff --git a/tests/import/pkg7/subpkg1/__init__.py b/tests/import/pkg7/subpkg1/__init__.py new file mode 100644 index 000000000..8b92fa996 --- /dev/null +++ b/tests/import/pkg7/subpkg1/__init__.py @@ -0,0 +1 @@ +print("pkg __name__:", __name__) diff --git a/tests/import/pkg7/subpkg1/subpkg2/__init__.py b/tests/import/pkg7/subpkg1/subpkg2/__init__.py new file mode 100644 index 000000000..8b92fa996 --- /dev/null +++ b/tests/import/pkg7/subpkg1/subpkg2/__init__.py @@ -0,0 +1 @@ +print("pkg __name__:", __name__) diff --git a/tests/import/pkg7/subpkg1/subpkg2/mod3.py b/tests/import/pkg7/subpkg1/subpkg2/mod3.py new file mode 100644 index 000000000..b85b34e60 --- /dev/null +++ b/tests/import/pkg7/subpkg1/subpkg2/mod3.py @@ -0,0 +1,4 @@ +from ... import mod1 +from ...mod2 import bar +print(mod1.foo) +print(bar) diff --git a/tests/io/file1.py b/tests/io/file1.py index 8f9e4ef6e..af4176b64 100644 --- a/tests/io/file1.py +++ b/tests/io/file1.py @@ -37,7 +37,7 @@ except OSError: print('OSError') f.close() -# readall() error (call read() for compat with CPy) +# read() w/o args error f = open('io/data/file1', 'ab') try: f.read() diff --git a/tests/micropython/heapalloc.py b/tests/micropython/heapalloc.py index a651158ca..62f26df6a 100644 --- a/tests/micropython/heapalloc.py +++ b/tests/micropython/heapalloc.py @@ -18,7 +18,7 @@ def f3(a, b, c, d): global_var = 1 def test(): - global global_var + global global_var, global_exc global_var = 2 # set an existing global variable for i in range(2): # for loop f1(i) # function call diff --git a/tests/micropython/heapalloc_inst_call.py b/tests/micropython/heapalloc_inst_call.py new file mode 100644 index 000000000..3cc497b73 --- /dev/null +++ b/tests/micropython/heapalloc_inst_call.py @@ -0,0 +1,31 @@ +# Test that calling clazz.__call__() with up to at least 3 arguments +# doesn't require heap allocation. +import micropython + +class Foo0: + def __call__(self): + print("__call__") + +class Foo1: + def __call__(self, a): + print("__call__", a) + +class Foo2: + def __call__(self, a, b): + print("__call__", a, b) + +class Foo3: + def __call__(self, a, b, c): + print("__call__", a, b, c) + +f0 = Foo0() +f1 = Foo1() +f2 = Foo2() +f3 = Foo3() + +micropython.heap_lock() +f0() +f1(1) +f2(1, 2) +f3(1, 2, 3) +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_inst_call.py.exp b/tests/micropython/heapalloc_inst_call.py.exp new file mode 100644 index 000000000..0b06bb2c9 --- /dev/null +++ b/tests/micropython/heapalloc_inst_call.py.exp @@ -0,0 +1,4 @@ +__call__ +__call__ 1 +__call__ 1 2 +__call__ 1 2 3 diff --git a/tests/micropython/heapalloc_traceback.py b/tests/micropython/heapalloc_traceback.py new file mode 100644 index 000000000..808df0225 --- /dev/null +++ b/tests/micropython/heapalloc_traceback.py @@ -0,0 +1,36 @@ +# test that we can generate a traceback without allocating + +import micropython +import sys +import uio + +# preallocate exception instance with some room for a traceback +global_exc = StopIteration() +try: + raise global_exc +except: + pass + +def test(): + global global_exc + global_exc.__traceback__ = None + try: + raise global_exc + except StopIteration: + print('StopIteration') + +# call test() with heap allocation disabled +micropython.heap_lock() +test() +micropython.heap_unlock() + +# print the exception that was raised +buf = uio.StringIO() +sys.print_exception(global_exc, buf) +for l in buf.getvalue().split("\n"): + # uPy on pyboard prints <stdin> as file, so remove filename. + if l.startswith(" File "): + l = l.split('"') + print(l[0], l[2]) + else: + print(l) diff --git a/tests/micropython/heapalloc_traceback.py.exp b/tests/micropython/heapalloc_traceback.py.exp new file mode 100644 index 000000000..9ba10948d --- /dev/null +++ b/tests/micropython/heapalloc_traceback.py.exp @@ -0,0 +1,5 @@ +StopIteration +Traceback (most recent call last): + File , line 18, in test +StopIteration: + diff --git a/tests/micropython/stack_use.py b/tests/micropython/stack_use.py new file mode 100644 index 000000000..bc714755a --- /dev/null +++ b/tests/micropython/stack_use.py @@ -0,0 +1,7 @@ +# tests stack_use function in micropython module +import micropython + +if not hasattr(micropython, 'stack_use'): + print('SKIP') +else: + print(type(micropython.stack_use())) # output varies diff --git a/tests/micropython/stack_use.py.exp b/tests/micropython/stack_use.py.exp new file mode 100644 index 000000000..fe37ceaa1 --- /dev/null +++ b/tests/micropython/stack_use.py.exp @@ -0,0 +1 @@ +<class 'int'> diff --git a/tests/micropython/viper_import.py b/tests/micropython/viper_import.py new file mode 100644 index 000000000..987800744 --- /dev/null +++ b/tests/micropython/viper_import.py @@ -0,0 +1,10 @@ +# test import within viper function + +@micropython.viper +def f(): + import micropython + print(micropython.const(1)) + + from micropython import const + print(const(2)) +f() diff --git a/tests/micropython/viper_import.py.exp b/tests/micropython/viper_import.py.exp new file mode 100644 index 000000000..1191247b6 --- /dev/null +++ b/tests/micropython/viper_import.py.exp @@ -0,0 +1,2 @@ +1 +2 diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index 677438b83..e8ec74b5d 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -118,3 +118,9 @@ print(ustruct.pack('bb', 1, 2, 3)) # struct pack with too few args, not checked by uPy print(ustruct.pack('bb', 1)) + +# array slice assignment with unsupported RHS +try: + bytearray(4)[0:1] = [1, 2] +except NotImplementedError: + print('NotImplementedError') diff --git a/tests/misc/non_compliant.py.exp b/tests/misc/non_compliant.py.exp index 737650e9e..caa5c4569 100644 --- a/tests/misc/non_compliant.py.exp +++ b/tests/misc/non_compliant.py.exp @@ -18,3 +18,4 @@ NotImplementedError NotImplementedError b'\x01\x02' b'\x01\x00' +NotImplementedError diff --git a/tests/pyb/i2c_error.py b/tests/pyb/i2c_error.py index d6c0debe2..3201d6367 100644 --- a/tests/pyb/i2c_error.py +++ b/tests/pyb/i2c_error.py @@ -7,7 +7,7 @@ from pyb import I2C pyb.Accel() # get I2C bus -i2c = I2C(1, I2C.MASTER) +i2c = I2C(1, I2C.MASTER, dma=True) # test polling mem_read pyb.disable_irq() diff --git a/tests/pyb/uart.py.exp b/tests/pyb/uart.py.exp index 4be50d328..b5fe0cd0b 100644 --- a/tests/pyb/uart.py.exp +++ b/tests/pyb/uart.py.exp @@ -12,8 +12,8 @@ UART XB UART YA UART YB ValueError Z -UART(1, baudrate=9600, bits=8, parity=None, stop=1, timeout=1000, timeout_char=2, read_buf_len=64) -UART(1, baudrate=2400, bits=8, parity=None, stop=1, timeout=1000, timeout_char=6, read_buf_len=64) +UART(1, baudrate=9600, bits=8, parity=None, stop=1, timeout=1000, timeout_char=3, read_buf_len=64) +UART(1, baudrate=2400, bits=8, parity=None, stop=1, timeout=1000, timeout_char=7, read_buf_len=64) 0 3 4 diff --git a/tests/run-tests b/tests/run-tests index 4ac7d8e28..91282667d 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -51,7 +51,7 @@ def convert_regex_escapes(line): def run_micropython(pyb, args, test_file): - special_tests = ('micropython/meminfo.py', 'basics/bytes_compare3.py') + special_tests = ('micropython/meminfo.py', 'basics/bytes_compare3.py', 'thread/thread_exc2.py') is_special = False if pyb is None: # run on PC @@ -99,6 +99,7 @@ def run_micropython(pyb, args, test_file): stderr=subprocess.STDOUT, bufsize=0) banner = get(True) output_mupy = banner + b''.join(send_get(line) for line in f) + send_get(b'\x04') # exit the REPL, so coverage info is saved p.kill() os.close(master) os.close(slave) @@ -194,12 +195,18 @@ def run_tests(pyb, tests, args): skip_tests = set() skip_native = False + skip_set_type = False # Check if micropython.native is supported, and skip such tests if it's not native = run_micropython(pyb, args, 'feature_check/native_check.py') if native == b'CRASH': skip_native = True + # Check if set type (and set literals) is supported, and skip such tests if it's not + native = run_micropython(pyb, args, 'feature_check/set_check.py') + if native == b'CRASH': + skip_set_type = True + # Check if emacs repl is supported, and skip such tests if it's not t = run_micropython(pyb, args, 'feature_check/repl_emacs_check.py') if not 'True' in str(t, 'ascii'): @@ -207,6 +214,7 @@ def run_tests(pyb, tests, args): upy_byteorder = run_micropython(pyb, args, 'feature_check/byteorder.py') has_complex = run_micropython(pyb, args, 'feature_check/complex.py') == b'complex\n' + has_coverage = run_micropython(pyb, args, 'feature_check/coverage.py') == b'coverage\n' cpy_byteorder = subprocess.check_output([CPYTHON3, 'feature_check/byteorder.py']) skip_endian = (upy_byteorder != cpy_byteorder) @@ -224,6 +232,9 @@ def run_tests(pyb, tests, args): skip_tests.add('float/true_value.py') skip_tests.add('float/types.py') + if not has_coverage: + skip_tests.add('cmdline/cmd_parsetree.py') + # Some tests shouldn't be run on a PC if pyb is None: # unix build does not have the GIL so can't run thread mutation tests @@ -270,7 +281,7 @@ def run_tests(pyb, tests, args): # Some tests are known to fail with native emitter # Remove them from the below when they work if args.emit == 'native': - skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_stopped gen_yield_from_throw generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send'.split()}) # require yield + skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_stopped gen_yield_from_throw gen_yield_from_throw2 generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class globals_del string_join'.split()}) # require yield skip_tests.update({'basics/async_%s.py' % t for t in 'def await await2 for for2 with with2'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'try_reraise try_reraise2'.split()}) # require raise_varargs @@ -291,6 +302,7 @@ def run_tests(pyb, tests, args): skip_tests.add('misc/rge_sm.py') # requires yield skip_tests.add('misc/print_exception.py') # because native doesn't have proper traceback info skip_tests.add('misc/sys_exc_info.py') # sys.exc_info() is not supported for native + skip_tests.add('micropython/heapalloc_traceback.py') # because native doesn't have proper traceback info for test_file in tests: test_file = test_file.replace('\\', '/') @@ -298,8 +310,14 @@ def run_tests(pyb, tests, args): test_name = os.path.splitext(test_basename)[0] is_native = test_name.startswith("native_") or test_name.startswith("viper_") is_endian = test_name.endswith("_endian") + is_set_type = test_name.startswith("set_") + + skip_it = test_file in skip_tests + skip_it |= skip_native and is_native + skip_it |= skip_endian and is_endian + skip_it |= skip_set_type and is_set_type - if test_file in skip_tests or (skip_native and is_native) or (skip_endian and is_endian): + if skip_it: print("skip ", test_file) skipped_tests.append(test_name) continue diff --git a/tests/thread/thread_exc2.py b/tests/thread/thread_exc2.py new file mode 100644 index 000000000..35cb32441 --- /dev/null +++ b/tests/thread/thread_exc2.py @@ -0,0 +1,10 @@ +# test raising exception within thread which is not caught +import utime +import _thread + +def thread_entry(): + raise ValueError + +_thread.start_new_thread(thread_entry, ()) +utime.sleep(1) +print('done') diff --git a/tests/thread/thread_exc2.py.exp b/tests/thread/thread_exc2.py.exp new file mode 100644 index 000000000..584bfab4d --- /dev/null +++ b/tests/thread/thread_exc2.py.exp @@ -0,0 +1,5 @@ +Unhandled exception in thread started by <function thread_entry at 0x\[0-9a-f\]\+> +Traceback (most recent call last): + File "thread/thread_exc2.py", line 6, in thread_entry +ValueError: +done diff --git a/tests/thread/thread_start2.py b/tests/thread/thread_start2.py index 4efa808eb..d0913e37c 100644 --- a/tests/thread/thread_start2.py +++ b/tests/thread/thread_start2.py @@ -16,4 +16,11 @@ _thread.start_new_thread(thread_entry, (10, 20), {'a2': 0, 'a3': 1}) # wait for thread to finish time.sleep(1) + +# incorrect argument where dictionary is needed for keyword args +try: + _thread.start_new_thread(thread_entry, (), ()) +except TypeError: + print('TypeError') + print('done') diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py index 72bcc9994..f2b40282b 100644 --- a/tests/unix/extra_coverage.py +++ b/tests/unix/extra_coverage.py @@ -13,3 +13,19 @@ print(hash(data[0])) print(hash(data[1])) print(hash(bytes(data[0], 'utf8'))) print(hash(str(data[1], 'utf8'))) + +# test basic import of frozen scripts +import frzstr1 +import frzmpy1 + +# test import of frozen packages with __init__.py +import frzstr_pkg1 +print(frzstr_pkg1.x) +import frzmpy_pkg1 +print(frzmpy_pkg1.x) + +# test import of frozen packages without __init__.py +from frzstr_pkg2.mod import Foo +print(Foo.x) +from frzmpy_pkg2.mod import Foo +print(Foo.x) diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index ea73a54e4..d3d725211 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -35,8 +35,26 @@ ementation 12345678 0 0 +# runtime utils +TypeError: can't convert str to int +TypeError: unsupported types for : 'str', 'str' +Warning: test +# format float +? ++1e+00 ++1e+00 ('0123456789', b'0123456789') 7300 7300 7300 7300 +frzstr1 +frzmpy1 +frzstr_pkg1.__init__ +1 +frzmpy_pkg1.__init__ +1 +frzstr_pkg2.mod +1 +frzmpy_pkg2.mod +1 diff --git a/tests/wipy/os.py b/tests/wipy/os.py index f81d1cee8..0596a16b5 100644 --- a/tests/wipy/os.py +++ b/tests/wipy/os.py @@ -38,7 +38,7 @@ n_w = f.write(test_bytes) print(n_w == len(test_bytes)) f.close() f = open('test.txt', 'r') -r = bytes(f.readall(), 'ascii') +r = bytes(f.read(), 'ascii') # check that we can write and read it correctly print(r == test_bytes) f.close() @@ -65,7 +65,7 @@ n_w = f.write(test_bytes) print(n_w == len(test_bytes)) f.close() f = open('test.txt', 'r') -r = bytes(f.readall(), 'ascii') +r = bytes(f.read(), 'ascii') # check that we can write and read it correctly print(r == test_bytes) f.close() diff --git a/tests/wipy/uart.py b/tests/wipy/uart.py index 5a5221e55..a3a1c14e8 100644 --- a/tests/wipy/uart.py +++ b/tests/wipy/uart.py @@ -72,7 +72,7 @@ print(uart1.readline() == b'1234567890') print(uart1.any() == 0) uart0.write(b'1234567890') -print(uart1.readall() == b'1234567890') +print(uart1.read() == b'1234567890') # tx only mode uart0 = UART(0, 1000000, pins=('GP12', None)) |