Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests fail to convert #2

Open
neonrust opened this issue Jul 17, 2015 · 10 comments
Open

Tests fail to convert #2

neonrust opened this issue Jul 17, 2015 · 10 comments

Comments

@neonrust
Copy link

According to the README the (upstream) tests should pass.
Wanting to check the tests out (as a form of documentational examples), I tried the mentioned "make test".
This, however, fails with the current head (0d41413):

python3 test/gen_index_cxx.py ... > build/tests/upstream_tests.cc
g++ -o build/tests/upstream_tests.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/upstream_tests.cc -Wno-unused-variable
g++ -o build/tests/test/upstream/changefeeds/table.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/changefeeds/table.cc -Wno-unused-variable
python3 test/yaml_to_cxx.py test/upstream/control.yaml > build/tests/test/upstream/control.cc
Discarding 'r.do(1, 2, lambda x: x)' ('err("RqlRuntimeError", \'Expected 1 argument but found 2.\', [1])')
Discarding 'r.do(1, 2, 3, lambda x, y: x + y)' ('err("RqlRuntimeError", \'Expected 2 arguments but found 3.\', [1])')
Discarding 'r.expr(0).do(lambda a,b: a + b)' ('err("RqlRuntimeError", \'Expected 2 arguments but found 1.\', [1])')
Discarding 'r.do(1, 2, lambda a: a)' ('err("RqlRuntimeError", \'Expected 1 argument but found 2.\', [1])')
While translating: NameConstant(value=True)
While translating: Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='branch', ctx=Load()), args=[NameConstant(value=True), Num(n=1), Num(n=2)], keywords=[], starargs=None, kwargs=None)
While translating: r.branch(True, 1, 2)
Could not translate: ast type: <class '_ast.NameConstant'>, fields: ('value',)
While translating: NameConstant(value=False)
While translating: Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='branch', ctx=Load()), args=[NameConstant(value=False), Num(n=1), Num(n=2)], keywords=[], starargs=None, kwargs=None)
While translating: r.branch(False, 1, 2)
Could not translate: ast type: <class '_ast.NameConstant'>, fields: ('value',)
While translating: NameConstant(value=False)
While translating: Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='branch', ctx=Load()), args=[Num(n=1), Str(s='c'), NameConstant(value=False)], keywords=[], starargs=None, kwargs=None)
While translating: r.branch(1, 'c', False)
Could not translate: ast type: <class '_ast.NameConstant'>, fields: ('value',)
While translating: NameConstant(value=False)
While translating: Call(func=Attribute(value=Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='expr', ctx=Load()), args=[List(elts=[Num(n=1), Num(n=2), Num(n=4)], ctx=Load())], keywords=[], starargs=None, kwargs=None), attr='filter', ctx=Load()), args=[NameConstant(value=False)], keywords=[], starargs=None, kwargs=None)
While translating: r.expr([1, 2, 4]).filter(False)
Could not translate: ast type: <class '_ast.NameConstant'>, fields: ('value',)
Makefile:78: recipe for target 'build/tests/test/upstream/control.cc' failed
make: *** [build/tests/test/upstream/control.cc] Error 1

Should it work? I mean, is the trouble on my end?

I'm using Ubuntu 15.04.

@AtnNn
Copy link
Owner

AtnNn commented Aug 1, 2015

It works for me, tested with Python 3.2.3 and 3.3.5. What version of Python 3 are you using?

Here's the generated file control.cc.

@neonrust
Copy link
Author

neonrust commented Aug 1, 2015

Thanks for replying!
But, strange... I'm on 3.4.3.

Testing with 3.2.3 gave me this instead:

