> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> دليل لاختبار ClickHouse وتشغيل مجموعة الاختبارات

# اختبار ClickHouse

<div id="test-types">
  ## أنواع الاختبارات
</div>

توجد الاختبارات التالية في ClickHouse:

* [الاختبارات الوظيفية](#functional-tests) - مجموعة من الاستعلامات والبرامج النصية التي تتضمن المجموعات الفرعية المتداخلة التالية
  * [Fast test](#running-fast-tests) - أصغر مجموعة فرعية
  * [الاختبارات عديمة الحالة](#running-stateless-tests) التي لا تتطلب تعبئة قواعد البيانات بالبيانات
  * الاختبارات المتسلسلة التي لا يمكن تشغيلها بالتوازي
* [اختبارات التكامل](#integration-tests)، وتُشغَّل بواسطة `pytest` على عنقود
* [اختبارات الوحدة](#unit-tests)
* [اختبارات الأداء](#performance-tests)
* [اختبارات البناء](#build-tests)
* [أدوات sanitizer](#sanitizers)
* [Fuzzers](#fuzzing)
  وبعض الاختبارات الأخرى، راجع الأقسام أدناه.

<div id="functional-tests">
  ## الاختبارات الوظيفية
</div>

تُعد الاختبارات الوظيفية الأبسط والأسهل استخدامًا.
يمكن اختبار معظم ميزات ClickHouse باستخدام الاختبارات الوظيفية، وهي إلزامية لكل تغيير في شيفرة ClickHouse يمكن اختباره بهذه الطريقة.

يرسل كل اختبار وظيفي استعلامًا واحدًا أو عدة استعلامات إلى خادم ClickHouse قيد التشغيل، ثم يقارن النتيجة بالمرجع.

توجد الاختبارات في الدليل `./tests/queries`.

يمكن أن يكون كل اختبار أحد نوعين: `.sql` و `.sh`.

* اختبار `.sql` هو برنامج SQL نصي بسيط يُمرَّر إلى `clickhouse-client` عبر pipe.
* اختبار `.sh` هو برنامج نصي يُشغَّل مباشرةً.

تكون اختبارات SQL هي الخيار المفضل عمومًا مقارنةً باختبارات `.sh`.
يجب ألا تستخدم اختبارات `.sh` إلا عند الحاجة إلى اختبار ميزة لا يمكن التحقق منها باستخدام SQL فقط، مثل تمرير بعض بيانات الإدخال إلى `clickhouse-client` عبر pipe أو اختبار `clickhouse-local`.

<Note>
  من الأخطاء الشائعة عند اختبار أنواع البيانات `DateTime` و `DateTime64` افتراض أن الخادم يستخدم منطقة زمنية محددة (مثل "UTC"). وهذا غير صحيح، إذ تُحدَّد المناطق الزمنية عشوائيًا عمدًا في تشغيلات اختبارات CI.
  وأسهل حل بديل هو تحديد المنطقة الزمنية لقيم الاختبار صراحةً، مثل `toDateTime64(val, 3, 'Europe/Amsterdam')`.
</Note>

<div id="running-a-test-locally">
  ### تشغيل اختبار محليًا
</div>

شغّل خادم ClickHouse محليًا، مع الاستماع على المنفذ الافتراضي (9000).
ولتشغيل الاختبار `01428_hash_set_nan_key`، على سبيل المثال، انتقل إلى مجلد المستودع ونفّذ الأمر التالي:

```sh theme={null}
PATH=<path to clickhouse-client>:$PATH tests/clickhouse-test 01428_hash_set_nan_key
```

تُكتب نتائج الاختبار (`stderr` و`stdout`) في الملفين `01428_hash_set_nan_key.[stderr|stdout]` الموجودين بجوار ملف الاختبار نفسه (بالنسبة إلى `queries/0_stateless/foo.sql`، سيكون الإخراج في `queries/0_stateless/foo.stdout`).

راجع `tests/clickhouse-test --help` للاطّلاع على جميع خيارات `clickhouse-test`.
يمكنك تشغيل جميع الاختبارات أو تشغيل مجموعة فرعية منها بتمرير عامل تصفية لأسماء الاختبارات: `./clickhouse-test substring`.
توجد أيضًا خيارات لتشغيل الاختبارات بالتوازي أو بترتيب عشوائي.

<div id="running-fast-tests">
  ### تشغيل الاختبارات السريعة
</div>

قد تحتاج إلى جهاز بمواصفات قوية نسبيًا لتشغيل مجموعة فرعية من الاختبارات (تُسمى "Fast test"). تنجح الخطوات التالية على مثيل AWS من النوع `t3.2xlarge` يعمل بنظام Ubuntu amd64 مع سعة تخزين تبلغ 100 GB.

1. ثبّت المتطلبات الأساسية ثم سجّل الدخول مرة أخرى.

```sh theme={null}
sudo apt-get update
sudo apt-get install docker.io
sudo usermod -aG docker "$USER"
```

2. نزّل الشيفرة المصدرية.

```sh theme={null}
git clone --single-branch https://github.com/ClickHouse/ClickHouse
cd ClickHouse
```

3. ابنِ الشيفرة البرمجية وشغّل "الاختبارات السريعة".

```sh theme={null}
python -m ci.praktika run fast
```

من المفترض أن تحصل على

```sh theme={null}
Failed: 0, Passed: 7394, Skipped: 1795
```

إذا تركت العملية تعمل دون مراقبة، فيمكنك استخدام `nohup` أو `disown` لإبقائها قيد التشغيل بعد انقطاع اتصال `ssh`.

<div id="running-stateless-tests">
  ### تشغيل الاختبارات عديمة الحالة
</div>

قد تحتاج إلى جهاز قوي إلى حدٍّ ما لتشغيل الاختبارات عديمة الحالة. نجحت الخطوات التالية على مثيل `m7i.8xlarge` من AWS بمعمارية amd64 ونظام Ubuntu، مع سعة تخزين تبلغ 200 جيجابايت.

1. ثبّت المتطلبات اللازمة ثم سجّل الدخول مجددًا.

```sh theme={null}
sudo apt-get update
sudo apt-get install docker.io
sudo usermod -aG docker "$USER"
sudo tee /etc/docker/daemon.json <<'EOF'
{
  "ipv6": true,
  "ip6tables": true
}
EOF
sudo systemctl restart docker
```

2. نزّل الشيفرة المصدرية.

```sh theme={null}
git clone --single-branch https://github.com/ClickHouse/ClickHouse
cd ClickHouse
```

3. قم ببناء الشيفرة.

```sh theme={null}
python -m ci.praktika run build_debug
cp ci/tmp/build/programs/clickhouse ci/tmp
```

4. شغّل الاختبارات عديمة الحالة التي يمكن تنفيذها بالتوازي.

```sh theme={null}
python -m ci.praktika run functional
```

من المفترض أن تحصل على

```sh theme={null}
Failed: 0, Passed: 8497, Skipped: 103
```

ملاحظة: تُشغِّل استدعاءات `python -m ci.praktika run` مهمةً محددة للتكامل المستمر، ويمكنك قراءة المزيد عن ClickHouse CI [هنا](/ar/resources/develop-contribute/contribute/continuous-integration#running-stateless-tests).

<div id="adding-a-new-test">
  ### إضافة اختبار جديد
</div>

لإضافة اختبار جديد، أنشئ أولًا ملفًا بامتداد `.sql` أو `.sh` في الدليل `queries/0_stateless`.
ثم أنشئ ملف `.reference` المقابل باستخدام `clickhouse-client < 12345_test.sql > 12345_test.reference` أو `./12345_test.sh > ./12345_test.reference`.

يجب أن تقتصر الاختبارات على إنشاء الجداول أو حذفها أو تنفيذ عمليات `select` عليها، وما إلى ذلك، ضمن قاعدة البيانات `test` فقط، وهي قاعدة بيانات تُنشأ تلقائيًا مسبقًا.
ولا بأس باستخدام الجداول المؤقتة.

ولإعداد البيئة نفسها المستخدمة في CI على جهازك المحلي، ثبّت إعدادات الاختبار (إذ ستستخدم تنفيذًا وهميًا لـ ZooKeeper وستعدّل بعض الإعدادات)

```sh theme={null}
cd <repository>/tests/config
sudo ./install.sh
```

<Note>
  يجب أن تكون الاختبارات

  * في أضيق حد ممكن: لا تُنشئ إلا الجداول والأعمدة وأدنى قدر لازم من التعقيد،
  * سريعة: ألّا تستغرق أكثر من بضع ثوانٍ (ويُفضَّل: أقل من ثانية)،
  * صحيحة وحتمية: أن تفشل إذا، وفقط إذا، كانت الميزة قيد الاختبار لا تعمل،
  * معزولة/عديمة الحالة: ألا تعتمد على البيئة أو التوقيت
  * شاملة: أن تغطي الحالات الطرفية مثل الأصفار، والقيم NULL، والمجموعات الفارغة، والاستثناءات (الاختبارات السلبية؛ استخدم الصياغة `-- { serverError xyz }` و `-- { clientError xyz }` لذلك)،
  * أن تنظّف الجداول في نهاية الاختبار (تحسّبًا لوجود بقايا)،
  * والتأكّد من أن الاختبارات الأخرى لا تختبر الشيء نفسه (أي استخدم `grep` أولًا).
</Note>

<div id="templated-tests-with-jinja">
  ### اختبارات القوالب باستخدام Jinja
</div>

يمكن كتابة اختبار بصيغة `.sql` على شكل قالب [Jinja2](https://jinja.palletsprojects.com/) بإضافة اللاحقة `.j2` إلى اسم الملف، بحيث يصبح `foo.sql` هو `foo.sql.j2`. قبل تشغيل الاختبار، يعرض `clickhouse-test` القالب كنص برمجي عادي بصيغة `.sql` ثم ينفّذ الناتج.

يفيد ذلك عندما يكرّر الاختبار الاستعلام نفسه مع اختلافات بسيطة: إذ تُنشئ الحلقة الاستعلامات انطلاقًا من قالب موجز بدلًا من كتابة كل استعلام يدويًا. وأكثر البنى شيوعًا هي:

* `{% for ... %} ... {% endfor %}` لتكرار كتلة،
* `{{ expression }}` لإدراج قيمة في المخرجات،
* `-%}` و`{%-` لحذف المسافات البيضاء المجاورة حتى يبقى النص البرمجي المُولَّد نظيفًا.

على سبيل المثال، هذا القالب:

```sql theme={null}
{% for type in ['UInt8', 'UInt16', 'UInt32'] -%}
SELECT toTypeName(0::{{ type }});
{% endfor -%}
```

يظهر بالشكل التالي:

```sql theme={null}
SELECT toTypeName(0::UInt8);
SELECT toTypeName(0::UInt16);
SELECT toTypeName(0::UInt32);
```

يمكن تقديم المخرجات المتوقعة إما كملف `<name>.reference` عادي يحتوي على النتائج الموسَّعة بالكامل، أو كقالب `<name>.reference.j2`، والذي يعالجه `clickhouse-test` بالطريقة نفسها قبل المقارنة. استخدم الصيغة المعتمدة على القوالب عندما تتبع المخرجات المتوقعة أيضًا نمطًا متكررًا. لمزيد من الأمثلة، راجع ملفات `*.sql.j2` الموجودة في `tests/queries/0_stateless/`.

<div id="restricting-test-runs">
  ### تقييد تشغيل الاختبارات
</div>

يمكن أن يتضمن الاختبار صفرًا أو أكثر من *الوسوم* التي تحدد القيود على السياقات التي يُشغَّل فيها الاختبار ضمن بيئة CI.

بالنسبة لاختبارات `.sql`، تُوضَع الوسوم في السطر الأول على شكل تعليق SQL:

```sql theme={null}
-- Tags: no-fasttest, no-replicated-database
-- no-fasttest: <provide_a_reason_for_the_tag_here>
-- no-replicated-database: <provide_a_reason_here>

SELECT 1
```

بالنسبة لاختبارات `.sh`، تُكتب الوسوم على شكل تعليق في السطر الثاني:

```bash theme={null}
#!/usr/bin/env bash
# Tags: no-fasttest, no-replicated-database
# - no-fasttest: <provide_a_reason_for_the_tag_here>
# - no-replicated-database: <provide_a_reason_here>
```

قائمة الوسوم المتاحة:

| اسم الوسم                      | ما يفعله                                                                         | مثال على الاستخدام                                                                       |
| ------------------------------ | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `disabled`                     | لا يتم تشغيل الاختبار                                                            |                                                                                          |
| `long`                         | تمتد مدة تنفيذ الاختبار من دقيقة واحدة إلى 10 دقائق                              |                                                                                          |
| `deadlock`                     | يتم تشغيل الاختبار في حلقة لمدة طويلة                                            |                                                                                          |
| `race`                         | مثل `deadlock`. يُفضَّل استخدام `deadlock`                                       |                                                                                          |
| `shard`                        | يجب أن يستمع الخادم إلى `127.0.0.*`                                              |                                                                                          |
| `distributed`                  | مثل `shard`. يُفضَّل استخدام `shard`                                             |                                                                                          |
| `global`                       | مثل `shard`. يُفضَّل استخدام `shard`                                             |                                                                                          |
| `zookeeper`                    | يتطلب الاختبار تشغيل Zookeeper أو ClickHouse Keeper                              | يستخدم الاختبار `ReplicatedMergeTree`                                                    |
| `replica`                      | مثل `zookeeper`. يُفضَّل استخدام `zookeeper`                                     |                                                                                          |
| `no-fasttest`                  | لا يتم تشغيل الاختبار ضمن [Fast test](#test-types)                               | يستخدم الاختبار محرك الجداول `MySQL` المعطَّل في Fast test                               |
| `fasttest-only`                | لا يتم تشغيل الاختبار إلا ضمن [Fast test](#test-types)                           |                                                                                          |
| `no-[asan, tsan, msan, ubsan]` | يعطّل الاختبارات في إصدارات البناء التي تستخدم [sanitizers](#sanitizers)         | يتم تشغيل الاختبار تحت QEMU، الذي لا يعمل مع sanitizers                                  |
| `no-replicated-database`       | يعطّل الاختبار عندما تستخدم قاعدة البيانات الافتراضية `ReplicatedDatabaseEngine` |                                                                                          |
| `no-ordinary-database`         | يعطّل الاختبار عندما يكون محرك قاعدة البيانات الافتراضية هو `Ordinary`           |                                                                                          |
| `no-parallel`                  | يعطّل تشغيل اختبارات أخرى بالتوازي مع هذا الاختبار                               | يقرأ الاختبار من جداول `system` وقد تنكسر الثوابت                                        |
| `no-parallel-replicas`         | يعطّل الاختبار عندما تكون parallel replicas مفعّلة                               |                                                                                          |
| `no-debug`                     | يعطّل الاختبارات في إصدارات Debug                                                |                                                                                          |
| `no-release`                   | يعطّل الاختبارات في إصدارات Release                                              |                                                                                          |
| `no-darwin`                    | يعطّل الاختبار على macOS (Darwin)                                                | يعتمد الاختبار على ميزات خاصة بـ Linux، مثل distributed queries أو `procfs` أو خادم HTTP |

تُدعَم أيضًا الخيارات التالية: `no-polymorphic-parts`, `no-random-settings`, `no-random-merge-tree-settings`, `no-backward-compatibility-check`, `no-cpu-x86_64`, `no-cpu-aarch64`, `no-cpu-ppc64le`, `no-s3-storage`.

بالإضافة إلى الإعدادات المذكورة أعلاه، يمكنك استخدام العلامات `USE_*` من `system.build_options` لتحديد استخدام ميزات معيّنة في ClickHouse.
على سبيل المثال، إذا كان اختبارك يستخدم جدول `MySQL`، فيجب إضافة الوسم `use-mysql`.

<div id="specifying-limits-for-random-settings">
  ### تحديد حدود الإعدادات العشوائية
</div>

يمكن للاختبار تحديد الحدين الأدنى والأقصى المسموح بهما للإعدادات التي يمكن تعيينها عشوائيًا أثناء تشغيل الاختبار.

بالنسبة إلى اختبارات `.sh`، تُكتب الحدود على هيئة تعليق في السطر المجاور للوسوم، أو في السطر الثاني إذا لم يتم تحديد أي وسوم:

```bash theme={null}
#!/usr/bin/env bash
# Tags: no-fasttest
# Random settings limits: max_block_size=(1000, 10000); index_granularity=(100, None)
```

بالنسبة إلى اختبارات `.sql`، توضع الوسوم على شكل تعليق SQL في السطر المجاور لها أو في السطر الأول:

```sql theme={null}
-- Tags: no-fasttest
-- Random settings limits: max_block_size=(1000, 10000); index_granularity=(100, None)
SELECT 1
```

إذا كنت تحتاج إلى تحديد حدّ واحد فقط، يمكنك استخدام `None` للحدّ الآخر.

<div id="choosing-the-test-name">
  ### اختيار اسم الاختبار
</div>

يبدأ اسم الاختبار ببادئة من خمسة أرقام، يليها اسم وصفي، مثل `00422_hash_function_constexpr.sql`.
ولاختيار البادئة، ابحث عن أكبر بادئة موجودة بالفعل في المجلد، ثم زِدها بمقدار واحد.

```sh theme={null}
ls tests/queries/0_stateless/[0-9]*.reference | tail -n 1
```

في هذه الأثناء، قد تُضاف اختبارات أخرى بالبادئة الرقمية نفسها، وهذا لا يسبب أي مشكلة، ولن تحتاج إلى تغييره لاحقًا.

<div id="checking-for-an-error-that-must-occur">
  ### التحقق من حدوث خطأ متوقّع
</div>

أحيانًا قد ترغب في اختبار حدوث خطأ من الخادم عند تنفيذ استعلام غير صحيح. ندعم لهذا الغرض وسومًا خاصة في اختبارات SQL، وذلك بالشكل التالي:

```sql theme={null}
SELECT x; -- { serverError 49 }
```

يضمن هذا الاختبار أن الخادم يُرجِع خطأً بالرمز 49 يفيد بوجود العمود غير المعروف `x`.
إذا لم يحدث أي خطأ، أو كان الخطأ مختلفًا، فسيفشل الاختبار.
إذا كنت تريد التأكد من حدوث خطأ على جانب العميل، فاستخدم الوسم `clientError` بدلًا من ذلك.

لا تتحقق من صياغة معيّنة لرسالة الخطأ، لأنها قد تتغير في المستقبل، وقد يؤدي ذلك إلى فشل الاختبار دون داعٍ.
تحقق فقط من رمز الخطأ.
إذا لم يكن رمز الخطأ الحالي دقيقًا بما يكفي لاحتياجاتك، ففكّر في إضافة رمز جديد.

<div id="testing-a-distributed-query">
  ### اختبار استعلام موزّع
</div>

إذا كنت تريد استخدام الاستعلامات الموزّعة في الاختبارات الوظيفية، فيمكنك الاستفادة من دالة الجدول `remote` مع العناوين `127.0.0.{1..2}` لكي يجري الخادم استعلامًا على نفسه؛ أو يمكنك استخدام عناقيد الاختبار المعرّفة مسبقًا في ملف إعدادات الخادم، مثل `test_shard_localhost`.
تذكّر إضافة الكلمتين `shard` أو `distributed` إلى اسم الاختبار، بحيث يُشغَّل في CI ضمن الإعدادات الصحيحة التي يكون فيها الخادم مهيّأً لدعم الاستعلامات الموزّعة.

<div id="working-with-temporary-files">
  ### العمل مع الملفات المؤقتة
</div>

قد تحتاج أحيانًا، في اختبار shell، إلى إنشاء ملف أثناء التنفيذ للعمل عليه.
ضع في اعتبارك أن بعض عمليات التحقق في CI تُشغِّل الاختبارات بالتوازي، لذا إذا كنت تُنشئ ملفًا مؤقتًا أو تحذفه في البرنامج النصي من دون اسم فريد، فقد يتسبب ذلك في فشل بعض عمليات التحقق في CI، مثل Flaky.
ولتفادي ذلك، ينبغي استخدام متغير البيئة `$CLICKHOUSE_TEST_UNIQUE_NAME` لمنح الملفات المؤقتة اسمًا فريدًا للاختبار الجاري تشغيله.
وبذلك يمكنك التأكد من أن الملف الذي تُنشئه أثناء الإعداد أو تحذفه أثناء التنظيف هو الملف المستخدم فقط من قِبل ذلك الاختبار، وليس من قِبل اختبار آخر يعمل بالتوازي.

<div id="known-bugs">
  ## الأخطاء المعروفة
</div>

إذا كنا نعرف بعض الأخطاء التي يمكن إعادة إنتاجها بسهولة من خلال الاختبارات الوظيفية، فنضع اختبارات وظيفية مُعَدّة مسبقًا في الدليل `tests/queries/bugs`.
وتُنقل هذه الاختبارات إلى `tests/queries/0_stateless` عند إصلاح الأخطاء.

<div id="integration-tests">
  ## اختبارات التكامل
</div>

تتيح اختبارات التكامل اختبار ClickHouse في إعداد عنقودي، وكذلك اختبار تفاعل ClickHouse مع خوادم أخرى مثل MySQL وPostgres وMongoDB.
وهي مفيدة لمحاكاة انقسامات الشبكة وفقدان الحزم وما إلى ذلك.
تُشغَّل هذه الاختبارات ضمن Docker، وتُنشئ عدة حاويات تضم برمجيات متنوعة.

راجع `tests/integration/README.md` لمعرفة كيفية تشغيل هذه الاختبارات.

لاحظ أن تكامل ClickHouse مع برامج تشغيل الجهات الخارجية لا يُختبَر.
كما أننا لا نملك حاليًا اختبارات تكامل لبرنامجي تشغيل JDBC وODBC الخاصين بنا.

<div id="unit-tests">
  ## اختبارات الوحدة
</div>

تكون اختبارات الوحدة مفيدة عندما تريد اختبار مكتبة أو فئة معزولة واحدة، لا ClickHouse بالكامل.
يمكنك تمكين بناء الاختبارات أو تعطيله باستخدام خيار CMake ‏`ENABLE_TESTS`.
توجد اختبارات الوحدة (وبرامج الاختبار الأخرى) في الأدلة الفرعية `tests` في أنحاء الشيفرة البرمجية.
لتشغيل اختبارات الوحدة، اكتب `ninja test`.
تستخدم بعض الاختبارات `gtest`، بينما يكون بعضها الآخر مجرد برامج تُرجع رمز خروج غير صفري عند فشل الاختبار.

ليس من الضروري وجود اختبارات وحدة إذا كانت الشيفرة البرمجية مشمولة بالفعل بالاختبارات الوظيفية (وعادةً ما تكون الاختبارات الوظيفية أبسط بكثير في الاستخدام).

يمكنك تشغيل فحوصات `gtest` الفردية باستدعاء الملف التنفيذي مباشرةً، على سبيل المثال:

```bash theme={null}
$ ./src/unit_tests_dbms --gtest_filter=LocalAddress*
```

<div id="performance-tests">
  ## اختبارات الأداء
</div>

تتيح اختبارات الأداء قياس ومقارنة أداء جزء معيّن ومعزول من ClickHouse باستخدام استعلامات اصطناعية.
توجد اختبارات الأداء في `tests/performance/`.
ويُمثَّل كل اختبار بملف `.xml` يصف حالة الاختبار.
تُشغَّل الاختبارات باستخدام الأداة `docker/test/performance-comparison`. راجع ملف readme لمعرفة طريقة التشغيل.

يُنفِّذ كل اختبار استعلامًا واحدًا أو عدة استعلامات (وقد تكون مع توليفات من المعلمات) ضمن حلقة.

إذا كنت تريد تحسين أداء ClickHouse في سيناريو معيّن، وكان بالإمكان ملاحظة التحسينات من خلال استعلامات بسيطة، فمن الموصى به بشدة كتابة اختبار أداء.
ويُوصى أيضًا بكتابة اختبارات أداء عند إضافة دوال SQL أو تعديلها إذا كانت معزولة نسبيًا وليست غامضة جدًا.
ومن المفيد دائمًا استخدام `perf top` أو أدوات `perf` الأخرى أثناء اختباراتك.

<div id="test-tools-and-scripts">
  ## أدوات الاختبار والبرامج النصية
</div>

بعض البرامج الموجودة في الدليل `tests` ليست اختبارات جاهزة، بل أدوات للاختبار.
فعلى سبيل المثال، بالنسبة إلى `Lexer` توجد أداة `src/Parsers/tests/lexer` لا تقوم إلا بتقسيم `stdin` إلى رموز، ثم تكتب النتيجة الملوّنة إلى `stdout`.
يمكنك استخدام هذا النوع من الأدوات كأمثلة على الشيفرة، وللاستكشاف والاختبار اليدوي.

<div id="miscellaneous-tests">
  ## اختبارات متفرقة
</div>

توجد اختبارات لنماذج التعلّم الآلي في `tests/external_models`.
هذه الاختبارات غير محدَّثة ويجب نقلها إلى اختبارات التكامل.

يوجد اختبار منفصل لعمليات الإدخال وفق النصاب.
يشغّل هذا الاختبار عنقود ClickHouse على خوادم منفصلة ويحاكي حالات فشل متنوعة: انقسام الشبكة، وفقدان الحزم (بين عُقد ClickHouse، وبين ClickHouse وZooKeeper، وبين خادم ClickHouse والعميل، وما إلى ذلك)، و`kill -9` و`kill -STOP` و`kill -CONT`، على غرار [Jepsen](https://aphyr.com/tags/Jepsen). ثم يتحقق الاختبار من أن جميع عمليات الإدخال التي تم الإقرار بها قد كُتبت، وأن جميع عمليات الإدخال المرفوضة لم تُكتب.

<div id="manual-testing">
  ## الاختبار اليدوي
</div>

عند تطوير ميزة جديدة، فمن المعقول أيضًا اختبارها يدويًا.
يمكنك القيام بذلك باتباع الخطوات التالية:

قم ببناء ClickHouse. شغّل ClickHouse من الطرفية: انتقل إلى الدليل `programs/clickhouse-server` ثم شغّله باستخدام `./clickhouse-server`. سيستخدم الإعدادات (`config.xml` و`users.xml` والملفات الموجودة داخل الدليلين `config.d` و`users.d`) من الدليل الحالي افتراضيًا. للاتصال بخادم ClickHouse، شغّل `programs/clickhouse-client/clickhouse-client`.

لاحظ أن جميع أدوات clickhouse (الخادم، والعميل، وما إلى ذلك) ليست سوى روابط رمزية لملف binary واحد باسم `clickhouse`.
يمكنك العثور على ملف binary هذا في `programs/clickhouse`.
يمكن أيضًا استدعاء جميع الأدوات بصيغة `clickhouse tool` بدلًا من `clickhouse-tool`.

بدلًا من ذلك، يمكنك تثبيت حزمة ClickHouse: إما إصدار stable من ClickHouse repository، أو بناء الحزمة بنفسك باستخدام `./release` في جذر ClickHouse sources.
ثم ابدأ الخادم باستخدام `sudo clickhouse start` (أو `stop` لإيقاف الخادم).
ابحث عن logs في `/etc/clickhouse-server/clickhouse-server.log`.

عندما يكون ClickHouse مثبتًا بالفعل على نظامك، يمكنك بناء ملف binary جديد باسم `clickhouse` واستبدال ملف binary الحالي:

```bash theme={null}
$ sudo clickhouse stop
$ sudo cp ./clickhouse /usr/bin/
$ sudo clickhouse start
```

يمكنك أيضًا إيقاف خدمة clickhouse-server الخاصة بالنظام وتشغيل نسختك الخاصة باستخدام الإعدادات نفسها، ولكن مع إخراج السجلات إلى الطرفية:

```bash theme={null}
$ sudo clickhouse stop
$ sudo -u clickhouse /usr/bin/clickhouse server --config-file /etc/clickhouse-server/config.xml
```

مثال باستخدام gdb:

```bash theme={null}
$ sudo -u clickhouse gdb --args /usr/bin/clickhouse server --config-file /etc/clickhouse-server/config.xml
```

إذا كانت خدمة `clickhouse-server` تعمل بالفعل ولا تريد إيقافها، فيمكنك تغيير أرقام المنافذ في ملف `config.xml` (أو إعادة تعريفها في ملف داخل دليل `config.d`)، وتحديد مسار البيانات المناسب، ثم تشغيله.

يكاد الملف التنفيذي `clickhouse` لا يعتمد على أي تبعيات، ويعمل على مجموعة واسعة من توزيعات Linux.
ولإجراء اختبار سريع ومبدئي لتغييراتك على خادم، يمكنك ببساطة استخدام `scp` لنسخ الملف التنفيذي `clickhouse` الذي بنيته حديثًا إلى خادمك، ثم تشغيله كما في الأمثلة أعلاه.

<div id="build-tests">
  ## اختبارات البناء
</div>

تتيح اختبارات البناء التحقق من أن عملية البناء لا تتعطل عند استخدام تهيئات بديلة متنوعة وعلى بعض الأنظمة الأخرى.
وهذه الاختبارات مؤتمتة أيضًا.

أمثلة:

* الترجمة العابرة إلى Darwin x86\_64 ‏(macOS)
* الترجمة العابرة إلى FreeBSD x86\_64
* الترجمة العابرة إلى Linux AArch64
* البناء على Ubuntu باستخدام مكتبات من حزم النظام (غير مستحسن)
* البناء مع الربط الديناميكي للمكتبات (غير مستحسن)

فعلى سبيل المثال، يُعدّ البناء باستخدام حزم النظام ممارسة غير جيدة، لأننا لا نستطيع ضمان الإصدار الدقيق للحزم المتوفر على أي نظام.
لكن هذا مطلوب فعلًا من القائمين على صيانة Debian.
ولهذا السبب، علينا على الأقل دعم هذا النمط من البناء.
ومثال آخر: الربط الديناميكي مصدر شائع للمشكلات، لكنه مطلوب لبعض المهتمين.

ومع أننا لا نستطيع تشغيل جميع الاختبارات على جميع أنواع البناء، فإننا نريد على الأقل التحقق من أن تنويعات البناء المختلفة لا تتعطل.
ولهذا الغرض نستخدم اختبارات البناء.

ونختبر أيضًا عدم وجود وحدات ترجمة طويلة أكثر من اللازم بحيث يصعب تجميعها أو تتطلب مقدارًا كبيرًا جدًا من RAM.

ونختبر أيضًا عدم وجود إطارات مكدس كبيرة أكثر من اللازم.

<div id="testing-for-protocol-compatibility">
  ## اختبار توافق البروتوكول
</div>

عندما نوسّع بروتوكول شبكة ClickHouse، نختبر يدويًا أن `clickhouse-client` القديم يعمل مع `clickhouse-server` الجديد، وأن `clickhouse-client` الجديد يعمل مع `clickhouse-server` القديم (وذلك ببساطة عبر تشغيل الملفات التنفيذية من الحزم المقابلة).

كما نختبر بعض الحالات تلقائيًا باستخدام اختبارات التكامل:

* ما إذا كان يمكن للنسخة الجديدة قراءة البيانات التي كتبتها نسخة قديمة من ClickHouse بنجاح؛
* وما إذا كانت الاستعلامات الموزعة تعمل في عنقود يضم إصدارات مختلفة من ClickHouse.

<div id="help-from-the-compiler">
  ## مساعدة من المترجم البرمجي
</div>

يُبنى كود ClickHouse الأساسي (الموجود في الدليل `src`) باستخدام `-Wall -Wextra -Werror`، إلى جانب بعض التحذيرات الإضافية المفعّلة.
لكن هذه الخيارات ليست مفعّلة لمكتبات الطرف الثالث.

يوفّر Clang تحذيرات مفيدة أكثر — يمكنك استعراضها باستخدام `-Weverything` واختيار ما يلائم البناء الافتراضي.

نحن نستخدم دائمًا clang لبناء ClickHouse، سواء للتطوير أو للإنتاج.
يمكنك إجراء البناء على جهازك باستخدام وضع debug (للحفاظ على بطارية حاسوبك المحمول)، لكن يُرجى ملاحظة أن المترجم البرمجي يمكنه توليد المزيد من التحذيرات مع `-O3` بفضل تحسين تحليل تدفّق التحكم والتحليل بين الإجراءات.
وعند البناء باستخدام clang في وضع debug، يُستخدم إصدار debug من `libc++`، ما يتيح اكتشاف المزيد من الأخطاء في وقت التشغيل.

<div id="sanitizers">
  ## أدوات اكتشاف الأخطاء
</div>

<Note>
  إذا تعطلت العملية (خادم ClickHouse أو العميل) عند بدء التشغيل أثناء تشغيلها محليًا، فقد تحتاج إلى تعطيل العشوائية في تخطيط مساحة العناوين: `sudo sysctl kernel.randomize_va_space=0`
</Note>

<div id="address-sanitizer">
  ### AddressSanitizer
</div>

نُجري الاختبارات الوظيفية، واختبارات التكامل، واختبارات الإجهاد، واختبارات الوحدة باستخدام ASan مع كل عملية commit.

<div id="thread-sanitizer">
  ### Thread sanitizer
</div>

نشغّل الاختبارات الوظيفية، واختبارات التكامل، واختبارات الإجهاد، واختبارات الوحدة باستخدام TSan مع كل commit.

<div id="memory-sanitizer">
  ### أداة فحص الذاكرة
</div>

نُشغِّل الاختبارات الوظيفية، واختبارات التكامل، واختبارات إجهاد، واختبارات الوحدة باستخدام MSan مع كل عملية commit.

<div id="undefined-behaviour-sanitizer">
  ### أداة كشف السلوك غير المعرّف
</div>

نجري الاختبارات الوظيفية، واختبارات التكامل، واختبارات إجهاد، واختبارات الوحدة باستخدام UBSan مع كل commit.
لا تخضع شيفرة بعض مكتبات الطرف الثالث لفحص UB.

<div id="valgrind-memcheck">
  ### Valgrind (memcheck)
</div>

كنا نُشغّل الاختبارات الوظيفية باستخدام Valgrind ليلًا، لكننا لم نعد نفعل ذلك.
يستغرق ذلك عدة ساعات.
يوجد حاليًا إنذار إيجابي كاذب واحد معروف في مكتبة `re2`، راجع [هذه المقالة](https://research.swtch.com/sparse).

<div id="fuzzing">
  ## التشويش
</div>

يُنفَّذ التشويش في ClickHouse باستخدام كلٍّ من [libFuzzer](https://llvm.org/docs/LibFuzzer.html) واستعلامات SQL العشوائية.
ويجب إجراء جميع اختبارات Fuzz باستخدام sanitizers ‏(Address وUndefined).

يُستخدم LibFuzzer لإجراء اختبارات Fuzz معزولة لكود المكتبات.
تُنفَّذ Fuzzers كجزء من كود الاختبار، وتحمل اللاحقة "\_fuzzer" في أسمائها.
يمكن العثور على Example لأحد Fuzzers في `src/Parsers/fuzzers/lexer_fuzzer.cpp`.
تُخزَّن إعدادات LibFuzzer الخاصة وDictionaries وcorpus في `tests/fuzz`.
ونشجّعك على كتابة اختبارات Fuzz لكل وظيفة تتعامل مع مدخلات المستخدم.

لا يتم بناء Fuzzers افتراضيًا.
ولبناء Fuzzers، يجب ضبط الخيارين `-DENABLE_FUZZING=1` و`-DENABLE_TESTS=1`.
ونوصي بتعطيل Jemalloc أثناء بناء Fuzzers.
يمكن العثور على configuration المستخدمة لدمج التشويش في ClickHouse مع
Google OSS-Fuzz في `docker/fuzz`.

ونستخدم أيضًا اختبار Fuzz بسيطًا لتوليد استعلامات SQL عشوائية والتحقق من أن server لا يتعطل أثناء تنفيذها.
يمكنك العثور عليه في `00746_sql_fuzzy.pl`.
ويجب تشغيل هذا الاختبار باستمرار (طوال الليل ولمدد أطول).

ونستخدم أيضًا Query Fuzzer متقدمًا قائمًا على AST، وقادرًا على اكتشاف عدد هائل من الحالات الطرفية.
فهو يُجري تبديلات وتبديلات substitution عشوائية في AST الخاصة بالاستعلامات.
كما يتذكر عُقد AST من الاختبارات السابقة لاستخدامها في التشويش للاختبارات اللاحقة، مع معالجتها بترتيب عشوائي.
يمكنك معرفة المزيد عن هذا fuzzer في [هذه المقالة على المدونة](https://clickhouse.com/blog/fuzzing-click-house).

<div id="stress-test">
  ## اختبار الإجهاد
</div>

اختبارات الإجهاد هي حالة أخرى من التشويش.
ويشغّل هذا الاختبار جميع الاختبارات الوظيفية بالتوازي وبترتيب عشوائي على خادم واحد.
ولا يتم التحقق من نتائج الاختبارات.

ويُتحقَّق مما يلي:

* ألّا يتعطل الخادم، وألّا يتم تفعيل أي مصائد Debug أو sanitizer؛
* عدم وجود حالات توقف متبادل؛
* أن تكون بنية قاعدة البيانات متسقة؛
* أن يتمكن الخادم من التوقف بنجاح بعد الاختبار ثم البدء مجددًا دون استثناءات.

هناك خمسة أنواع (Debug, ASan, TSan, MSan, UBSan).

<div id="thread-fuzzer">
  ## Thread fuzzer
</div>

يُعد Thread Fuzzer (يرجى عدم الخلط بينه وبين Thread Sanitizer) نوعًا آخر من الاختبار بالتشويش يتيح جعل ترتيب تنفيذ الخيوط عشوائيًا.
ويساعد ذلك في اكتشاف المزيد من الحالات الخاصة.

<div id="security-audit">
  ## تدقيق أمني
</div>

أجرى فريق الأمن لدينا مراجعة أولية لإمكانات ClickHouse من منظور أمني.

<div id="static-analyzers">
  ## أدوات التحليل الساكن
</div>

نشغّل `clang-tidy` مع كل `commit`.
كما أن فحوصات `clang-static-analyzer` مفعّلة أيضًا.
ويُستخدم `clang-tidy` كذلك لبعض فحوصات الأسلوب.

لقد قيّمنا `clang-tidy` و`Coverity` و`cppcheck` و`PVS-Studio` و`tscancode` و`CodeQL`.
ستجد تعليمات الاستخدام في الدليل `tests/instructions/`.

إذا كنت تستخدم `CLion` بوصفه بيئة تطوير متكاملة، فيمكنك الاستفادة مباشرةً من بعض فحوصات `clang-tidy` الجاهزة.

كما نستخدم `shellcheck` للتحليل الساكن لبرامج `shell` النصية.

<div id="hardening">
  ## التحصين
</div>

في بنية debug، نستخدم allocator مخصصًا يطبّق ASLR على تخصيصات مستوى المستخدم.

ونحمي أيضًا يدويًا مناطق الذاكرة التي يُفترض أن تصبح readonly بعد التخصيص.

في بنية debug، نستخدم أيضًا تخصيصًا لـ libc يضمن عدم استدعاء أي دوال "ضارة" (مهجورة، غير آمنة، غير thread-safe).

تُستخدم تأكيدات Debug على نطاق واسع.

في بنية debug، إذا تم إطلاق استثناء بالرمز "logical error" (مما يشير إلى وجود خلل برمجي)، فسيُنهي البرنامج عمله مبكرًا.
وهذا يتيح استخدام الاستثناءات في بنية release، مع التعامل معها كتأكيد في بنية debug.

تُستخدم نسخة Debug من jemalloc في بنيات debug.
وتُستخدم نسخة Debug من libc++ في بنيات debug.

<div id="runtime-integrity-checks">
  ## فحوصات سلامة البيانات أثناء التشغيل
</div>

تُحمى البيانات المخزنة على القرص باستخدام checksums.
وتُحمى البيانات في جداول MergeTree باستخدام checksums بثلاث طرق متزامنة\* (كتل البيانات المضغوطة، وكتل البيانات غير المضغوطة، وإجمالي checksum عبر الكتل).
كما تُحمى البيانات المنقولة عبر الشبكة بين client وserver أو بين الخوادم باستخدام checksums.
ويضمن النسخ المتماثل تطابق البيانات على مستوى البِتّات في replicas.

وهذا ضروري للحماية من أعطال العتاد (تلف البِتّات على وسائط التخزين، وانقلاب البِتّات في RAM على server، وانقلاب البِتّات في RAM في وحدة تحكم الشبكة، وانقلاب البِتّات في RAM في مبدّل الشبكة، وانقلاب البِتّات في RAM لدى client، وانقلاب البِتّات على wire).
لاحظ أن انقلاب البِتّات شائع، ومن المرجّح أن يحدث حتى مع ECC RAM ومع وجود checksums الخاصة بـ TCP (إذا كنت تدير آلاف الخوادم التي تعالج بيتابايتات من البيانات يوميًا).
[شاهد الفيديو (بالروسية)](https://www.youtube.com/watch?v=ooBAQIe0KlQ).

يوفّر ClickHouse أدوات تشخيص تساعد مهندسي العمليات على اكتشاف العتاد المعيب.

* وهو ليس بطيئًا.

<div id="code-style">
  ## نمط الشيفرة
</div>

قواعد نمط الشيفرة موضحة [هنا](/ar/resources/develop-contribute/contribute/style).

للتحقق من بعض مخالفات النمط الشائعة، يمكنك استخدام السكربت `utils/check-style`.

لفرض نمط الشيفرة الصحيح، يمكنك استخدام `clang-format`.
يوجد الملف `.clang-format` في جذر الشيفرة المصدرية.
وهو يتوافق في الغالب مع نمط الشيفرة المعتمد لدينا.
لكن لا يُنصح بتطبيق `clang-format` على الملفات الموجودة مسبقًا لأنه قد يجعل التنسيق أسوأ.
يمكنك استخدام الأداة `clang-format-diff` التي يمكنك العثور عليها في مستودع clang المصدري.

بدلًا من ذلك، يمكنك تجربة الأداة `uncrustify` لإعادة تنسيق الشيفرة.
يوجد ملف الإعدادات `uncrustify.cfg` في جذر الشيفرة المصدرية.
وهي أقل اختبارًا من `clang-format`.

يمتلك `CLion` منسّق شيفرة خاصًا به، ويجب ضبطه ليتوافق مع نمط الشيفرة لدينا.

<div id="test-coverage">
  ## تغطية الاختبارات
</div>

كما نتتبّع تغطية الاختبارات، لكن للاختبارات الوظيفية فقط، ولـ clickhouse-server فقط.
ويتم ذلك يوميًا.

<div id="tests-for-tests">
  ## اختبارات خاصة بالاختبارات
</div>

يوجد تحقّق آلي من الاختبارات غير المستقرة.
ويشغّل جميع الاختبارات الجديدة 100 مرة (بالنسبة إلى الاختبارات الوظيفية) أو 10 مرات (بالنسبة إلى اختبارات التكامل).
إذا فشل الاختبار حتى مرة واحدة، فيُعد اختبارًا غير مستقر.

<div id="test-automation">
  ## أتمتة الاختبارات
</div>

نُجري الاختبارات باستخدام [GitHub Actions](https://github.com/features/actions).

تُشغَّل مهام البناء والاختبارات في Sandbox لكل commit.
تُنشر الحزم الناتجة ونتائج الاختبارات على GitHub، ويمكن تنزيلها عبر روابط مباشرة.
تُحفَظ الملفات الناتجة لعدة أشهر.
عندما ترسل طلب سحب على GitHub، نضع عليه الوسم "can be tested"، ثم يبني نظام CI لدينا حزم ClickHouse لك (إصدار release، وإصدار debug، ومع address sanitizer، وغير ذلك).
