This document is stored in an electronic form using Git source control management software.
+
+
Introduction
+
+
This section provides an introduction to the project or the feature.
+All SRS documents must be uniquely identified by a number. In this
+case this document is identified by the number
+
+
CH-SRS001
+
+
+
The document number must always be used as a prefix to the document title. For example,
+
+
CH-SRSxxx Name of the document
+
+
+
All the requirements must be specified in the Requirements section.
+
+
Table of Contents
+
+
Note that currently the table of contents is generated manually using
+
+
cat CH_SRS001_ClickHouse.md | tfs document toc
+
+
+
command and needs to be updated any time requirement name is changed
+or a new requirement is added.
+
+
Generating HTML version
+
+
You can easily generate a pretty HTML version of this document using the command.
You can define terminolgy using the examples below and make you can make them
+linkable as SRS by defining the links in the References section.
+
+
SRS
+
+
Software Requirements Specification
+
+
Some term that you will use
+
+
Some description of the term that you would like to use.
+
+
Requirements
+
+
This section includes all the requirements. This section can be structured in any way one sees fit.
+
+
Each requirement is defined by the section that starts with
+the following prefix:
+
+
RQ.[document id].[requirement name]
+
+
+
then immediately followed by a one-line block that contains the
+the version of the requirement.
+
+
RQ.CH-SRS001.Example short description of the requirement
+
+
version: 1.0
+
+
This is a long description of the requirement that can include any
+relevant information.
+
+
The one-line block that follows the requirement defines the version
+of the requirement. The version is controlled manually and is used
+to indicate material changes to the requirement that would
+require tests that cover this requirement to be updated.
+
+
It is a good practice to use requirement names that are broken
+up into groups. It is not recommended to use only numbers
+because if the requirement must be moved the numbering will not match.
+Therefore, the requirement name should start with the group
+name which is then followed by a number if any. For example,
+
+
RQ.SRS001.Group.Subgroup.1
+
+
+
To keep names short, try to use abbreviations for the requirement's group name.
+
+
RQ.CH-SRS001.Example.Subgroup short description of the sub-requirement
+
+
version: 1.0
+
+
This an example of a sub-requirement of the RQ.CH-SRS001.Example.
+CH_SRS001_Software_Requirements_Template.md
+
+
RQ.CH-SRS001.Example.Select.1
+
+
version: 1.0
+
+
ClickHouse SHALL return 1 when user executes query
+
+
+
\ No newline at end of file
diff --git a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
new file mode 100644
index 00000000000..370ff14c2cb
--- /dev/null
+++ b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
@@ -0,0 +1,136 @@
+# CH-SRS001 ClickHouse Software Requirements Specification Template
+
+**Author:** [name of the author]
+
+**Date:** [date]
+
+## Table of Contents
+
+* 1 [Revision History](#revision-history)
+* 2 [Introduction](#introduction)
+ * 2.1 [Table of Contents](#table-of-contents)
+ * 2.2 [Generating HTML version](#generating-html-version)
+ * 2.3 [Generating Python Requirements](#generating-python-requirements)
+* 3 [Terminology](#terminology)
+ * 3.1 [SRS](#srs)
+ * 3.2 [Some term that you will use](#some-term-that-you-will-use)
+* 4 [Requirements](#requirements)
+ * 4.1 [RQ.CH-SRS001.Example short description of the requirement ](#rqch-srs001example-short-description-of-the-requirement-)
+ * 4.2 [RQ.CH-SRS001.Example.Subgroup short description of the sub-requirement](#rqch-srs001examplesubgroup-short-description-of-the-sub-requirement)
+ * 4.3 [RQ.CH-SRS001.Example.Select.1](#rqch-srs001exampleselect1)
+* 5 [References](#references)
+
+## Revision History
+
+This document is stored in an electronic form using [Git] source control management software.
+
+## Introduction
+
+This section provides an introduction to the project or the feature.
+All [SRS] documents must be uniquely identified by a number. In this
+case this document is identified by the number
+
+ CH-SRS001
+
+The document number must always be used as a prefix to the document title. For example,
+
+ CH-SRSxxx Name of the document
+
+All the requirements must be specified in the [Requirements](#requirements) section.
+
+### Table of Contents
+
+Note that currently the table of contents is generated manually using
+
+```bash
+cat CH_SRS001_ClickHouse.md | tfs document toc
+```
+
+command and needs to be updated any time requirement name is changed
+or a new requirement is added.
+
+### Generating HTML version
+
+You can easily generate a pretty HTML version of this document using the command.
+
+```bash
+cat CH_SRS001_ClickHouse.md | tfs document convert > CH_SRS001_ClickHouse.html
+```
+
+### Generating Python Requirements
+
+You can convert this [SRS] into the `requirements.py` by using the command.
+
+```bash
+cat CH_SRS001_ClickHouse.md | tfs requirements generate > requirements.py
+```
+
+## Terminology
+
+You can define terminolgy using the examples below and make you can make them
+linkable as [SRS] by defining the links in the [References](#References) section.
+
+### SRS
+
+Software Requirements Specification
+
+### Some term that you will use
+
+Some description of the term that you would like to use.
+
+## Requirements
+
+This section includes all the requirements. This section can be structured in any way one sees fit.
+
+Each requirement is defined by the section that starts with
+the following prefix:
+
+ RQ.[document id].[requirement name]
+
+then immediately followed by a one-line block that contains the
+the `version` of the requirement.
+
+### RQ.CH-SRS001.Example short description of the requirement
+version: 1.0
+
+This is a long description of the requirement that can include any
+relevant information.
+
+The one-line block that follows the requirement defines the `version`
+of the requirement. The version is controlled manually and is used
+to indicate material changes to the requirement that would
+require tests that cover this requirement to be updated.
+
+It is a good practice to use requirement names that are broken
+up into groups. It is not recommended to use only numbers
+because if the requirement must be moved the numbering will not match.
+Therefore, the requirement name should start with the group
+name which is then followed by a number if any. For example,
+
+ RQ.SRS001.Group.Subgroup.1
+
+To keep names short, try to use abbreviations for the requirement's group name.
+
+### RQ.CH-SRS001.Example.Subgroup short description of the sub-requirement
+version: 1.0
+
+This an example of a sub-requirement of the [RQ.CH-SRS001.Example](#rqch-srs001example).
+CH_SRS001_Software_Requirements_Template.md
+
+### RQ.CH-SRS001.Example.Select.1
+version: 1.0
+
+[ClickHouse] SHALL return `1` when user executes query
+
+```sql
+SELECT 1
+```
+
+## References
+
+* **ClickHouse:** https://clickhouse.tech
+
+[SRS]: #SRS
+[Some term that you will use]: #Sometermthatyouwilluse
+[ClickHouse]: https://clickhouse.tech
+[Git]: https://git-scm.com/
diff --git a/tests/testflows/example/requirements/requirements.py b/tests/testflows/example/requirements/requirements.py
index 9a0b4922f19..f890b9a1daf 100644
--- a/tests/testflows/example/requirements/requirements.py
+++ b/tests/testflows/example/requirements/requirements.py
@@ -1,9 +1,66 @@
+# These requirements were auto generated
+# from software requirements specification (SRS)
+# document by TestFlows v1.6.200627.1211752.
+# Do not edit by hand but re-generate instead
+# using 'tfs requirements generate' command.
from testflows.core import Requirement
-RQ_ClickHouse_Select_1 = Requirement(
- name='RQ.ClickHouse.Select.1',
+RQ_CH_SRS001_Example_short_description_of_the_requirement_ = Requirement(
+ name='RQ.CH-SRS001.Example short description of the requirement ',
version='1.0',
+ priority=None,
+ group=None,
+ type=None,
+ uid=None,
description=(
- '[ClickHouse] SHALL return `1` when user sends a simple `SELECT 1` query.\n'
- )
+ 'This is a long description of the requirement that can include any\n'
+ 'relevant information. \n'
+ '\n'
+ 'The one-line block that follows the requirement defines the `version` \n'
+ 'of the requirement. The version is controlled manually and is used\n'
+ 'to indicate material changes to the requirement that would \n'
+ 'require tests that cover this requirement to be updated.\n'
+ '\n'
+ 'It is a good practice to use requirement names that are broken\n'
+ 'up into groups. It is not recommended to use only numbers\n'
+ 'because if the requirement must be moved the numbering will not match.\n'
+ 'Therefore, the requirement name should start with the group\n'
+ 'name which is then followed by a number if any. For example,\n'
+ '\n'
+ ' RQ.SRS001.Group.Subgroup.1\n'
+ '\n'
+ "To keep names short, try to use abbreviations for the requirement's group name.\n"
+ ),
+ link=None
+ )
+
+RQ_CH_SRS001_Example_Subgroup_short_description_of_the_sub_requirement = Requirement(
+ name='RQ.CH-SRS001.Example.Subgroup short description of the sub-requirement',
+ version='1.0',
+ priority=None,
+ group=None,
+ type=None,
+ uid=None,
+ description=(
+ 'This an example of a sub-requirement of the [RQ.CH-SRS001.Example](#rqch-srs001example).\n'
+ 'CH_SRS001_Software_Requirements_Template.md\n'
+ ),
+ link=None
+ )
+
+RQ_CH_SRS001_Example_Select_1 = Requirement(
+ name='RQ.CH-SRS001.Example.Select.1',
+ version='1.0',
+ priority=None,
+ group=None,
+ type=None,
+ uid=None,
+ description=(
+ '[ClickHouse] SHALL return `1` when user executes query\n'
+ '\n'
+ '```sql\n'
+ 'SELECT 1\n'
+ '```\n'
+ ),
+ link=None
)
diff --git a/tests/testflows/example/tests/example.py b/tests/testflows/example/tests/example.py
index 8559f290cc4..6586fa80e41 100644
--- a/tests/testflows/example/tests/example.py
+++ b/tests/testflows/example/tests/example.py
@@ -6,7 +6,7 @@ from example.requirements import *
@TestScenario
@Name("select 1")
@Requirements(
- RQ_ClickHouse_Select_1("1.0")
+ RQ_CH_SRS001_Example_Select_1("1.0")
)
def scenario(self, node="clickhouse1"):
"""Check that ClickHouse returns 1 when user executes `SELECT 1` query.
From a233aa257d6bb7a3a1249c25ca0f90703e6aa642 Mon Sep 17 00:00:00 2001
From: Vitaliy Zakaznikov
Date: Thu, 2 Jul 2020 20:48:17 +0200
Subject: [PATCH 04/12] Small changes to the SRS template.
---
.../example/requirements/CH_SRS001_ClickHouse.html | 8 ++++----
.../example/requirements/CH_SRS001_ClickHouse.md | 8 ++++----
tests/testflows/example/requirements/requirements.py | 8 ++++----
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
index 5aedad25979..ec466d16888 100644
--- a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
+++ b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
@@ -1313,8 +1313,8 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
then immediately followed by a one-line block that contains the
the version of the requirement.
-
RQ.CH-SRS001.Example short description of the requirement
+
RQ.CH-SRS001.Example
version: 1.0
@@ -1413,7 +1413,7 @@ name which is then followed by a number if any. For example,
To keep names short, try to use abbreviations for the requirement's group name.
-
RQ.CH-SRS001.Example.Subgroup short description of the sub-requirement
+
RQ.CH-SRS001.Example.Subgroup
version: 1.0
diff --git a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
index 370ff14c2cb..284c6810958 100644
--- a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
+++ b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
@@ -15,8 +15,8 @@
* 3.1 [SRS](#srs)
* 3.2 [Some term that you will use](#some-term-that-you-will-use)
* 4 [Requirements](#requirements)
- * 4.1 [RQ.CH-SRS001.Example short description of the requirement ](#rqch-srs001example-short-description-of-the-requirement-)
- * 4.2 [RQ.CH-SRS001.Example.Subgroup short description of the sub-requirement](#rqch-srs001examplesubgroup-short-description-of-the-sub-requirement)
+ * 4.1 [RQ.CH-SRS001.Example](#rqch-srs001example)
+ * 4.2 [RQ.CH-SRS001.Example.Subgroup](#rqch-srs001examplesubgroup)
* 4.3 [RQ.CH-SRS001.Example.Select.1](#rqch-srs001exampleselect1)
* 5 [References](#references)
@@ -90,7 +90,7 @@ the following prefix:
then immediately followed by a one-line block that contains the
the `version` of the requirement.
-### RQ.CH-SRS001.Example short description of the requirement
+### RQ.CH-SRS001.Example
version: 1.0
This is a long description of the requirement that can include any
@@ -111,7 +111,7 @@ name which is then followed by a number if any. For example,
To keep names short, try to use abbreviations for the requirement's group name.
-### RQ.CH-SRS001.Example.Subgroup short description of the sub-requirement
+### RQ.CH-SRS001.Example.Subgroup
version: 1.0
This an example of a sub-requirement of the [RQ.CH-SRS001.Example](#rqch-srs001example).
diff --git a/tests/testflows/example/requirements/requirements.py b/tests/testflows/example/requirements/requirements.py
index f890b9a1daf..b42a73c293e 100644
--- a/tests/testflows/example/requirements/requirements.py
+++ b/tests/testflows/example/requirements/requirements.py
@@ -5,8 +5,8 @@
# using 'tfs requirements generate' command.
from testflows.core import Requirement
-RQ_CH_SRS001_Example_short_description_of_the_requirement_ = Requirement(
- name='RQ.CH-SRS001.Example short description of the requirement ',
+RQ_CH_SRS001_Example = Requirement(
+ name='RQ.CH-SRS001.Example',
version='1.0',
priority=None,
group=None,
@@ -34,8 +34,8 @@ RQ_CH_SRS001_Example_short_description_of_the_requirement_ = Requirement(
link=None
)
-RQ_CH_SRS001_Example_Subgroup_short_description_of_the_sub_requirement = Requirement(
- name='RQ.CH-SRS001.Example.Subgroup short description of the sub-requirement',
+RQ_CH_SRS001_Example_Subgroup = Requirement(
+ name='RQ.CH-SRS001.Example.Subgroup',
version='1.0',
priority=None,
group=None,
From 464eb70ca4d4602116d15b694a6483cf591ed3dc Mon Sep 17 00:00:00 2001
From: Vitaliy Zakaznikov
Date: Thu, 2 Jul 2020 20:52:17 +0200
Subject: [PATCH 05/12] Removing unnecessary text.
---
tests/testflows/example/requirements/CH_SRS001_ClickHouse.html | 3 +--
tests/testflows/example/requirements/CH_SRS001_ClickHouse.md | 1 -
tests/testflows/example/requirements/requirements.py | 1 -
3 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
index ec466d16888..9cfb3564288 100644
--- a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
+++ b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
@@ -1417,8 +1417,7 @@ name which is then followed by a number if any. For example,
version: 1.0
-
This an example of a sub-requirement of the RQ.CH-SRS001.Example.
-CH_SRS001_Software_Requirements_Template.md
diff --git a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
index 284c6810958..e4eb2e38c79 100644
--- a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
+++ b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
@@ -115,7 +115,6 @@ To keep names short, try to use abbreviations for the requirement's group name.
version: 1.0
This an example of a sub-requirement of the [RQ.CH-SRS001.Example](#rqch-srs001example).
-CH_SRS001_Software_Requirements_Template.md
### RQ.CH-SRS001.Example.Select.1
version: 1.0
diff --git a/tests/testflows/example/requirements/requirements.py b/tests/testflows/example/requirements/requirements.py
index b42a73c293e..ef28a5fe149 100644
--- a/tests/testflows/example/requirements/requirements.py
+++ b/tests/testflows/example/requirements/requirements.py
@@ -43,7 +43,6 @@ RQ_CH_SRS001_Example_Subgroup = Requirement(
uid=None,
description=(
'This an example of a sub-requirement of the [RQ.CH-SRS001.Example](#rqch-srs001example).\n'
- 'CH_SRS001_Software_Requirements_Template.md\n'
),
link=None
)
From 3f9dd7f62bae54ad6a8292bbbf511ae3f66c72e3 Mon Sep 17 00:00:00 2001
From: Vitaliy Zakaznikov
Date: Thu, 2 Jul 2020 21:02:15 +0200
Subject: [PATCH 06/12] Fix small typo.
---
tests/testflows/example/requirements/CH_SRS001_ClickHouse.html | 2 +-
tests/testflows/example/requirements/CH_SRS001_ClickHouse.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
index 9cfb3564288..8c40d7484cd 100644
--- a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
+++ b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.html
@@ -1366,7 +1366,7 @@ or a new requirement is added.
Terminology
-
You can define terminolgy using the examples below and make you can make them
+
You can define terminolgy using the examples below and you can make them
linkable as SRS by defining the links in the References section.
SRS
diff --git a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
index e4eb2e38c79..36445fab6cf 100644
--- a/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
+++ b/tests/testflows/example/requirements/CH_SRS001_ClickHouse.md
@@ -67,7 +67,7 @@ cat CH_SRS001_ClickHouse.md | tfs requirements generate > requirements.py
## Terminology
-You can define terminolgy using the examples below and make you can make them
+You can define terminolgy using the examples below and you can make them
linkable as [SRS] by defining the links in the [References](#References) section.
### SRS
From a449f3e9ff950e88de9269ae01c61e0bde99e6b2 Mon Sep 17 00:00:00 2001
From: Alexander Kazakov
Date: Tue, 7 Jul 2020 12:03:37 +0300
Subject: [PATCH 07/12] A test for UInt8 as bool
---
.../00552_logical_functions_uint8_as_bool.reference | 8 ++++++++
.../00552_logical_functions_uint8_as_bool.sql | 11 +++++++++++
2 files changed, 19 insertions(+)
create mode 100644 tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.reference
create mode 100644 tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.sql
diff --git a/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.reference b/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.reference
new file mode 100644
index 00000000000..9a65a2603dc
--- /dev/null
+++ b/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.reference
@@ -0,0 +1,8 @@
+0 0 0 0 0
+0 0 1 0 1
+0 2 0 0 1
+0 2 1 0 1
+4 0 0 0 1
+4 0 1 0 1
+4 2 0 0 1
+4 2 1 1 1
diff --git a/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.sql b/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.sql
new file mode 100644
index 00000000000..46a5fa39d47
--- /dev/null
+++ b/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.sql
@@ -0,0 +1,11 @@
+
+-- Test that UInt8 type is processed correctly as bool
+
+SELECT
+ toUInt8(bitAnd(number, 4)) AS a,
+ toUInt8(bitAnd(number, 2)) AS b,
+ toUInt8(bitAnd(number, 1)) AS c,
+ a AND b AND c AS AND,
+ a OR b OR c AS OR
+FROM numbers(8)
+;
\ No newline at end of file
From 66128acd113bbcaf8c43bac9de13b39093f6775b Mon Sep 17 00:00:00 2001
From: Alexander Kazakov
Date: Tue, 7 Jul 2020 12:17:35 +0300
Subject: [PATCH 08/12] Included const uint8 values in test
---
.../00552_logical_functions_uint8_as_bool.reference | 1 +
.../00552_logical_functions_uint8_as_bool.sql | 11 ++++++++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.reference b/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.reference
index 9a65a2603dc..2a1151dc692 100644
--- a/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.reference
+++ b/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.reference
@@ -1,3 +1,4 @@
+1 1 1 1 1 1
0 0 0 0 0
0 0 1 0 1
0 2 0 0 1
diff --git a/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.sql b/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.sql
index 46a5fa39d47..feee33add1c 100644
--- a/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.sql
+++ b/tests/queries/0_stateless/00552_logical_functions_uint8_as_bool.sql
@@ -1,6 +1,15 @@
-- Test that UInt8 type is processed correctly as bool
+SELECT
+ 1 AND 2,
+ 2 AND 4,
+ 1 AND 2 AND 4,
+ 1 OR 2,
+ 2 OR 4,
+ 1 OR 2 OR 4
+;
+
SELECT
toUInt8(bitAnd(number, 4)) AS a,
toUInt8(bitAnd(number, 2)) AS b,
@@ -8,4 +17,4 @@ SELECT
a AND b AND c AS AND,
a OR b OR c AS OR
FROM numbers(8)
-;
\ No newline at end of file
+;
From 2906ae37f50bfb5504ad80ec56585d245caa6f54 Mon Sep 17 00:00:00 2001
From: Alexander Kazakov
Date: Tue, 7 Jul 2020 13:26:11 +0300
Subject: [PATCH 09/12] Simple (and fast) inplace fix for UInt8 -> bool
---
src/Functions/FunctionsLogical.cpp | 14 ++++++++------
src/Functions/FunctionsLogical.h | 9 ++++++---
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/src/Functions/FunctionsLogical.cpp b/src/Functions/FunctionsLogical.cpp
index 07351f6f2c9..5443df33d79 100644
--- a/src/Functions/FunctionsLogical.cpp
+++ b/src/Functions/FunctionsLogical.cpp
@@ -71,7 +71,7 @@ bool tryConvertColumnToBool(const IColumn * column, UInt8Container & res)
std::transform(
col->getData().cbegin(), col->getData().cend(), res.begin(),
- [](const auto x) { return x != 0; });
+ [](const auto x) { return !!x; });
return true;
}
@@ -145,6 +145,7 @@ inline bool extractConstColumnsAsTernary(ColumnRawPtrs & in, UInt8 & res_3v)
}
+/// N.B. This class calculates result only for non-nullable types
template
class AssociativeApplierImpl
{
@@ -158,7 +159,7 @@ public:
/// Returns a combination of values in the i-th row of all columns stored in the constructor.
inline ResultValueType apply(const size_t i) const
{
- const auto & a = vec[i];
+ const auto a = !!vec[i];
if constexpr (Op::isSaturable())
return Op::isSaturatedValue(a) ? a : Op::apply(a, next.apply(i));
else
@@ -179,7 +180,7 @@ public:
explicit AssociativeApplierImpl(const UInt8ColumnPtrs & in)
: vec(in[in.size() - 1]->getData()) {}
- inline ResultValueType apply(const size_t i) const { return vec[i]; }
+ inline ResultValueType apply(const size_t i) const { return !!vec[i]; }
private:
const UInt8Container & vec;
@@ -247,7 +248,7 @@ public:
{
const auto a = val_getter(i);
if constexpr (Op::isSaturable())
- return Op::isSaturatedValue(a) ? a : Op::apply(a, next.apply(i));
+ return Op::isSaturatedValueTernary(a) ? a : Op::apply(a, next.apply(i));
else
return Op::apply(a, next.apply(i));
}
@@ -332,7 +333,7 @@ static void executeForTernaryLogicImpl(ColumnRawPtrs arguments, ColumnWithTypeAn
{
/// Combine all constant columns into a single constant value.
UInt8 const_3v_value = 0;
- const bool has_consts = extractConstColumnsTernary(arguments, const_3v_value);
+ const bool has_consts = extractConstColumnsAsTernary(arguments, const_3v_value);
/// If the constant value uniquely determines the result, return it.
if (has_consts && (arguments.empty() || Op::isSaturatedValue(const_3v_value)))
@@ -402,12 +403,13 @@ struct TypedExecutorInvoker
};
+/// Types of all of the arguments are guaranteed to be non-nullable here
template
static void basicExecuteImpl(ColumnRawPtrs arguments, ColumnWithTypeAndName & result_info, size_t input_rows_count)
{
/// Combine all constant columns into a single constant value.
UInt8 const_val = 0;
- bool has_consts = extractConstColumns(arguments, const_val);
+ bool has_consts = extractConstColumnsAsBool(arguments, const_val);
/// If the constant value uniquely determines the result, return it.
if (has_consts && (arguments.empty() || Op::apply(const_val, 0) == Op::apply(const_val, 1)))
diff --git a/src/Functions/FunctionsLogical.h b/src/Functions/FunctionsLogical.h
index 520a2418890..4751f0b7548 100644
--- a/src/Functions/FunctionsLogical.h
+++ b/src/Functions/FunctionsLogical.h
@@ -61,7 +61,8 @@ struct AndImpl
using ResultType = UInt8;
static inline constexpr bool isSaturable() { return true; }
- static inline constexpr bool isSaturatedValue(UInt8 a) { return a == Ternary::False; }
+ static inline constexpr bool isSaturatedValue(bool a) { return !a; }
+ static inline constexpr bool isSaturatedValueTernary(UInt8 a) { return a == Ternary::False; }
static inline constexpr ResultType apply(UInt8 a, UInt8 b) { return a & b; }
static inline constexpr bool specialImplementationForNulls() { return true; }
};
@@ -71,7 +72,8 @@ struct OrImpl
using ResultType = UInt8;
static inline constexpr bool isSaturable() { return true; }
- static inline constexpr bool isSaturatedValue(UInt8 a) { return a == Ternary::True; }
+ static inline constexpr bool isSaturatedValue(bool a) { return a; }
+ static inline constexpr bool isSaturatedValueTernary(UInt8 a) { return a == Ternary::True; }
static inline constexpr ResultType apply(UInt8 a, UInt8 b) { return a | b; }
static inline constexpr bool specialImplementationForNulls() { return true; }
};
@@ -82,7 +84,8 @@ struct XorImpl
static inline constexpr bool isSaturable() { return false; }
static inline constexpr bool isSaturatedValue(bool) { return false; }
- static inline constexpr ResultType apply(UInt8 a, UInt8 b) { return !!a != !!b; }
+ static inline constexpr bool isSaturatedValueTernary(UInt8) { return false; }
+ static inline constexpr ResultType apply(UInt8 a, UInt8 b) { return a != b; }
static inline constexpr bool specialImplementationForNulls() { return false; }
#if USE_EMBEDDED_COMPILER
From f5a7d8a5c73254d2457b04f87b4f1fc80effc28f Mon Sep 17 00:00:00 2001
From: alesapin
Date: Tue, 7 Jul 2020 15:35:06 +0300
Subject: [PATCH 10/12] Add runner for testflows
---
docker/test/testflows/runner/Dockerfile | 76 +++++++++++
.../testflows/runner/dockerd-entrypoint.sh | 26 ++++
docker/test/testflows/runner/modprobe.sh | 20 +++
tests/testflows/runner | 121 ++++++++++++++++++
4 files changed, 243 insertions(+)
create mode 100644 docker/test/testflows/runner/Dockerfile
create mode 100755 docker/test/testflows/runner/dockerd-entrypoint.sh
create mode 100755 docker/test/testflows/runner/modprobe.sh
create mode 100755 tests/testflows/runner
diff --git a/docker/test/testflows/runner/Dockerfile b/docker/test/testflows/runner/Dockerfile
new file mode 100644
index 00000000000..7dd73b0e0bb
--- /dev/null
+++ b/docker/test/testflows/runner/Dockerfile
@@ -0,0 +1,76 @@
+# docker build -t yandex/clickhouse-testflows-runner .
+FROM ubuntu:20.04
+
+RUN apt-get update \
+ && env DEBIAN_FRONTEND=noninteractive apt-get install --yes \
+ ca-certificates \
+ bash \
+ btrfs-progs \
+ e2fsprogs \
+ iptables \
+ xfsprogs \
+ tar \
+ pigz \
+ wget \
+ git \
+ iproute2 \
+ cgroupfs-mount \
+ python3-pip \
+ tzdata \
+ libreadline-dev \
+ libicu-dev \
+ bsdutils \
+ curl \
+ liblua5.1-dev \
+ luajit \
+ libssl-dev \
+ libcurl4-openssl-dev \
+ gdb \
+ && rm -rf \
+ /var/lib/apt/lists/* \
+ /var/cache/debconf \
+ /tmp/* \
+ && apt-get clean
+
+ENV TZ=Europe/Moscow
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+RUN pip3 install urllib3 testflows==1.6.24 docker-compose docker dicttoxml kazoo tzlocal
+
+ENV DOCKER_CHANNEL stable
+ENV DOCKER_VERSION 17.09.1-ce
+
+RUN set -eux; \
+ \
+# this "case" statement is generated via "update.sh"
+ \
+ if ! wget -O docker.tgz "https://download.docker.com/linux/static/${DOCKER_CHANNEL}/x86_64/docker-${DOCKER_VERSION}.tgz"; then \
+ echo >&2 "error: failed to download 'docker-${DOCKER_VERSION}' from '${DOCKER_CHANNEL}' for '${x86_64}'"; \
+ exit 1; \
+ fi; \
+ \
+ tar --extract \
+ --file docker.tgz \
+ --strip-components 1 \
+ --directory /usr/local/bin/ \
+ ; \
+ rm docker.tgz; \
+ \
+ dockerd --version; \
+ docker --version
+
+COPY modprobe.sh /usr/local/bin/modprobe
+COPY dockerd-entrypoint.sh /usr/local/bin/
+
+RUN set -x \
+ && addgroup --system dockremap \
+ && adduser --system dockremap \
+ && adduser dockremap dockremap \
+ && echo 'dockremap:165536:65536' >> /etc/subuid \
+ && echo 'dockremap:165536:65536' >> /etc/subgid
+
+VOLUME /var/lib/docker
+EXPOSE 2375
+ENTRYPOINT ["dockerd-entrypoint.sh"]
+CMD ["sh", "-c", "python3 regression.py --local --clickhouse-binary-path ${CLICKHOUSE_TESTS_SERVER_BIN_PATH} --log test.log ${TESTFLOWS_OPTS} && cat test.log | tfs report results --format json > results.json"]
+
diff --git a/docker/test/testflows/runner/dockerd-entrypoint.sh b/docker/test/testflows/runner/dockerd-entrypoint.sh
new file mode 100755
index 00000000000..b10deaded08
--- /dev/null
+++ b/docker/test/testflows/runner/dockerd-entrypoint.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+set -e
+
+dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2375 &>/var/log/somefile &
+
+set +e
+reties=0
+while true; do
+ docker info &>/dev/null && break
+ reties=$[$reties+1]
+ if [[ $reties -ge 100 ]]; then # 10 sec max
+ echo "Can't start docker daemon, timeout exceeded." >&2
+ exit 1;
+ fi
+ sleep 0.1
+done
+set -e
+
+echo "Start tests"
+export CLICKHOUSE_TESTS_SERVER_BIN_PATH=/clickhouse
+export CLICKHOUSE_TESTS_CLIENT_BIN_PATH=/clickhouse
+export CLICKHOUSE_TESTS_BASE_CONFIG_DIR=/clickhouse-config
+export CLICKHOUSE_ODBC_BRIDGE_BINARY_PATH=/clickhouse-odbc-bridge
+
+cd /ClickHouse/tests/testflows
+exec "$@"
diff --git a/docker/test/testflows/runner/modprobe.sh b/docker/test/testflows/runner/modprobe.sh
new file mode 100755
index 00000000000..cb6a527736b
--- /dev/null
+++ b/docker/test/testflows/runner/modprobe.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+set -eu
+
+# "modprobe" without modprobe
+# https://twitter.com/lucabruno/status/902934379835662336
+
+# this isn't 100% fool-proof, but it'll have a much higher success rate than simply using the "real" modprobe
+
+# Docker often uses "modprobe -va foo bar baz"
+# so we ignore modules that start with "-"
+for module; do
+ if [ "${module#-}" = "$module" ]; then
+ ip link show "$module" || true
+ lsmod | grep "$module" || true
+ fi
+done
+
+# remove /usr/local/... from PATH so we can exec the real modprobe as a last resort
+export PATH='/usr/sbin:/usr/bin:/sbin:/bin'
+exec modprobe "$@"
diff --git a/tests/testflows/runner b/tests/testflows/runner
new file mode 100755
index 00000000000..eef51b3c20f
--- /dev/null
+++ b/tests/testflows/runner
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+#-*- coding: utf-8 -*-
+import subprocess
+import os
+import getpass
+import argparse
+import logging
+import signal
+import subprocess
+import sys
+
+CUR_FILE_DIR = os.path.dirname(os.path.realpath(__file__))
+DEFAULT_CLICKHOUSE_ROOT = os.path.abspath(os.path.join(CUR_FILE_DIR, "../../"))
+CURRENT_WORK_DIR = os.getcwd()
+CONTAINER_NAME = "clickhouse_testflows_tests"
+
+DIND_TESTFLOWS_TESTS_IMAGE_NAME = "yandex/clickhouse-testflows-runner"
+
+def check_args_and_update_paths(args):
+ if not os.path.isabs(args.binary):
+ args.binary = os.path.abspath(os.path.join(CURRENT_WORK_DIR, args.binary))
+
+ if not args.bridge_binary:
+ args.bridge_binary = os.path.join(os.path.dirname(args.binary), 'clickhouse-odbc-bridge')
+ elif not os.path.isabs(args.bridge_binary):
+ args.bridge_binary = os.path.abspath(os.path.join(CURRENT_WORK_DIR, args.bridge_binary))
+
+ if not os.path.isabs(args.configs_dir):
+ args.configs_dir = os.path.abspath(os.path.join(CURRENT_WORK_DIR, args.configs_dir))
+
+ if not os.path.isabs(args.clickhouse_root):
+ args.clickhouse_root = os.path.abspath(os.path.join(CURRENT_WORK_DIR, args.clickhouse_root))
+
+ for path in [args.binary, args.configs_dir, args.clickhouse_root]:
+ if not os.path.exists(path):
+ raise Exception("Path {} doesn't exists".format(path))
+
+def docker_kill_handler_handler(signum, frame):
+ subprocess.check_call('docker kill $(docker ps -a -q --filter name={name} --format="{{{{.ID}}}}")'.format(name=CONTAINER_NAME), shell=True)
+ raise KeyboardInterrupt("Killed by Ctrl+C")
+
+signal.signal(signal.SIGINT, docker_kill_handler_handler)
+
+if __name__ == "__main__":
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
+ parser = argparse.ArgumentParser(description="ClickHouse testflows runner")
+
+ parser.add_argument(
+ "--binary",
+ default=os.environ.get("CLICKHOUSE_TESTS_SERVER_BIN_PATH", os.environ.get("CLICKHOUSE_TESTS_CLIENT_BIN_PATH", "/usr/bin/clickhouse")),
+ help="Path to clickhouse binary")
+
+ parser.add_argument(
+ "--bridge-binary",
+ default=os.environ.get("CLICKHOUSE_TESTS_ODBC_BRIDGE_BIN_PATH", ""),
+ help="Path to clickhouse-odbc-bridge binary. Defaults to clickhouse-odbc-bridge in the same dir as clickhouse.")
+
+ parser.add_argument(
+ "--configs-dir",
+ default=os.environ.get("CLICKHOUSE_TESTS_BASE_CONFIG_DIR", os.path.join(DEFAULT_CLICKHOUSE_ROOT, "programs/server")),
+ help="Path to clickhouse configs directory")
+
+ parser.add_argument(
+ "--clickhouse-root",
+ default=DEFAULT_CLICKHOUSE_ROOT,
+ help="Path to repository root folder")
+
+ parser.add_argument(
+ "--command",
+ default='',
+ help="Set it to run some other command in container (for example bash)")
+
+ parser.add_argument(
+ "--disable-net-host",
+ action='store_true',
+ default=False,
+ help="Don't use net host in parent docker container")
+
+ parser.add_argument(
+ "--docker-image-version",
+ default="latest",
+ help="Version of docker image which runner will use to run tests")
+
+
+ parser.add_argument('testflows_args', nargs='*', help="args for testflows command")
+
+ args = parser.parse_args()
+
+ check_args_and_update_paths(args)
+
+ net = ""
+ if not args.disable_net_host:
+ net = "--net=host"
+
+ # create named volume which will be used inside to store images and other docker related files,
+ # to avoid redownloading it every time
+ #
+ # should be removed manually when not needed
+ subprocess.check_call('docker volume create {name}_volume'.format(name=CONTAINER_NAME), shell=True)
+
+ # enable tty mode & interactive for docker if we have real tty
+ tty = ""
+ if sys.stdout.isatty() and sys.stdin.isatty():
+ tty = "-it"
+
+ cmd = "docker run {net} {tty} --rm --name {name} --privileged --volume={bridge_bin}:/clickhouse-odbc-bridge --volume={bin}:/clickhouse \
+ --volume={cfg}:/clickhouse-config --volume={pth}:/ClickHouse --volume={name}_volume:/var/lib/docker -e TESTFLOWS_OPTS='{opts}' {img} {command}".format(
+ net=net,
+ tty=tty,
+ bin=args.binary,
+ bridge_bin=args.bridge_binary,
+ cfg=args.configs_dir,
+ pth=args.clickhouse_root,
+ opts=' '.join(args.testflows_args),
+ img=DIND_TESTFLOWS_TESTS_IMAGE_NAME + ":" + args.docker_image_version,
+ name=CONTAINER_NAME,
+ command=args.command
+ )
+
+ print("Running testflows container as: '" + cmd + "'.")
+ subprocess.check_call(cmd, shell=True)
From e89ccfd5bf99e5c98abe18b0290990d47cd350f6 Mon Sep 17 00:00:00 2001
From: alesapin
Date: Tue, 7 Jul 2020 16:11:19 +0300
Subject: [PATCH 11/12] No color
---
docker/test/testflows/runner/Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/test/testflows/runner/Dockerfile b/docker/test/testflows/runner/Dockerfile
index 7dd73b0e0bb..71dca40bca6 100644
--- a/docker/test/testflows/runner/Dockerfile
+++ b/docker/test/testflows/runner/Dockerfile
@@ -72,5 +72,5 @@ RUN set -x \
VOLUME /var/lib/docker
EXPOSE 2375
ENTRYPOINT ["dockerd-entrypoint.sh"]
-CMD ["sh", "-c", "python3 regression.py --local --clickhouse-binary-path ${CLICKHOUSE_TESTS_SERVER_BIN_PATH} --log test.log ${TESTFLOWS_OPTS} && cat test.log | tfs report results --format json > results.json"]
+CMD ["sh", "-c", "python3 regression.py --no-color --local --clickhouse-binary-path ${CLICKHOUSE_TESTS_SERVER_BIN_PATH} --log test.log ${TESTFLOWS_OPTS} && cat test.log | tfs report results --format json > results.json"]
From a7348ed2c8fdc6b4ec67b82ee071fea8086b50e6 Mon Sep 17 00:00:00 2001
From: alesapin
Date: Tue, 7 Jul 2020 18:48:47 +0300
Subject: [PATCH 12/12] Add to images.json
---
docker/images.json | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docker/images.json b/docker/images.json
index 23f8cc0d9fd..45209fc775f 100644
--- a/docker/images.json
+++ b/docker/images.json
@@ -79,5 +79,9 @@
"docker/test/integration/runner": {
"name": "yandex/clickhouse-integration-tests-runner",
"dependent": []
+ },
+ "docker/test/testflows/runner": {
+ "name": "yandex/clickhouse-testflows-runner",
+ "dependent": []
}
}