g++ -o build/tests/testlib.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c test/testlib.cc
g++ -o build/tests/test.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c test/test.cc
python3.2 test/gen_index_cxx.py ... > build/tests/upstream_tests.cc
g++ -o build/tests/upstream_tests.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/upstream_tests.cc -Wno-unused-variable
python3.2 test/yaml_to_cxx.py test/upstream/aggregation.yaml > build/tests/test/upstream/aggregation.cc
Discarding "tbl4.group('time').coerce_to('array')" ("({frozenset([('$reql_type$','TIME'),('timezone','+00:00'),('epoch_time',1375115782.24)]):[{'id':0,'time':{'timezone':'+00:00','$reql_type$':'TIME','epoch_time':1375115782.24}}],frozenset([('$reql_type$','TIME'),('timezone','+00:00'),('epoch_time',1375147296.68)]):[{'id':1,'time':{'timezone':'+00:00','$reql_type$':'TIME','epoch_time':1375147296.68}}]})")
g++ -o build/tests/test/upstream/aggregation.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/aggregation.cc -Wno-unused-variable
python3.2 test/yaml_to_cxx.py test/upstream/arraylimits.yaml > build/tests/test/upstream/arraylimits.cc
g++ -o build/tests/test/upstream/arraylimits.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/arraylimits.cc -Wno-unused-variable
python3.2 test/yaml_to_cxx.py test/upstream/changefeeds/idxcopy.yaml > build/tests/test/upstream/changefeeds/idxcopy.cc
g++ -o build/tests/test/upstream/changefeeds/idxcopy.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/changefeeds/idxcopy.cc -Wno-unused-variable
python3.2 test/yaml_to_cxx.py test/upstream/changefeeds/include_states.yaml > build/tests/test/upstream/changefeeds/include_states.cc
g++ -o build/tests/test/upstream/changefeeds/include_states.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/changefeeds/include_states.cc -Wno-unused-variable
python3.2 test/yaml_to_cxx.py test/upstream/changefeeds/point.yaml > build/tests/test/upstream/changefeeds/point.cc
Discarding 'basic.close()' (None)
g++ -o build/tests/test/upstream/changefeeds/point.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/changefeeds/point.cc -Wno-unused-variable
python3.2 test/yaml_to_cxx.py test/upstream/changefeeds/sindex.yaml > build/tests/test/upstream/changefeeds/sindex.cc
g++ -o build/tests/test/upstream/changefeeds/sindex.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/changefeeds/sindex.cc -Wno-unused-variable
python3.2 test/yaml_to_cxx.py test/upstream/changefeeds/table.yaml > build/tests/test/upstream/changefeeds/table.cc
g++ -o build/tests/test/upstream/changefeeds/table.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/changefeeds/table.cc -Wno-unused-variable
python3.2 test/yaml_to_cxx.py test/upstream/control.yaml > build/tests/test/upstream/control.cc
Discarding 'r.do(1, 2, lambda x: x)' ('err("RqlRuntimeError", \'Expected 1 argument but found 2.\', [1])')
Discarding 'r.do(1, 2, 3, lambda x, y: x + y)' ('err("RqlRuntimeError", \'Expected 2 arguments but found 3.\', [1])')
Discarding 'r.expr(0).do(lambda a,b: a + b)' ('err("RqlRuntimeError", \'Expected 2 arguments but found 1.\', [1])')
Discarding 'r.do(1, 2, lambda a: a)' ('err("RqlRuntimeError", \'Expected 1 argument but found 2.\', [1])')
g++ -o build/tests/test/upstream/control.o  -std=c++11 -I'build/gen' -Wall -pthread -fPIC -isystem build/include -I test -c build/tests/test/upstream/control.cc -Wno-unused-variable
In file included from test/testlib.h:8:0,
                 from build/tests/test/upstream/control.cc:2:
build/include/rethinkdb.h: In instantiation of ‘RethinkDB::Query RethinkDB::expr(T&&) [with T = test_upstream_control()::<lambda()>]’:
build/include/rethinkdb.h:1441:35:   required from ‘RethinkDB::Query RethinkDB::do_(R&&, T&& ...) [with R = test_upstream_control()::<lambda()>; T = {}]’
build/tests/test/upstream/control.cc:12:5:   required from here
build/include/rethinkdb.h:1294:36: error: no matching function for call to ‘RethinkDB::Query::Query(test_upstream_control()::<lambda()>)’
     return Query(std::forward<T>(a));
                                    ^
build/include/rethinkdb.h:1294:36: note: candidates are:
build/include/rethinkdb.h:1283:5: note: RethinkDB::Query::Query(RethinkDB::Query&&, RethinkDB::OptArgs&&)
     Query(Query&& orig, OptArgs&& optargs);
     ^
