From 63a03f047568667132935ac9af76d1f8f1253aa8 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Sun, 23 Nov 2025 10:06:12 +0100 Subject: [PATCH] Bump minimum OTP version to 26, Elixir to 1.17 Simplify tests and remove support for opcodes that are not emitted by OTP26+, significantly reducing the virtual machine size. Update build-and-test.yaml workflow matrix with 44 jobs: - every compiler - latest three OTP versions with default compiler versions - next OTP version (29) with and without JIT - two previous Elixir versions (1.17 and 1.18) with compatible OTP versions among the last three - arm64 with and without JIT - armv6m with and without JIT - riscv32 with and without JIT - i386 - s390x - x86-64 with JIT - stacktraces disabled - 32 bits floats - OTP master and Elixir main - -Os optimization on x86-64 Signed-off-by: Paul Guyot --- .github/workflows/build-and-test-macos.yaml | 16 +- .github/workflows/build-and-test.yaml | 286 ++--- .github/workflows/codeql-analysis.yaml | 13 +- .github/workflows/run-tests-with-beam.yaml | 28 - CHANGELOG.md | 1 + CMakeLists.txt | 6 - doc/release-notes.md.in | 13 +- doc/src/differences-with-beam.md | 4 +- libs/CMakeLists.txt | 9 +- libs/estdlib/src/dist_util.erl | 5 +- src/libAtomVM/CMakeLists.txt | 6 - src/libAtomVM/opcodesswitch.h | 1074 ++--------------- src/platforms/emscripten/CMakeLists.txt | 1 - src/platforms/esp32/CMakeLists.txt | 1 - src/platforms/rp2/CMakeLists.txt | 1 - src/platforms/stm32/CMakeLists.txt | 1 - tests/CMakeLists.txt | 5 +- tests/erlang_tests/CMakeLists.txt | 23 +- .../erlang_tests/bs_get_binary_fixed_size.erl | 19 +- .../bs_get_float_dynamic_size.erl | 5 +- .../bs_get_integer_fixed_size.erl | 5 +- tests/erlang_tests/maps_nifs.erl | 18 +- tests/erlang_tests/test_base64.erl | 22 +- tests/erlang_tests/test_binary_to_term.erl | 521 +++----- tests/erlang_tests/test_bs.erl | 51 +- .../erlang_tests/test_bs_create_bin_accum.erl | 17 +- tests/erlang_tests/test_code_server_nifs.erl | 9 +- tests/erlang_tests/test_crypto.erl | 18 +- tests/erlang_tests/test_ets.erl | 30 +- tests/erlang_tests/test_is_integer_3.erl | 2 - tests/erlang_tests/test_map.erl | 7 - tests/erlang_tests/test_min_max_guard.erl | 11 - .../test_multi_value_comprehension.erl | 2 - tests/erlang_tests/test_node.erl | 8 +- tests/erlang_tests/test_op_bs_create_bin.erl | 26 +- tests/erlang_tests/test_op_bs_start_match.erl | 20 +- tests/erlang_tests/test_stacktrace.erl | 33 +- tests/erlang_tests/test_system_info.erl | 2 +- tests/erlang_tests/test_utf8_atoms.erl | 10 +- tests/libs/eavmlib/test_ahttp_client.erl | 18 +- tests/libs/estdlib/test_epmd.erl | 66 +- tests/libs/estdlib/test_gen_server.erl | 44 +- tests/libs/estdlib/test_gen_tcp.erl | 57 +- tests/libs/estdlib/test_gen_udp.erl | 17 +- tests/libs/estdlib/test_inet.erl | 21 +- tests/libs/estdlib/test_maps.erl | 1 - tests/libs/estdlib/test_net_kernel.erl | 69 +- tests/libs/estdlib/test_proc_lib.erl | 15 +- tests/libs/estdlib/test_queue.erl | 70 +- tests/libs/estdlib/test_tcp_socket.erl | 29 +- tests/libs/estdlib/tests.erl | 29 +- 51 files changed, 573 insertions(+), 2192 deletions(-) diff --git a/.github/workflows/build-and-test-macos.yaml b/.github/workflows/build-and-test-macos.yaml index ebf3f16cd2..fcf1e309bf 100644 --- a/.github/workflows/build-and-test-macos.yaml +++ b/.github/workflows/build-and-test-macos.yaml @@ -39,7 +39,7 @@ jobs: fail-fast: false matrix: os: ["macos-14", "macos-15", "macos-15-intel", "macos-26"] - otp: ["24", "25", "26", "27", "28"] + otp: ["26", "27", "28"] mbedtls: ["mbedtls@3"] cmake_opts_other: [""] @@ -67,22 +67,8 @@ jobs: submodules: 'recursive' - name: "Install deps" - if: matrix.otp != '24' && matrix.otp != '25' run: brew update && HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install gperf doxygen erlang@${{ matrix.otp }} gleam ${{ matrix.mbedtls }} rebar3 - - name: "Install deps" - if: matrix.otp == '24' || matrix.otp == '25' - run: | - brew update - HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install gperf doxygen erlang@${{ matrix.otp }} gleam ${{ matrix.mbedtls }} - wget https://github.com/erlang/rebar3/releases/download/3.23.0/rebar3 - chmod +x rebar3 - for bin_dir in {/usr/local,/opt/homebrew}/opt/erlang@{24,25}/bin/ ; do - if [ -e ${bin_dir} ]; then - sudo cp rebar3 ${bin_dir} - fi - done - - name: "Workaround for nxdomain random issues" run: | # https://github.com/actions/runner-images/issues/8649#issuecomment-2231240347 diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index c4fdfc38bc..cedf1ae5bc 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -32,6 +32,14 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref != 'refs/heads/main' && github.ref || github.run_id }} cancel-in-progress: true +env: + DEFAULT_OTP_VERSION: "28" + DEFAULT_ELIXIR_VERSION: "1.19" + DEFAULT_REBAR3_VERSION: "3.25.1" + DEFAULT_GLEAM_VERSION: "1.11.1" + DEFAULT_CFLAGS: "-O3" + DEFAULT_CMAKE_OPTS_OTHER: "-DAVM_WARNINGS_ARE_ERRORS=ON" + jobs: build-and-test: runs-on: ${{ matrix.os || 'ubuntu-24.04' }} @@ -48,252 +56,141 @@ jobs: # Ubuntu 22.04 has clang from 12 to 15 ("clang" is 14) # Ubuntu 24.04 has clang from 14 to 18 ("clang" is 18) # We want to test every compiler but don't need to test every OS - # We only test several OTP versions with default compilers (gcc-9, 11, 13, clang-10, 14, 18) - cc: ["gcc-9", "gcc-11", "gcc-13", "clang-10", "clang-14", "clang-18"] - cflags: ["-O3"] - otp: ["25", "26", "27"] - gleam_version: ["1.11.1"] + # We only test several OTP versions with default compilers for supported OSes (gcc 11, gcc 13, clang 14, clang 18) + cc: ["gcc-11", "gcc-13", "clang-14", "clang-18"] + otp: ["26", "27", "28"] include: + ### gcc + # erlef/setup-beam officially supports ubuntu 22 and 24, we are getting + # warnings for gcc 7 and 8 that require ubuntu 20. - cc: "gcc-7" cxx: "g++-7" compiler_pkgs: "gcc-7 g++-7" container: "ubuntu:20.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" + cmake_opts_other: " " - cc: "gcc-8" cxx: "g++-8" compiler_pkgs: "gcc-8 g++-8" container: "ubuntu:20.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" + # from gcc 9 we can use ubuntu 24. - cc: "gcc-9" cxx: "g++-9" compiler_pkgs: "gcc-9 g++-9" - container: "ubuntu:20.04" - # otp: all - cc: "gcc-10" cxx: "g++-10" compiler_pkgs: "gcc-10 g++-10" - # Use Werror for recent GCC versions that have better diagnostics - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-22.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cc: "gcc-11" cxx: "g++-11" compiler_pkgs: "gcc-11 g++-11" - # Use Werror for recent GCC versions that have better diagnostics - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-22.04" # otp: all - cc: "gcc-12" cxx: "g++-12" compiler_pkgs: "gcc-12 g++-12" - # Use Werror for recent GCC versions that have better diagnostics - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-24.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cc: "gcc-13" cxx: "g++-13" compiler_pkgs: "gcc-13 g++-13" - # Use Werror for recent GCC versions that have better diagnostics - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-24.04" # otp: all - cc: "gcc-14" cxx: "g++-14" compiler_pkgs: "gcc-14 g++-14" - # Use Werror for recent GCC versions that have better diagnostics - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-24.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" + ### clang - cc: "clang-10" cxx: "clang++-10" compiler_pkgs: "clang-10" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" container: "ubuntu:20.04" - # otp: all - cc: "clang-11" cxx: "clang++-11" compiler_pkgs: "clang-11" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" container: "ubuntu:20.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" + + # from clang 12 we can use ubuntu 22 - cc: "clang-12" cxx: "clang++-12" compiler_pkgs: "clang-12" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" os: "ubuntu-22.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cc: "clang-13" cxx: "clang++-13" compiler_pkgs: "clang-13" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" os: "ubuntu-22.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cc: "clang-14" cxx: "clang++-14" compiler_pkgs: "clang-14" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-22.04" # otp: all - cc: "clang-15" cxx: "clang++-15" compiler_pkgs: "clang-15" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-24.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cc: "clang-16" cxx: "clang++-16" compiler_pkgs: "clang-16" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-24.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cc: "clang-17" cxx: "clang++-17" compiler_pkgs: "clang-17" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-24.04" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cc: "clang-18" cxx: "clang++-18" compiler_pkgs: "clang-18" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON" - os: "ubuntu-24.04" # otp: all - - otp: "25" - elixir_version: "1.14" - rebar3_version: "3.24.0" - - - otp: "26" - elixir_version: "1.17" - rebar3_version: "3.24.0" - - - otp: "27" - elixir_version: "1.18" - rebar3_version: "3.24.0" - - # Old versions of OTP/Elixir - - container: "ubuntu:20.04" - cc: "cc" + # Additional runs with older elixir + - cc: "cc" cxx: "c++" - cflags: "" - otp: "21" - elixir_version: "1.8" - rebar3_version: "3.15.2" - compiler_pkgs: "g++" + otp: "27" + elixir_version: "1.18" - - container: "ubuntu:20.04" - cc: "cc" + - cc: "cc" cxx: "c++" - cflags: "" - otp: "22" - elixir_version: "1.8" - rebar3_version: "3.18.0" - compiler_pkgs: "g++" + otp: "27" + elixir_version: "1.17" - - container: "ubuntu:20.04" - cc: "cc" + - cc: "cc" cxx: "c++" - cflags: "" - otp: "23" - elixir_version: "1.11" - rebar3_version: "3.20.0" - compiler_pkgs: "g++" + otp: "26" + elixir_version: "1.18" - - container: "ubuntu:20.04" - cc: "cc" + - cc: "cc" cxx: "c++" - cflags: "" - otp: "24" - elixir_version: "1.14" - rebar3_version: "3.23.0" - compiler_pkgs: "g++" + otp: "26" + elixir_version: "1.17" - - os: "ubuntu-24.04" - cc: "cc" + # Additional run with OTP master and default compiler + - cc: "cc" cxx: "c++" otp: "master" elixir_version: "main" - rebar3_version: "3.24.0" - - # Additional default compiler builds - - container: "ubuntu:20.04" - cc: "cc" - cxx: "c++" - cflags: "" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - compiler_pkgs: "g++" - - - os: "ubuntu-22.04" - cc: "cc" - cxx: "c++" - cflags: "" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" # Additional latest & -Os compiler builds - - os: "ubuntu-24.04" - cc: "gcc-14" + - cc: "gcc-14" cxx: "g++-14" cflags: "-Os" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" compiler_pkgs: "gcc-14 g++-14" - - os: "ubuntu-24.04" - cc: "clang-18" + - cc: "clang-18" cxx: "clang++-18" cflags: "-Os" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" compiler_pkgs: "clang-18" # Additional build with 32 bits floats - - os: "ubuntu-24.04" - cc: "cc" + - cc: "cc" cxx: "c++" - otp: "27" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cmake_opts_other: "-DAVM_USE_32BIT_FLOAT=ON" + cmake_opts_other: "-DAVM_USE_32BIT_FLOAT=ON -DAVM_WARNINGS_ARE_ERRORS=ON" + + # Additional run with -DAVM_CREATE_STACKTRACES=off + - cc: "cc" + cxx: "c++" + cmake_opts_other: "-DAVM_CREATE_STACKTRACES=off -DAVM_WARNINGS_ARE_ERRORS=ON" + + # JIT build + - cc: "cc" + cxx: "c++" + cmake_opts_other: "-DAVM_DISABLE_JIT=OFF" + jit_target_arch: "x86_64" # Additional 32 bits build - container: "ubuntu:20.04" cc: "gcc-10" cxx: "g++-10" cflags: "-m32 -O3" - otp: "23" - elixir_version: "1.11" - rebar3_version: "3.20.0" - # Use Werror so we get an error with 32 bit specific warnings cmake_opts_other: "-DAVM_CREATE_STACKTRACES=off -DAVM_WARNINGS_ARE_ERRORS=ON" arch: "i386" compiler_pkgs: "gcc-10 g++-10 gcc-10-multilib g++-10-multilib libc6-dev-i386 @@ -305,8 +202,6 @@ jobs: cxx: "c++" cflags: "" otp: "28" - elixir_version: "1.17" - rebar3_version: "3.24.0" cmake_opts_other: "-DAVM_DISABLE_JIT=OFF" jit_target_arch: "x86_64" @@ -326,46 +221,29 @@ jobs: - os: "ubuntu-24.04-arm" cc: "cc" cxx: "c++" - cflags: "-O2" - otp: "28" - elixir_version: "1.17" - rebar3_version: "3.24.0" - cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=OFF" - os: "ubuntu-24.04-arm" cc: "cc" cxx: "c++" - cflags: "" - otp: "28" - elixir_version: "1.17" - rebar3_version: "3.24.0" cmake_opts_other: "-DAVM_DISABLE_JIT=OFF" jit_target_arch: "aarch64" # armhf builds - - os: "ubuntu-24.04" - cc: "arm-linux-gnueabihf-gcc" + - cc: "arm-linux-gnueabihf-gcc" cxx: "arm-linux-gnueabihf-g++" # -D_FILE_OFFSET_BITS=64 is required for making atomvm:posix_readdir/1 test work # otherwise readdir will fail due to 64 bits inode numbers with 32 bit ino_t - cflags: "-mcpu=cortex-a7 -mfloat-abi=hard -O2 -mthumb -mthumb-interwork -D_FILE_OFFSET_BITS=64" - otp: "28" - elixir_version: "1.17" - rebar3_version: "3.24.0" + cflags: "-mcpu=cortex-a7 -mfloat-abi=hard -O3 -mthumb -mthumb-interwork -D_FILE_OFFSET_BITS=64" cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON -DCMAKE_TOOLCHAIN_FILE=${RUNNER_TEMP}/armhf_toolchain.cmake" compiler_pkgs: "crossbuild-essential-armhf libc6-dbg:armhf zlib1g-dev:armhf libmbedtls-dev:armhf qemu-user qemu-user-binfmt binfmt-support" arch: "armhf" library-arch: arm-linux-gnueabihf - - os: "ubuntu-24.04" - cc: "arm-linux-gnueabihf-gcc" + - cc: "arm-linux-gnueabihf-gcc" cxx: "arm-linux-gnueabihf-g++" # -D_FILE_OFFSET_BITS=64 is required for making atomvm:posix_readdir/1 test work # otherwise readdir will fail due to 64 bits inode numbers with 32 bit ino_t - cflags: "-mcpu=cortex-a7 -mfloat-abi=hard -O2 -mthumb -mthumb-interwork -D_FILE_OFFSET_BITS=64" - otp: "28" - elixir_version: "1.17" - rebar3_version: "3.24.0" + cflags: "-mcpu=cortex-a7 -mfloat-abi=hard -O3 -mthumb -mthumb-interwork -D_FILE_OFFSET_BITS=64" cmake_opts_other: "-DAVM_DISABLE_JIT=OFF -DAVM_JIT_TARGET_ARCH=armv6m -DCMAKE_TOOLCHAIN_FILE=${RUNNER_TEMP}/armhf_toolchain.cmake" compiler_pkgs: "crossbuild-essential-armhf libc6-dbg:armhf zlib1g-dev:armhf libmbedtls-dev:armhf qemu-user qemu-user-binfmt binfmt-support" arch: "armhf" @@ -373,15 +251,8 @@ jobs: jit_target_arch: "armv6m" # s390x build - - os: "ubuntu-24.04" - cc: "s390x-linux-gnu-gcc" + - cc: "s390x-linux-gnu-gcc" cxx: "s390x-linux-gnu-g++" - # -D_FILE_OFFSET_BITS=64 is required for making atomvm:posix_readdir/1 test work - # otherwise readdir will fail due to 64 bits inode numbers with 32 bit ino_t - cflags: "-O2" - otp: "28" - elixir_version: "1.17" - rebar3_version: "3.24.0" cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON -DCMAKE_TOOLCHAIN_FILE=${RUNNER_TEMP}/s390x_toolchain.cmake" compiler_pkgs: "crossbuild-essential-s390x libc6-dbg:s390x zlib1g-dev:s390x libmbedtls-dev:s390x qemu-user qemu-user-binfmt binfmt-support" arch: "s390x" @@ -391,10 +262,6 @@ jobs: - os: "ubuntu-24.04" cc: "riscv32-unknown-linux-gnu-gcc" cxx: "riscv32-unknown-linux-gnu-g++" - cflags: "-O2" - otp: "28" - elixir_version: "1.17" - rebar3_version: "3.24.0" cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON -DCMAKE_TOOLCHAIN_FILE=${RUNNER_TEMP}/riscv32_ilp32_toolchain.cmake" compiler_pkgs: "qemu-user qemu-user-binfmt binfmt-support" arch: "riscv32" @@ -404,10 +271,6 @@ jobs: - os: "ubuntu-24.04" cc: "riscv32-unknown-linux-gnu-gcc" cxx: "riscv32-unknown-linux-gnu-g++" - cflags: "-O2" - otp: "28" - elixir_version: "1.17" - rebar3_version: "3.24.0" cmake_opts_other: "-DAVM_DISABLE_JIT=OFF -DAVM_JIT_TARGET_ARCH=riscv32 -DCMAKE_TOOLCHAIN_FILE=${RUNNER_TEMP}/riscv32_ilp32_toolchain.cmake" compiler_pkgs: "qemu-user qemu-user-binfmt binfmt-support" arch: "riscv32" @@ -425,6 +288,13 @@ jobs: steps: # Setup + - name: "Set CFLAGS" + run: | + if [ $"CFLAGS" = "" ]; then + echo "CFLAGS=$DEFAULT_CFLAGS" >> $GITHUB_ENV + echo "CXXFLAGS=$DEFAULT_CFLAGS" >> $GITHUB_ENV + fi + - name: "Install deps for containers" if: matrix.container != '' run: apt-get update && apt-get install -y --no-install-recommends sudo unzip git tzdata @@ -578,13 +448,28 @@ jobs: with: submodules: 'recursive' + # There is no working arm64 binary for gleam + # https://github.com/erlef/setup-beam/issues/398 - uses: erlef/setup-beam@v1 + if: matrix.os != 'ubuntu-24.04-arm' with: version-type: ${{ matrix.version_type || 'loose' }} - otp-version: ${{ matrix.otp }} - elixir-version: ${{ matrix.elixir_version }} - rebar3-version: ${{ matrix.rebar3_version }} - gleam-version: ${{ matrix.gleam_version }} + otp-version: ${{ matrix.otp || env.DEFAULT_OTP_VERSION }} + elixir-version: ${{ matrix.elixir_version || env.DEFAULT_ELIXIR_VERSION }} + rebar3-version: ${{ matrix.rebar3_version || env.DEFAULT_REBAR3_VERSION }} + gleam-version: ${{ matrix.gleam_version || env.DEFAULT_GLEAM_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://repo.hex.pm + https://cdn.jsdelivr.net/hex + + - uses: erlef/setup-beam@v1 + if: matrix.os == 'ubuntu-24.04-arm' + with: + version-type: ${{ matrix.version_type || 'loose' }} + otp-version: ${{ matrix.otp || env.DEFAULT_OTP_VERSION }} + elixir-version: ${{ matrix.elixir_version || env.DEFAULT_ELIXIR_VERSION }} + rebar3-version: ${{ matrix.rebar3_version || env.DEFAULT_REBAR3_VERSION }} hexpm-mirrors: | https://builds.hex.pm https://repo.hex.pm @@ -600,6 +485,8 @@ jobs: echo "**C Compiler version:**" $CC --version $CXX --version + echo "**CFLAGS:**" + echo $CFLAGS echo "**Linker version:**" ld --version echo "**CMake version:**" @@ -615,12 +502,12 @@ jobs: id: cache with: path: 'build/tests/**/*.beam' - key: ${{ matrix.otp }}-${{ hashFiles('**/build-and-test.yaml', 'tests/**/*.erl', 'tests/**/*.hrl', 'tests/**/*.ex') }}-${{ matrix.jit_target_arch || 'nojit' }} + key: ${{ matrix.otp || env.DEFAULT_OTP_VERSION }}-${{ hashFiles('**/build-and-test.yaml', 'tests/**/*.erl', 'tests/**/*.hrl', 'tests/**/*.ex') }}-${{ matrix.jit_target_arch || 'nojit' }} - name: "Build: run cmake" working-directory: build run: | - cmake ${{ matrix.cmake_opts_fp }} ${{ matrix.cmake_opts_smp }} ${{ matrix.cmake_opts_other }} .. + cmake ${{ matrix.cmake_opts_fp }} ${{ matrix.cmake_opts_smp }} ${{ matrix.cmake_opts_other || env.DEFAULT_CMAKE_OPTS_OTHER }} .. # git clone will use more recent timestamps than cached beam files # touch them so we can benefit from the cache and avoid costly beam file rebuild. find . -name '*.beam' -exec touch {} \; @@ -762,7 +649,7 @@ jobs: ./src/AtomVM ./tests/libs/eavmlib/test_eavmlib.avm - name: "Test: test_jit.avm with valgrind" - if: matrix.library-arch == '' && matrix.otp != '21' && matrix.otp != '22' + if: matrix.library-arch == '' timeout-minutes: 60 working-directory: build run: | @@ -771,7 +658,6 @@ jobs: - name: "Test: test_jit.avm" timeout-minutes: 60 - if: matrix.otp != '21' && matrix.otp != '22' working-directory: build run: | ulimit -c unlimited @@ -853,7 +739,7 @@ jobs: uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: core-${{ matrix.os }}-${{ matrix.cc }}-${{ matrix.otp }}-${{ github.run_id }}-${{ github.run_attempt }} + name: core-${{ matrix.os }}-${{ matrix.cc }}-${{ matrix.otp || env.DEFAULT_OTP_VERSION }}-${{ github.run_id }}-${{ github.run_attempt }} path: | core/* retention-days: 5 diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index b6b744d623..8ff728d336 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -55,7 +55,18 @@ jobs: run: sudo apt update -y - name: "Install deps" - run: sudo apt install -y cmake gperf zlib1g-dev ninja-build erlang rebar3 + run: sudo apt install -y cmake gperf zlib1g-dev ninja-build + + - uses: erlef/setup-beam@v1 + with: + otp-version: "28" + elixir-version: "1.19" + rebar3-version: "3.25.1" + gleam-version: "1.11.1" + hexpm-mirrors: | + https://builds.hex.pm + https://repo.hex.pm + https://cdn.jsdelivr.net/hex - name: "Checkout repository" uses: actions/checkout@v4 diff --git a/.github/workflows/run-tests-with-beam.yaml b/.github/workflows/run-tests-with-beam.yaml index 40f206c05c..e3faa4c71e 100644 --- a/.github/workflows/run-tests-with-beam.yaml +++ b/.github/workflows/run-tests-with-beam.yaml @@ -40,34 +40,6 @@ jobs: fail-fast: false matrix: include: - - os: "ubuntu-24.04" - test_erlang_opts: "-s prime_smp" - container: erlang:21 - otp: "21" - archive: "true" - - - os: "ubuntu-24.04" - test_erlang_opts: "-s prime_smp" - container: erlang:22 - otp: "22" - archive: "true" - - - os: "ubuntu-24.04" - test_erlang_opts: "-s prime_smp" - container: erlang:23 - otp: "23" - archive: "true" - - - os: "ubuntu-24.04" - test_erlang_opts: "-s prime_smp" - otp: "24" - container: erlang:24 - - - os: "ubuntu-24.04" - test_erlang_opts: "-s prime_smp" - otp: "25" - container: erlang:25 - - os: "ubuntu-24.04" test_erlang_opts: "-s prime_smp" otp: "26" diff --git a/CHANGELOG.md b/CHANGELOG.md index 74deb1433c..7c565808e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,6 +115,7 @@ table. - ESP32 ports now flash a complete working image using the `idf.py flash` task. - ESP32 platform now uses reproducible builds. - C API: `externalterm` module was renamed to `external_term` and it has a completely new API +- Removed support for OTP versions < 26 ### Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index b950dc3f5b..2407dfa858 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,6 @@ find_package(Erlang) find_package(Elixir) find_package(Gleam) -option(AVM_ENABLE_OLD_OTP_VERSIONS "Enable OTP version < 26" ON) option(AVM_DISABLE_FP "Disable floating point support." OFF) option(AVM_DISABLE_SMP "Disable SMP." OFF) option(AVM_DISABLE_TASK_DRIVER "Disable task driver support." OFF) @@ -43,11 +42,6 @@ option(COVERAGE "Build for code coverage" OFF) option(AVM_PRINT_PROCESS_CRASH_DUMPS "Print crash reports when processes die with non-standard reasons" ON) # JIT & execution of precompiled code -if(NOT Erlang_VERSION VERSION_GREATER_EQUAL "23") - if (NOT AVM_DISABLE_JIT) - message(FATAL "JIT compiler cannot be compiled by OTP < 23") - endif() -endif() if(NOT Erlang_VERSION VERSION_GREATER_EQUAL "28") if (NOT AVM_DISABLE_JIT) message(WARNING "JIT compiler currently only supports opcodes generated by OTP28") diff --git a/doc/release-notes.md.in b/doc/release-notes.md.in index 7a8b5b92a6..aa2d5cbd8e 100644 --- a/doc/release-notes.md.in +++ b/doc/release-notes.md.in @@ -27,14 +27,13 @@ AtomVM will run BEAM files that have been compiled using the following Erlang an | Erlang Version | Elixir Version | |----------------|----------------| -| ✅ OTP 21 | ✅ 1.7 | -| ✅ OTP 22 | ✅ 1.8 | -| ✅ OTP 23 | ✅ 1.11 | -| ✅ OTP 24 | ✅ 1.14 | -| ✅ OTP 25 | ✅ 1.14 | -| ✅ OTP 26 | ✅ 1.15 | +| ✅ OTP 26 | ✅ 1.17 | +| ✅ OTP 26 | ✅ 1.18 | +| ✅ OTP 26 | ✅ 1.19 | | ✅ OTP 27 | ✅ 1.17 | -| ✅ OTP 28 | ✅ 1.17 | +| ✅ OTP 27 | ✅ 1.18 | +| ✅ OTP 27 | ✅ 1.19 | +| ✅ OTP 28 | ✅ 1.19 | | ✅ OTP 29 | ✅ 1.19 | ```{note} diff --git a/doc/src/differences-with-beam.md b/doc/src/differences-with-beam.md index 952bb837c9..687af7ee04 100644 --- a/doc/src/differences-with-beam.md +++ b/doc/src/differences-with-beam.md @@ -219,8 +219,8 @@ Ports are also executed by the schedulers and should return quickly. ### BEAM file compatibility -AtomVM can run BEAM files generated by `erlc` compiler from OTP21 to the latest master version, -while BEAM cannot and often requires to recompile. +AtomVM can run BEAM files generated by `erlc` compiler from the latest three releases, even in +cases where latest BEAM would require a recompile. ### Stacktraces and exceptions diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index a7173df44d..278d779132 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -27,10 +27,7 @@ add_subdirectory(alisp/src) add_subdirectory(etest/src) add_subdirectory(esp32boot) add_subdirectory(esp32devmode/src) -# JIT compiler doesn't compile with OTP < 23 -if(Erlang_VERSION VERSION_GREATER_EQUAL "23") - add_subdirectory(jit/src) -endif() +add_subdirectory(jit/src) set(ATOMVM_LIBS eavmlib estdlib alisp) @@ -84,9 +81,7 @@ if (Dialyzer_FOUND) ${CMAKE_CURRENT_BINARY_DIR}/eavmlib_beams.txt ${CMAKE_CURRENT_BINARY_DIR}/alisp_beams.txt ) - if(Erlang_VERSION VERSION_GREATER_EQUAL "23") - set(dialyzer_lists ${dialyzer_lists} ${CMAKE_CURRENT_BINARY_DIR}/jit_beams.txt) - endif() + set(dialyzer_lists ${dialyzer_lists} ${CMAKE_CURRENT_BINARY_DIR}/jit_beams.txt) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/atomvmlib.plt DEPENDS ${dialyzer_lists} diff --git a/libs/estdlib/src/dist_util.erl b/libs/estdlib/src/dist_util.erl index 52e59d7bad..5767632fcb 100644 --- a/libs/estdlib/src/dist_util.erl +++ b/libs/estdlib/src/dist_util.erl @@ -47,9 +47,8 @@ % Required include headers -include_lib("kernel/include/dist_util.hrl"). -% Because this module can be compiled with OTP21 headers, we need to define -% flags that we support and that OTP-21 doesn't know. For this reason, we don't -% include dist.hrl but instead define the flags here. +% We don't include dist.hrl but instead define the flags here, so they are +% available regardless of the OTP version used to compile this module. % OTP-21: -define(DFLAG_PUBLISHED, 1). diff --git a/src/libAtomVM/CMakeLists.txt b/src/libAtomVM/CMakeLists.txt index 8fdb354b65..c116e990d7 100644 --- a/src/libAtomVM/CMakeLists.txt +++ b/src/libAtomVM/CMakeLists.txt @@ -199,12 +199,6 @@ if(AVM_SELECT_IN_TASK) target_compile_definitions(libAtomVM PUBLIC AVM_SELECT_IN_TASK) endif() -# Start phasing out old OTP versions -if(NOT AVM_ENABLE_OLD_OTP_VERSIONS) -target_compile_definitions(libAtomVM PUBLIC MINIMUM_OTP_COMPILER_VERSION=26) -target_compile_definitions(libAtomVM PUBLIC MAXIMUM_OTP_COMPILER_VERSION=29) -endif() - include(CheckIncludeFile) CHECK_INCLUDE_FILE(stdatomic.h STDATOMIC_INCLUDE) include(CheckCSourceCompiles) diff --git a/src/libAtomVM/opcodesswitch.h b/src/libAtomVM/opcodesswitch.h index ab78fb8392..6d090683bf 100644 --- a/src/libAtomVM/opcodesswitch.h +++ b/src/libAtomVM/opcodesswitch.h @@ -50,7 +50,7 @@ // These constants can be used to reduce the size of the VM for a specific // range of compiler versions #ifndef MINIMUM_OTP_COMPILER_VERSION -#define MINIMUM_OTP_COMPILER_VERSION 21 +#define MINIMUM_OTP_COMPILER_VERSION 26 #endif #ifndef MAXIMUM_OTP_COMPILER_VERSION #define MAXIMUM_OTP_COMPILER_VERSION 29 @@ -2690,36 +2690,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } -#if MINIMUM_OTP_COMPILER_VERSION <= 23 - case OP_ALLOCATE_HEAP_ZERO: { - uint32_t stack_need; - DECODE_LITERAL(stack_need, pc); - uint32_t heap_need; - DECODE_ALLOCATOR_LIST(heap_need, pc); - uint32_t live; - DECODE_LITERAL(live, pc); - TRACE("allocate_heap_zero/3 stack_need=%i, heap_need=%i, live=%i\n", stack_need, heap_need, live); - USED_BY_TRACE(stack_need); - USED_BY_TRACE(heap_need); - USED_BY_TRACE(live); - - #ifdef IMPL_EXECUTE_LOOP - if (ctx->heap.root->next || ((ctx->heap.heap_ptr + heap_need) > ctx->e - (stack_need + 1))) { - TRIM_LIVE_REGS(live); - if (UNLIKELY(memory_ensure_free_with_roots(ctx, heap_need + stack_need + 1, live, x_regs, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - } - ctx->e -= stack_need + 1; - for (uint32_t s = 0; s < stack_need; s++) { - ctx->e[s] = term_nil(); - } - ctx->e[stack_need] = ctx->cp; - #endif - break; - } -#endif - case OP_TEST_HEAP: { uint32_t heap_need; DECODE_ALLOCATOR_LIST(heap_need, pc); @@ -3713,45 +3683,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } -#if MINIMUM_OTP_COMPILER_VERSION <= 21 - case OP_PUT_TUPLE: { - uint32_t size; - DECODE_LITERAL(size, pc); - - #ifdef IMPL_EXECUTE_LOOP - term t = term_alloc_tuple(size, &ctx->heap); - #endif - - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - - TRACE("put_tuple/2 size=%u, dest=%c%i\n", (unsigned) size, T_DEST_REG(dreg)); - - #ifdef IMPL_EXECUTE_LOOP - WRITE_REGISTER(dreg, t); - #endif - - for (uint32_t j = 0; j < size; j++) { - if (*pc++ != OP_PUT) { - fprintf(stderr, "Expected put, got opcode: %i\n", pc[-1]); - AVM_ABORT(); - } - term put_value; - DECODE_COMPACT_TERM(put_value, pc); - #ifdef IMPL_CODE_LOADER - TRACE("put/2\n"); - UNUSED(put_value); - #endif - - #ifdef IMPL_EXECUTE_LOOP - TRACE("put/2 elem=%i, value=0x%" TERM_X_FMT "\n", j, put_value); - term_put_tuple_element(t, j, put_value); - #endif - } - break; - } -#endif - case OP_BADMATCH: { term arg1; DECODE_COMPACT_TERM(arg1, pc) @@ -4176,163 +4107,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } -#if MINIMUM_OTP_COMPILER_VERSION <= 24 - case OP_BS_INIT2: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term size; - DECODE_COMPACT_TERM(size, pc) - uint32_t words; - DECODE_LITERAL(words, pc) - uint32_t live; - DECODE_LITERAL(live, pc) - term flags; - UNUSED(flags); - DECODE_COMPACT_TERM(flags, pc) - - #ifdef IMPL_CODE_LOADER - TRACE("bs_init2/6\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_INTEGER(size, "bs_init2", 0); - avm_int_t size_val = term_to_int(size); - - TRIM_LIVE_REGS(live); - if (UNLIKELY(memory_ensure_free_with_roots(ctx, words + term_binary_heap_size(size_val), live, x_regs, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - term t = term_create_empty_binary(size_val, &ctx->heap, ctx->global); - if (UNLIKELY(term_is_invalid_term(t))) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - - ctx->bs = t; - ctx->bs_offset = 0; - #endif - - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - - #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_init2/6, fail=%u size=" AVM_INT_FMT " words=%u live=%u dreg=%c%i\n", (unsigned) fail, size_val, (unsigned) words, (unsigned) live, T_DEST_REG(dreg)); - WRITE_REGISTER(dreg, t); - #endif - break; - } - - case OP_BS_INIT_BITS: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term size; - DECODE_COMPACT_TERM(size, pc) - uint32_t words; - DECODE_LITERAL(words, pc) - uint32_t live; - DECODE_LITERAL(live, pc) - uint32_t flags_value; - DECODE_LITERAL(flags_value, pc) - - #ifdef IMPL_CODE_LOADER - TRACE("bs_init_bits/6\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_INTEGER(size, "bs_init_bits", 0); - avm_int_t size_val = term_to_int(size); - if (size_val % 8 != 0) { - TRACE("bs_init_bits: size_val (" AVM_INT_FMT ") is not evenly divisible by 8\n", size_val); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - if (flags_value != 0) { - TRACE("bs_init_bits: neither signed nor native or little endian encoding supported.\n"); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - - TRIM_LIVE_REGS(live); - if (UNLIKELY(memory_ensure_free_with_roots(ctx, words + term_binary_heap_size(size_val / 8), live, x_regs, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - term t = term_create_empty_binary(size_val / 8, &ctx->heap, ctx->global); - if (UNLIKELY(term_is_invalid_term(t))) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - - ctx->bs = t; - ctx->bs_offset = 0; - #endif - - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - - #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_init_bits/6, fail=%i size=" AVM_INT_FMT " words=%i live=%u dreg=%c%i\n", fail, size_val, words, (unsigned) live, T_DEST_REG(dreg)); - WRITE_REGISTER(dreg, t); - #endif - break; - } - - case OP_BS_UTF8_SIZE: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term src; - DECODE_COMPACT_TERM(src, pc) - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - #ifdef IMPL_CODE_LOADER - TRACE("bs_utf8_size/3\n"); - #endif - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_INTEGER(src, "bs_utf8_size/3", 0); - avm_int_t src_value = term_to_int(src); - TRACE("bs_utf8_size/3 fail=%i src=0x%lx dreg=%c%i\n", fail, (long) src_value, T_DEST_REG(dreg)); - size_t utf8_size; - if (UNLIKELY(!bitstring_utf8_size(src_value, &utf8_size))) { - RAISE_ERROR(BADARG_ATOM); - } - WRITE_REGISTER(dreg, term_from_int(utf8_size)); - #endif - break; - } - - case OP_BS_PUT_UTF8: { - uint32_t fail; - DECODE_LABEL(fail, pc) - uint32_t flags; - DECODE_LITERAL(flags, pc) - term src; - DECODE_COMPACT_TERM(src, pc) - #ifdef IMPL_CODE_LOADER - TRACE("bs_put_utf8/3 flags=%x\n", (int) flags); - if (flags != 0) { - fprintf(stderr, "bs_put_utf8/3 : unsupported flags %x\n", (int) flags); - AVM_ABORT(); - } - #endif - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_INTEGER(src, "bs_put_utf8/3", 0); - avm_int_t src_value = term_to_int(src); - TRACE("bs_put_utf8/3 flags=%x, src=0x%lx\n", (int) flags, (long) src_value); - if (UNLIKELY(!term_is_binary(ctx->bs))) { - TRACE("bs_put_utf8/3: Bad state. ctx->bs is not a binary.\n"); - RAISE_ERROR(BADARG_ATOM); - } - if (ctx->bs_offset % 8 != 0) { - TRACE("bs_put_utf8/3: Unsupported bit syntax operation. Writing strings must be byte-aligend.\n"); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - size_t byte_size; - bool result = bitstring_insert_utf8(ctx->bs, ctx->bs_offset, src_value, &byte_size); - if (UNLIKELY(!result)) { - TRACE("bs_put_utf8/3: Failed to insert character as utf8 into binary: %i\n", result); - RAISE_ERROR(BADARG_ATOM); - } - ctx->bs_offset += byte_size * 8; - #endif - break; - } -#endif - case OP_BS_GET_UTF8: { uint32_t fail; DECODE_LABEL(fail, pc) @@ -4398,679 +4172,184 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) size_t out_size = 0; bool is_valid = bitstring_match_utf8(src_bin, (size_t) offset_bits, &c, &out_size); - if (!is_valid) { - pc = mod->labels[fail]; - } else { - term_set_match_state_offset(src, offset_bits + (out_size * 8)); - } - #endif - - break; - } - -#if MINIMUM_OTP_COMPILER_VERSION <= 24 - case OP_BS_UTF16_SIZE: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term src; - DECODE_COMPACT_TERM(src, pc) - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - #ifdef IMPL_CODE_LOADER - TRACE("bs_utf16_size/3\n"); - #endif - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_INTEGER(src, "bs_utf16_size/3", 0); - avm_int_t src_value = term_to_int(src); - TRACE("bs_utf16_size/3 fail=%i src=0x%lx dreg=%c%i\n", fail, (long) src_value, T_DEST_REG(dreg)); - size_t utf16_size; - if (UNLIKELY(!bitstring_utf16_size(src_value, &utf16_size))) { - RAISE_ERROR(BADARG_ATOM); - } - WRITE_REGISTER(dreg, term_from_int(utf16_size)); - #endif - break; - } - - case OP_BS_PUT_UTF16: { - uint32_t fail; - DECODE_LABEL(fail, pc) - uint32_t flags; - DECODE_LITERAL(flags, pc) - term src; - DECODE_COMPACT_TERM(src, pc) - #ifdef IMPL_CODE_LOADER - TRACE("bs_put_utf16/3 flags=%x\n", (int) flags); - if (flags != 0 && flags != LittleEndianInteger && flags != NativeEndianInteger) { - fprintf(stderr, "bs_put_utf16/3 : unsupported flags %x\n", (int) flags); - AVM_ABORT(); - } - #endif - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_INTEGER(src, "bs_put_utf16/3", 0); - avm_int_t src_value = term_to_int(src); - TRACE("bs_put_utf16/3 flags=%x, src=" AVM_INT_FMT "\n", (int) flags, src_value); - if (UNLIKELY(!term_is_binary(ctx->bs))) { - TRACE("bs_put_utf16: Bad state. ctx->bs is not a binary.\n"); - RAISE_ERROR(BADARG_ATOM); - } - if (ctx->bs_offset % 8 != 0) { - TRACE("bs_put_utf16: Unsupported bit syntax operation. Writing strings must be byte-aligend.\n"); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - size_t byte_size; - bool result = bitstring_insert_utf16(ctx->bs, ctx->bs_offset, src_value, flags, &byte_size); - if (UNLIKELY(!result)) { - TRACE("bs_put_utf8/3: Failed to insert character as utf8 into binary: %i\n", result); - RAISE_ERROR(BADARG_ATOM); - } - ctx->bs_offset += byte_size * 8; - #endif - break; - } -#endif - - case OP_BS_GET_UTF16: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term src; - DECODE_COMPACT_TERM(src, pc); - term arg2; - DECODE_COMPACT_TERM(arg2, pc); - uint32_t flags_value; - DECODE_LITERAL(flags_value, pc); - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - - #ifdef IMPL_CODE_LOADER - TRACE("bs_get_utf16/5\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_get_utf16/5, fail=%i src=0x%" TERM_X_FMT " arg2=0x%" TERM_X_FMT " flags=0x%"PRIu32" dreg=%c%i\n", fail, src, arg2, flags_value, T_DEST_REG(dreg)); - - assert(term_is_match_state(src)); - - term src_bin = term_get_match_state_binary(src); - avm_int_t offset_bits = term_get_match_state_offset(src); - - int32_t val = 0; - size_t out_size = 0; - bool is_valid = bitstring_match_utf16(src_bin, (size_t) offset_bits, &val, &out_size, flags_value); - - if (!is_valid) { - pc = mod->labels[fail]; - } else { - term_set_match_state_offset(src, offset_bits + (out_size * 8)); - WRITE_REGISTER(dreg, term_from_int(val)); - } - #endif - - break; - } - - case OP_BS_SKIP_UTF16: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term src; - DECODE_COMPACT_TERM(src, pc); - term arg2; - DECODE_COMPACT_TERM(arg2, pc); - uint32_t flags_value; - DECODE_LITERAL(flags_value, pc); - - #ifdef IMPL_CODE_LOADER - TRACE("bs_skip_utf16/5\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_skip_utf16/5, fail=%i src=0x%" TERM_X_FMT " arg2=0x%" TERM_X_FMT " flags=0x%" TERM_X_FMT "\n", fail, src, arg2, flags); - - assert(term_is_match_state(src)); - - term src_bin = term_get_match_state_binary(src); - avm_int_t offset_bits = term_get_match_state_offset(src); - - int32_t val = 0; - size_t out_size = 0; - bool is_valid = bitstring_match_utf16(src_bin, (size_t) offset_bits, &val, &out_size, flags_value); - - if (!is_valid) { - pc = mod->labels[fail]; - } else { - term_set_match_state_offset(src, offset_bits + (out_size * 8)); - } - #endif - - break; - } - -#if MINIMUM_OTP_COMPILER_VERSION <= 24 - case OP_BS_PUT_UTF32: { - uint32_t fail; - DECODE_LABEL(fail, pc) - uint32_t flags; - DECODE_LITERAL(flags, pc) - term src; - DECODE_COMPACT_TERM(src, pc) - #ifdef IMPL_CODE_LOADER - TRACE("bs_put_utf32/3 flags=%x\n", (int) flags); - if (flags != 0 && flags != LittleEndianInteger && flags != NativeEndianInteger) { - fprintf(stderr, "bs_put_utf32/3 : unsupported flags %x\n", (int) flags); - AVM_ABORT(); - } - #endif - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_INTEGER(src, "bs_put_utf32/3", 0); - avm_int_t src_value = term_to_int(src); - TRACE("bs_put_utf32/3 flags=%x, src=" AVM_INT_FMT "\n", (int) flags, src_value); - if (UNLIKELY(!term_is_binary(ctx->bs))) { - TRACE("bs_put_utf32/3: Bad state. ctx->bs is not a binary.\n"); - RAISE_ERROR(BADARG_ATOM); - } - if (ctx->bs_offset % 8 != 0) { - TRACE("bs_put_utf32/3: Unsupported bit syntax operation. Writing strings must be byte-aligend.\n"); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - bool result = bitstring_insert_utf32(ctx->bs, ctx->bs_offset, src_value, flags); - if (UNLIKELY(!result)) { - TRACE("bs_put_utf32/3: Failed to insert integer into binary: %i\n", result); - RAISE_ERROR(BADARG_ATOM); - } - ctx->bs_offset += 4 * 8; - #endif - break; - } -#endif - - case OP_BS_GET_UTF32: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term src; - DECODE_COMPACT_TERM(src, pc); - term arg2; - DECODE_COMPACT_TERM(arg2, pc); - uint32_t flags_value; - DECODE_LITERAL(flags_value, pc); - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - - #ifdef IMPL_CODE_LOADER - TRACE("bs_get_utf32/5\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_get_utf32/5, fail=%i src=0x%" TERM_X_FMT " arg2=0x%" TERM_X_FMT " flags=0x%"PRIu32" dreg=%c%i\n", fail, src, arg2, flags_value, T_DEST_REG(dreg)); - - assert(term_is_match_state(src)); - - term src_bin = term_get_match_state_binary(src); - avm_int_t offset_bits = term_get_match_state_offset(src); - - int32_t val = 0; - bool is_valid = bitstring_match_utf32(src_bin, (size_t) offset_bits, &val, flags_value); - - if (!is_valid) { - pc = mod->labels[fail]; - } else { - term_set_match_state_offset(src, offset_bits + 32); - WRITE_REGISTER(dreg, term_from_int(val)); - } - #endif - - break; - } - - case OP_BS_SKIP_UTF32: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term src; - DECODE_COMPACT_TERM(src, pc); - term arg2; - DECODE_COMPACT_TERM(arg2, pc); - uint32_t flags_value; - DECODE_LITERAL(flags_value, pc); - - #ifdef IMPL_CODE_LOADER - TRACE("bs_skip_utf32/5\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_skip_utf32/5, fail=%i src=0x%" TERM_X_FMT " arg2=0x%" TERM_X_FMT " flags=0x%" TERM_X_FMT "\n", fail, src, arg2, flags); - - assert(term_is_match_state(src)); - - term src_bin = term_get_match_state_binary(src); - avm_int_t offset_bits = term_get_match_state_offset(src); - - int32_t val = 0; - bool is_valid = bitstring_match_utf32(src_bin, (size_t) offset_bits, &val, flags_value); - - if (!is_valid) { - pc = mod->labels[fail]; - } else { - term_set_match_state_offset(src, offset_bits + 32); - } - #endif - - break; - } - - case OP_BS_INIT_WRITABLE: { - - TRACE("bs_init_writable/0\n"); - - #ifdef IMPL_EXECUTE_LOOP - if (UNLIKELY(memory_ensure_free_opt(ctx, term_binary_heap_size(0), MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - term t = term_create_empty_binary(0, &ctx->heap, ctx->global); - if (UNLIKELY(term_is_invalid_term(t))) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - - ctx->bs = t; - ctx->bs_offset = 0; - x_regs[0] = t; - #endif - break; - } - -#if MINIMUM_OTP_COMPILER_VERSION <= 24 - case OP_BS_APPEND: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term size; - DECODE_COMPACT_TERM(size, pc) - term extra; - UNUSED(extra); - DECODE_COMPACT_TERM(extra, pc) - uint32_t live; - UNUSED(live); - DECODE_LITERAL(live, pc); - uint32_t unit; - DECODE_LITERAL(unit, pc); - term src; - DECODE_COMPACT_TERM(src, pc) - term flags; - UNUSED(flags); - DECODE_COMPACT_TERM(flags, pc) - - #ifdef IMPL_CODE_LOADER - TRACE("bs_append/8\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_BINARY(src, "bs_append", 0); - VERIFY_IS_INTEGER(size, "bs_append", 0); - VERIFY_IS_INTEGER(extra, "bs_append", 0); - avm_int_t size_val = term_to_int(size); - avm_int_t extra_val = term_to_int(extra); - - if (size_val % 8 != 0) { - TRACE("bs_append: size_val (" AVM_INT_FMT ") is not evenly divisible by 8\n", size_val); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - if (unit != 8) { - TRACE("bs_append: unit is not equal to 8; unit=%u\n", (unsigned) unit); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - - size_t src_size = term_binary_size(src); - TRIM_LIVE_REGS(live); - // there is always room for a MAX_REG + 1 register, used as working register - x_regs[live] = src; - // TODO: further investigate extra_val - if (UNLIKELY(memory_ensure_free_with_roots(ctx, src_size + term_binary_heap_size(size_val / 8) + extra_val, live + 1, x_regs, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - #endif - - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - - #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_append/8, fail=%u size=" AVM_INT_FMT " unit=%u src=0x%" TERM_X_FMT " dreg=%c%i\n", (unsigned) fail, size_val, (unsigned) unit, src, T_DEST_REG(dreg)); - src = x_regs[live]; - term t = term_create_empty_binary(src_size + size_val / 8, &ctx->heap, ctx->global); - if (UNLIKELY(term_is_invalid_term(t))) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - memcpy((void *) term_binary_data(t), (void *) term_binary_data(src), src_size); - - ctx->bs = t; - ctx->bs_offset = src_size * 8; - - WRITE_REGISTER(dreg, t); - #endif - break; - } - - case OP_BS_PRIVATE_APPEND: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term size; - DECODE_COMPACT_TERM(size, pc) - uint32_t unit; - DECODE_LITERAL(unit, pc); - term src; - #ifdef IMPL_EXECUTE_LOOP - const uint8_t *src_pc = pc; - #endif - DECODE_COMPACT_TERM(src, pc) - term flags; - UNUSED(flags); - DECODE_COMPACT_TERM(flags, pc) - - #ifdef IMPL_CODE_LOADER - TRACE("bs_private_append/6\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_BINARY(src, "bs_private_append", 0); - VERIFY_IS_INTEGER(size, "bs_private_append", 0); - avm_int_t size_val = term_to_int(size); - - if (size_val % 8 != 0) { - TRACE("bs_private_append: size_val (%li) is not evenly divisible by 8\n", (long int) size_val); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - // TODO: further investigate unit. - // We currently do not support unaligned binaries, unit seems to be equal to 1 binary comprehensions - size_t src_size = term_binary_size(src); - if (UNLIKELY(memory_ensure_free_opt(ctx, src_size + term_binary_heap_size(size_val / 8), MEMORY_NO_GC) != MEMORY_GC_OK)) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - DECODE_COMPACT_TERM(src, src_pc) - term t = term_reuse_binary(src, src_size + size_val / 8, &ctx->heap, ctx->global); - if (UNLIKELY(term_is_invalid_term(t))) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - - ctx->bs = t; - ctx->bs_offset = src_size * 8; - #endif - - DEST_REGISTER(dreg); - DECODE_DEST_REGISTER(dreg, pc); - - #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_private_append/6, fail=%u size=" AVM_INT_FMT " unit=%u src=0x%" TERM_X_FMT " dreg=%c%i\n", (unsigned) fail, size_val, (unsigned) unit, src, T_DEST_REG(dreg)); - WRITE_REGISTER(dreg, t); - #endif - break; - } - - case OP_BS_PUT_INTEGER: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term size; - DECODE_COMPACT_TERM(size, pc) - uint32_t unit; - DECODE_LITERAL(unit, pc); - uint32_t flags_value; - DECODE_LITERAL(flags_value, pc) - term src; - DECODE_COMPACT_TERM(src, pc); - - #ifdef IMPL_CODE_LOADER - TRACE("bs_put_integer/5\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_ANY_INTEGER(src, "bs_put_integer", 0); - VERIFY_IS_INTEGER(size, "bs_put_integer", 0); - - avm_int_t size_value = term_to_int(size); - - if (term_is_int(src) - || term_boxed_size(src) <= BOXED_TERMS_REQUIRED_FOR_INT64) { - avm_int64_t src_value = term_maybe_unbox_int64(src); - - TRACE("bs_put_integer/5, fail=%u size=" AVM_INT_FMT - " unit=%u flags=%x src=%i\n", - (unsigned) fail, size_value, (unsigned) unit, (int) flags_value, - (unsigned int) src_value); - - bool result = bitstring_insert_integer( - ctx->bs, ctx->bs_offset, src_value, size_value * unit, flags_value); - if (UNLIKELY(!result)) { - TRACE("bs_put_integer: Failed to insert integer into binary\n"); - RAISE_ERROR(BADARG_ATOM); - } - } else { - const intn_digit_t *big_src_value = NULL; - size_t big_len = 0; - intn_integer_sign_t big_sign; - - term_to_bigint(src, &big_src_value, &big_len, &big_sign); - - // when building a binary, `signed` flag is implicit - intn_from_integer_options_t intn_flags - = bitstring_flags_to_intn_opts(flags_value); - int byte_offset = ctx->bs_offset / 8; - uint8_t *dst = (uint8_t *) term_binary_data(ctx->bs) + byte_offset; - size_t t_capacity = term_binary_size(ctx->bs); - size_t avail = t_capacity - byte_offset; - - int written = intn_to_integer_bytes( - big_src_value, big_len, big_sign, intn_flags, dst, avail); - if (UNLIKELY(written < 0)) { - TRACE("bs_create_bin/6: Failed to insert integer into " - "binary\n"); - RAISE_ERROR(BADARG_ATOM); - } - } - - ctx->bs_offset += size_value * unit; + if (!is_valid) { + pc = mod->labels[fail]; + } else { + term_set_match_state_offset(src, offset_bits + (out_size * 8)); + } #endif + break; } - case OP_BS_PUT_BINARY: { + case OP_BS_GET_UTF16: { uint32_t fail; DECODE_LABEL(fail, pc) - term size; - DECODE_COMPACT_TERM(size, pc) - uint32_t unit; - DECODE_LITERAL(unit, pc); - uint32_t flags_value; - DECODE_LITERAL(flags_value, pc) term src; DECODE_COMPACT_TERM(src, pc); + term arg2; + DECODE_COMPACT_TERM(arg2, pc); + uint32_t flags_value; + DECODE_LITERAL(flags_value, pc); + DEST_REGISTER(dreg); + DECODE_DEST_REGISTER(dreg, pc); #ifdef IMPL_CODE_LOADER - TRACE("bs_put_binary/5\n"); + TRACE("bs_get_utf16/5\n"); #endif #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_BINARY(src, "bs_put_binary", 0); - unsigned long size_val = 0; - if (term_is_integer(size)) { - avm_int_t bit_size = term_to_int(size) * unit; - if (bit_size % 8 != 0) { - TRACE("bs_put_binary: Bit size must be evenly divisible by 8.\n"); - RAISE_ERROR(UNSUPPORTED_ATOM); - } - size_val = bit_size / 8; - } else if (size == ALL_ATOM) { - size_val = term_binary_size(src); - } else { - TRACE("bs_put_binary: Unsupported size term type in put binary: %p\n", (void *) size); - RAISE_ERROR(BADARG_ATOM); - } - if (size_val > term_binary_size(src)) { - TRACE("bs_put_binary: binary data size (%li) larger than source binary size (%li)\n", size_val, term_binary_size(src)); - RAISE_ERROR(BADARG_ATOM); - } - if (flags_value != 0) { - TRACE("bs_put_binary: neither signed nor native or little endian encoding supported.\n"); - RAISE_ERROR(UNSUPPORTED_ATOM); - } + TRACE("bs_get_utf16/5, fail=%i src=0x%" TERM_X_FMT " arg2=0x%" TERM_X_FMT " flags=0x%"PRIu32" dreg=%c%i\n", fail, src, arg2, flags_value, T_DEST_REG(dreg)); - if (ctx->bs_offset % 8 != 0) { - TRACE("bs_put_binary: Unsupported bit syntax operation. Writing binaries must be byte-aligend.\n"); - RAISE_ERROR(UNSUPPORTED_ATOM); - } + assert(term_is_match_state(src)); - TRACE("bs_put_binary/5, fail=%u size=%li unit=%u flags=%x src=0x%x\n", (unsigned) fail, size_val, (unsigned) unit, (int) flags_value, (unsigned int) src); + term src_bin = term_get_match_state_binary(src); + avm_int_t offset_bits = term_get_match_state_offset(src); - int result = term_bs_insert_binary(ctx->bs, ctx->bs_offset, src, size_val); - if (UNLIKELY(result)) { - TRACE("bs_put_binary: Failed to insert binary into binary: %i\n", result); - RAISE_ERROR(BADARG_ATOM); + int32_t val = 0; + size_t out_size = 0; + bool is_valid = bitstring_match_utf16(src_bin, (size_t) offset_bits, &val, &out_size, flags_value); + + if (!is_valid) { + pc = mod->labels[fail]; + } else { + term_set_match_state_offset(src, offset_bits + (out_size * 8)); + WRITE_REGISTER(dreg, term_from_int(val)); } - ctx->bs_offset += 8 * size_val; #endif + break; } -#if MINIMUM_OTP_COMPILER_VERSION <= 24 - case OP_BS_PUT_FLOAT: { + case OP_BS_SKIP_UTF16: { uint32_t fail; DECODE_LABEL(fail, pc) - term size; - DECODE_COMPACT_TERM(size, pc) - uint32_t unit; - DECODE_LITERAL(unit, pc); - uint32_t flags_value; - DECODE_LITERAL(flags_value, pc) term src; DECODE_COMPACT_TERM(src, pc); + term arg2; + DECODE_COMPACT_TERM(arg2, pc); + uint32_t flags_value; + DECODE_LITERAL(flags_value, pc); #ifdef IMPL_CODE_LOADER - TRACE("bs_put_float/5\n"); + TRACE("bs_skip_utf16/5\n"); #endif #ifdef IMPL_EXECUTE_LOOP - avm_float_t float_value = 0; - bool is_number = false; - if (term_is_float(src)) { - float_value = term_to_float(src); - is_number = true; - } else if (term_is_any_integer(src)) { - float_value = term_conv_to_float(src); - is_number = isfinite(float_value); - } + TRACE("bs_skip_utf16/5, fail=%i src=0x%" TERM_X_FMT " arg2=0x%" TERM_X_FMT " flags=0x%" TERM_X_FMT "\n", fail, src, arg2, flags); - if (UNLIKELY(!is_number)) { - if (fail == 0) { - RAISE_ERROR(BADARG_ATOM); - } else { - JUMP_TO_LABEL(mod, fail); - } - } + assert(term_is_match_state(src)); - avm_int_t signed_size_value = 64; - if (size != term_nil()) { - VERIFY_IS_INTEGER(size, "bs_create_bin/6", fail); - signed_size_value = term_to_int(size); - if (UNLIKELY(signed_size_value != 16 && signed_size_value != 32 && signed_size_value != 64)) { - if (fail == 0) { - RAISE_ERROR(BADARG_ATOM); - } else { - JUMP_TO_LABEL(mod, fail); - } - } - } + term src_bin = term_get_match_state_binary(src); + avm_int_t offset_bits = term_get_match_state_offset(src); - bool result; - if (signed_size_value == 16) { - result = bitstring_insert_f16(ctx->bs, ctx->bs_offset, float_value, flags_value); - } else if (signed_size_value == 32) { - result = bitstring_insert_f32(ctx->bs, ctx->bs_offset, float_value, flags_value); - } else { - result = bitstring_insert_f64(ctx->bs, ctx->bs_offset, float_value, flags_value); - } + int32_t val = 0; + size_t out_size = 0; + bool is_valid = bitstring_match_utf16(src_bin, (size_t) offset_bits, &val, &out_size, flags_value); - if (UNLIKELY(!result)) { - TRACE("bs_put_float: Failed to insert float into binary\n"); - RAISE_ERROR(BADARG_ATOM); + if (!is_valid) { + pc = mod->labels[fail]; + } else { + term_set_match_state_offset(src, offset_bits + (out_size * 8)); } - - ctx->bs_offset += signed_size_value * unit; #endif + break; } -#endif - case OP_BS_PUT_STRING: { - uint32_t size; - DECODE_LITERAL(size, pc); - uint32_t offset; - DECODE_LITERAL(offset, pc); + case OP_BS_GET_UTF32: { + uint32_t fail; + DECODE_LABEL(fail, pc) + term src; + DECODE_COMPACT_TERM(src, pc); + term arg2; + DECODE_COMPACT_TERM(arg2, pc); + uint32_t flags_value; + DECODE_LITERAL(flags_value, pc); + DEST_REGISTER(dreg); + DECODE_DEST_REGISTER(dreg, pc); #ifdef IMPL_CODE_LOADER - TRACE("bs_put_string/2\n"); + TRACE("bs_get_utf32/5\n"); #endif #ifdef IMPL_EXECUTE_LOOP - if (UNLIKELY(!term_is_binary(ctx->bs))) { - TRACE("bs_put_string: Bad state. ctx->bs is not a binary.\n"); - RAISE_ERROR(BADARG_ATOM); - } + TRACE("bs_get_utf32/5, fail=%i src=0x%" TERM_X_FMT " arg2=0x%" TERM_X_FMT " flags=0x%"PRIu32" dreg=%c%i\n", fail, src, arg2, flags_value, T_DEST_REG(dreg)); - TRACE("bs_put_string/2, size=%u offset=%u\n", size, offset); + assert(term_is_match_state(src)); - size_t remaining = 0; - const uint8_t *str = module_get_str(mod, offset, &remaining); - if (IS_NULL_PTR(str)) { - TRACE("bs_put_string: Bad offset in strings table.\n"); - RAISE_ERROR(BADARG_ATOM); - } + term src_bin = term_get_match_state_binary(src); + avm_int_t offset_bits = term_get_match_state_offset(src); + + int32_t val = 0; + bool is_valid = bitstring_match_utf32(src_bin, (size_t) offset_bits, &val, flags_value); - size_t size_in_bits = size * 8; - uint8_t *dst = (uint8_t *) term_binary_data(ctx->bs); - bitstring_copy_bits(dst, ctx->bs_offset, str, size_in_bits); - ctx->bs_offset += size_in_bits; + if (!is_valid) { + pc = mod->labels[fail]; + } else { + term_set_match_state_offset(src, offset_bits + 32); + WRITE_REGISTER(dreg, term_from_int(val)); + } #endif + break; } -#endif -#if MINIMUM_OTP_COMPILER_VERSION <= 21 - case OP_BS_START_MATCH2: { + case OP_BS_SKIP_UTF32: { uint32_t fail; DECODE_LABEL(fail, pc) term src; DECODE_COMPACT_TERM(src, pc); - uint32_t live; - DECODE_LITERAL(live, pc); - term slots_term; - DECODE_COMPACT_TERM(slots_term, pc); - GC_SAFE_DEST_REGISTER(dreg); - DECODE_DEST_REGISTER_GC_SAFE(dreg, pc); + term arg2; + DECODE_COMPACT_TERM(arg2, pc); + uint32_t flags_value; + DECODE_LITERAL(flags_value, pc); #ifdef IMPL_CODE_LOADER - TRACE("bs_start_match2/5\n"); + TRACE("bs_skip_utf32/5\n"); #endif #ifdef IMPL_EXECUTE_LOOP - TRACE("bs_start_match2/5, fail=%i src=0x%" TERM_X_FMT " live=%u arg3=0x%" TERM_X_FMT " dreg=%c%i\n", fail, src, (unsigned) live, slots_term, T_DEST_REG_GC_SAFE(dreg)); - if (!(term_is_binary(src) || term_is_match_state(src))) { - WRITE_REGISTER_GC_SAFE(dreg, src); + TRACE("bs_skip_utf32/5, fail=%i src=0x%" TERM_X_FMT " arg2=0x%" TERM_X_FMT " flags=0x%" TERM_X_FMT "\n", fail, src, arg2, flags); + + assert(term_is_match_state(src)); + + term src_bin = term_get_match_state_binary(src); + avm_int_t offset_bits = term_get_match_state_offset(src); + + int32_t val = 0; + bool is_valid = bitstring_match_utf32(src_bin, (size_t) offset_bits, &val, flags_value); + + if (!is_valid) { pc = mod->labels[fail]; } else { - int slots = term_to_int(slots_term); + term_set_match_state_offset(src, offset_bits + 32); + } + #endif - TRIM_LIVE_REGS(live); - // MEMORY_CAN_SHRINK because bs_start_match is classified as gc in beam_ssa_codegen.erl - x_regs[live] = src; - if (memory_ensure_free_with_roots(ctx, TERM_BOXED_BIN_MATCH_STATE_SIZE + slots, live + 1, x_regs, MEMORY_CAN_SHRINK) != MEMORY_GC_OK) { - RAISE_ERROR(OUT_OF_MEMORY_ATOM); - } - src = x_regs[live]; + break; + } - term match_state = term_alloc_bin_match_state(src, slots, &ctx->heap); + case OP_BS_INIT_WRITABLE: { - WRITE_REGISTER_GC_SAFE(dreg, match_state); + TRACE("bs_init_writable/0\n"); + + #ifdef IMPL_EXECUTE_LOOP + if (UNLIKELY(memory_ensure_free_opt(ctx, term_binary_heap_size(0), MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + term t = term_create_empty_binary(0, &ctx->heap, ctx->global); + if (UNLIKELY(term_is_invalid_term(t))) { + RAISE_ERROR(OUT_OF_MEMORY_ATOM); } + + ctx->bs = t; + ctx->bs_offset = 0; + x_regs[0] = t; #endif break; } -#endif -#if MAXIMUM_OTP_COMPILER_VERSION >= 22 case OP_BS_START_MATCH3: { uint32_t fail; DECODE_LABEL(fail, pc) @@ -5201,8 +4480,8 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) #endif break; } -#endif +#if MINIMUM_OTP_COMPILER_VERSION <= 27 case OP_BS_MATCH_STRING: { uint32_t fail; DECODE_LABEL(fail, pc) @@ -5284,64 +4563,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) #endif break; } - -#if MINIMUM_OTP_COMPILER_VERSION <= 21 - case OP_BS_SAVE2: { - term src; - DECODE_COMPACT_TERM(src, pc); - term index = 0; - DECODE_COMPACT_TERM(index, pc); - - #ifdef IMPL_CODE_LOADER - TRACE("bs_save2/2\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_MATCH_STATE(src, "bs_save2", 0); - - avm_int_t index_val; - if (index == START_ATOM) { - // TODO: not sure if 'start' is used anytime in generated code - term_match_state_save_start_offset(src); - } else if (term_is_integer(index)) { - index_val = term_to_int(index); - term_match_state_save_offset(src, index_val); - } else { - AVM_ABORT(); - } - - TRACE("bs_save2/2, src=0x%" TERM_X_FMT " pos=" AVM_INT_FMT "\n", src, index == START_ATOM ? -1 : index_val); - #endif - break; - } - - case OP_BS_RESTORE2: { - term src; - DECODE_COMPACT_TERM(src, pc); - term index = 0; - DECODE_COMPACT_TERM(index, pc); - - #ifdef IMPL_CODE_LOADER - TRACE("bs_restore2/5\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_MATCH_STATE(src, "bs_restore2", 0); - - avm_int_t index_val; - if (index == START_ATOM) { - term_match_state_restore_start_offset(src); - } else if (term_is_integer(index)) { - index_val = term_to_int(index); - term_match_state_restore_offset(src, index_val); - } else { - AVM_ABORT(); - } - - TRACE("bs_restore2/2, src=0x%" TERM_X_FMT " pos=" AVM_INT_FMT "\n", src, index == START_ATOM ? -1 : index_val); - #endif - break; - } #endif case OP_BS_SKIP_BITS2: { @@ -5382,33 +4603,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } -#if MINIMUM_OTP_COMPILER_VERSION <= 24 - case OP_BS_TEST_UNIT: { - uint32_t fail; - DECODE_LABEL(fail, pc) - term src; - DECODE_COMPACT_TERM(src, pc); - uint32_t unit; - DECODE_LITERAL(unit, pc); - - #ifdef IMPL_CODE_LOADER - TRACE("bs_test_unit/3\n"); - #endif - - #ifdef IMPL_EXECUTE_LOOP - VERIFY_IS_MATCH_STATE(src, "bs_test_unit", 0); - - TRACE("bs_test_unit/3, fail=%u src=%p unit=%u\n", (unsigned) fail, (void *) src, (unsigned) unit); - - avm_int_t bs_offset = term_get_match_state_offset(src); - if ((term_binary_size(src) * 8 - bs_offset) % unit != 0) { - TRACE("bs_test_unit: Available bits in source not evenly divisible by unit\n"); - JUMP_TO_ADDRESS(mod->labels[fail]); - } - #endif - break; - } - +#if MINIMUM_OTP_COMPILER_VERSION <= 26 case OP_BS_TEST_TAIL2: { uint32_t fail; DECODE_LABEL(fail, pc) @@ -6079,28 +5274,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } -#if MINIMUM_OTP_COMPILER_VERSION <= 23 - //it looks like it can be safely left unimplemented - case OP_RECV_MARK: { - uint32_t label; - DECODE_LABEL(label, pc); - - TRACE("recv_mark/1 label=%i\n", label); - USED_BY_TRACE(label); - break; - } - - //it looks like it can be safely left unimplemented - case OP_RECV_SET: { - uint32_t label; - DECODE_LABEL(label, pc); - - TRACE("recv_set/1 label=%i\n", label); - USED_BY_TRACE(label); - break; - } -#endif - case OP_LINE: { #ifdef IMPL_CODE_LOADER unsigned int offset = pc - code; @@ -6449,21 +5622,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } -#if MINIMUM_OTP_COMPILER_VERSION <= 23 - case OP_FCLEARERROR: { - // This can be a noop as we raise from bifs - TRACE("fclearerror/0\n"); - break; - } - - case OP_FCHECKERROR: { - // This can be a noop as we raise from bifs - int fail_label; - DECODE_LABEL(fail_label, pc); - break; - } -#endif - case OP_FMOVE: { if (IS_EXTENDED_FP_REGISTER(pc)) { int freg; @@ -6807,7 +5965,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } -#if MAXIMUM_OTP_COMPILER_VERSION >= 22 case OP_PUT_TUPLE2: { DEST_REGISTER(dreg); DECODE_DEST_REGISTER(dreg, pc); @@ -6840,9 +5997,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) #endif break; } -#endif -#if MAXIMUM_OTP_COMPILER_VERSION >= 23 case OP_SWAP: { DEST_REGISTER(reg_a); DECODE_DEST_REGISTER(reg_a, pc); @@ -6900,9 +6055,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) #endif break; } -#endif -#if MAXIMUM_OTP_COMPILER_VERSION >= 24 case OP_MAKE_FUN3: { uint32_t fun_index; DECODE_LITERAL(fun_index, pc); @@ -6984,9 +6137,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) TRACE("recv_marker_use/1: reg1=%c%i\n", T_DEST_REG(reg_a)); break; } -#endif -#if MAXIMUM_OTP_COMPILER_VERSION >= 25 case OP_BS_CREATE_BIN: { uint32_t fail; DECODE_LABEL(fail, pc); @@ -7457,9 +6608,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } -#endif -#if MAXIMUM_OTP_COMPILER_VERSION >= 26 case OP_UPDATE_RECORD: { #ifdef IMPL_CODE_LOADER TRACE("update_record/5\n"); @@ -7836,7 +6985,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) break; } } -#endif default: printf("Undecoded opcode: %i\n", pc[-1]); diff --git a/src/platforms/emscripten/CMakeLists.txt b/src/platforms/emscripten/CMakeLists.txt index fef8d18aa5..ce48ac2d16 100644 --- a/src/platforms/emscripten/CMakeLists.txt +++ b/src/platforms/emscripten/CMakeLists.txt @@ -29,7 +29,6 @@ if (NOT CMAKE_TOOLCHAIN_FILE) endif () # Options that make sense for this platform -option(AVM_ENABLE_OLD_OTP_VERSIONS "Enable OTP version < 26" OFF) option(AVM_DISABLE_SMP "Disable SMP." OFF) option(AVM_USE_32BIT_FLOAT "Use 32 bit floats." OFF) option(AVM_VERBOSE_ABORT "Print module and line number on VM abort" OFF) diff --git a/src/platforms/esp32/CMakeLists.txt b/src/platforms/esp32/CMakeLists.txt index 7eeee320df..e725bcd577 100644 --- a/src/platforms/esp32/CMakeLists.txt +++ b/src/platforms/esp32/CMakeLists.txt @@ -96,7 +96,6 @@ if (-std=gnu99 IN_LIST c_compile_options ) endif() # Options that make sense for this platform -option(AVM_ENABLE_OLD_OTP_VERSIONS "Enable OTP version < 26" OFF) option(AVM_DISABLE_SMP "Disable SMP." OFF) option(AVM_USE_32BIT_FLOAT "Use 32 bit floats." OFF) option(AVM_VERBOSE_ABORT "Print module and line number on VM abort" OFF) diff --git a/src/platforms/rp2/CMakeLists.txt b/src/platforms/rp2/CMakeLists.txt index 474f78aa0b..6c7e639746 100644 --- a/src/platforms/rp2/CMakeLists.txt +++ b/src/platforms/rp2/CMakeLists.txt @@ -58,7 +58,6 @@ set(HAVE_EXECVE "" CACHE INTERNAL "Have symbol execve" FORCE) set(HAVE_GETCWD "" CACHE INTERNAL "Have symbol getcwd" FORCE) # Options that make sense for this platform -option(AVM_ENABLE_OLD_OTP_VERSIONS "Enable OTP version < 26" OFF) option(AVM_DISABLE_SMP "Disable SMP support." OFF) option(AVM_USE_32BIT_FLOAT "Use 32 bit floats." OFF) option(AVM_VERBOSE_ABORT "Print module and line number on VM abort" OFF) diff --git a/src/platforms/stm32/CMakeLists.txt b/src/platforms/stm32/CMakeLists.txt index 24fa027562..3c1c1063b5 100644 --- a/src/platforms/stm32/CMakeLists.txt +++ b/src/platforms/stm32/CMakeLists.txt @@ -26,7 +26,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../CMakeModules set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) # Options that make sense for this platform -option(AVM_ENABLE_OLD_OTP_VERSIONS "Enable OTP version < 26" OFF) option(AVM_USE_32BIT_FLOAT "Use 32 bit floats." ON) option(AVM_VERBOSE_ABORT "Print module and line number on VM abort" OFF) option(AVM_CREATE_STACKTRACES "Create stacktraces" ON) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c7652f4b65..e274e4926a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -114,10 +114,7 @@ if (NOT "${CMAKE_GENERATOR}" MATCHES "Xcode") add_subdirectory(libs/estdlib) add_subdirectory(libs/eavmlib) add_subdirectory(libs/alisp) - # JIT compiler doesn't compile with OTP < 23 - if(Erlang_VERSION VERSION_GREATER_EQUAL "23") - add_subdirectory(libs/jit) - endif() + add_subdirectory(libs/jit) if (Elixir_FOUND) add_subdirectory(libs/exavmlib) else() diff --git a/tests/erlang_tests/CMakeLists.txt b/tests/erlang_tests/CMakeLists.txt index 2d96b4a1a4..6a6c058f5d 100644 --- a/tests/erlang_tests/CMakeLists.txt +++ b/tests/erlang_tests/CMakeLists.txt @@ -642,23 +642,6 @@ compile_erlang(test_is_integer_3) compile_erlang(test_inline_arith) -if(Erlang_VERSION VERSION_GREATER_EQUAL "23") - set(OTP23_OR_GREATER_TESTS - test_op_bs_start_match_asm.beam - bs_get_binary2_all_asm.beam - ) -else() - set(OTP23_OR_GREATER_TESTS) -endif() - -if(Erlang_VERSION VERSION_GREATER_EQUAL "25") - set(OTP25_OR_GREATER_TESTS - test_op_bs_create_bin_asm.beam - test_bs_create_bin_accum_asm.beam - ) -else() - set(OTP25_OR_GREATER_TESTS) -endif() set(erlang_test_beams add.beam @@ -1194,8 +1177,10 @@ set(erlang_test_beams test_multi_value_comprehension.beam test_is_integer_3.beam - ${OTP23_OR_GREATER_TESTS} - ${OTP25_OR_GREATER_TESTS} + test_op_bs_start_match_asm.beam + bs_get_binary2_all_asm.beam + test_op_bs_create_bin_asm.beam + test_bs_create_bin_accum_asm.beam ) if(NOT AVM_DISABLE_JIT) diff --git a/tests/erlang_tests/bs_get_binary_fixed_size.erl b/tests/erlang_tests/bs_get_binary_fixed_size.erl index 8ee98e0fe1..7f8c6849c2 100644 --- a/tests/erlang_tests/bs_get_binary_fixed_size.erl +++ b/tests/erlang_tests/bs_get_binary_fixed_size.erl @@ -21,13 +21,10 @@ -module(bs_get_binary_fixed_size). %% Force the compiler to use bs_get_binary2 opcode instead of the -%% newer bs_match opcode (OTP 25+). On older OTP this is ignored. -%% The no_bs_match option was removed in OTP 29. --ifdef(OTP_RELEASE). +%% newer bs_match opcode. The no_bs_match option was removed in OTP 29. -if(?OTP_RELEASE =< 28). -compile([no_bs_match]). -endif. --endif. -export([start/0]). @@ -35,19 +32,7 @@ start() -> Bin = id(<<1, 2, 3, 4, 5, 6, 7, 8>>), ok = test_match_4(Bin), ok = test_match_3(Bin), - %% bs_get_binary2_all_asm uses bs_start_match4 which requires OTP 23+ - HasAsmModule = - case erlang:system_info(machine) of - "BEAM" -> - erlang:system_info(otp_release) >= "23"; - "ATOM" -> - ?OTP_RELEASE >= 23 - end, - ok = - if - HasAsmModule -> test_match_all(Bin); - true -> ok - end, + ok = test_match_all(Bin), ok = test_match_fail(Bin), 0. diff --git a/tests/erlang_tests/bs_get_float_dynamic_size.erl b/tests/erlang_tests/bs_get_float_dynamic_size.erl index a59f5dcc89..3dc54e24c7 100644 --- a/tests/erlang_tests/bs_get_float_dynamic_size.erl +++ b/tests/erlang_tests/bs_get_float_dynamic_size.erl @@ -21,13 +21,10 @@ -module(bs_get_float_dynamic_size). %% Force the compiler to use bs_get_float2 opcode instead of the -%% newer bs_match opcode (OTP 25+). On older OTP this is ignored. -%% The no_bs_match option was removed in OTP 29. --ifdef(OTP_RELEASE). +%% newer bs_match opcode. The no_bs_match option was removed in OTP 29. -if(?OTP_RELEASE =< 28). -compile([no_bs_match]). -endif. --endif. -export([start/0]). diff --git a/tests/erlang_tests/bs_get_integer_fixed_size.erl b/tests/erlang_tests/bs_get_integer_fixed_size.erl index a4263bbd40..fd4dae4097 100644 --- a/tests/erlang_tests/bs_get_integer_fixed_size.erl +++ b/tests/erlang_tests/bs_get_integer_fixed_size.erl @@ -21,13 +21,10 @@ -module(bs_get_integer_fixed_size). %% Force the compiler to use bs_get_integer2 opcode instead of the -%% newer bs_match opcode (OTP 25+). On older OTP this is ignored. -%% The no_bs_match option was removed in OTP 29. --ifdef(OTP_RELEASE). +%% newer bs_match opcode. The no_bs_match option was removed in OTP 29. -if(?OTP_RELEASE =< 28). -compile([no_bs_match]). -endif. --endif. -export([start/0]). diff --git a/tests/erlang_tests/maps_nifs.erl b/tests/erlang_tests/maps_nifs.erl index ca8104ea6c..9d6d8052c4 100644 --- a/tests/erlang_tests/maps_nifs.erl +++ b/tests/erlang_tests/maps_nifs.erl @@ -23,17 +23,10 @@ -export([start/0, fact/1, make_value/1, get_expected/1, get_list/1]). start() -> - test_maps_from_keys(get_otp_version()). - -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> list_to_integer(erlang:system_info(otp_release)); - _ -> atomvm - end. + ok = test_maps_from_keys(), + 0. -test_maps_from_keys(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_maps_from_keys() -> M1 = #{1 => [], 5 => [], 6 => [], 8 => [], 9 => [], 24 => [], 43 => [], 100 => []}, M1 = maps:from_keys(?MODULE:get_list(1), []), @@ -52,10 +45,7 @@ test_maps_from_keys(OTPVersion) when 0 = map_size(M5), M5 = ?MODULE:get_expected(5), - 0; -test_maps_from_keys(OTPVersion) -> - % test skipped: maps:from_keys not supported on OTP < 24 - 0. + ok. fact(0) -> 1; diff --git a/tests/erlang_tests/test_base64.erl b/tests/erlang_tests/test_base64.erl index 69d70ee277..ae551b76fe 100644 --- a/tests/erlang_tests/test_base64.erl +++ b/tests/erlang_tests/test_base64.erl @@ -82,20 +82,12 @@ start() -> <<1, 2, 3, 4, 5, 6>> = base64:decode(["AQ", "ID", <<"BAUG">>]) end, - test_padding_option(get_otp_version()), - test_urlsafe_mode(get_otp_version()), + test_padding_option(), + test_urlsafe_mode(), 0. -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> list_to_integer(erlang:system_info(otp_release)); - _ -> atomvm - end. - -test_padding_option(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 26) orelse OTPVersion == atomvm --> +test_padding_option() -> %% encode/2 with padding => true behaves identically to encode/1 <<"AQID">> = base64:encode(<<1, 2, 3>>, #{padding => true}), <<"AQIDBA==">> = base64:encode(<<1, 2, 3, 4>>, #{padding => true}), @@ -152,16 +144,12 @@ test_padding_option(OTPVersion) when || I <- lists_seq(0, 20) ++ [50, 100, 131, 147, 200, 201] ], - ok; -test_padding_option(_OTPVersion) -> ok. lists_seq(0, 20) -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]. -test_urlsafe_mode(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 26) orelse OTPVersion == atomvm --> +test_urlsafe_mode() -> %% Known vectors: bytes that produce + or / in standard mode %% Generated via OTP: base64:encode(Bin, #{mode => urlsafe}) UrlsafeVectors = [ @@ -239,8 +227,6 @@ test_urlsafe_mode(OTPVersion) when %% round-trip with mode => urlsafe for various sizes [verify_b64_urlsafe(rand_bytes(I)) || I <- lists_seq(0, 20) ++ [50, 100, 131]], - ok; -test_urlsafe_mode(_OTPVersion) -> ok. verify_b64_urlsafe(Input) -> diff --git a/tests/erlang_tests/test_binary_to_term.erl b/tests/erlang_tests/test_binary_to_term.erl index eb6129dc74..027187166e 100644 --- a/tests/erlang_tests/test_binary_to_term.erl +++ b/tests/erlang_tests/test_binary_to_term.erl @@ -34,9 +34,8 @@ ]). start() -> - % Starting from OTP-26, atoms are encoded as UTF-8 by default. - test_reverse(foo, {<<131, 119, 3, 102, 111, 111>>, <<131, 100, 0, 3, 102, 111, 111>>}), - test_reverse(bar, {<<131, 119, 3, 98, 97, 114>>, <<131, 100, 0, 3, 98, 97, 114>>}), + test_reverse(foo, <<131, 119, 3, 102, 111, 111>>), + test_reverse(bar, <<131, 119, 3, 98, 97, 114>>), test_reverse( '∀x∃y.f(x,y)', <<131, 119, 15, 226, 136, 128, 120, 226, 136, 131, 121, 46, 102, 40, 120, 44, 121, 41>>, @@ -55,57 +54,32 @@ start() -> test_reverse(32768, <<131, 98, 0, 0, 128, 0>>), test_reverse(-32768, <<131, 98, 255, 255, 128, 0>>), test_reverse( - {foo, bar}, { - <<131, 104, 2, 119, 3, 102, 111, 111, 119, 3, 98, 97, 114>>, - <<131, 104, 2, 100, 0, 3, 102, 111, 111, 100, 0, 3, 98, 97, 114>> - } + {foo, bar}, <<131, 104, 2, 119, 3, 102, 111, 111, 119, 3, 98, 97, 114>> ), - test_reverse({foo, 0}, { - <<131, 104, 2, 119, 3, 102, 111, 111, 97, 0>>, - <<131, 104, 2, 100, 0, 3, 102, 111, 111, 97, 0>> - }), + test_reverse({foo, 0}, <<131, 104, 2, 119, 3, 102, 111, 111, 97, 0>>), test_reverse([], <<131, 106>>), test_reverse( - [{foo, 0}, {bar, 1}], { - <<131, 108, 0, 0, 0, 2, 104, 2, 119, 3, 102, 111, 111, 97, 0, 104, 2, 119, 3, 98, 97, - 114, 97, 1, 106>>, - <<131, 108, 0, 0, 0, 2, 104, 2, 100, 0, 3, 102, 111, 111, 97, 0, 104, 2, 100, 0, 3, 98, - 97, 114, 97, 1, 106>> - } + [{foo, 0}, {bar, 1}], + <<131, 108, 0, 0, 0, 2, 104, 2, 119, 3, 102, 111, 111, 97, 0, 104, 2, 119, 3, 98, 97, 114, + 97, 1, 106>> ), test_reverse( [improper | list], - { - <<131, 108, 0, 0, 0, 1, 119, 8, 105, 109, 112, 114, 111, 112, 101, 114, 119, 4, 108, - 105, 115, 116>>, - <<131, 108, 0, 0, 0, 1, 100, 0, 8, 105, 109, 112, 114, 111, 112, 101, 114, 100, 0, 4, - 108, 105, 115, 116>> - } + <<131, 108, 0, 0, 0, 1, 119, 8, 105, 109, 112, 114, 111, 112, 101, 114, 119, 4, 108, 105, + 115, 116>> ), - test_reverse({foo, bar}, { - <<131, 104, 2, 119, 3, 102, 111, 111, 119, 3, 98, 97, 114>>, - <<131, 104, 2, 100, 0, 3, 102, 111, 111, 100, 0, 3, 98, 97, 114>> - }), - test_reverse({foo, 0}, { - <<131, 104, 2, 119, 3, 102, 111, 111, 97, 0>>, - <<131, 104, 2, 100, 0, 3, 102, 111, 111, 97, 0>> - }), + test_reverse({foo, bar}, <<131, 104, 2, 119, 3, 102, 111, 111, 119, 3, 98, 97, 114>>), + test_reverse({foo, 0}, <<131, 104, 2, 119, 3, 102, 111, 111, 97, 0>>), test_reverse([], <<131, 106>>), test_reverse( - [{foo, 0}, {bar, 1}], { - <<131, 108, 0, 0, 0, 2, 104, 2, 119, 3, 102, 111, 111, 97, 0, 104, 2, 119, 3, 98, 97, - 114, 97, 1, 106>>, - <<131, 108, 0, 0, 0, 2, 104, 2, 100, 0, 3, 102, 111, 111, 97, 0, 104, 2, 100, 0, 3, 98, - 97, 114, 97, 1, 106>> - } + [{foo, 0}, {bar, 1}], + <<131, 108, 0, 0, 0, 2, 104, 2, 119, 3, 102, 111, 111, 97, 0, 104, 2, 119, 3, 98, 97, 114, + 97, 1, 106>> ), test_reverse( - [improper | list], { - <<131, 108, 0, 0, 0, 1, 119, 8, 105, 109, 112, 114, 111, 112, 101, 114, 119, 4, 108, - 105, 115, 116>>, - <<131, 108, 0, 0, 0, 1, 100, 0, 8, 105, 109, 112, 114, 111, 112, 101, 114, 100, 0, 4, - 108, 105, 115, 116>> - } + [improper | list], + <<131, 108, 0, 0, 0, 1, 119, 8, 105, 109, 112, 114, 111, 112, 101, 114, 119, 4, 108, 105, + 115, 116>> ), test_reverse(<<"foobar">>, <<131, 109, 0, 0, 0, 6, 102, 111, 111, 98, 97, 114>>), test_reverse(<<":アトムVM">>, <<131, 109, 0, 0, 0, 6, 58, 162, 200, 224, 54, 45>>), @@ -185,15 +159,6 @@ start() -> test_reverse(T, Interop) -> test_reverse(T, Interop, []). -test_reverse(T, {Utf8Interop, Latin1Interop}, Options) -> - case get_otp_version() of - X when is_integer(X) andalso X >= 26 -> - test_reverse(T, Utf8Interop, Options); - atomvm -> - test_reverse(T, Utf8Interop, Options); - _ -> - test_reverse(T, Latin1Interop, Options) - end; test_reverse(T, Interop, Options) when is_binary(Interop) andalso is_list(Options) -> Bin = case Options of @@ -271,21 +236,10 @@ mutate_bin(Bin, I) -> test_external_function() -> T = T = [?MODULE:id(fun ?MODULE:apply/2), ?MODULE:id(fun ?MODULE:apply/3)], Bin = - case get_otp_version() of - X when is_integer(X) andalso X >= 26 orelse X == atomvm -> - %% expect SMALL_ATOM_UTF8_EXT encoding - <<131, 108, 0, 0, 0, 2, 113, 119, 19, 116, 101, 115, 116, 95, 98, 105, 110, 97, 114, - 121, 95, 116, 111, 95, 116, 101, 114, 109, 119, 5, 97, 112, 112, 108, 121, 97, - 2, 113, 119, 19, 116, 101, 115, 116, 95, 98, 105, 110, 97, 114, 121, 95, 116, - 111, 95, 116, 101, 114, 109, 119, 5, 97, 112, 112, 108, 121, 97, 3, 106>>; - _ -> - %% expect ATOM_EXT encoding - <<131, 108, 0, 0, 0, 2, 113, 100, 0, 19, 116, 101, 115, 116, 95, 98, 105, 110, 97, - 114, 121, 95, 116, 111, 95, 116, 101, 114, 109, 100, 0, 5, 97, 112, 112, 108, - 121, 97, 2, 113, 100, 0, 19, 116, 101, 115, 116, 95, 98, 105, 110, 97, 114, 121, - 95, 116, 111, 95, 116, 101, 114, 109, 100, 0, 5, 97, 112, 112, 108, 121, 97, 3, - 106>> - end, + <<131, 108, 0, 0, 0, 2, 113, 119, 19, 116, 101, 115, 116, 95, 98, 105, 110, 97, 114, 121, + 95, 116, 111, 95, 116, 101, 114, 109, 119, 5, 97, 112, 112, 108, 121, 97, 2, 113, 119, + 19, 116, 101, 115, 116, 95, 98, 105, 110, 97, 114, 121, 95, 116, 111, 95, 116, 101, 114, + 109, 119, 5, 97, 112, 112, 108, 121, 97, 3, 106>>, Bin = erlang:term_to_binary(T), @@ -489,21 +443,7 @@ test_encode_pid() -> hello -> ok after 500 -> error end, - {ExpectedSize, CreationOrder} = - case erlang:system_info(machine) of - "ATOM" -> - {29, true}; - "BEAM" -> - OTPRelease = erlang:system_info(otp_release), - if - OTPRelease =:= "21" -> {27, true}; - OTPRelease =:= "22" -> {27, false}; - OTPRelease < "26" -> {30, true}; - % small utf8 atom - true -> {29, true} - end - end, - ExpectedSize = byte_size(Bin), + 29 = byte_size(Bin), % Creation is not displayed in list representation FalsePid1 = binary_to_term_idempotent( @@ -516,7 +456,7 @@ test_encode_pid() -> ), "<0.1.0>" = pid_to_list(FalsePid1Cr), false = FalsePid1 =:= FalsePid1Cr, - CreationOrder = FalsePid1 < FalsePid1Cr, + true = FalsePid1 < FalsePid1Cr, % Order is done by pid on a given node FalsePid2 = binary_to_term_idempotent( @@ -601,47 +541,32 @@ test_encode_pid() -> error:badarg -> ok end, - case has_setnode_creation() of - true -> - % Test distributed pid - Ref42 = do_setnode(test@test_node, 42), - DistributedPid1 = binary_to_term( - <<131, 88, 119, 14, "test@test_node", 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 42>> - ), - true = is_pid(DistributedPid1), - true = is_process_alive(DistributedPid1), - - DistributedBin42 = term_to_binary(self()), - true = DistributedBin42 =/= Bin, - DistributedPid42 = binary_to_term(DistributedBin42), - true = DistributedPid42 =:= Pid, - ExpectedSize = byte_size(DistributedBin42) - 1, - - ok = do_unsetnode(Ref42), - Bin = term_to_binary(self()), - - Ref43 = do_setnode(test@test_node, 43), - DistributedBin43 = term_to_binary(self()), - true = DistributedBin43 =/= DistributedBin42, - DistributedPid43 = binary_to_term(DistributedBin43), - true = DistributedPid43 =:= Pid, - - ok = do_unsetnode(Ref43), - Bin = term_to_binary(self()), - ok; - false -> - ok - end, - ok. + % Test distributed pid + Ref42 = do_setnode(test@test_node, 42), + DistributedPid1 = binary_to_term( + <<131, 88, 119, 14, "test@test_node", 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 42>> + ), + true = is_pid(DistributedPid1), + true = is_process_alive(DistributedPid1), -has_setnode_creation() -> - case erlang:system_info(machine) of - "ATOM" -> - true; - "BEAM" -> - OTPRelease = erlang:system_info(otp_release), - OTPRelease >= "23" - end. + DistributedBin42 = term_to_binary(self()), + true = DistributedBin42 =/= Bin, + DistributedPid42 = binary_to_term(DistributedBin42), + true = DistributedPid42 =:= Pid, + 30 = byte_size(DistributedBin42), + + ok = do_unsetnode(Ref42), + Bin = term_to_binary(self()), + + Ref43 = do_setnode(test@test_node, 43), + DistributedBin43 = term_to_binary(self()), + true = DistributedBin43 =/= DistributedBin42, + DistributedPid43 = binary_to_term(DistributedBin43), + true = DistributedPid43 =:= Pid, + + ok = do_unsetnode(Ref43), + Bin = term_to_binary(self()), + ok. do_setnode(Node, Creation) -> {NetKernelPid, MonitorRef} = spawn_opt( @@ -680,102 +605,73 @@ test_encode_port() -> Bin = term_to_binary(TestPort), TestPort = binary_to_term(Bin), true = is_port(TestPort), - {ExpectedSize, SupportsV4PortEncoding} = - case erlang:system_info(machine) of - "ATOM" -> - % small utf8 atom - {29, true}; - "BEAM" -> - OTPRelease = erlang:system_info(otp_release), - if - OTPRelease < "23" -> {23, false}; - OTPRelease < "24" -> {26, false}; - % v4 is supported but not the default - OTPRelease < "26" -> {26, true}; - % small utf8 atom - true -> {29, true} - end - end, - ExpectedSize = byte_size(Bin), - case SupportsV4PortEncoding of - true -> - LocalPort1 = binary_to_term( - <<131, 120, 119, 13, "nonode@nohost", 1:64, 0:32>> - ), - true = is_port(LocalPort1), - "#Port<0.1>" = port_to_list(LocalPort1), - Port1 = binary_to_term(<<131, 120, 119, 4, "true", 43:64, 0:32>>), - Port2 = binary_to_term(<<131, 120, 119, 4, "true", 43:64, 1:32>>), - false = Port1 =:= Port2, - true = Port1 < Port2, - "#Port<1.43>" = port_to_list(Port1), - "#Port<1.43>" = port_to_list(Port2), - - % Order - FalsePort_42_43 = binary_to_term_idempotent( - <<131, 120, 119, 5, "false", 42:64, 43:32>>, "26" - ), - FalsePort_43_42 = binary_to_term_idempotent( - <<131, 120, 119, 5, "false", 43:64, 42:32>>, "26" - ), - FalsePort_43_43 = binary_to_term_idempotent( - <<131, 120, 119, 5, "false", 43:64, 43:32>>, "26" - ), - FalsfPort_42_41 = binary_to_term_idempotent( - <<131, 120, 119, 5, "falsf", 42:64, 41:32>>, "26" - ), - - % Node first, creation second, number third - true = FalsePort_42_43 > FalsePort_43_42, - true = FalsfPort_42_41 > FalsePort_42_43, - true = FalsfPort_42_41 > FalsePort_43_42, - true = FalsePort_43_42 < FalsePort_43_43, - - % Order is done by node atom, with local pid as nonode@nohost - true = - TestPort > - binary_to_term_idempotent(<<131, 120, 119, 5, "false", 1:64, 0:32>>, "26"), - true = - TestPort > - binary_to_term_idempotent(<<131, 120, 119, 6, "nonode", 1:64, 0:32>>, "26"), - true = - TestPort < - binary_to_term_idempotent(<<131, 120, 119, 6, "nonodf", 1:64, 0:32>>, "26"), + 29 = byte_size(Bin), + LocalPort1 = binary_to_term( + <<131, 120, 119, 13, "nonode@nohost", 1:64, 0:32>> + ), + true = is_port(LocalPort1), + "#Port<0.1>" = port_to_list(LocalPort1), + Port1 = binary_to_term(<<131, 120, 119, 4, "true", 43:64, 0:32>>), + Port2 = binary_to_term(<<131, 120, 119, 4, "true", 43:64, 1:32>>), + false = Port1 =:= Port2, + true = Port1 < Port2, + "#Port<1.43>" = port_to_list(Port1), + "#Port<1.43>" = port_to_list(Port2), - ok; - false -> - ok - end, - case has_setnode_creation() of - true -> - % Test distributed ports - % Test doesn't pass on BEAM if we use 42 and 43 like for refs, - % as there probably is a side-effect we don't have - Ref42 = do_setnode(test@test_node, 1042), - DistributedBin42 = term_to_binary(TestPort), - true = DistributedBin42 =/= Bin, - TestRef42 = binary_to_term(DistributedBin42), - true = TestRef42 =:= TestPort, - ExpectedSize = byte_size(DistributedBin42) - 1, - - ok = do_unsetnode(Ref42), - - Ref43 = do_setnode(test@test_node, 1043), - DistributedBin43 = term_to_binary(TestPort), - true = DistributedBin43 =/= DistributedBin42, - TestRef43 = binary_to_term(DistributedBin43), - true = TestRef43 =:= TestPort, - ExpectedSize = byte_size(DistributedBin43) - 1, - - % If our creation is 1043, encoded binary with creation 1042 is a different port - TestRef42_43 = binary_to_term(DistributedBin42), - false = TestRef42_43 =:= TestPort, - - ok = do_unsetnode(Ref43), - ok; - false -> - ok - end, + % Order + FalsePort_42_43 = binary_to_term_idempotent( + <<131, 120, 119, 5, "false", 42:64, 43:32>>, "26" + ), + FalsePort_43_42 = binary_to_term_idempotent( + <<131, 120, 119, 5, "false", 43:64, 42:32>>, "26" + ), + FalsePort_43_43 = binary_to_term_idempotent( + <<131, 120, 119, 5, "false", 43:64, 43:32>>, "26" + ), + FalsfPort_42_41 = binary_to_term_idempotent( + <<131, 120, 119, 5, "falsf", 42:64, 41:32>>, "26" + ), + + % Node first, creation second, number third + true = FalsePort_42_43 > FalsePort_43_42, + true = FalsfPort_42_41 > FalsePort_42_43, + true = FalsfPort_42_41 > FalsePort_43_42, + true = FalsePort_43_42 < FalsePort_43_43, + + % Order is done by node atom, with local pid as nonode@nohost + true = + TestPort > + binary_to_term_idempotent(<<131, 120, 119, 5, "false", 1:64, 0:32>>, "26"), + true = + TestPort > + binary_to_term_idempotent(<<131, 120, 119, 6, "nonode", 1:64, 0:32>>, "26"), + true = + TestPort < + binary_to_term_idempotent(<<131, 120, 119, 6, "nonodf", 1:64, 0:32>>, "26"), + % Test distributed ports + % Test doesn't pass on BEAM if we use 42 and 43 like for refs, + % as there probably is a side-effect we don't have + Ref42 = do_setnode(test@test_node, 1042), + DistributedBin42 = term_to_binary(TestPort), + true = DistributedBin42 =/= Bin, + TestRef42 = binary_to_term(DistributedBin42), + true = TestRef42 =:= TestPort, + ExpectedSize = byte_size(DistributedBin42) - 1, + + ok = do_unsetnode(Ref42), + + Ref43 = do_setnode(test@test_node, 1043), + DistributedBin43 = term_to_binary(TestPort), + true = DistributedBin43 =/= DistributedBin42, + TestRef43 = binary_to_term(DistributedBin43), + true = TestRef43 =:= TestPort, + ExpectedSize = byte_size(DistributedBin43) - 1, + + % If our creation is 1043, encoded binary with creation 1042 is a different port + TestRef42_43 = binary_to_term(DistributedBin42), + false = TestRef42_43 =:= TestPort, + + ok = do_unsetnode(Ref43), ok. test_encode_reference() -> @@ -787,20 +683,14 @@ test_encode_reference() -> <<131, 90, 0, 2, 119, 13, "nonode@nohost", 0:32, 1:32, 2:32>> ), true = is_reference(Ref123), - {ExpectedSize, HasV4NC} = + ExpectedSize = case erlang:system_info(machine) of "ATOM" -> % small utf8 atom & reference with 2 words - {31, true}; + 31; "BEAM" -> - OTPRelease = erlang:system_info(otp_release), - if - OTPRelease < "23" -> {33, false}; - OTPRelease < "24" -> {36, false}; - OTPRelease < "26" -> {36, true}; - % small utf8 atom - true -> {35, true} - end + % small utf8 atom + 35 end, ExpectedSize = byte_size(Bin), @@ -832,32 +722,27 @@ test_encode_reference() -> true = Ref6 > Ref3, % Starting from OTP-24 that introduced DFLAG_V4_NC, references can have 4 or 5 words - if - HasV4NC -> - Ref7 = binary_to_term_idempotent( - <<131, 90, 0, 4, 119, 4, "true", 1:32, 41:32, 42:32, 43:32, 44:32>>, "26" - ), - Ref8 = binary_to_term_idempotent( - <<131, 90, 0, 4, 119, 4, "true", 1:32, 44:32, 43:32, 42:32, 41:32>>, "26" - ), - "#Ref<1.44.43.42.41>" = ref_to_list(Ref7), - "#Ref<1.41.42.43.44>" = ref_to_list(Ref8), - true = Ref7 > Ref8, - true = Ref8 > Ref5, - - Ref9 = binary_to_term_idempotent( - <<131, 90, 0, 5, 119, 4, "true", 1:32, 40:32, 41:32, 42:32, 43:32, 44:32>>, "26" - ), - RefA = binary_to_term_idempotent( - <<131, 90, 0, 5, 119, 4, "true", 1:32, 44:32, 43:32, 42:32, 41:32, 40:32>>, "26" - ), - "#Ref<1.44.43.42.41.40>" = ref_to_list(Ref9), - "#Ref<1.40.41.42.43.44>" = ref_to_list(RefA), - true = Ref9 > RefA, - true = RefA > Ref7; - true -> - ok - end, + Ref7 = binary_to_term_idempotent( + <<131, 90, 0, 4, 119, 4, "true", 1:32, 41:32, 42:32, 43:32, 44:32>>, "26" + ), + Ref8 = binary_to_term_idempotent( + <<131, 90, 0, 4, 119, 4, "true", 1:32, 44:32, 43:32, 42:32, 41:32>>, "26" + ), + "#Ref<1.44.43.42.41>" = ref_to_list(Ref7), + "#Ref<1.41.42.43.44>" = ref_to_list(Ref8), + true = Ref7 > Ref8, + true = Ref8 > Ref5, + + Ref9 = binary_to_term_idempotent( + <<131, 90, 0, 5, 119, 4, "true", 1:32, 40:32, 41:32, 42:32, 43:32, 44:32>>, "26" + ), + RefA = binary_to_term_idempotent( + <<131, 90, 0, 5, 119, 4, "true", 1:32, 44:32, 43:32, 42:32, 41:32, 40:32>>, "26" + ), + "#Ref<1.44.43.42.41.40>" = ref_to_list(Ref9), + "#Ref<1.40.41.42.43.44>" = ref_to_list(RefA), + true = Ref9 > RefA, + true = RefA > Ref7, % Zero-length is tolerated RefB = binary_to_term_idempotent(<<131, 90, 0, 0, 119, 4, "true", 1:32>>, "26"), @@ -1020,62 +905,52 @@ test_encode_reference() -> error:badarg -> ok end, - case has_setnode_creation() of - true -> - % Test distributed pid - Ref42 = do_setnode(test@test_node, 42), - DistributedRef123_42 = binary_to_term( - <<131, 90, 0, 2, 119, 14, "test@test_node", 42:32, 1:32, 2:32>> - ), - true = is_reference(DistributedRef123_42), - true = DistributedRef123_42 =:= Ref123, - - DistributedBin42 = term_to_binary(TestRef), - true = DistributedBin42 =/= Bin, - TestRef42 = binary_to_term(DistributedBin42), - true = TestRef42 =:= TestRef, - ExpectedSize = byte_size(DistributedBin42) - 1, - - ok = do_unsetnode(Ref42), - - Ref43 = do_setnode(test@test_node, 43), - DistributedRef123_43 = binary_to_term( - <<131, 90, 0, 2, 119, 14, "test@test_node", 43:32, 1:32, 2:32>> - ), - true = is_reference(DistributedRef123_43), - true = DistributedRef123_43 =:= Ref123, - - DistributedRef123_42_43 = binary_to_term( - <<131, 90, 0, 2, 119, 14, "test@test_node", 42:32, 1:32, 2:32>> - ), - true = is_reference(DistributedRef123_42_43), - false = DistributedRef123_42_43 =:= Ref123, - - DistributedBin43 = term_to_binary(TestRef), - true = DistributedBin43 =/= Bin, - TestRef43 = binary_to_term(DistributedBin43), - true = TestRef43 =:= TestRef, - - ok = do_unsetnode(Ref43), - ok; - false -> - ok - end, + % Test distributed pid + Ref42 = do_setnode(test@test_node, 42), + DistributedRef123_42 = binary_to_term( + <<131, 90, 0, 2, 119, 14, "test@test_node", 42:32, 1:32, 2:32>> + ), + true = is_reference(DistributedRef123_42), + true = DistributedRef123_42 =:= Ref123, + + DistributedBin42 = term_to_binary(TestRef), + true = DistributedBin42 =/= Bin, + TestRef42 = binary_to_term(DistributedBin42), + true = TestRef42 =:= TestRef, + ExpectedSize = byte_size(DistributedBin42) - 1, + + ok = do_unsetnode(Ref42), + + Ref43 = do_setnode(test@test_node, 43), + DistributedRef123_43 = binary_to_term( + <<131, 90, 0, 2, 119, 14, "test@test_node", 43:32, 1:32, 2:32>> + ), + true = is_reference(DistributedRef123_43), + true = DistributedRef123_43 =:= Ref123, + + DistributedRef123_42_43 = binary_to_term( + <<131, 90, 0, 2, 119, 14, "test@test_node", 42:32, 1:32, 2:32>> + ), + true = is_reference(DistributedRef123_42_43), + false = DistributedRef123_42_43 =:= Ref123, + + DistributedBin43 = term_to_binary(TestRef), + true = DistributedBin43 =/= Bin, + TestRef43 = binary_to_term(DistributedBin43), + true = TestRef43 =:= TestRef, + + ok = do_unsetnode(Ref43), ok. test_encode_resource() -> OTPVersion = get_otp_version(), test_encode_resource(OTPVersion). -test_encode_resource(21) -> - ok; test_encode_resource(OTPVersion) -> R = socket:open(inet, stream, tcp), case OTPVersion of atomvm -> {ok, {Resource, _Ref}} = R; - 22 -> - {ok, {socket, Resource}} = R; _ -> {ok, {'$socket', Resource}} = R end, @@ -1096,7 +971,7 @@ test_encode_resource(OTPVersion) -> <<131, 90, 0, 4, 119, 13, "nonode@nohost", 0:32, A:32, (B + 4):32, C:32, D:32>>, AlteredResourceBin4 = <<131, 90, 0, 4, 119, 13, "nonode@nohost", 0:32, (A + 4):32, B:32, C:32, D:32>>; - OTPVersion >= 26 -> + true -> <<131, 90, 0, 3, 119, 13, "nonode@nohost", 0:32, A:32, B:32, C:32>> = ResourceBin, AlteredResourceBin1 = <<131, 90, 0, 3, 119, 13, "nonode@nohost", 0:32, A:32, B:32, (C + 1):32>>, @@ -1105,27 +980,7 @@ test_encode_resource(OTPVersion) -> AlteredResourceBin3 = <<131, 90, 0, 3, 119, 13, "nonode@nohost", 0:32, A:32, (B + 4):32, C:32>>, AlteredResourceBin4 = - <<131, 90, 0, 3, 119, 13, "nonode@nohost", 0:32, (A + 4):32, B:32, C:32>>; - OTPVersion >= 23 -> - <<131, 90, 0, 3, 100, 0, 13, "nonode@nohost", 0:32, A:32, B:32, C:32>> = ResourceBin, - AlteredResourceBin1 = - <<131, 90, 0, 3, 100, 0, 13, "nonode@nohost", 0:32, A:32, B:32, (C + 1):32>>, - AlteredResourceBin2 = - <<131, 90, 0, 3, 100, 0, 13, "nonode@nohost", 0:32, A:32, B:32, (C + 4):32>>, - AlteredResourceBin3 = - <<131, 90, 0, 3, 100, 0, 13, "nonode@nohost", 0:32, A:32, (B + 4):32, C:32>>, - AlteredResourceBin4 = - <<131, 90, 0, 3, 100, 0, 13, "nonode@nohost", 0:32, (A + 4):32, B:32, C:32>>; - OTPVersion =:= 22 -> - <<131, 114, 0, 3, 100, 0, 13, "nonode@nohost", 0, A:32, B:32, C:32>> = ResourceBin, - AlteredResourceBin1 = - <<131, 114, 0, 3, 100, 0, 13, "nonode@nohost", 0, A:32, B:32, (C + 1):32>>, - AlteredResourceBin2 = - <<131, 114, 0, 3, 100, 0, 13, "nonode@nohost", 0, A:32, B:32, (C + 4):32>>, - AlteredResourceBin3 = - <<131, 114, 0, 3, 100, 0, 13, "nonode@nohost", 0, A:32, (B + 4):32, C:32>>, - AlteredResourceBin4 = - <<131, 114, 0, 3, 100, 0, 13, "nonode@nohost", 0, (A + 4):32, B:32, C:32>> + <<131, 90, 0, 3, 119, 13, "nonode@nohost", 0:32, (A + 4):32, B:32, C:32>> end, AlteredResource1 = binary_to_term(AlteredResourceBin1), false = AlteredResource1 =:= Resource, @@ -1137,20 +992,10 @@ test_encode_resource(OTPVersion) -> false = AlteredResource4 =:= Resource, ok. -% Some binaries are re-encoded differently on earlier BEAM. Verify -% term_to_binary(binary_to_term(Bin)) is idempotent on AtomVM and recent OTPs. -binary_to_term_idempotent(Binary, OTPVersion) -> +% Verify term_to_binary(binary_to_term(Bin)) is idempotent. +binary_to_term_idempotent(Binary, _OTPVersion) -> Term = binary_to_term(Binary), - case erlang:system_info(machine) of - "ATOM" -> - Binary = term_to_binary(Term); - "BEAM" -> - OTPRelease = erlang:system_info(otp_release), - if - OTPRelease >= OTPVersion -> Binary = term_to_binary(Term); - true -> ok - end - end, + Binary = term_to_binary(Term), Term. test_atom_encoding() -> @@ -1175,13 +1020,7 @@ compare_pair_encoding(Id) -> A = ?MODULE:get_atom(Id), B = ?MODULE:get_binary(Id), A = erlang:binary_to_term(erlang:term_to_binary(A)), - OTPVersion = get_otp_version(), - if - OTPVersion =:= atomvm orelse OTPVersion >= 26 -> - B == erlang:term_to_binary(A); - true -> - true - end. + B == erlang:term_to_binary(A). % We don't have access to erlang module in tests. apply(F, []) -> diff --git a/tests/erlang_tests/test_bs.erl b/tests/erlang_tests/test_bs.erl index 55b9abcbbc..76d0950b0b 100644 --- a/tests/erlang_tests/test_bs.erl +++ b/tests/erlang_tests/test_bs.erl @@ -504,10 +504,8 @@ test_large() -> true = id(X) =:= <<42:1024>>, ok. -% From OTP22, the sequence 1:1,11:4,3:3 is converted to a string of 1 byte -% OTP 25-26 use OP_BS_CREATE_BIN with STRING -% OTP 22-24 use OP_BS_PUT_STRING -% OTP 21 uses OP_BS_PUT_INTEGER +% The sequence 1:1,11:4,3:3 is converted to a string of 1 byte +% OTP 26 uses OP_BS_CREATE_BIN with STRING test_copy_bits_string() -> A = id(42), X1 = id(0), @@ -551,8 +549,7 @@ test_bs_match_string_select() -> end, id(Z). -% With OTP25 and lower, this generates bs_skip_init2 with flags equal to 2 (little) -% More recent versions of OTP use bs_match +% OTP 26+ uses bs_match for this pattern test_bs_skip_bits2_little() -> ok = check_x86_64_jt(id(<<16#e9, 0:32>>)). @@ -630,21 +627,13 @@ test_float() -> <<192, 0, 0, 0, 0, 0, 0, 0>> = <>, <<66, 0, 0, 0>> = <>, - % 16-bit floats are supported in OTP 24+ and AtomVM - case has_16bit_floats() of - true -> - % Test that 16-bit floats work - Pi16 = id(3.14), - <<66, 72>> = <>, - <<66, 72>> = <>, - <<72, 66>> = <>, - <> = <<66, 72, 3, 14>>, - <> = <<72, 66, 3, 14>>, - true = abs(Pi16B - Pi16) < 0.001, - ok; - false -> - ok - end, + Pi16 = id(3.14), + <<66, 72>> = <>, + <<66, 72>> = <>, + <<72, 66>> = <>, + <> = <<66, 72, 3, 14>>, + <> = <<72, 66, 3, 14>>, + true = abs(Pi16B - Pi16) < 0.001, ok = test_integer_outside_float_limits(), ok = test_create_with_invalid_float_value(), @@ -687,15 +676,9 @@ test_integer_outside_float_limits() -> <<127, 128, 0, 0>> = create_float_binary(V, id(32)), <<255, 128, 0, 0>> = create_float_binary(-V, id(32)), - % 16-bit floats are supported in OTP 24+ and AtomVM - case has_16bit_floats() of - true -> - <<124, 0>> = create_float_binary(V, id(16)), - <<252, 0>> = create_float_binary(-V, id(16)), - ok; - false -> - ok - end + <<124, 0>> = create_float_binary(V, id(16)), + <<252, 0>> = create_float_binary(-V, id(16)), + ok end, ok. @@ -712,11 +695,3 @@ ext_id(X) -> X. join(X, Y) -> <>. - -has_16bit_floats() -> - case erlang:system_info(machine) of - "BEAM" -> - erlang:system_info(otp_release) >= "24"; - "ATOM" -> - true - end. diff --git a/tests/erlang_tests/test_bs_create_bin_accum.erl b/tests/erlang_tests/test_bs_create_bin_accum.erl index 644ee5e534..b5b94e142e 100644 --- a/tests/erlang_tests/test_bs_create_bin_accum.erl +++ b/tests/erlang_tests/test_bs_create_bin_accum.erl @@ -23,21 +23,8 @@ -export([start/0]). start() -> - HasBSCreateBin = - case erlang:system_info(machine) of - "BEAM" -> - erlang:system_info(otp_release) >= "25"; - "ATOM" -> - ?OTP_RELEASE >= 25 - end, - ok = - if - HasBSCreateBin -> - ok = test_int_utf8(), - ok = test_int_float(); - true -> - ok - end, + ok = test_int_utf8(), + ok = test_int_float(), 0. test_int_utf8() -> diff --git a/tests/erlang_tests/test_code_server_nifs.erl b/tests/erlang_tests/test_code_server_nifs.erl index f1418e40ac..27b237af92 100644 --- a/tests/erlang_tests/test_code_server_nifs.erl +++ b/tests/erlang_tests/test_code_server_nifs.erl @@ -23,18 +23,11 @@ -export([start/0, test_literals/0]). start() -> + ok = test_is_loaded(), case erlang:system_info(machine) of "BEAM" -> - OTPRelease = erlang:system_info(otp_release), - if - OTPRelease >= "26" -> - ok = test_is_loaded(); - true -> - ok - end, ok; "ATOM" -> - ok = test_is_loaded(), case erlang:system_info(emu_flavor) of jit -> ok = test_atom_resolver(), diff --git a/tests/erlang_tests/test_crypto.erl b/tests/erlang_tests/test_crypto.erl index cefb8e1b09..e3e99b1d66 100644 --- a/tests/erlang_tests/test_crypto.erl +++ b/tests/erlang_tests/test_crypto.erl @@ -23,14 +23,8 @@ start() -> ok = test_hash(), - OTPVersion = get_otp_version(), - case OTPVersion =:= atomvm orelse OTPVersion >= 24 of - true -> - ok = test_crypto_one_time(), - ok = test_available_ciphers(); - false -> - ok - end, + ok = test_crypto_one_time(), + ok = test_available_ciphers(), 0. test_hash() -> @@ -215,11 +209,3 @@ get_error(F) -> catch _:E -> E end. - -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> - list_to_integer(erlang:system_info(otp_release)); - _ -> - atomvm - end. diff --git a/tests/erlang_tests/test_ets.erl b/tests/erlang_tests/test_ets.erl index 2b5963d671..e0b858b1e9 100644 --- a/tests/erlang_tests/test_ets.erl +++ b/tests/erlang_tests/test_ets.erl @@ -58,10 +58,7 @@ test_ets_new() -> ets:new(heir_test, [{heir, none}]), ets:new(write_conc_test, [{write_concurrency, true}]), ets:new(read_conc_test, [{read_concurrency, true}]), - case otp_version() of - OTP when OTP >= 23 -> ets:new(decent_counters_test, [{decentralized_counters, true}]); - _ -> ok - end, + ets:new(decent_counters_test, [{decentralized_counters, true}]), ets:new(compressed_test, [compressed]), ok. @@ -131,10 +128,7 @@ test_keys() -> #{another => "map"} => erlang:make_ref(), <<1, 2, 3, 4>> => <<-4, -3, -2, -1>> }), - case supports_v4_port_encoding() of - true -> ok = assert_stored_key(T, binary_to_term(DistributedPortBin)); - false -> ok - end, + ok = assert_stored_key(T, binary_to_term(DistributedPortBin)), ok. test_keypos() -> @@ -309,23 +303,3 @@ assert_badarg(Fun) -> OtherClass:OtherError -> erlang:error({OtherClass, OtherError}) end. - -supports_v4_port_encoding() -> - case erlang:system_info(machine) of - "ATOM" -> - % small utf8 atom - true; - "BEAM" -> - OTP = otp_version(), - if - OTP < 24 -> false; - % v4 is supported but not the default - OTP < 26 -> true; - % small utf8 atom - true -> true - end - end. - -otp_version() -> - OTPRelease = erlang:system_info(otp_release), - list_to_integer(OTPRelease). diff --git a/tests/erlang_tests/test_is_integer_3.erl b/tests/erlang_tests/test_is_integer_3.erl index 9b682ba450..a235ecb8b7 100644 --- a/tests/erlang_tests/test_is_integer_3.erl +++ b/tests/erlang_tests/test_is_integer_3.erl @@ -20,11 +20,9 @@ -module(test_is_integer_3). --ifdef(OTP_RELEASE). -if(?OTP_RELEASE >= 29). -define(OTP29_OR_LATER, true). -endif. --endif. -ifdef(OTP29_OR_LATER). diff --git a/tests/erlang_tests/test_map.erl b/tests/erlang_tests/test_map.erl index fc4f14f912..2d9cb7d1c5 100644 --- a/tests/erlang_tests/test_map.erl +++ b/tests/erlang_tests/test_map.erl @@ -80,8 +80,6 @@ test_map_size_bif() -> ok end. -%% OTP 21 or later --ifdef(OTP_RELEASE). test_is_map_key_bif() -> ok = case id(#{a => 1, b => 2}) of @@ -142,11 +140,6 @@ test_map_get_bif() -> _:{badmap, _} -> ok end. --else. -test_is_map_key_bif() -> ok. - -test_map_get_bif() -> ok. --endif. test_literal_map() -> Map = #{a => 1, b => 2}, diff --git a/tests/erlang_tests/test_min_max_guard.erl b/tests/erlang_tests/test_min_max_guard.erl index f6eb973597..4b5d95bb91 100644 --- a/tests/erlang_tests/test_min_max_guard.erl +++ b/tests/erlang_tests/test_min_max_guard.erl @@ -30,23 +30,12 @@ start() -> ok = test_tail(), 0. --ifdef(OTP_RELEASE). -%% OTP 21 or higher --if(?OTP_RELEASE >= 26). test_guard(min, X, Y, Z) when min(X, Y) < Z -> ok; test_guard(max, X, Y, Z) when max(X, Y) > Z -> ok; test_guard(_Op, _X, _Y, _Z) -> fail. --else. -test_guard(_Op, _X, _Y, _Z) -> - ok. --endif. --else. -test_guard(_Op, _X, _Y, _Z) -> - ok. --endif. test_without_guard(min, X, Y, Z) -> case min(X, Y) < Z of diff --git a/tests/erlang_tests/test_multi_value_comprehension.erl b/tests/erlang_tests/test_multi_value_comprehension.erl index d0bee6fd58..2bed72f008 100644 --- a/tests/erlang_tests/test_multi_value_comprehension.erl +++ b/tests/erlang_tests/test_multi_value_comprehension.erl @@ -24,11 +24,9 @@ %% Test multi-valued comprehensions (EEP 78, OTP 29+) --ifdef(OTP_RELEASE). -if(?OTP_RELEASE >= 29). -define(OTP29_OR_LATER, true). -endif. --endif. -ifdef(OTP29_OR_LATER). diff --git a/tests/erlang_tests/test_node.erl b/tests/erlang_tests/test_node.erl index dc0077b90d..bdaac120c2 100644 --- a/tests/erlang_tests/test_node.erl +++ b/tests/erlang_tests/test_node.erl @@ -67,13 +67,7 @@ test_node_distribution() -> ok. has_setnode_creation() -> - case erlang:system_info(machine) of - "ATOM" -> - true; - "BEAM" -> - OTPRelease = erlang:system_info(otp_release), - OTPRelease >= "23" - end. + true. get_creation() -> case erlang:system_info(machine) of diff --git a/tests/erlang_tests/test_op_bs_create_bin.erl b/tests/erlang_tests/test_op_bs_create_bin.erl index 0d8610af3a..03875c662f 100644 --- a/tests/erlang_tests/test_op_bs_create_bin.erl +++ b/tests/erlang_tests/test_op_bs_create_bin.erl @@ -23,26 +23,12 @@ -export([start/0]). start() -> - HasBSCreateBin = - case erlang:system_info(machine) of - "BEAM" -> - erlang:system_info(otp_release) >= "25"; - "ATOM" -> - % If code was compiled with OTP < 25, we won't have bs_create_bin asm file - ?OTP_RELEASE >= 25 - end, - ok = - if - HasBSCreateBin -> - ok = test_bs_create_bin_utf8(), - ok = test_bs_create_bin_utf16(), - ok = test_bs_create_bin_utf32(), - ok = test_bs_create_bin_integer(), - ok = test_bs_create_bin_binary(), - ok = test_bs_create_bin_alloc_list(); - true -> - ok - end, + ok = test_bs_create_bin_utf8(), + ok = test_bs_create_bin_utf16(), + ok = test_bs_create_bin_utf32(), + ok = test_bs_create_bin_integer(), + ok = test_bs_create_bin_binary(), + ok = test_bs_create_bin_alloc_list(), 0. test_bs_create_bin_utf8() -> diff --git a/tests/erlang_tests/test_op_bs_start_match.erl b/tests/erlang_tests/test_op_bs_start_match.erl index ed9364dad4..b44201ad83 100644 --- a/tests/erlang_tests/test_op_bs_start_match.erl +++ b/tests/erlang_tests/test_op_bs_start_match.erl @@ -23,23 +23,9 @@ -export([start/0]). start() -> - HasBSStartMatch4 = - case erlang:system_info(machine) of - "BEAM" -> - erlang:system_info(otp_release) >= "23"; - "ATOM" -> - % If code was compiled with OTP < 23, we won't have bs_start_match asm file - ?OTP_RELEASE >= 23 - end, - ok = - if - HasBSStartMatch4 -> - ok = test_bs_start_match3_fail_label(), - ok = test_bs_start_match4_fail_label(), - ok = test_bs_start_match4_nofail_resume(); - true -> - ok - end, + ok = test_bs_start_match3_fail_label(), + ok = test_bs_start_match4_fail_label(), + ok = test_bs_start_match4_nofail_resume(), 0. test_bs_start_match3_fail_label() -> diff --git a/tests/erlang_tests/test_stacktrace.erl b/tests/erlang_tests/test_stacktrace.erl index 945b0d0380..cd4a62bf0c 100644 --- a/tests/erlang_tests/test_stacktrace.erl +++ b/tests/erlang_tests/test_stacktrace.erl @@ -29,25 +29,20 @@ -include("test_stacktrace.hrl"). start() -> - case ?OTP_RELEASE of - OTPVersion when OTPVersion >= 23 -> - ok = test_local_throw(), - ok = test_local_error(), - ok = test_badmatch(), - ok = test_apply(), - ok = test_fun(), - ok = test_remote_throw(), - ok = test_tail_recursive_throw(), - ok = test_body_recursive_throw(), - ok = test_spawned_throw(), - ok = test_catch(), - ok = maybe_test_filelineno(), - ok = maybe_test_filelineno_other_file(), - ok = maybe_test_filelineno_large(), - 0; - _ -> - 0 - end. + ok = test_local_throw(), + ok = test_local_error(), + ok = test_badmatch(), + ok = test_apply(), + ok = test_fun(), + ok = test_remote_throw(), + ok = test_tail_recursive_throw(), + ok = test_body_recursive_throw(), + ok = test_spawned_throw(), + ok = test_catch(), + ok = maybe_test_filelineno(), + ok = maybe_test_filelineno_other_file(), + ok = maybe_test_filelineno_large(), + 0. test_local_throw() -> ok = diff --git a/tests/erlang_tests/test_system_info.erl b/tests/erlang_tests/test_system_info.erl index f44d5e1bb6..4c48898b5c 100644 --- a/tests/erlang_tests/test_system_info.erl +++ b/tests/erlang_tests/test_system_info.erl @@ -46,7 +46,7 @@ start() -> OTPRelease = erlang:system_info(otp_release), true = is_list(OTPRelease), OTPReleaseInt = list_to_integer(OTPRelease), - true = OTPReleaseInt > 20, + true = OTPReleaseInt >= 26, case Machine of "BEAM" -> % beam raises badarg, and probably so should AtomVM. diff --git a/tests/erlang_tests/test_utf8_atoms.erl b/tests/erlang_tests/test_utf8_atoms.erl index 90835d26f2..e5164462d8 100644 --- a/tests/erlang_tests/test_utf8_atoms.erl +++ b/tests/erlang_tests/test_utf8_atoms.erl @@ -187,15 +187,7 @@ comp(A, A) -> 1; comp(_A, _B) -> 0. comp_opt(Fun1, Fun2) -> - case erlang:system_info(machine) of - "BEAM" -> - case erlang:system_info(otp_release) of - Version when Version >= "23" -> comp(Fun1(), Fun2()); - _OldVersion -> 1 - end; - _ -> - comp(Fun1(), Fun2()) - end. + comp(Fun1(), Fun2()). get_atom(Id) -> case Id of diff --git a/tests/libs/eavmlib/test_ahttp_client.erl b/tests/libs/eavmlib/test_ahttp_client.erl index 7f8fb45dd5..6ef1adb675 100644 --- a/tests/libs/eavmlib/test_ahttp_client.erl +++ b/tests/libs/eavmlib/test_ahttp_client.erl @@ -24,13 +24,9 @@ test() -> ok = test_passive(), ok = test_active(), - case get_otp_version() of - Version when Version =:= atomvm orelse (is_integer(Version) andalso Version >= 24) -> - ok = test_passive_socket(), - ok = test_active_socket(); - _ -> - ok - end. + ok = test_passive_socket(), + ok = test_active_socket(), + ok. test_passive() -> ok = ssl:start(), @@ -162,11 +158,3 @@ parse_responses( _Expected ) -> Resp#{done => true}. - -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> - list_to_integer(erlang:system_info(otp_release)); - _ -> - atomvm - end. diff --git a/tests/libs/estdlib/test_epmd.erl b/tests/libs/estdlib/test_epmd.erl index 4c99d7ef47..9b3fc59b72 100644 --- a/tests/libs/estdlib/test_epmd.erl +++ b/tests/libs/estdlib/test_epmd.erl @@ -25,35 +25,21 @@ -define(EPMD_PORT, 4369). test() -> - % AtomVM's epmd only runs on AtomVM and OTP 24+ - CanRunEpmd = - case erlang:system_info(machine) of - "ATOM" -> - true; - "BEAM" -> - OTPRelease = erlang:system_info(otp_release), - OTPRelease >= "24" - end, - if - CanRunEpmd -> - case stop_epmd() of - ok -> - {ok, Pid} = epmd:start_link([]), - ok = test_client(), - ok = test_two_clients(), - MonitorRef = monitor(process, Pid), - unlink(Pid), - exit(Pid, shutdown), - ok = - receive - {'DOWN', MonitorRef, process, Pid, shutdown} -> ok - after 5000 -> timeout - end, - ok; - {error, not_found} -> - ok - end; - true -> + case stop_epmd() of + ok -> + {ok, Pid} = epmd:start_link([]), + ok = test_client(), + ok = test_two_clients(), + MonitorRef = monitor(process, Pid), + unlink(Pid), + exit(Pid, shutdown), + ok = + receive + {'DOWN', MonitorRef, process, Pid, shutdown} -> ok + after 5000 -> timeout + end, + ok; + {error, not_found} -> ok end, case start_epmd() of @@ -177,28 +163,10 @@ stop_epmd() -> test_client() -> {ok, Pid1} = erl_epmd:start_link(), - ok = - case erl_epmd:port_please("test_epmd", "host.invalid") of - noport -> - ok; - {error, nxdomain} -> - "BEAM" = erlang:system_info(machine), - true = erlang:system_info(otp_release) =< "22", - ok - end, + noport = erl_epmd:port_please("test_epmd", "host.invalid"), noport = erl_epmd:port_please("test_epmd", "localhost"), {ok, Creation1} = erl_epmd:register_node("test_epmd", 12345), - {port, 12345, Version} = erl_epmd:port_please("test_epmd", "localhost"), - case erlang:system_info(machine) of - "BEAM" -> - case erlang:system_info(otp_release) of - "21" -> 5 = Version; - "22" -> 5 = Version; - _ -> 6 = Version - end; - "ATOM" -> - 6 = Version - end, + {port, 12345, 6} = erl_epmd:port_please("test_epmd", "localhost"), {error, already_registered} = erl_epmd:register_node("test_epmd", 12345), {error, already_registered} = erl_epmd:register_node("test_epmd_new", 12346), {ok, Names} = erl_epmd:names("localhost"), diff --git a/tests/libs/estdlib/test_gen_server.erl b/tests/libs/estdlib/test_gen_server.erl index c9323772fe..3b75cafa7a 100644 --- a/tests/libs/estdlib/test_gen_server.erl +++ b/tests/libs/estdlib/test_gen_server.erl @@ -94,23 +94,17 @@ test_start_link() -> ok. test_start_monitor() -> - case get_otp_version() of - %% Test on AtomVM and OTP 23 and later - Version when Version >= 23 -> - {ok, {Pid, Ref}} = gen_server:start_monitor(?MODULE, [], []), + {ok, {Pid, Ref}} = gen_server:start_monitor(?MODULE, [], []), - pong = gen_server:call(Pid, ping), - pong = gen_server:call(Pid, reply_ping), - ok = gen_server:cast(Pid, crash), - ok = - receive - {'DOWN', Ref, process, Pid, _Reason} -> ok - after 30000 -> timeout - end, - ok; - _ -> - ok - end. + pong = gen_server:call(Pid, ping), + pong = gen_server:call(Pid, reply_ping), + ok = gen_server:cast(Pid, crash), + ok = + receive + {'DOWN', Ref, process, Pid, _Reason} -> ok + after 30000 -> timeout + end, + ok. test_start_name() -> undefined = whereis(?MODULE), @@ -131,18 +125,12 @@ test_start_name() -> undefined = whereis(?MODULE), true = erlang:process_flag(trap_exit, PreviousTrapExit), - case get_otp_version() of - %% Test on AtomVM and OTP 23 and later - Version when Version >= 23 -> - {ok, {Pid3, MonitorRef}} = gen_server:start_monitor({local, ?MODULE}, ?MODULE, [], []), - Pid3 = whereis(?MODULE), - % Demonitor to avoid any DOWN message - true = demonitor(MonitorRef), - ok = gen_server:stop(Pid3), - undefined = whereis(?MODULE); - _ -> - ok - end, + {ok, {Pid3, MonitorRef}} = gen_server:start_monitor({local, ?MODULE}, ?MODULE, [], []), + Pid3 = whereis(?MODULE), + % Demonitor to avoid any DOWN message + true = demonitor(MonitorRef), + ok = gen_server:stop(Pid3), + undefined = whereis(?MODULE), ok. test_continue() -> diff --git a/tests/libs/estdlib/test_gen_tcp.erl b/tests/libs/estdlib/test_gen_tcp.erl index 9b01ad1da1..1ae52886b6 100644 --- a/tests/libs/estdlib/test_gen_tcp.erl +++ b/tests/libs/estdlib/test_gen_tcp.erl @@ -138,13 +138,8 @@ loop(Socket, I) -> end. test_listen_connect_parameters() -> - case get_otp_version() of - Version when Version =:= atomvm orelse (is_integer(Version) andalso Version >= 24) -> - ok = test_listen_connect_parameters(socket, socket), - ok = test_listen_connect_parameters(inet, inet); - _ -> - ok = test_listen_connect_parameters(inet, inet) - end, + ok = test_listen_connect_parameters(socket, socket), + ok = test_listen_connect_parameters(inet, inet), ok. test_listen_connect_parameters(InetClientBackend, InetServerBackend) -> @@ -169,15 +164,8 @@ test_listen_connect_parameters( InetClientBackend, InetServerBackend, ListenMode, ConnectMode, ListenActive, ConnectActive ) -> etest:flush_msg_queue(), - - case get_otp_version() of - Version when Version =:= atomvm orelse (is_integer(Version) andalso Version >= 24) -> - ServerBackendOption = [{inet_backend, InetServerBackend}], - ClientBackendOption = [{inet_backend, InetClientBackend}]; - _ -> - ServerBackendOption = [], - ClientBackendOption = [] - end, + ServerBackendOption = [{inet_backend, InetServerBackend}], + ClientBackendOption = [{inet_backend, InetClientBackend}], io:format( "GEN_TCP-TEST> ServerBackendOption=~p ClientBackendOption=~p ListenMode=~p ConnectMode=~p ListenActive=~p ConnectActive=~p~n", @@ -378,21 +366,12 @@ test_connect_parameters() -> end, Hostname = "www.atomvm.org", Port = 80, - OptTests = - case get_otp_version() of - Version when Version =:= atomvm orelse (is_integer(Version) andalso Version >= 24) -> - [ - [{active, true}], - [{active, false}], - [{inet_backend, socket}, {active, true}], - [{inet_backend, socket}, {active, false}] - ]; - _ -> - [ - [{active, true}], - [{active, false}] - ] - end, + OptTests = [ + [{active, true}], + [{active, false}], + [{inet_backend, socket}, {active, true}], + [{inet_backend, socket}, {active, false}] + ], test_connect_parameters(OptTests, IP, Hostname, Port, []). test_connect_parameters([], _IP, _Host, _Port, Results) -> @@ -427,13 +406,7 @@ test_connect_parameters([Test | TestOpts], IP, Host, Port, Results) -> test_connect_bad_address() -> InetTest = test_connect_bad_address(inet_backend, []), - SocketTest = - case get_otp_version() of - Version when Version =:= atomvm orelse (is_integer(Version) andalso Version >= 24) -> - test_connect_bad_address(socket_backend, [{inet_backend, socket}]); - _ -> - ok - end, + SocketTest = test_connect_bad_address(socket_backend, [{inet_backend, socket}]), Result = [InetTest, SocketTest], case Result of [ok, ok] -> @@ -532,11 +505,3 @@ test_tcp_double_close() -> ok = gen_tcp:close(Socket), {error, closed} = gen_tcp:recv(Socket, 512, 5000), ok. - -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> - list_to_integer(erlang:system_info(otp_release)); - _ -> - atomvm - end. diff --git a/tests/libs/estdlib/test_gen_udp.erl b/tests/libs/estdlib/test_gen_udp.erl index e6e1bc515a..83c237901c 100644 --- a/tests/libs/estdlib/test_gen_udp.erl +++ b/tests/libs/estdlib/test_gen_udp.erl @@ -25,19 +25,12 @@ -include("etest.hrl"). test() -> - BackendOptions = - case get_otp_version() of - Version when Version =:= atomvm orelse (is_integer(Version) andalso Version >= 24) -> - [[{inet_backend, inet}], [{inet_backend, socket}]]; - _ -> - [[]] - end, [ ok = test_send_receive(SpawnControllingProcess, IsActive, Mode, BackendOption) || SpawnControllingProcess <- [false, true], IsActive <- [false, true], Mode <- [binary, list], - BackendOption <- BackendOptions + BackendOption <- [[{inet_backend, inet}], [{inet_backend, socket}]] ], ok. @@ -163,11 +156,3 @@ count_passive_received(Socket, Mode, I) -> erlang:display({count_passive_received, unexpected, Other}), count_passive_received(Socket, Mode, I) end. - -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> - list_to_integer(erlang:system_info(otp_release)); - _ -> - atomvm - end. diff --git a/tests/libs/estdlib/test_inet.erl b/tests/libs/estdlib/test_inet.erl index e3e77aaf0d..bb9d8e89fe 100644 --- a/tests/libs/estdlib/test_inet.erl +++ b/tests/libs/estdlib/test_inet.erl @@ -50,25 +50,12 @@ test_ntoa() -> "192.168.0.1" = inet:ntoa({192, 168, 0, 1}), "0.0.0.0" = inet:ntoa({0, 0, 0, 0}), "255.255.255.255" = inet:ntoa({255, 255, 255, 255}), - case get_otp_version() of - OTPVersion when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm - -> - {error, einval} = inet:ntoa({256, 0, 0, 1}), - {error, einval} = inet:ntoa({0, 0, 0, -1}), - {error, einval} = inet:ntoa({1, 2, 3}), - {error, einval} = inet:ntoa(not_an_address); - _ -> - ok - end, + {error, einval} = inet:ntoa({256, 0, 0, 1}), + {error, einval} = inet:ntoa({0, 0, 0, -1}), + {error, einval} = inet:ntoa({1, 2, 3}), + {error, einval} = inet:ntoa(not_an_address), ok. -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> list_to_integer(erlang:system_info(otp_release)); - _ -> atomvm - end. - test_parse_address() -> {ok, {127, 0, 0, 1}} = inet:parse_address("127.0.0.1"), {ok, {192, 168, 0, 1}} = inet:parse_address("192.168.0.1"), diff --git a/tests/libs/estdlib/test_maps.erl b/tests/libs/estdlib/test_maps.erl index 38439b7d25..8282f78b2c 100644 --- a/tests/libs/estdlib/test_maps.erl +++ b/tests/libs/estdlib/test_maps.erl @@ -383,7 +383,6 @@ check_bad_key(F, _Key) -> F(), fail catch - %% TODO OTP23 compiler compiles to erlang:map_ equivalents error:{badkey, _} -> ok end. diff --git a/tests/libs/estdlib/test_net_kernel.erl b/tests/libs/estdlib/test_net_kernel.erl index 05bbbb7d9c..64e4933ffb 100644 --- a/tests/libs/estdlib/test_net_kernel.erl +++ b/tests/libs/estdlib/test_net_kernel.erl @@ -30,21 +30,21 @@ start() -> test() -> Platform = erlang:system_info(machine), - case has_compatible_erl(Platform) andalso has_epmd(Platform) of + case has_command(Platform, "erl") andalso has_epmd(Platform) of true -> ok = ensure_epmd(Platform), ok = test_ping_from_beam(Platform), ok = test_fail_with_wrong_cookie(Platform), ok = test_rpc_from_beam(Platform), ok = test_rpc_loop_from_beam(Platform), - ok = test_autoconnect_fail(Platform), + ok = test_autoconnect_fail(), ok = test_autoconnect_to_beam(Platform), ok = test_groupleader(Platform), ok = test_link_remote_exit_remote(Platform), ok = test_link_remote_exit_local(Platform), ok = test_link_local_unlink_remote(Platform), ok = test_link_local_unlink_local(Platform), - ok = test_is_alive(Platform), + ok = test_is_alive(), ok = test_ping_with_avm_dist_opts(Platform), ok; false -> @@ -52,23 +52,6 @@ test() -> ok end. -%% Determine if we can connect with BEAM. -%% This test currently supports AtomVM connecting with OTP 24+ -%% as well as any version of OTP connecting with OTP -has_compatible_erl("BEAM" = Platform) -> - has_command(Platform, "erl"); -has_compatible_erl("ATOM") -> - case has_command("ATOM", "erl") of - true -> - Result = execute_command( - "ATOM", - "erl -eval \"io:put_chars(erlang:system_info(otp_release) ++ [13,10]).\" -s init stop -noshell" - ), - Result >= "24"; - false -> - false - end. - has_epmd(Platform) -> has_command(Platform, "epmd"). @@ -96,10 +79,9 @@ ensure_epmd("ATOM") -> ok. test_ping_from_beam(Platform) -> - {ok, _NetKernelPid} = net_kernel_start(Platform, atomvm), + {ok, _NetKernelPid} = net_kernel:start(atomvm, #{name_domain => shortnames}), Node = node(), - % erlang:set_cookie/1 is from OTP 24.1 - erlang:set_cookie(Node, 'AtomVM'), + erlang:set_cookie('AtomVM'), Result = execute_command( Platform, "erl -sname " ++ ?OTP_SNAME ++ " -setcookie AtomVM -eval \"R = net_adm:ping('" ++ @@ -111,9 +93,9 @@ test_ping_from_beam(Platform) -> ok. test_fail_with_wrong_cookie(Platform) -> - {ok, _NetKernelPid} = net_kernel_start(Platform, atomvm), + {ok, _NetKernelPid} = net_kernel:start(atomvm, #{name_domain => shortnames}), Node = node(), - erlang:set_cookie(Node, 'AtomVM'), + erlang:set_cookie('AtomVM'), Result = execute_command( Platform, "erl -sname " ++ ?OTP_SNAME ++ " -setcookie Wrong -eval \"R = net_adm:ping('" ++ @@ -125,9 +107,9 @@ test_fail_with_wrong_cookie(Platform) -> ok. test_rpc_from_beam(Platform) -> - {ok, _NetKernelPid} = net_kernel_start(Platform, atomvm), + {ok, _NetKernelPid} = net_kernel:start(atomvm, #{name_domain => shortnames}), Node = node(), - erlang:set_cookie(Node, 'AtomVM'), + erlang:set_cookie('AtomVM'), Result = execute_command( Platform, "erl -sname " ++ ?OTP_SNAME ++ " -setcookie AtomVM -eval \"R = rpc:call('" ++ @@ -139,9 +121,9 @@ test_rpc_from_beam(Platform) -> ok. test_rpc_loop_from_beam(Platform) -> - {ok, _NetKernelPid} = net_kernel_start(Platform, atomvm), + {ok, _NetKernelPid} = net_kernel:start(atomvm, #{name_domain => shortnames}), Node = node(), - erlang:set_cookie(Node, 'AtomVM'), + erlang:set_cookie('AtomVM'), Result = execute_command( Platform, "erl -sname " ++ ?OTP_SNAME ++ @@ -153,10 +135,10 @@ test_rpc_loop_from_beam(Platform) -> net_kernel:stop(), ok. -test_autoconnect_fail(Platform) -> - {ok, _NetKernelPid} = net_kernel_start(Platform, atomvm), +test_autoconnect_fail() -> + {ok, _NetKernelPid} = net_kernel:start(atomvm, #{name_domain => shortnames}), Node = node(), - erlang:set_cookie(Node, 'AtomVM'), + erlang:set_cookie('AtomVM'), [_, Host] = string:split(atom_to_list(Node), "@"), OTPNode = list_to_atom("otp@" ++ Host), {beam, OTPNode} ! {self(), ping}, @@ -165,10 +147,10 @@ test_autoconnect_fail(Platform) -> test_autoconnect_to_beam(Platform) -> OtpSname = ?OTP_SNAME, - {ok, _NetKernelPid} = net_kernel_start(Platform, atomvm), + {ok, _NetKernelPid} = net_kernel:start(atomvm, #{name_domain => shortnames}), Node = node(), Parent = self(), - erlang:set_cookie(Node, 'AtomVM'), + erlang:set_cookie('AtomVM'), {Pid, MonitorRef} = spawn_opt( fun() -> Command = @@ -242,9 +224,9 @@ test_autoconnect_to_beam(Platform) -> ok. start_apply_loop(Platform) -> - {ok, _NetKernelPid} = net_kernel_start(Platform, atomvm), + {ok, _NetKernelPid} = net_kernel:start(atomvm, #{name_domain => shortnames}), Node = node(), - erlang:set_cookie(Node, 'AtomVM'), + erlang:set_cookie('AtomVM'), register(atomvm, self()), Parent = self(), {Pid, MonitorRef} = spawn_opt( @@ -476,9 +458,9 @@ test_link_local_unlink_local(Platform) -> ok = stop_apply_loop(BeamMainPid, Pid, MonitorRef), ok. -test_is_alive(Platform) -> +test_is_alive() -> false = is_alive(), - {ok, _NetKernelPid} = net_kernel_start(Platform, atomvm), + {ok, _NetKernelPid} = net_kernel:start(atomvm, #{name_domain => shortnames}), true = is_alive(), net_kernel:stop(), false = is_alive(), @@ -565,14 +547,3 @@ beam_loop_read(Port, Acc) -> after 5000 -> exit(timeout) end. - -net_kernel_start("ATOM", Nodename) -> - net_kernel:start(Nodename, #{name_domain => shortnames}); -net_kernel_start("BEAM", Nodename) -> - OTPRelease = erlang:system_info(otp_release), - if - OTPRelease >= "24" -> - net_kernel:start(Nodename, #{name_domain => shortnames}); - true -> - net_kernel:start([Nodename, shortnames]) - end. diff --git a/tests/libs/estdlib/test_proc_lib.erl b/tests/libs/estdlib/test_proc_lib.erl index 2c783d1960..c905c0c7cf 100644 --- a/tests/libs/estdlib/test_proc_lib.erl +++ b/tests/libs/estdlib/test_proc_lib.erl @@ -28,12 +28,7 @@ test() -> ok = test_start_monitor_badarg(), ok = test_start_link_sync(), ok = test_start_link_opt_sync(), - case get_otp_version() of - Version when Version >= 23 -> - ok = test_start_monitor_sync(); - _ -> - ok - end, + ok = test_start_monitor_sync(), ok = test_start_timeout(), ok = test_start_crash(), ok = test_initial_call_and_ancestors(), @@ -268,11 +263,3 @@ init_crash({Class, Reason, Stacktrace}) -> init_initial_call_ancestors(Parent) -> proc_lib:init_ack(Parent, {ok, get('$initial_call'), get('$ancestors')}). - -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> - list_to_integer(erlang:system_info(otp_release)); - _ -> - atomvm - end. diff --git a/tests/libs/estdlib/test_queue.erl b/tests/libs/estdlib/test_queue.erl index 569aa93209..0b5de70683 100644 --- a/tests/libs/estdlib/test_queue.erl +++ b/tests/libs/estdlib/test_queue.erl @@ -48,23 +48,17 @@ test() -> ok = test_split(), ok = test_filter(), ok = test_filter_replace(), - ok = test_filtermap(get_otp_version()), - ok = test_filtermap_replace(get_otp_version()), - ok = test_fold(get_otp_version()), - ok = test_any(get_otp_version()), - ok = test_all(get_otp_version()), - ok = test_delete(get_otp_version()), - ok = test_delete_with(get_otp_version()), - ok = test_delete_with_r(get_otp_version()), + ok = test_filtermap(), + ok = test_filtermap_replace(), + ok = test_fold(), + ok = test_any(), + ok = test_all(), + ok = test_delete(), + ok = test_delete_with(), + ok = test_delete_with_r(), ok = test_complete_flow(), ok. -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> list_to_integer(erlang:system_info(otp_release)); - _ -> atomvm - end. - test_from_to_list() -> L = [1, -1, 2, -3], Q = queue:from_list(L), @@ -234,83 +228,51 @@ test_filter_replace() -> ?ASSERT_MATCH(queue:to_list(Q1), [1, 2, 2, 3, 3, 4, 4, 5, 5, 6]), ok. -test_filtermap(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_filtermap() -> Q = queue:from_list([1, 2, 3, 4, 5]), Q1 = queue:filtermap(fun(E) -> E > 2 end, Q), ?ASSERT_MATCH(queue:to_list(Q1), [3, 4, 5]), - ok; -test_filtermap(_) -> ok. -test_filtermap_replace(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_filtermap_replace() -> Q = queue:from_list([1, 2, 3, 4, 5]), Q1 = queue:filtermap(fun(E) -> {true, E + 100} end, Q), ?ASSERT_MATCH(queue:to_list(Q1), [101, 102, 103, 104, 105]), - ok; -test_filtermap_replace(_) -> ok. -test_fold(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_fold() -> Q = queue:from_list([1, 2, 3, 4, 5]), ?ASSERT_MATCH(queue:fold(fun(X, Sum) -> X + Sum end, 0, Q), 15), - ok; -test_fold(_) -> ok. -test_any(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_any() -> Q = queue:from_list([1, 2, 3, 4, 5]), ?ASSERT_MATCH(queue:any(fun(E) -> E > 10 end, Q), false), ?ASSERT_MATCH(queue:any(fun(E) -> E > 3 end, Q), true), - ok; -test_any(_) -> ok. -test_all(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_all() -> Q = queue:from_list([1, 2, 3, 4, 5]), ?ASSERT_MATCH(queue:all(fun(E) -> E > 3 end, Q), false), ?ASSERT_MATCH(queue:all(fun(E) -> E > 0 end, Q), true), - ok; -test_all(_) -> ok. -test_delete(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_delete() -> Q = queue:from_list([1, 2, 3, 4, 5]), Q1 = queue:delete(3, Q), ?ASSERT_MATCH(queue:member(3, Q1), false), - ok; -test_delete(_) -> ok. -test_delete_with(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_delete_with() -> Q = queue:from_list([100, 1, 2, 3, 4, 5]), Q1 = queue:delete_with(fun(E) -> E > 0 end, Q), ?ASSERT_MATCH(queue:to_list(Q1), [1, 2, 3, 4, 5]), - ok; -test_delete_with(_) -> ok. -test_delete_with_r(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion == atomvm --> +test_delete_with_r() -> Q = queue:from_list([1, 2, 3, 4, 5, 100]), Q1 = queue:delete_with_r(fun(E) -> E > 10 end, Q), ?ASSERT_MATCH(queue:to_list(Q1), [1, 2, 3, 4, 5]), - ok; -test_delete_with_r(_) -> ok. test_complete_flow() -> diff --git a/tests/libs/estdlib/test_tcp_socket.erl b/tests/libs/estdlib/test_tcp_socket.erl index c7e71188b4..3a4c6dede2 100644 --- a/tests/libs/estdlib/test_tcp_socket.erl +++ b/tests/libs/estdlib/test_tcp_socket.erl @@ -31,10 +31,10 @@ test() -> ok = test_recv_nowait(), ok = test_accept_nowait(), ok = test_setopt_getopt(), - case get_otp_version() of - atomvm -> + case erlang:system_info(machine) of + "ATOM" -> ok = test_abandon_select(); - _ -> + "BEAM" -> ok end, ok. @@ -234,7 +234,7 @@ echo(Pid, Socket) -> {error, closed} -> Pid ! recv_terminated, ok; - %% OTP-24 + %% OTP returns this in some (random) cases {error, econnreset} -> Pid ! recv_terminated, ok; @@ -466,18 +466,11 @@ test_recv_nowait(ReceiveFun) -> ok = close_listen_socket(ListenSocket). test_accept_nowait() -> - OTPVersion = get_otp_version(), - ok = test_accept_nowait(nowait, OTPVersion), - ok = test_accept_nowait(make_ref(), OTPVersion), + ok = test_accept_nowait(nowait), + ok = test_accept_nowait(make_ref()), ok. -% actually since 22.1, but let's simplify here. -test_accept_nowait(_NoWaitRef, Version) when Version =/= atomvm andalso Version < 23 -> ok; -test_accept_nowait(Ref, Version) when - is_reference(Ref) andalso Version =/= atomvm andalso Version < 24 --> - ok; -test_accept_nowait(NoWaitRef, _Version) -> +test_accept_nowait(NoWaitRef) -> etest:flush_msg_queue(), {ok, Socket} = socket:open(inet, stream, tcp), @@ -577,13 +570,5 @@ test_abandon_select() -> erlang:garbage_collect(), ok. -get_otp_version() -> - case erlang:system_info(machine) of - "BEAM" -> - list_to_integer(erlang:system_info(otp_release)); - _ -> - atomvm - end. - id(X) -> X. diff --git a/tests/libs/estdlib/tests.erl b/tests/libs/estdlib/tests.erl index 566b9843db..53b73b6633 100644 --- a/tests/libs/estdlib/tests.erl +++ b/tests/libs/estdlib/tests.erl @@ -41,7 +41,7 @@ start() -> end, NetworkingTests = if - Networking -> get_networking_tests(OTPVersion); + Networking -> get_networking_tests(); true -> [] end, ok = etest:test(NonNetworkingTests ++ NetworkingTests). @@ -55,18 +55,12 @@ get_otp_version() -> end. % test_sets heavily relies on is_equal that is from OTP-27 -get_non_networking_tests(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 27) orelse OTPVersion =:= atomvm --> - [test_sets | get_non_networking_tests(undefined)]; -% test_binary uses encode_hex/1 (OTP-24), encode_hex/2 (OTP-26) -get_non_networking_tests(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 26) orelse OTPVersion =:= atomvm --> - [test_binary | get_non_networking_tests(undefined)]; +get_non_networking_tests(OTPVersion) when OTPVersion >= 27 -> + [test_sets | get_non_networking_tests(26)]; get_non_networking_tests(_OTPVersion) -> [ test_apply, + test_binary, test_lists, test_calendar, test_gen_event, @@ -86,16 +80,15 @@ get_non_networking_tests(_OTPVersion) -> test_file ]. -get_networking_tests(OTPVersion) when - (is_integer(OTPVersion) andalso OTPVersion >= 24) orelse OTPVersion =:= atomvm --> +get_networking_tests() -> [ test_tcp_socket, test_udp_socket, test_epmd, test_net, - test_ssl - | get_networking_tests(undefined) - ]; -get_networking_tests(_OTPVersion) -> - [test_gen_udp, test_gen_tcp, test_inet, test_net_kernel]. + test_ssl, + test_gen_udp, + test_gen_tcp, + test_inet, + test_net_kernel + ].