File 3541-features-test-Add-lux-tests-for-features.patch of Package erlang
From 47b0f7d3dc289f5805a5b6d68a992bee834df383 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cons=20T=20=C3=85hs?= <cons@erlang.org>
Date: Tue, 4 Jan 2022 15:41:12 +0100
Subject: [PATCH 1/7] [features, test] Add (lux) tests for features
* lux used for speed/simplicity, will be converted before release
* Features for test (present in erl_features) are used if env
variable OTP_TEST_FEATURES is set to true
* Input files for test are located in input directory
* Tests for compiler directives
* direct (long) options to erlc
* options using +term
* Tests for feature macros
* Tests for keyword warnings
* Tests for output of keywords (should be quoted when feature
is enabled)
* Tests for checking features used in module (data added to new
Meta chunk in beam file)
* Tests for runtime properties (known features and option to erl)
* Tests for include files
* Tests for disabling features
* Tests for directives
* Test for using 'else' as a keyword
* This reflects the reality of the maybe_expr feature
* ('else' is also used by the preprocessor)
* Some older, not relevant, tests also present. These will be removed
when test are converted to other test framework
---
erts/test/lux/bad_feature_erlc.lux | 238 ++++++++++
erts/test/lux/feature_erl.lux | 74 +++
erts/test/lux/feature_erlc.lux | 432 ++++++++++++++++++
erts/test/lux/feature_erlcold.lux | 158 +++++++
erts/test/lux/feature_ifnot.lux | 196 ++++++++
erts/test/lux/feature_include.lux | 87 ++++
erts/test/lux/feature_output.lux | 31 ++
erts/test/lux/feature_runtime.lux | 90 ++++
erts/test/lux/features.luxinc | 85 ++++
erts/test/lux/input/README | 3 +
erts/test/lux/input/enable.hrl | 1 +
erts/test/lux/input/f_bad_ifnot.erl | 30 ++
erts/test/lux/input/f_directives.erl | 33 ++
erts/test/lux/input/f_directives_2.erl | 46 ++
erts/test/lux/input/f_directives_3.erl | 44 ++
erts/test/lux/input/f_disable.erl | 52 +++
erts/test/lux/input/f_ifn.erl | 32 ++
erts/test/lux/input/f_ifnot.erl | 47 ++
erts/test/lux/input/f_include_1.erl | 22 +
erts/test/lux/input/f_include_2.erl | 22 +
erts/test/lux/input/f_include_3.erl | 22 +
erts/test/lux/input/f_include_maybe.erl | 18 +
.../test/lux/input/f_incorrect_directives.erl | 40 ++
erts/test/lux/input/f_incorrect_disable.erl | 57 +++
erts/test/lux/input/f_macros.erl | 65 +++
erts/test/lux/input/f_maybe.erl | 32 ++
erts/test/lux/input/f_maybe_ifn.erl | 32 ++
erts/test/lux/input/f_use_ifn.erl | 28 ++
.../lux/input/feature_directive_maybe_ifn.erl | 87 ++++
erts/test/lux/input/feature_ifn.erl | 12 +
erts/test/lux/input/feature_ignorant.erl | 17 +
erts/test/lux/input/feature_maybe.erl | 12 +
erts/test/lux/input/feature_maybe_ifn.erl | 12 +
erts/test/lux/input/foo.erl | 6 +
erts/test/lux/input/ignorant.erl | 40 ++
erts/test/lux/input/ignorant_directive.erl | 42 ++
erts/test/lux/input/is_enabled.hrl | 3 +
erts/test/lux/input/macro_enabled.hrl | 5 +
erts/test/lux/input/maybe.hrl | 10 +
erts/test/lux/input/older.erl | 6 +
erts/test/lux/older.beam | Bin 0 -> 592 bytes
41 files changed, 2269 insertions(+)
create mode 100644 erts/test/lux/bad_feature_erlc.lux
create mode 100644 erts/test/lux/feature_erl.lux
create mode 100644 erts/test/lux/feature_erlc.lux
create mode 100644 erts/test/lux/feature_erlcold.lux
create mode 100644 erts/test/lux/feature_ifnot.lux
create mode 100644 erts/test/lux/feature_include.lux
create mode 100644 erts/test/lux/feature_output.lux
create mode 100644 erts/test/lux/feature_runtime.lux
create mode 100644 erts/test/lux/features.luxinc
create mode 100644 erts/test/lux/input/README
create mode 100644 erts/test/lux/input/enable.hrl
create mode 100644 erts/test/lux/input/f_bad_ifnot.erl
create mode 100644 erts/test/lux/input/f_directives.erl
create mode 100644 erts/test/lux/input/f_directives_2.erl
create mode 100644 erts/test/lux/input/f_directives_3.erl
create mode 100644 erts/test/lux/input/f_disable.erl
create mode 100644 erts/test/lux/input/f_ifn.erl
create mode 100644 erts/test/lux/input/f_ifnot.erl
create mode 100644 erts/test/lux/input/f_include_1.erl
create mode 100644 erts/test/lux/input/f_include_2.erl
create mode 100644 erts/test/lux/input/f_include_3.erl
create mode 100644 erts/test/lux/input/f_include_maybe.erl
create mode 100644 erts/test/lux/input/f_incorrect_directives.erl
create mode 100644 erts/test/lux/input/f_incorrect_disable.erl
create mode 100644 erts/test/lux/input/f_macros.erl
create mode 100644 erts/test/lux/input/f_maybe.erl
create mode 100644 erts/test/lux/input/f_maybe_ifn.erl
create mode 100644 erts/test/lux/input/f_use_ifn.erl
create mode 100644 erts/test/lux/input/feature_directive_maybe_ifn.erl
create mode 100644 erts/test/lux/input/feature_ifn.erl
create mode 100644 erts/test/lux/input/feature_ignorant.erl
create mode 100644 erts/test/lux/input/feature_maybe.erl
create mode 100644 erts/test/lux/input/feature_maybe_ifn.erl
create mode 100644 erts/test/lux/input/foo.erl
create mode 100644 erts/test/lux/input/ignorant.erl
create mode 100644 erts/test/lux/input/ignorant_directive.erl
create mode 100644 erts/test/lux/input/is_enabled.hrl
create mode 100644 erts/test/lux/input/macro_enabled.hrl
create mode 100644 erts/test/lux/input/maybe.hrl
create mode 100644 erts/test/lux/input/older.erl
create mode 100644 erts/test/lux/older.beam
diff --git a/erts/test/lux/bad_feature_erlc.lux b/erts/test/lux/bad_feature_erlc.lux
new file mode 100644
index 0000000000..84afadc8ff
--- /dev/null
+++ b/erts/test/lux/bad_feature_erlc.lux
@@ -0,0 +1,238 @@
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2021-2022. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+
+[doc Tests of using enable_feature as an option to erlc]
+
+[include features.luxinc]
+
+[macro syntax-error expr]
+ ?syntax error before: $expr
+[endmacro]
+
+[invoke setup]
+
+[newshell cmds]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ -Unknown option
+ # DO not user erlc server as it seems that under "sometimes" new
+ # servers are added and left lingering
+ !export ERLC_USE_SERVER=$erlcserver
+ ?SH-PROMPT:
+ [invoke compile ignorant.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile ignorant.erl "+'{enable_feature, ifn}'"]
+ ?the feature 'ifn' does not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile ignorant.erl "+'{enable_feature, maybe}'"]
+ ?the feature 'maybe' does not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile ignorant.erl "+'{enable_feature, ifn}' +'{enable_feature, maybe}'"]
+ # FIXME these are in the wrong order
+ ??the features 'maybe' and 'ifn' do not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_ifn.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_ifn.erl "-enable-feature ifn"]
+ ?the feature 'ifn' does not exist
+ [invoke notok]
+
+ [invoke compile f_ifn.erl "'+{enable_feature, maybe}'"]
+ ?the feature 'maybe' does not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_ifn.erl "-enable-feature maybe"]
+ ?the feature 'maybe' does not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_ifn.erl "'+{enable_feature, maybe}' '+{enable_feature, ifn}'"]
+ # FIXME Fix order!
+ ??the features 'ifn' and 'maybe' do not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_ifn.erl "-enable-feature maybe -enable-feature ifn"]
+ # FIXME Fix order!
+ ??the features 'maybe' and 'ifn' do not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe.erl "'+{enable_feature, maybe}'"]
+ ?the feature 'maybe' does not exist
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "-enable-feature maybe"]
+ ?the feature 'maybe' does not exist
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "'+{enable_feature, ifn}'"]
+ ?the feature 'ifn' does not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "-enable-feature ifn"]
+ ?the feature 'ifn' does not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "'+{enable_feature, maybe}' '+{enable_feature, ifn}'"]
+ # FIXME fix order
+ ??the features 'ifn' and 'maybe' do not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "-enable-feature maybe -enable-feature ifn"]
+ # FIXE fix order
+ ??the features 'maybe' and 'ifn' do not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "-enable-feature maybe -enable-feature ifn -enable-feature unless"]
+ # FIXME fix order
+ ??the features 'maybe', 'ifn' and 'unless' do not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe_ifn.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+
+ # This file has instances of -feature(enable, ..}) inside
+ [invoke compile f_incorrect_directives.erl ""]
+ # FIXME Should we report an incorrect feature when it is in the wrong place?
+ # ?the feature 'ifn' does not exist
+ # ?%.*[0-9]+\| -feature
+ ?feature directive not allowed after anything interesting
+ ?%.*[0-9]+\| -feature
+
+[newshell erl]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ -undefined function
+ !erl -pa $outdir
+ ?$ERLPROMPT
+ [invoke erl-compile ignorant.erl []]
+ ???{ok,ignorant}
+ ?$ERLPROMPT
+
+ [invoke erl-compile ignorant.erl [{enable_feature,ifn}]]
+ ?the feature 'ifn' does not exist
+ ?error
+ ?$ERLPROMPT
+
+ [invoke erl-compile ignorant.erl [{enable_feature,ifn},{enable_feature,while}]]
+ ??the features 'ifn' and 'while' do not exist
+ ?error
+ ?$ERLPROMPT
+
+ [invoke erl-compile ignorant.erl [{enable_feature,unless},{enable_feature,ifn},{enable_feature,while}]]
+ ??the features 'unless', 'ifn' and 'while' do not exist
+ ?error
+ ?$ERLPROMPT
+
+ [invoke erl-compile f_directives.erl []]
+ ???{ok,f_directives}
+ ?$ERLPROMPT
+
+ # Test a sequence of enable and disable of the same feature
+ # FIXME This should perhaps be elsewhere
+ [invoke erl-compile f_directives_2.erl []]
+ ???{ok,f_directives_2}
+ ?$ERLPROMPT
+
+[shell cmds]
+ # Enable a feature on the command line and disable it in a directive
+ # FIXME This should perhaps be elsewhere
+ [invoke compile f_directives_3.erl "-enable-feature while_expr"]
+ [invoke ok]
+
+ [invoke compile f_macros.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ # Verify that only ifn_expr is used
+ !Fs = erl_features:features_used(f_directives_2).
+ ?$ERLPROMPT
+ [invoke same-members Fs "[ifn_expr,cond_expr,maps]"]
+ !f(Fs).
+ ?$ERLPROMPT
+
+ # Verify that only ifn_expr is used
+ !Fs = erl_features:features_used(f_directives_3).
+ ?$ERLPROMPT
+ [invoke same-members Fs "[ifn_expr,cond_expr,maps]"]
+ !f(Fs).
+ ?$ERLPROMPT
+
+ !l(f_macros).
+ ?{module,f_macros}
+ ?$ERLPROMPT
+
+ !f_macros:has_ifn().
+ ?true
+ ?$ERLPROMPT
+
+ !f_macros:has_hindly_milner().
+ ?false
+ ?$ERLPROMPT
+
+ !f_macros:uses_ifn().
+ ?false
+ ?$ERLPROMPT
+
+ !f_macros:uses_maybe().
+ ?false
+ ?$ERLPROMPT
+
+
+
+[shell cmds]
+ [invoke compile f_incorrect_disable.erl "-disable-feature ifn"]
+ ?the feature 'ifn' does not exist
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_incorrect_disable.erl ""]
+ ?the feature 'unless' does not exist
+ ?%.*[0-9]+\| -feature
+ ?SH-PROMPT:
+ [invoke notok]
+
+[cleanup]
+ [invoke no-dump]
+ !rm -fr $outdir
diff --git a/erts/test/lux/feature_erl.lux b/erts/test/lux/feature_erl.lux
new file mode 100644
index 0000000000..88d71a06a6
--- /dev/null
+++ b/erts/test/lux/feature_erl.lux
@@ -0,0 +1,74 @@
+[doc Testing of enabling features on command line]
+
+[include features.luxinc]
+
+[invoke setup]
+
+[newshell erl]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ -undefined function
+ [invoke start-erl ""]
+
+ [invoke same-members "erl_features:enabled_features()" "[maps,cond_expr]"]
+
+ [invoke quit-erl]
+
+ [invoke start-erl "-enable-feature ifn_expr"]
+
+ [invoke same-members "erl_features:enabled_features()" "[maps,cond_expr,ifn_expr]"]
+
+ [invoke quit-erl]
+
+ [invoke start-erl "-enable-feature ifn_expr -enable-feature while_expr"]
+
+ [invoke same-members "erl_features:enabled_features()" "[maps,cond_expr,while_expr,ifn_expr]"]
+
+ [invoke quit-erl]
+
+
+ [invoke start-erl "-enable-feature ifn_expr while_expr"]
+
+ [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,while_expr,ifn_expr]"]
+
+ [invoke quit-erl]
+
+ [invoke start-erl "-enable-feature ifn_expr while_expr -enable-feature ifnot_expr"]
+
+ [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,while_expr,ifn_expr,ifnot_expr]"]
+
+ [invoke quit-erl]
+
+ # Enabling the same feature twice does not hurt
+ [invoke start-erl "-enable-feature ifn_expr while_expr -enable-feature ifnot_expr ifn_expr"]
+
+ [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,while_expr,ifn_expr,ifnot_expr]"]
+
+ [invoke quit-erl]
+
+ # Now for some bad stuff
+ # Enabling a feature that doen't exist
+ # FIXME shouldn't this give an error? Yes, but here we have a
+ # problem since we have a lazy init of the feature set.
+ [invoke start-erl "-enable-feature no_ftr"]
+
+ [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps]"]
+
+ [invoke quit-erl]
+
+ [invoke start-erl "-disable-feature cond_expr"]
+
+ [invoke same-members "erl_features:enabled_features()" "[maps]"]
+ # FIXME Need to check that keywords have changed as well!
+ [invoke quit-erl]
+
+ [invoke start-erl "-disable-feature all"]
+ !erl_features:enabled_features().
+ ??[]
+ ?$ERLPROMPT
+
+ [invoke quit-erl]
+
+[cleanup]
+ [invoke no-dump]
+ # done
diff --git a/erts/test/lux/feature_erlc.lux b/erts/test/lux/feature_erlc.lux
new file mode 100644
index 0000000000..83647db856
--- /dev/null
+++ b/erts/test/lux/feature_erlc.lux
@@ -0,0 +1,432 @@
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2021-2022. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+
+[doc Tests of using enable_feature as an option to erlc]
+
+[include features.luxinc]
+
+[macro syntax-error expr]
+ ?syntax error before: $expr
+[endmacro]
+
+[invoke setup]
+
+[newshell cmds]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ -Unknown option
+ # DO not user erlc server as it seems that under "sometimes" new
+ # servers are added and left lingering
+ !export ERLC_USE_SERVER=$erlcserver
+ ?SH-PROMPT:
+ [invoke compile ignorant.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile ignorant.erl "+'{enable_feature, ifn_expr}'"]
+ ?syntax error before:
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile ignorant.erl "+'{enable_feature, while_expr}'"]
+ ?syntax error before: while
+ ?syntax error before: while
+ ?syntax error before: until
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile ignorant.erl "+'{enable_feature, ifn_expr}' +'{enable_feature, while_expr}'"]
+ ?syntax error before:
+ ?syntax error before: while
+ ?syntax error before: until
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_ifn.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_ifn.erl "'+{enable_feature, ifn_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_ifn.erl "'+{enable_feature, while_expr}'"]
+ [invoke syntax-error while]
+ [invoke syntax-error until]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_ifn.erl "-enable-feature while_expr"]
+ [invoke syntax-error while]
+ [invoke syntax-error until]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_ifn.erl "'+{enable_feature, while_expr}' '+{enable_feature, ifn_expr}'"]
+ [invoke syntax-error while]
+ [invoke syntax-error until]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_ifn.erl "-enable-feature while_expr -enable-feature ifn_expr"]
+ [invoke syntax-error while]
+ [invoke syntax-error until]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe.erl "'+{enable_feature, while_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe.erl "-enable-feature while_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe.erl "'+{enable_feature, ifn_expr}'"]
+ ?syntax error before:
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "-enable-feature ifn_expr"]
+ ?syntax error before:
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "'+{enable_feature, while_expr}' '+{enable_feature, ifn_expr}'"]
+ ?syntax error before:
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe.erl "-enable-feature while_expr -enable-feature ifn_expr"]
+ ?syntax error before:
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_maybe_ifn.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe_ifn.erl "'+{enable_feature, while_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe_ifn.erl "-enable-feature while_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe_ifn.erl "'+{enable_feature, ifn_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe_ifn.erl "-enable-feature ifn_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe_ifn.erl "'+{enable_feature, while_expr}' '+{enable_feature, ifn_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile f_maybe_ifn.erl "-enable-feature while_expr -enable-feature ifn_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ # Long options
+ [invoke compile f_ifn.erl "-enable-feature ifn_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ # This file has instances of -compile({enable_feature, ..}) inside
+ [invoke compile f_directives.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[newshell erl]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ -undefined function
+ [invoke start-erl ""]
+ [invoke erl-compile ignorant.erl []]
+ ???{ok,ignorant}
+ ?$ERLPROMPT
+
+ [invoke erl-compile ignorant.erl [{enable_feature,ifn_expr}]]
+ ?syntax error before:
+ ?syntax error before:
+ ?error
+ ?$ERLPROMPT
+
+ [invoke erl-compile ignorant.erl [{enable_feature,ifn_expr},{enable_feature,while_expr}]]
+ ?syntax error before:
+ ?syntax error before: while
+ ?syntax error before: until
+ ?syntax error before: ifn
+ ?error
+ ?$ERLPROMPT
+
+ [invoke erl-compile f_directives.erl []]
+ ???{ok,f_directives}
+ ?$ERLPROMPT
+
+ # As we have not enabled any features, this load should not be
+ # allowed (if we have inserted the features used in the meta chunk).
+ !l(f_directives).
+ ??{error,not_allowed}
+ ?$ERLPROMPT
+
+ !Fs = erl_features:features_used(f_maybe_ifn).
+ [invoke same-members Fs "[cond_expr,maps,while_expr,ifn_expr]"]
+ !f(Fs).
+ ?$ERLPROMPT
+
+ # Try to load the binary directly
+ !{Mod,Bin,FName}=code:get_object_code(f_maybe_ifn).
+ ?$ERLPROMPT
+ !code:load_binary(Mod,FName,Bin).
+ ??{error,not_allowed}
+ ?$ERLPROMPT
+
+[shell cmds]
+ [invoke compile f_macros.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ !l(f_macros).
+ ?{module,f_macros}
+ ?$ERLPROMPT
+
+ !f_macros:has_ifn().
+ ?true
+ ?$ERLPROMPT
+
+ !f_macros:has_hindly_milner().
+ ?false
+ ?$ERLPROMPT
+
+ !f_macros:with_hm().
+ ?false
+ ?$ERLPROMPT
+
+ !f_macros:uses_ifn().
+ ?false
+ ?$ERLPROMPT
+
+ !f_macros:uses_maybe().
+ ?false
+ ?$ERLPROMPT
+
+[shell cmds]
+ [invoke compile f_macros.erl "-enable-feature ifn_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ !l(f_macros).
+ ??{error,not_allowed}
+ ?$ERLPROMPT
+
+ # Check which features were used during compilation
+ !Fs = erl_features:features_used(f_macros).
+ ?$ERLPROMPT
+ [invoke same-members Fs "[maps,cond_expr,ifn_expr]"]
+ !f(Fs).
+ ?$ERLPROMPT
+
+ # Somewhat questionable if we really should allow this in runtime
+ # FIXME WE should *not* allow this at runtime.
+ !Fs = erl_features:enable_feature(ifn_expr).
+ ?$ERLPROMPT
+ [invoke same-members Fs "[cond_expr,maps,ifn_expr]"]
+ !f(Fs).
+ ?$ERLPROMPT
+
+ !l(f_macros).
+ ?{module,f_macros}
+ ?$ERLPROMPT
+
+ !f_macros:uses_ifn().
+ ?true
+ ?$ERLPROMPT
+
+ !f_macros:uses_maybe().
+ ?false
+ ?$ERLPROMPT
+
+ [invoke quit-erl]
+
+ !rm -f $outdir/f_macros.beam
+ ?SH-PROMPT:
+
+ [invoke start-erl ""]
+
+ [invoke erl-compile f_macros.erl [{enable_feature,ifn_expr}]]
+ ???{ok,f_macros}
+ ?$ERLPROMPT
+
+ # This should be allowed as we have not enabled the feature in the
+ # runtime
+ !l(f_macros).
+ ??{error,not_allowed}
+ ?$ERLPROMPT
+
+ [invoke quit-erl]
+
+ [invoke start-erl "-enable-feature ifn_expr"]
+ !l(f_macros).
+ ??{module,f_macros}
+ ?$ERLPROMPT
+
+ [invoke quit-erl]
+
+ [invoke start-erl ""]
+
+[shell cmds]
+ [invoke compile f_macros.erl "-enable-feature while_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ # FIXME This should not be allowed at runtime..
+ !Fs = erl_features:enable_feature(ifn_expr).
+ ?$ERLPROMPT
+ [invoke same-members Fs "[cond_expr,maps,ifn_expr]"]
+ !f(Fs).
+ ?$ERLPROMPT
+
+ # FIXME This should not be allowed at runtime..
+ !Fs = erl_features:enable_feature(while_expr).
+ ?$ERLPROMPT
+ [invoke same-members Fs "[cond_expr,maps,ifn_expr,while_expr]"]
+ !f(Fs).
+ ?$ERLPROMPT
+
+ !l(f_macros).
+ ?{module,f_macros}
+ ?$ERLPROMPT
+
+ !f_macros:uses_ifn().
+ ?false
+ ?$ERLPROMPT
+
+ !f_macros:uses_maybe().
+ ?true
+ ?$ERLPROMPT
+
+[shell cmds]
+ [invoke compile f_macros.erl "-enable-feature ifn_expr -enable-feature while_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ !l(f_macros).
+ ?{module,f_macros}
+ ?$ERLPROMPT
+
+ !f_macros:uses_ifn().
+ ?true
+ ?$ERLPROMPT
+
+ !f_macros:uses_maybe().
+ ?true
+ ?$ERLPROMPT
+
+
+[shell cmds]
+ [invoke compile f_disable.erl "-enable-feature ifn_expr -enable-feature while_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ !f_disable:no_ifn().
+ # FIXME Should really be 'maybe' since it is enabled
+ ???['ifn','while',no_ifn]
+ ?$ERLPROMPT
+
+ !f_disable:no_ftrs().
+ ???['ifn','while','until',no_maybe]
+ ?$ERLPROMPT
+
+[shell cmds]
+ [invoke compile ignorant.erl "+warn_keywords"]
+ # Note: not all messges are checked
+ ?atom 'while' is reserved in the experimental feature 'while_expr'
+ ?atom 'until' is reserved in the experimental feature 'while_expr'
+ ?atom 'ifn' is reserved in the experimental feature 'ifn_expr'
+ [invoke ok]
+
+ [invoke compile ignorant.erl "+warn_keywords -Werror"]
+ # Note: not all messges are checked
+ ?atom 'while' is reserved in the experimental feature 'while_expr'
+ ?atom 'until' is reserved in the experimental feature 'while_expr'
+ ?atom 'ifn' is reserved in the experimental feature 'ifn_expr'
+ [invoke notok]
+
+ # This file has a directive for keyword warnings
+ [invoke compile ignorant_directive.erl ""]
+ # Note: not all messges are checked
+ ?Warning: atom 'while' is reserved in the experimental feature 'while_expr'
+ ?Warning: atom 'until' is reserved in the experimental feature 'while_expr'
+ ?Warning: atom 'ifn' is reserved in the experimental feature 'ifn_expr'
+ [invoke ok]
+
+ # This file has a directive for keyword warnings
+ # NOTE: This behaviour is inconsistent with that of enabling features,
+ # where what is in the file takes precedence.
+ [invoke compile ignorant_directive.erl "+nowarn_keywords"]
+ # Expect no warning
+ -Warning
+ [invoke ok]
+
+[shell cmds]
+ [invoke compile foo.erl "-enable-feature all"]
+ [invoke ok]
+
+[shell erl]
+ !Fs = erl_features:features_used(foo).
+ ?$ERLPROMPT
+ [invoke same-members Fs "[unless_expr,ifn_expr,while_expr,cond_expr,maps,ifnot_expr]"]
+ !f(Fs).
+ ?$ERLPROMPT
+ # !maps:from_keys([unless_expr,ifn_expr,maybe_expr,cond_expr,maps,ifnot_expr],true) == maps:from_keys(Fs, true).
+ # ?true
+ # ?$ERLPROMPT
+
+[shell cmds]
+ [invoke compile foo.erl "-enable-feature all -disable-feature unless_expr"]
+ [invoke ok]
+
+[shell erl]
+ !Fs = erl_features:features_used(foo).
+ ?$ERLPROMPT
+ !maps:from_keys([ifn_expr,while_expr,cond_expr,maps,ifnot_expr], foo) == maps:from_keys(Fs, foo).
+ ?true
+ ?$ERLPROMPT
+ !f(Fs).
+ ?$ERLPROMPT
+
+[cleanup]
+ [invoke no-dump]
+ !rm -fr $outdir
diff --git a/erts/test/lux/feature_erlcold.lux b/erts/test/lux/feature_erlcold.lux
new file mode 100644
index 0000000000..82ee437b97
--- /dev/null
+++ b/erts/test/lux/feature_erlcold.lux
@@ -0,0 +1,158 @@
+# FIXME This is the old version of feature_erlc, possibily useful
+# for finding some errors that need to be caught and presented.
+[doc Tests of using enable_feature as an option to erlc]
+
+[include features.luxinc]
+
+[macro syntax-error expr]
+ ?syntax error before: $expr
+[endmacro]
+
+[invoke setup]
+
+[newshell cmds]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ !export ERLC_USE_SERVER=$erlcserver
+ ?SH-PROMPT:
+ [invoke compile feature_ignorant.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ # Different error message when ifn is not in parser
+ [invoke compile feature_ignorant.erl "+'{enable_feature, ifn_expr}'"]
+ ?syntax error before:
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ # Different error message when ifn is not in parser
+ [invoke compile feature_ignorant.erl "-enable-feature ifn_expr"]
+ ?syntax error before:
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ignorant.erl "+'{enable_feature, while_expr}'"]
+ ?syntax error before: while
+ ?syntax error before: while
+ ?syntax error before: until
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ignorant.erl "-enable-feature while_expr"]
+ ?syntax error before: while
+ ?syntax error before: while
+ ?syntax error before: until
+ ?SH-PROMPT:
+ [invoke notok]
+
+ # Different error message when ifn not in parser
+ [invoke compile feature_ignorant.erl "+'{enable_feature, ifn_expr}' +'{enable_feature, while_expr}'"]
+ ?syntax error before:
+ ?syntax error before: while
+ ?syntax error before: until
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ # Different error message when ifn not in parser
+ [invoke compile feature_ignorant.erl "-enable-feature ifn_expr -enable-feature while_expr"]
+ ?syntax error before:
+ ?syntax error before: while
+ ?syntax error before: until
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ifn.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile feature_ifn.erl "'+{enable_feature, ifn_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile feature_ifn.erl "-enable-feature ifn_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile feature_ifn.erl "'+{enable_feature, while_expr}'"]
+ [invoke syntax-error while]
+ [invoke syntax-error until]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ifn.erl "-enable-feature while_expr"]
+ [invoke syntax-error while]
+ [invoke syntax-error until]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ifn.erl "'+{enable_feature, while_expr}' '+{enable_feature, ifn_expr}'"]
+ [invoke syntax-error while]
+ [invoke syntax-error until]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ifn.erl "-enable-feature while_expr -enable-feature ifn_expr"]
+ [invoke syntax-error while]
+ [invoke syntax-error until]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_maybe.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile feature_maybe.erl "'+{enable_feature, while_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ # Different error message when ifn not in parser
+ [invoke compile feature_maybe.erl "'+{enable_feature, ifn_expr}'"]
+ [invoke syntax-error ifn]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ # Different error message when ifn not in parser
+ [invoke compile feature_maybe.erl "'+{enable_feature, while_expr}' '+{enable_feature, ifn_expr}'"]
+ [invoke syntax-error ifn]
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_maybe_ifn.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile feature_maybe_ifn.erl "'+{enable_feature, while_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile feature_maybe_ifn.erl "'+{enable_feature, ifn_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [invoke compile feature_maybe_ifn.erl "'+{enable_feature, while_expr}' '+{enable_feature, ifn_expr}'"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[newshell erl]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ !erl
+ ?$ERLPROMPT
+ [invoke erl-compile feature_ignorant.erl []]
+ ???{ok,feature_ignorant}
+ ?$ERLPROMPT
+
+ # Different error message when ifn not in parser
+ [invoke erl-compile feature_ignorant.erl [{enable_feature,ifn_expr}]]
+ ?syntax error before: ifn
+ ?syntax error before: ifn
+ ?error
+ ?$ERLPROMPT
+
+[cleanup]
+ [invoke no-dump]
+ !rm -fr $outdir
diff --git a/erts/test/lux/feature_ifnot.lux b/erts/test/lux/feature_ifnot.lux
new file mode 100644
index 0000000000..fc3b332816
--- /dev/null
+++ b/erts/test/lux/feature_ifnot.lux
@@ -0,0 +1,196 @@
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2021-2022. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+
+[doc Testing of more general experimental feature]
+
+[include features.luxinc]
+
+[invoke setup]
+
+[newshell erl]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ -undefined function
+ !erl -pa $outdir
+ ?$ERLPROMPT
+
+ !erl_features:enable_feature(ifnot_expr).
+ ?[ifnot_expr]
+ ?$ERLPROMPT
+
+ !ifnot false -> 40 + 2 end.
+ ?42
+ ?$ERLPROMPT
+
+ !ifnot true -> 42 end.
+ ?ok
+ ?$ERLPROMPT
+
+ !ifnot begin X = 2, X > 2 end -> true end.
+ ?true
+ ?$ERLPROMPT
+ !f(X).
+ ?$ERLPROMPT
+
+ # Names bound are exported
+ !ifnot begin X = 3, X > 4 end -> Y=7+X, X end.
+ ?3
+ ?$ERLPROMPT
+ !Y.
+ ?10
+ ?$ERLPROMPT
+
+[newshell cmds]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ [invoke compile f_ifnot.erl ""]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ !l(f_ifnot).
+ ??{module,f_ifnot}
+ ?$ERLPROMPT
+
+ !f_ifnot:f0().
+ ?42
+ ?$ERLPROMPT
+
+ !f_ifnot:f1().
+ ?ok
+ ?$ERLPROMPT
+
+ !f_ifnot:f2().
+ ?true
+ ?$ERLPROMPT
+
+ !f_ifnot:f3().
+ ??{3,10}
+ ?$ERLPROMPT
+
+ !f_ifnot:f4(true).
+ ?ok
+ ?$ERLPROMPT
+
+ !f_ifnot:f4(false).
+ ?foo
+ ?$ERLPROMPT
+
+ !f_ifnot:f4(foo).
+ ?not_boolean
+ ?$ERLPROMPT
+
+[shell cmds]
+ [invoke compile f_bad_ifnot.erl ""]
+ # FIXME It should really be 'ifnot' since it is reserved (at that point)
+ ?variable 'Y' unsafe in ifnot
+ ?SH-PROMPT
+ [invoke notok]
+
+ # Moved from feature_erlc.lux. This assumes that ifn is available
+ # in parser, which is no longer true.
+[shell cmds]
+ [invoke compile f_use_ifn.erl ""]
+ ?syntax error before: X
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile f_use_ifn.erl "-enable-feature ifn_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+ [shell erl]
+ !f_use_ifn:use_ifn(0).
+ ???!(0 > 0)
+ ?$ERLPROMPT
+
+ # Moved from feature_erlcold.lux as ifn is no longer present in parser
+ [invoke compile feature_ignorant.erl "+'{enable_feature, ifn_expr}'"]
+ ?syntax error before: ','
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ignorant.erl "-enable-feature ifn_expr"]
+ ?syntax error before: ','
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ignorant.erl "+'{enable_feature, ifn_expr}' +'{enable_feature, maybe_expr}'"]
+ ?syntax error before: ','
+ ?syntax error before: maybe
+ ?syntax error before: else
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_ignorant.erl "-enable-feature ifn_expr -enable-feature maybe_expr"]
+ ?syntax error before: ','
+ ?syntax error before: maybe
+ ?syntax error before: else
+ ?syntax error before: ifn
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_maybe.erl "'+{enable_feature, ifn_expr}'"]
+ [invoke syntax-error ',']
+ ?SH-PROMPT:
+ [invoke notok]
+
+ [invoke compile feature_maybe.erl "'+{enable_feature, maybe_expr}' '+{enable_feature, ifn_expr}'"]
+ [invoke syntax-error ',']
+ ?SH-PROMPT:
+ [invoke notok]
+
+ # This file has instances of -compile({enable_feature, ..}) inside
+ [invoke compile feature_directive_maybe_ifn.erl "-enable-feature ifn_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ [invoke erl-compile feature_ignorant.erl [{enable_feature,ifn_expr}]]
+ ?syntax error before: ','
+ ?syntax error before: ifn
+ ?error
+ ?$ERLPROMPT
+
+ # Moved from feature_output.lux
+[newshell compile]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ !export ERLC_USE_SERVER=$erlcserver
+ ?SH-PROMPT:
+ # This file has instances of -compile({enable_feature, ..}) inside
+ [invoke compile feature_directive_maybe_ifn.erl "-enable-feature ifn_expr"]
+ ?SH-PROMPT:
+ [invoke ok]
+
+[shell erl]
+ !l(feature_directive_maybe_ifn).
+ ??{module,feature_directive_maybe_ifn}
+ ?$ERLPROMPT
+
+ !feature_directive_maybe_ifn:foo().
+ ??['ifn','maybe','else','if']
+ ?$ERLPROMPT
+
+[cleanup]
+ !rm -fr $outdir
diff --git a/erts/test/lux/feature_include.lux b/erts/test/lux/feature_include.lux
new file mode 100644
index 0000000000..9e2b74cc2e
--- /dev/null
+++ b/erts/test/lux/feature_include.lux
@@ -0,0 +1,87 @@
+[doc Tests regarding feature enabling with include files]
+
+[include features.luxinc]
+
+[invoke setup]
+
+[newshell cmds]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ # Do not use erlc server as it seems that under "sometimes" new
+ # servers are added and left lingering
+ !export ERLC_USE_SERVER=$erlcserver
+ ?SH-PROMPT:
+ # Ensure that the feature unless_expr is enabled in the
+ # include file and generates an error
+ [invoke compile f_include_1.erl ""]
+ ??syntax error before
+ [invoke notok]
+
+[shell cmds]
+ # Ensure that the macro knows that unless_expr is enabled in the
+ # include file
+ [invoke compile f_include_2.erl ""]
+ [invoke ok]
+
+[newshell erl]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ [invoke start-erl "-enable-feature unless_expr"]
+ !l(f_include_2).
+ ??{module,f_include_2}
+ ?$ERLPROMPT
+
+ !f_include_2:foo(2).
+ ?active
+ ?$ERLPROMPT
+
+[shell cmds]
+ [invoke compile f_include_3.erl "-Dend_prefix"]
+ ?feature directive not allowed after anything interesting
+ [invoke notok]
+
+[shell cmds]
+ [invoke compile f_include_1.erl "-Dend_include"]
+ ?feature directive not allowed after anything interesting
+ [invoke notok]
+
+[shell cmds]
+ [invoke compile f_include_maybe.erl "-Denable_maybe=0"]
+ [invoke ok]
+
+[shell erl]
+ !l(f_include_maybe).
+ ??{module,f_include_maybe}
+ ?$ERLPROMPT
+ !f_include_maybe:foo().
+ ??{conditional,on,until}
+ ?$ERLPROMPT
+
+[shell cmds]
+ [invoke compile f_include_maybe.erl "-enable-feature while_expr"]
+ ??input/maybe.hrl
+ ??syntax error before
+ [invoke notok]
+
+ [invoke compile f_include_maybe.erl "-Denable_maybe=1"]
+ ??input/f_include_maybe.erl
+ ??syntax error before
+ [invoke notok]
+
+ [invoke compile f_include_maybe.erl "-enable-feature while_expr -Denable_maybe=2"]
+ [invoke ok]
+
+[shell erl]
+ [invoke quit-erl]
+
+ [invoke start-erl "-enable-feature while_expr"]
+ !l(f_include_maybe).
+ ??{module,f_include_maybe}
+ ?$ERLPROMPT
+ !f_include_maybe:foo().
+ ??{conditional,off,none}
+ ?$ERLPROMPT
+
+[cleanup]
+ [invoke no-dump]
+ # done
diff --git a/erts/test/lux/feature_output.lux b/erts/test/lux/feature_output.lux
new file mode 100644
index 0000000000..0b20d3fc4a
--- /dev/null
+++ b/erts/test/lux/feature_output.lux
@@ -0,0 +1,31 @@
+[doc Testing of output when features have been enabled]
+
+[include features.luxinc]
+
+[invoke setup]
+
+[newshell erl]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ -undefined function
+ !erl -pa $outdir
+ ?$ERLPROMPT
+
+ # Output should should know about the new reserved words during runtime
+
+ [invoke same-members "erl_features:enable_feature(while_expr)" "[cond_expr,maps,while_expr]"]
+
+ [invoke same-members "erl_features:enable_feature(ifn_expr)" "[cond_expr,maps,while_expr,ifn_expr]"]
+
+ # !feature_directive_maybe_ifn:foo().
+ !['ifn','while','until','if'].
+ ??['ifn','while','until','if']
+ ?$ERLPROMPT
+
+ !erl_features:enable_feature(ifn_expr).
+ ?[ifn_expr,maybe_expr]
+ ?$ERLPROMPT
+
+[cleanup]
+ [invoke no-dump]
+ !rm -fr $outdir
diff --git a/erts/test/lux/feature_runtime.lux b/erts/test/lux/feature_runtime.lux
new file mode 100644
index 0000000000..723d650d5a
--- /dev/null
+++ b/erts/test/lux/feature_runtime.lux
@@ -0,0 +1,90 @@
+[doc Test general working of runtime state of features]
+
+[include features.luxinc]
+
+[invoke setup]
+
+[newshell erl]
+ !export OTP_TEST_FEATURES=true
+ ?SH-PROMPT:
+ -undefined function
+ !erl
+ ?$ERLPROMPT
+
+ [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps]"]
+
+ !erl_features:keywords().
+ ??[]
+ ?$ERLPROMPT
+
+ [invoke same-members "erl_features:enable_feature(while_expr)" "[cond_expr,maps,while_expr]"]
+
+ !erl_features:keywords().
+ ??['while','until']
+ ?$ERLPROMPT
+
+ [invoke same-members "erl_features:disable_feature(while_expr)" "[cond_expr,maps]"]
+
+ !erl_features:keywords().
+ ??[]
+ ?$ERLPROMPT
+
+ [invoke same-members "erl_features:enable_feature(ifn_expr)" "[cond_expr,maps,ifn_expr]"]
+
+ [invoke same-members "erl_features:enable_feature(while_expr)" "[cond_expr,maps,ifn_expr,while_expr]"]
+
+ [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,ifn_expr,while_expr]"]
+
+ !erl_features:keywords().
+ ??['while','until','ifn']
+
+ [invoke same-members "erl_features:disable_feature(ifn_expr)" "[cond_expr,maps,while_expr]"]
+
+ [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,while_expr]"]
+
+ !erl_features:keywords().
+ ??['while','until']
+ ?$ERLPROMPT
+
+ [invoke same-members "erl_features:disable_feature(while_expr)" "[cond_expr,maps]"]
+
+ !erl_features:keywords().
+ ??[]
+ ?$ERLPROMPT
+
+ !erl_features:enable_feature(misfeature).
+ ??invalid_feature
+ ??argument 1: unknown feature
+ ?$ERLPROMPT
+
+[shell erl]
+ [invoke quit-erl]
+
+ [invoke start-erl ""]
+ !while.
+ ?while
+ ?$ERLPROMPT
+
+ # If there is no Meta chunk, we should just get [] as answer,
+ # not a failure. We use a file compiled with an older release to be
+ # sure no meta chunk is present
+ !erl_features:features_used(older).
+ ???[]
+ ?$ERLPROMPT
+
+ !erl_features:features_used("older.beam").
+ ???[]
+ ?$ERLPROMPT
+
+
+ # Test getting used features for unknown modules and files
+ !erl_features:features_used(no_module).
+ ??not_found
+ ?$ERLPROMPT
+
+ !erl_features:features_used("none.beam").
+ ??not_found
+ ?$ERLPROMPT
+
+[cleanup]
+ [invoke no-dump]
diff --git a/erts/test/lux/features.luxinc b/erts/test/lux/features.luxinc
new file mode 100644
index 0000000000..2998f67dd9
--- /dev/null
+++ b/erts/test/lux/features.luxinc
@@ -0,0 +1,85 @@
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2021-2022. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+
+[global ERLPROMPT=[0-9]*>]
+
+# Directory holding input files for feature tests
+[global input=input]
+
+[global erlcserver=true]
+
+[macro ok]
+ !echo ==$$?==
+ ?==0==
+ ?SH-PROMPT:
+[endmacro]
+
+[macro notok]
+ !echo ==$$?==
+ ?==[1-9][0-9]*==
+ ?SH-PROMPT:
+[endmacro]
+
+[macro compile file opts]
+ !erlc $opts -o $outdir $input/$file
+[endmacro]
+
+[macro erl-compile file opts]
+ !compile:file("$input/$file", $opts ++ [report_errors,{outdir,"$outdir"}]).
+[endmacro]
+
+# Create a tmp directory and bind outdir
+[macro setup]
+ [newshell setup]
+ !mktemp -d
+ ?(/tmp.*)
+ [global outdir=$1]
+ ?SH-PROMPT:
+ # Make sure there is no erl_crash.dump present
+ !rm -f erl_crash.dump
+ ?SH-PROMPT:
+[endmacro]
+
+[macro start-erl args]
+ !erl -pa $outdir $args
+ ?$ERLPROMPT
+[endmacro]
+
+[macro quit-erl]
+ !q().
+ ?SH-PROMPT:
+[endmacro]
+
+# Nifty way to compare that two lists have the same members
+# One drawback is that it os not easy to debug, i.e., see the actual
+# members.
+[macro same-members l1 l2]
+ !maps:from_keys($l1,foo) == maps:from_keys($l2,foo).
+ ?true
+ ?$ERLPROMPT
+[endmacro]
+
+[macro no-dump]
+ !ls erl_crash.dump
+ ?SH-PROMPT:
+ !echo ==$?==
+ ?==2==
+ ?SH-PROMPT:
+[endmacro]
diff --git a/erts/test/lux/input/README b/erts/test/lux/input/README
new file mode 100644
index 0000000000..3ff7601113
--- /dev/null
+++ b/erts/test/lux/input/README
@@ -0,0 +1,3 @@
+This directory contains Erlang files used as input when testing the
+compiler. They are probably not the best examples of Erlang code with
+any deeper meaning.
diff --git a/erts/test/lux/input/enable.hrl b/erts/test/lux/input/enable.hrl
new file mode 100644
index 0000000000..d8eb0f1fc7
--- /dev/null
+++ b/erts/test/lux/input/enable.hrl
@@ -0,0 +1 @@
+-feature(enable, maybe_expr).
diff --git a/erts/test/lux/input/f_bad_ifnot.erl b/erts/test/lux/input/f_bad_ifnot.erl
new file mode 100644
index 0000000000..e4c50f4303
--- /dev/null
+++ b/erts/test/lux/input/f_bad_ifnot.erl
@@ -0,0 +1,30 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_bad_ifnot).
+
+-feature(enable, ifnot_expr).
+
+-export([f3/0]).
+
+f3() ->
+ Z = ifnot begin X = 3, X > 4 end -> Y=7+X, {X, Y} end,
+ %% Y should be reported as unsafe
+ {Y, Z}.
diff --git a/erts/test/lux/input/f_directives.erl b/erts/test/lux/input/f_directives.erl
new file mode 100644
index 0000000000..47ee210fd1
--- /dev/null
+++ b/erts/test/lux/input/f_directives.erl
@@ -0,0 +1,33 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_directives).
+
+%% This module uses both features ifn_expr and maybe_expr, so atoms
+%% belonging to these need t be quoted.
+
+-feature(enable, ifn_expr).
+-feature(enable, while_expr).
+
+-export([bar/0
+ ]).
+
+bar() ->
+ ['xelse', 'xwhile', 'ifn'].
diff --git a/erts/test/lux/input/f_directives_2.erl b/erts/test/lux/input/f_directives_2.erl
new file mode 100644
index 0000000000..07c93440f0
--- /dev/null
+++ b/erts/test/lux/input/f_directives_2.erl
@@ -0,0 +1,46 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_directives_2).
+
+%% This module uses the feature ifn_expr, so atoms belonging to that
+%% featurfe need to be quoted.
+
+-feature(enable, while_expr).
+-feature(enable, ifn_expr).
+%% Disable feature so atoms beonging to maybe_expr can be unquoted
+-feature(disable, while_expr).
+
+-export([foo/0,
+ bar/0,
+ baz/1
+ ]).
+
+foo() ->
+ %% Note: xmaybe_expr not active here
+ ['ifn', while, until, 'if'].
+
+bar() ->
+ ['until', 'while'].
+
+baz(0) ->
+ [while];
+baz(1) ->
+ [until].
diff --git a/erts/test/lux/input/f_directives_3.erl b/erts/test/lux/input/f_directives_3.erl
new file mode 100644
index 0000000000..279c519150
--- /dev/null
+++ b/erts/test/lux/input/f_directives_3.erl
@@ -0,0 +1,44 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_directives_3).
+
+%% This module uses the feature ifn_expr, so atoms from that feature
+%% need to be quoted.
+
+-feature(enable, ifn_expr).
+-feature(disable, while_expr).
+
+-export([foo/0,
+ bar/0,
+ baz/1
+ ]).
+
+foo() ->
+ %% Note: maybe_expr not active here
+ ['ifn', while, until, 'if'].
+
+bar() ->
+ ['until', 'while'].
+
+baz(0) ->
+ [while];
+baz(1) ->
+ [until].
diff --git a/erts/test/lux/input/f_disable.erl b/erts/test/lux/input/f_disable.erl
new file mode 100644
index 0000000000..b72dfdb550
--- /dev/null
+++ b/erts/test/lux/input/f_disable.erl
@@ -0,0 +1,52 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_disable).
+
+-feature(disable, ifn_expr).
+-feature(disable, while_expr).
+
+-export([no_ifn/0,
+ no_ftrs/0]).
+
+-if(?FEATURE_ENABLED(ifn_expr)).
+-define(FOO, has_ifn).
+-else.
+-define(FOO, no_ifn).
+-endif.
+
+no_ifn() ->
+ [ifn, 'while', ?FOO].
+
+-if(?FEATURE_ENABLED(while_expr)).
+-define(BAR, has_maybe).
+-else.
+-define(BAR, no_maybe).
+-endif.
+
+no_ftrs() ->
+ [ifn, while, until, ?BAR].
+
+%% -compile({enable_feature, ifn_expr}).
+
+%% do(X) ->
+%% ifn X > 10 ->
+%% maybe
+%% end.
diff --git a/erts/test/lux/input/f_ifn.erl b/erts/test/lux/input/f_ifn.erl
new file mode 100644
index 0000000000..5ae4bcfa46
--- /dev/null
+++ b/erts/test/lux/input/f_ifn.erl
@@ -0,0 +1,32 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% This module knows about the feature ifn, but not about maybe thus
+%% use maybe and else as ordinary atoms.
+
+-module(f_ifn).
+
+-export([foo/0]).
+
+foo() ->
+ ['ifn', while, until].
+
+bar() ->
+ [until, while].
diff --git a/erts/test/lux/input/f_ifnot.erl b/erts/test/lux/input/f_ifnot.erl
new file mode 100644
index 0000000000..bb81239e7f
--- /dev/null
+++ b/erts/test/lux/input/f_ifnot.erl
@@ -0,0 +1,47 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_ifnot).
+
+-feature(enable, ifnot_expr).
+
+-export([f0/0,
+ f1/0,
+ f2/0,
+ f3/0,
+ f4/1]).
+
+f0() ->
+ ifnot false -> 40 + 2 end.
+
+f1() ->
+ ifnot true -> 42 end.
+
+f2() ->
+ ifnot begin X = 2, X > 2 end -> true end.
+
+f3() ->
+ Z = ifnot begin X = 3, X > 4 end -> Y=7+X, {X, Y} end,
+ Z.
+
+f4(X) ->
+ ifnot X ->
+ foo
+ end.
diff --git a/erts/test/lux/input/f_include_1.erl b/erts/test/lux/input/f_include_1.erl
new file mode 100644
index 0000000000..c8dce1e503
--- /dev/null
+++ b/erts/test/lux/input/f_include_1.erl
@@ -0,0 +1,22 @@
+-module(f_include_1).
+
+-feature(enable, unless_expr).
+
+-ifdef(end_prefix).
+-record(constant, {value = 42}).
+-endif.
+
+-ifdef(end_include).
+-feature(enable, maybe_expr).
+-endif.
+
+-include("is_enabled.hrl").
+
+-ifdef(end_include).
+-feature(enable, ifnot_expr).
+-endif.
+
+%% At this point the prefix will definitely end, if it has not already
+-export([foo/1]).
+
+foo(1) -> one.
diff --git a/erts/test/lux/input/f_include_2.erl b/erts/test/lux/input/f_include_2.erl
new file mode 100644
index 0000000000..209c454fc9
--- /dev/null
+++ b/erts/test/lux/input/f_include_2.erl
@@ -0,0 +1,22 @@
+-module(f_include_2).
+
+-feature(enable, unless_expr).
+
+-ifdef(end_prefix).
+-record(constant, {value = 42}).
+-endif.
+
+-ifdef(end_include).
+-feature(enable, maybe_expr).
+-endif.
+
+-include("macro_enabled.hrl").
+
+-ifdef(end_include).
+-feature(enable, ifnot_expr).
+-endif.
+
+%% At this point the prefix will definitely end, if it has not already
+-export([foo/1]).
+
+foo(2) -> ?UNLESS.
diff --git a/erts/test/lux/input/f_include_3.erl b/erts/test/lux/input/f_include_3.erl
new file mode 100644
index 0000000000..dba4a78dbb
--- /dev/null
+++ b/erts/test/lux/input/f_include_3.erl
@@ -0,0 +1,22 @@
+-module(f_include_3).
+
+-feature(enable, unless_expr).
+
+-ifdef(end_prefix).
+-record(constant, {value = 42}).
+-endif.
+
+-ifdef(end_include).
+-feature(enable, maybe_expr).
+-endif.
+
+-include("enable.hrl").
+
+-ifdef(end_include).
+-feature(enable, ifnot_expr).
+-endif.
+
+%% At this point the prefix will definitely end, if it has not already
+-export([foo/1]).
+
+foo(1) -> one.
diff --git a/erts/test/lux/input/f_include_maybe.erl b/erts/test/lux/input/f_include_maybe.erl
new file mode 100644
index 0000000000..102e6f95d2
--- /dev/null
+++ b/erts/test/lux/input/f_include_maybe.erl
@@ -0,0 +1,18 @@
+-module(f_include_maybe).
+
+-include("maybe.hrl").
+
+-export([foo/0,
+ bar/0]).
+
+
+foo() ->
+ #conditional{}.
+
+-if(?enable_maybe == 1).
+bar() ->
+ until.
+-else.
+bar() ->
+ no.
+-endif.
diff --git a/erts/test/lux/input/f_incorrect_directives.erl b/erts/test/lux/input/f_incorrect_directives.erl
new file mode 100644
index 0000000000..5e9129d1a1
--- /dev/null
+++ b/erts/test/lux/input/f_incorrect_directives.erl
@@ -0,0 +1,40 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% This module knows about the both features ifn and maybe
+%% These atoms are thus quoted
+
+-module(f_incorrect_directives).
+
+-export([foo/0,
+ bar/0
+ ]).
+
+%% FIXME This is out of place, but not check in any test.
+-feature(enable, ifn).
+
+foo() ->
+ %% Note: maybe_expr not active here
+ ['ifn', maybe, then, 'if'].
+
+-feature(enable, maybe).
+
+bar() ->
+ ['then', 'maybe'].
diff --git a/erts/test/lux/input/f_incorrect_disable.erl b/erts/test/lux/input/f_incorrect_disable.erl
new file mode 100644
index 0000000000..19f80c2e2c
--- /dev/null
+++ b/erts/test/lux/input/f_incorrect_disable.erl
@@ -0,0 +1,57 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% FIXME This file contains too much in erlation to what it tests
+
+-module(f_incorrect_disable).
+
+-feature(disable, unless).
+
+-export([do/1,
+ no_ifn/0,
+ no_ftrs/0]).
+
+
+-if(?FEATURE_ENABLED(ifn_expr)).
+-define(FOO, has_ifn).
+-else.
+-define(FOO, no_ifn).
+-endif.
+
+no_ifn() ->
+ [ifn, 'maybe', ?FOO].
+
+-feature(disable, maybe_expr).
+
+-if(?FEATURE_ENABLED(maybe_expr)).
+-define(BAR, has_maybe).
+-else.
+-define(BAR, no_maybe).
+-endif.
+
+no_ftrs() ->
+ [ifn, maybe, then, ?BAR].
+
+-feature(enable, ifn_expr).
+
+do(X) ->
+ ifn X > 10 ->
+ maybe
+ end.
diff --git a/erts/test/lux/input/f_macros.erl b/erts/test/lux/input/f_macros.erl
new file mode 100644
index 0000000000..3b10e4e7af
--- /dev/null
+++ b/erts/test/lux/input/f_macros.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_macros).
+
+-export([has_ifn/0,
+ has_hindly_milner/0,
+ with_hm/0,
+ uses_ifn/0,
+ uses_maybe/0
+ ]).
+
+%% This test feature exists
+-if(?FEATURE_AVAILABLE(ifn_expr)).
+has_ifn() ->
+ true.
+-else.
+has_ifn() ->
+ false.
+-endif.
+
+%% This feature will probably never exist :-(
+-if(?FEATURE_AVAILABLE(hindley_milner)).
+has_hindly_milner() ->
+ true.
+-else.
+has_hindly_milner() ->
+ false.
+-endif.
+
+with_hm() ->
+ ?FEATURE_ENABLED(hindley_milner).
+
+-if(?FEATURE_ENABLED(ifn_expr)).
+uses_ifn() ->
+ true.
+-else.
+uses_ifn() ->
+ false.
+-endif.
+
+-if(?FEATURE_ENABLED(while_expr)).
+uses_maybe() ->
+ true.
+-else.
+uses_maybe() ->
+ false.
+-endif.
diff --git a/erts/test/lux/input/f_maybe.erl b/erts/test/lux/input/f_maybe.erl
new file mode 100644
index 0000000000..40b4cc135f
--- /dev/null
+++ b/erts/test/lux/input/f_maybe.erl
@@ -0,0 +1,32 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% This module knows about the feature maybe, but not about maybe ifn
+%% and thus use ifn as an ordinary atom
+
+-module(f_maybe).
+
+-export([foo/0]).
+
+foo() ->
+ [ifn, 'xmaybe', 'then'].
+
+bar() ->
+ ['then', 'xmaybe'].
diff --git a/erts/test/lux/input/f_maybe_ifn.erl b/erts/test/lux/input/f_maybe_ifn.erl
new file mode 100644
index 0000000000..46cd376dcc
--- /dev/null
+++ b/erts/test/lux/input/f_maybe_ifn.erl
@@ -0,0 +1,32 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% This module knows about the both features ifn and maybe
+%% These atoms are thus quoted
+
+-module(f_maybe_ifn).
+
+-export([foo/0]).
+
+foo() ->
+ ['ifn', 'while', 'until'].
+
+bar() ->
+ ['until', 'while'].
diff --git a/erts/test/lux/input/f_use_ifn.erl b/erts/test/lux/input/f_use_ifn.erl
new file mode 100644
index 0000000000..c156b942e9
--- /dev/null
+++ b/erts/test/lux/input/f_use_ifn.erl
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_use_ifn).
+
+-export([use_ifn/1]).
+
+use_ifn(X) ->
+ ifn X > 0 ->
+ io:format("!(~p > 0)\n", [X])
+ end.
diff --git a/erts/test/lux/input/feature_directive_maybe_ifn.erl b/erts/test/lux/input/feature_directive_maybe_ifn.erl
new file mode 100644
index 0000000000..82f448dc1a
--- /dev/null
+++ b/erts/test/lux/input/feature_directive_maybe_ifn.erl
@@ -0,0 +1,87 @@
+%% This module knows about the both features ifn and maybe
+%% These atoms are thus quoted
+
+-module(feature_directive_maybe_ifn).
+
+-export([foo/0,
+ bar/0,
+ foo_feature/0,
+ ifn_0/0,
+ ifn_1/0,
+ ifn_2/0,
+ maybe_0/0,
+ maybe_1/0,
+ use_ifn/1
+ ]).
+
+-define(XLINE, 42).
+
+use_ifn(X) ->
+ ifn X > 0 ->
+ io:format("!(~p > 0)\n", [X])
+ end.
+
+-if(?FEATURE_AVAILABLE('ifn_expr')).
+foo_feature() ->
+ true.
+-else.
+foo_feature() ->
+ false.
+-endif.
+
+-if(?FEATURE_ENABLED('ifn_expr')).
+ifn_0() ->
+ true.
+-else.
+ifn_0() -> false.
+-endif.
+
+
+-define(FOO(X), ((X) == 'ifn' orelse (X) == 'maybe')).
+-define(BAR(X), false).
+%% NOTE: We need to quote the feature name due to it being the same as
+%% the new reserved word and it might have been enabled earlier, i.e.,
+%% from the command line or in argumemts to compile:file/..
+-compile({enable_feature, 'ifn_expr'}).
+
+%% use_ifn(X) ->
+%% ifn X > 0 ->
+%% io:format("!(~p > 0\n", [X])
+%% end.
+
+-if(?FEATURE_ENABLED('ifn_expr')).
+ifn_1() ->
+ true.
+-else.
+ifn_1() -> false.
+-endif.
+
+foo() ->
+ %% Note: maybe not active here
+ ['ifn', maybe, else, 'if'].
+
+-if(?FEATURE_ENABLED('maybe_expr')).
+maybe_0() ->
+ true.
+-else.
+maybe_0() -> false.
+-endif.
+
+-compile({enable_feature, 'maybe_expr'}).
+
+-if(?FEATURE_ENABLED('maybe_expr')).
+maybe_1() ->
+ true.
+-else.
+maybe_1() -> false.
+-endif.
+
+-if(?FEATURE_ENABLED('ifn_expr')).
+ifn_2() ->
+ true.
+-else.
+ifn_2() -> false.
+-endif.
+
+bar() ->
+ ['else', 'maybe'].
diff --git a/erts/test/lux/input/feature_ifn.erl b/erts/test/lux/input/feature_ifn.erl
new file mode 100644
index 0000000000..b8d1697cf5
--- /dev/null
+++ b/erts/test/lux/input/feature_ifn.erl
@@ -0,0 +1,12 @@
+%% This module knows about the feature ifn, but not abuot maybe thus
+%% use maybe and then as ordinary atoms.
+
+-module(feature_ifn).
+
+-export([foo/0]).
+
+foo() ->
+ ['ifn', while, until].
+
+bar() ->
+ [until, while].
diff --git a/erts/test/lux/input/feature_ignorant.erl b/erts/test/lux/input/feature_ignorant.erl
new file mode 100644
index 0000000000..7156b704c5
--- /dev/null
+++ b/erts/test/lux/input/feature_ignorant.erl
@@ -0,0 +1,17 @@
+%% This module is ignorant about any features and thus use 'ifn',
+%% 'maybe' and 'then' as ordinary atoms.
+
+-module(feature_ignorant).
+
+-export([foo/0]).
+
+foo() ->
+ [ifn, while, until].
+
+frob(while) -> false.
+
+bar() ->
+ [until, while].
+
+baz(ifn) ->
+ true.
diff --git a/erts/test/lux/input/feature_maybe.erl b/erts/test/lux/input/feature_maybe.erl
new file mode 100644
index 0000000000..58493bfd1c
--- /dev/null
+++ b/erts/test/lux/input/feature_maybe.erl
@@ -0,0 +1,12 @@
+%% This module knows about the feature while, but not about ifn
+%% and thus use ifn as an ordinary atom
+
+-module(feature_maybe).
+
+-export([foo/0]).
+
+foo() ->
+ [ifn, 'while', 'until'].
+
+bar() ->
+ ['until', 'while'].
diff --git a/erts/test/lux/input/feature_maybe_ifn.erl b/erts/test/lux/input/feature_maybe_ifn.erl
new file mode 100644
index 0000000000..8e4aeafe59
--- /dev/null
+++ b/erts/test/lux/input/feature_maybe_ifn.erl
@@ -0,0 +1,12 @@
+%% This module knows about the both features ifn and maybe
+%% These atoms are thus quoted
+
+-module(feature_maybe_ifn).
+
+-export([foo/0]).
+
+foo() ->
+ ['ifn', 'maybe', 'then'].
+
+bar() ->
+ ['then', 'maybe'].
diff --git a/erts/test/lux/input/foo.erl b/erts/test/lux/input/foo.erl
new file mode 100644
index 0000000000..60f2aca8f6
--- /dev/null
+++ b/erts/test/lux/input/foo.erl
@@ -0,0 +1,6 @@
+-module foo.
+
+-export [foo/0].
+
+foo() ->
+ foo.
diff --git a/erts/test/lux/input/ignorant.erl b/erts/test/lux/input/ignorant.erl
new file mode 100644
index 0000000000..d010b5cf72
--- /dev/null
+++ b/erts/test/lux/input/ignorant.erl
@@ -0,0 +1,40 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% This module is ignorant about any features and thus use 'ifn',
+%% 'maybe' and 'then' as ordinary atoms.
+
+-module(ignorant).
+
+-export([foo/0,
+ frob/1,
+ bar/0,
+ baz/1]).
+
+foo() ->
+ [ifn, while, until].
+
+frob(while) -> false.
+
+bar() ->
+ [until, while].
+
+baz(ifn) ->
+ true.
diff --git a/erts/test/lux/input/ignorant_directive.erl b/erts/test/lux/input/ignorant_directive.erl
new file mode 100644
index 0000000000..28709f7a2f
--- /dev/null
+++ b/erts/test/lux/input/ignorant_directive.erl
@@ -0,0 +1,42 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% This module is ignorant about any features and thus use 'ifn',
+%% 'maybe' and 'then' as ordinary atoms.
+
+-module(ignorant_directive).
+
+-compile(warn_keywords).
+
+-export([foo/0,
+ frob/1,
+ bar/0,
+ baz/1]).
+
+foo() ->
+ [ifn, while, until].
+
+frob(while) -> false.
+
+bar() ->
+ [until, while].
+
+baz(ifn) ->
+ true.
diff --git a/erts/test/lux/input/is_enabled.hrl b/erts/test/lux/input/is_enabled.hrl
new file mode 100644
index 0000000000..3884eaafac
--- /dev/null
+++ b/erts/test/lux/input/is_enabled.hrl
@@ -0,0 +1,3 @@
+%% This will fail when unless_expr is not enabled
+%% or end the prefix when it is enabled
+-record(random, {unless = 42, maybe = 17}).
diff --git a/erts/test/lux/input/macro_enabled.hrl b/erts/test/lux/input/macro_enabled.hrl
new file mode 100644
index 0000000000..86ace3899f
--- /dev/null
+++ b/erts/test/lux/input/macro_enabled.hrl
@@ -0,0 +1,5 @@
+-if(?FEATURE_ENABLED(unless_expr)).
+-define(UNLESS, active).
+-else.
+-define(UNLESS, inactive).
+-endif.
diff --git a/erts/test/lux/input/maybe.hrl b/erts/test/lux/input/maybe.hrl
new file mode 100644
index 0000000000..ffa665f0eb
--- /dev/null
+++ b/erts/test/lux/input/maybe.hrl
@@ -0,0 +1,10 @@
+-if(?enable_maybe > 0).
+-feature(enable, while_expr).
+-record(conditional, {on=off, 'until'=none}).
+-else.
+-record(conditional, {on=on, until=until}).
+-endif.
+
+%% -record(foo, {bar=outer, baz}).
+
+%% -record(conditional, {on, else}).
diff --git a/erts/test/lux/input/older.erl b/erts/test/lux/input/older.erl
new file mode 100644
index 0000000000..06bb154e28
--- /dev/null
+++ b/erts/test/lux/input/older.erl
@@ -0,0 +1,6 @@
+-module(older).
+
+-export([none/0]).
+
+none() ->
+ old.
--
2.34.1