build/include/rethinkdb.h:1283:5: note:   candidate expects 2 arguments, 1 provided
build/include/rethinkdb.h:978:5: note: RethinkDB::Query::Query(RethinkDB::Protocol::Term::TermType, std::vector<RethinkDB::Query>&&, RethinkDB::OptArgs&&)
     Query(Protocol::Term::TermType type, std::vector<Query>&& args, OptArgs&& optargs) : datum(Array()) {
     ^
build/include/rethinkdb.h:978:5: note:   candidate expects 3 arguments, 1 provided
build/include/rethinkdb.h:970:5: note: RethinkDB::Query::Query(RethinkDB::Protocol::Term::TermType, std::vector<RethinkDB::Query>&&)
     Query(Protocol::Term::TermType type, std::vector<Query>&& args) : datum(Array()) {
     ^
build/include/rethinkdb.h:970:5: note:   candidate expects 2 arguments, 1 provided
In file included from test/testlib.h:8:0,
                 from build/tests/test/upstream/control.cc:2:
build/include/rethinkdb.h:968:5: note: RethinkDB::Query::Query(std::function<RethinkDB::Query(RethinkDB::Var, RethinkDB::Var, RethinkDB::Var)>)
     Query(std::function<Query(Var, Var, Var)> f) : datum(Nil()) { set_function<std::function<Query(Var, Var, Var)>, Var, Var, Var>(f); }
     ^
build/include/rethinkdb.h:968:5: note:   no known conversion for argument 1 from ‘test_upstream_control()::<lambda()>’ to ‘std::function<RethinkDB::Query(RethinkDB::Var, RethinkDB::Var, RethinkDB::Var)>’
build/include/rethinkdb.h:967:5: note: RethinkDB::Query::Query(std::function<RethinkDB::Query(RethinkDB::Var, RethinkDB::Var)>)
     Query(std::function<Query(Var, Var)> f) : datum(Nil()) { set_function<std::function<Query(Var, Var)>, Var, Var>(f); }
     ^
build/include/rethinkdb.h:967:5: note:   no known conversion for argument 1 from ‘test_upstream_control()::<lambda()>’ to ‘std::function<RethinkDB::Query(RethinkDB::Var, RethinkDB::Var)>’
build/include/rethinkdb.h:966:5: note: RethinkDB::Query::Query(std::function<RethinkDB::Query(RethinkDB::Var)>)
     Query(std::function<Query(Var)> f) : datum(Nil()) { set_function<std::function<Query(Var)>, Var>(f); }
     ^
build/include/rethinkdb.h:966:5: note:   no known conversion for argument 1 from ‘test_upstream_control()::<lambda()>’ to ‘std::function<RethinkDB::Query(RethinkDB::Var)>’
build/include/rethinkdb.h:961:14: note: RethinkDB::Query::Query(RethinkDB::OptArgs&&)
     explicit Query(OptArgs&&);
              ^
build/include/rethinkdb.h:961:14: note:   no known conversion for argument 1 from ‘test_upstream_control()::<lambda()>’ to ‘RethinkDB::OptArgs&& {aka std::map<std::basic_string<char>, RethinkDB::Query>&&}’
build/include/rethinkdb.h:960:14: note: RethinkDB::Query::Query(RethinkDB::Datum&&)
     explicit Query(Datum&&);
              ^
build/include/rethinkdb.h:960:14: note:   no known conversion for argument 1 from ‘test_upstream_control()::<lambda()>’ to ‘RethinkDB::Datum&&’
build/include/rethinkdb.h:956:5: note: RethinkDB::Query::Query(RethinkDB::Query&&)
     Query(Query&& other) = default;
     ^
build/include/rethinkdb.h:956:5: note:   no known conversion for argument 1 from ‘test_upstream_control()::<lambda()>’ to ‘RethinkDB::Query&&’
build/include/rethinkdb.h:955:5: note: RethinkDB::Query::Query(const RethinkDB::Query&)
     Query(const Query& other) = default;
     ^
build/include/rethinkdb.h:955:5: note:   no known conversion for argument 1 from ‘test_upstream_control()::<lambda()>’ to ‘const RethinkDB::Query&’
Makefile:86: recipe for target 'build/tests/test/upstream/control.o' failed
make: *** [build/tests/test/upstream/control.o] Error 1
Exit 2

Seems to work better...(?) but not all the way. :(

It's not apparent from the errors, but could I be missing some dependency?

@neonrust
Copy link
Author

neonrust commented Aug 2, 2015

I'm not spending a lot of time trying to find what the problem is. I'm still on my vacation... I'll take some further dives into this when I'm back at work. :)

However, I noticed that there definitely is some problem related to the python version:

# python3.2 yaml_to_cxx.py upstream/selection.yaml >/dev/null
Could not translate: syntax error: invalid syntax (upstream_selection, line 1): tbl3.insert({'id':u'Здравствуй','value':u'Земля!'})
Could not translate: syntax error: invalid syntax (upstream_selection, line 1): tbl3.get(u'Здравствуй')
Could not translate: syntax error: invalid syntax (upstream_selection, line 1): tbl3.filter({'value':u'Земля!'})

So, apparently some unicode troubles...

But with 3.4 it's (strangely) worse, and different:

# python3.4 yaml_to_cxx.py upstream/selection.yaml > /dev/null
While translating: NameConstant(value=True)
While translating: Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='table', ctx=Load()), args=[Str(s='test2')], keywords=[keyword(arg='use_outdated', value=NameConstant(value=True))], starargs=None, kwargs=None)
While translating: Attribute(value=Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='table', ctx=Load()), args=[Str(s='test2')], keywords=[keyword(arg='use_outdated', value=NameConstant(value=True))], starargs=None, kwargs=None), attr='count', ctx=Load())
While translating: Call(func=Attribute(value=Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='table', ctx=Load()), args=[Str(s='test2')], keywords=[keyword(arg='use_outdated', value=NameConstant(value=True))], starargs=None, kwargs=None), attr='count', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None)
While translating: r.table('test2', use_outdated=True).count()
Could not translate: ast type: <class '_ast.NameConstant'>, fields: ('value',)
While translating: NameConstant(value=True)
While translating: Call(func=Attribute(value=Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='db', ctx=Load()), args=[Str(s='test')], keywords=[], starargs=None, kwargs=None), attr='table', ctx=Load()), args=[Str(s='test2')], keywords=[keyword(arg='use_outdated', value=NameConstant(value=True))], starargs=None, kwargs=None)
While translating: Attribute(value=Call(func=Attribute(value=Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='db', ctx=Load()), args=[Str(s='test')], keywords=[], starargs=None, kwargs=None), attr='table', ctx=Load()), args=[Str(s='test2')], keywords=[keyword(arg='use_outdated', value=NameConstant(value=True))], starargs=None, kwargs=None), attr='count', ctx=Load())
While translating: Call(func=Attribute(value=Call(func=Attribute(value=Call(func=Attribute(value=Name(id='r', ctx=Load()), attr='db', ctx=Load()), args=[Str(s='test')], keywords=[], starargs=None, kwargs=None), attr='table', ctx=Load()), args=[Str(s='test2')], keywords=[keyword(arg='use_outdated', value=NameConstant(value=True))], starargs=None, kwargs=None), attr='count', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None)
While translating: r.db('test').table('test2', use_outdated=True).count()
Could not translate: ast type: <class '_ast.NameConstant'>, fields: ('value',)

But anyway, as mentioned, I'll look some more later.

@AtnNn
Copy link
Owner

AtnNn commented Aug 3, 2015

Thanks for investigating. It appears that Python 3.2 doesn't support the u prefix for strings, which causes some tests to be skipped.

I've added support for Python 3.4's ast.NameConstant on my local branch, I'll push it to github tonight. It seems to fix the first set of errors you encountered.

I was also able to reproduce the set of C++ errors you saw. It looks as if R::expr in master doesn't work with raw lambdas.

@neonrust
Copy link
Author

neonrust commented Aug 4, 2015

Oh, good to hear it's not only me! :)
I also did an half-assed, hacky attempt at handling the NameConstant token, but I've never used ast so progress was absent...
Maybe I'll have some time to night to try it out the generation fixes. Good work!

@AtnNn AtnNn mentioned this issue Aug 5, 2015
@AtnNn
Copy link
Owner

AtnNn commented Aug 5, 2015

I've pushed e57c430 which fixes issues in building the tests. Let me know if it doesn't work for you.

Running the tests now reports 10 of 2054 tests failed. I've opened #3 for that.

Thanks @tatsujin1.

@neonrust
Copy link
Author

neonrust commented Aug 5, 2015

Cool, it's much smoother now! Conversion seems to be successful.
But what does the "Discarding" message mean?
Not applicable tests? I don't see a common denominator...

$ python3 test/yaml_to_cxx.py test/upstream/control.yaml >/dev/null
Discarding 'r.do(1, 2, lambda x: x)' ('err("RqlRuntimeError", \'Expected 1 argument but found 2.\', [1])')
Discarding 'r.do(1, 2, 3, lambda x, y: x + y)' ('err("RqlRuntimeError", \'Expected 2 arguments but found 3.\', [1])')
Discarding 'r.expr(0).do(lambda a,b: a + b)' ('err("RqlRuntimeError", \'Expected 2 arguments but found 1.\', [1])')
Discarding 'r.do(1, 2, lambda a: a)' ('err("RqlRuntimeError", \'Expected 1 argument but found 2.\', [1])')
$ python3 test/yaml_to_cxx.py test/upstream/aggregation.yaml >/dev/null
Discarding "tbl4.group('time').coerce_to('array')" ("({frozenset([('$reql_type$','TIME'),('timezone','+00:00'),('epoch_time',1375115782.24)]):[{'id':0,'time':{'timezone':'+00:00','$reql_type$':'TIME','epoch_time':1375115782.24}}],frozenset([('$reql_type$','TIME'),('timezone','+00:00'),('epoch_time',1375147296.68)]):[{'id':1,'time':{'timezone':'+00:00','$reql_type$':'TIME','epoch_time':1375147296.68}}]})")
$ python3 test/yaml_to_cxx.py test/upstream/changefeeds/point.yaml  >/dev/null
Discarding 'basic.close()' (None)
$ python3 test/yaml_to_cxx.py test/upstream/datum/binary.yaml >/dev/null
Discarding "r.binary(u'イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム'.encode('utf-8'))" ("u'イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム'.encode('utf-8')")
Discarding "r.binary(u'ƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏ'.encode('utf-16'))" ("u'ƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏ'.encode('utf-16')")
Discarding "r.binary(u'lorem ipsum'.encode('ascii'))" ("u'lorem ipsum'.encode('ascii')")
Discarding "r.binary(u'イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム'.encode('utf-8')).coerce_to('string')" ("u'イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム'")
Discarding "r.binary(u'lorem ipsum'.encode('ascii')).coerce_to('string')" ("u'lorem ipsum'")
$ python3 test/yaml_to_cxx.py test/upstream/datum/object.yaml  >/dev/null
Discarding "r.expr({12:'a'})" ('err_regex("RqlDriverError", "Object keys must be strings")')
Discarding "r.expr({'a':{12:'b'}})" ('err_regex("RqlDriverError", "Object keys must be strings")')
Discarding 'r.expr({}, "foo")' ('err("RqlDriverError", "Second argument to `r.expr` must be a number.")')
$ python3 test/yaml_to_cxx.py test/upstream/math_logic/logic.yaml >/dev/null
Discarding 'r.expr(r.expr(True) & r.expr(False) == r.expr(False) | r.expr(True))' ('err("RqlDriverError", "Calling \'==\' on result of infix bitwise operator.", [])')
$ python3 test/yaml_to_cxx.py test/upstream/meta/table.yaml >/dev/null
Discarding "db.table_create('nonsense', 'foo')" ('err("RqlCompileError", "Expected between 1 and 2 arguments but found 3.", [])')
$ python3 test/yaml_to_cxx.py test/upstream/range.yaml >/dev/null
Discarding 'r.range(2, 5, 8)' ('err("RqlCompileError", "Expected between 0 and 2 arguments but found 3.", [])')
$ python3 test/yaml_to_cxx.py test/upstream/regression/632.yaml >/dev/null
Discarding "r.expr({1:'a'})" ('err_regex("RqlDriverError", "Object keys must be strings.")')
$ python3 test/yaml_to_cxx.py test/upstream/sindex/api.yaml >/dev/null
Discarding "tbl.get(1, 'ai')" ('err("RqlCompileError", "Expected 2 arguments but found 3.", [])')
$ python3 test/yaml_to_cxx.py test/upstream/times/api.yaml >/dev/null
Discarding 'r.time(2013, r.july, 29, 23, 30, 0.1).to_epoch_time()' ('err("RqlRuntimeError", "Got 6 arguments to TIME (expected 4 or 7).", [])')
Discarding 'r.time(2013, r.july, 29, 23, 30, 0.1).timezone()' ('err("RqlRuntimeError", "Got 6 arguments to TIME (expected 4 or 7).", [])')
Discarding 'r.time(2013, r.july, 29, 23, 30).to_epoch_time()' ('err("RqlRuntimeError", "Got 5 arguments to TIME (expected 4 or 7).", [])')
Discarding 'r.time(2013, r.july, 29).to_epoch_time()' ('err("RqlCompileError", "Expected between 4 and 7 arguments but found 3.", [])')
Discarding 'r.time(2013, r.july, 29).timezone()' ('err("RqlCompileError", "Expected between 4 and 7 arguments but found 3.", [])')

Btw, I see that in some messages, the unicode "u" is still there (e.g. strings with japanese)...

@AtnNn
Copy link
Owner

AtnNn commented Aug 5, 2015

I've added small descriptions to the "Discarding" messages in 8f90a7c

@neonrust
Copy link
Author

neonrust commented Aug 5, 2015

Ah, I see... "not implemented" :)

@AtnNn
Copy link
Owner

AtnNn commented Aug 9, 2015

Some of the discarded tests are also Python specific, or test failures that are compile-time errors in C++.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants