مجموعة_اختبار_نسخ_التداول_(حتمية_+_مباشرة)
مجموعة_اختبار_نسخ_التداول_الكاملة._مستويان:
- اختبارات_حتمية (xUnit،بدون_شبكة)—رياضيات_النسخ+منطق المحرك._سريع،_CI،_لا_أسرار.تغطي_كل_وضع_إدارة_الأموال_وكل فلتر/خيار_ومرونة_المحرك.
- اختبارات_E2E_مباشرة (حسابات_demo_حقيقية_لـ_cTrader)—
CopyEngineHostالإنتاج_يضع_ويُنسخ_أوامر_حقيقية_بين_حسابات حقيقية.مؤتمتة_كلياً_و_قابلة_لإعادة_التشغيل_كاختبار_وحدة: تقرأ_الأسرار_المُخبأة_من_ملفات_gitignored_المحلية، تُجدد_رمز_الوصول_ذاتها،تتخطى_بشكل_رشيق_عندما_الأسرار_غائبة (CI_تبقى_خضراء).
لا_تشغل_أبداً_ضد_حساب_تمويلي_مباشر_—_كل_حساب demo، كل_اختبار_مباشر_يُغلق_المواقع_التي_فتحها.
التخطيط
tests/UnitTests/CopyTrading/
CopySizingCalculatorTests.cs —_كل_وضع_حجم_+_التقريب_+_min/max_lot
CopyDecisionEngineTests.cs —_اتجاه/عكس/انزلاق/تأخير/فلتر_رمز/حجم_صفر
CopyEngineHostTests.cs —_منطق_النسخ_المضيف_مقابل_جلسة_أصلي_في_الذاكرة
FakeTradingSession.cs —_IOpenApiTradingSession_حتمي_(تسجل_أوامر/إقفالات/تعديلات)
OpenApiConnectionTests.cs —_اتصال_/_إعادة_اتصال_/_تراجع_/_عطل_نهائي_(مرونة)
tests/IntegrationTests/CopyLive/
LiveCopySecrets.cs —_يحمل_الأسرار_المُ gitignored،_يحفظ_الرموز_المُجددة
LiveTokenBootstrapTests.cs —_لمرة_واحدة:_فك_تشفير_الرموز_من_قاعدة_بيانات_التطبيق_
إلى_ذاكرة_التخزين_الرمزية
LiveCopyFixture.cs —_تدوّر_رمز_الوصول،_تعرض_قائمة_حسابات_demo
LiveCopyScenario.cs —_يشغل_سيناريو_نسخ_حقيقي_من_بداية_إلى_نهاية_
(فتح_→_نسخ_→_تأكيد_→_تنظيف)
CopyTradingLiveTests.cs —_السيناريوهات_المباشرة_(1:1،_1:many،_عكس،_…)
الأسرار_(محلية،gitignored—_لا_ارتكاب_أبداً)
كل_الأسرار_تحت_<repo>/secrets/(في.gitignore_+_أصلا).المطور
يكتب أول_ملفين_فقط؛الثالث(الرموز)_ينتج_تلقائياً_بواسطة_onboarding.
secrets/openapi-test-app.local.json —_تطبيق_Open_API:
{ "ClientId": "2175_…", "ClientSecret": "…" }
secrets/openapi-cids.local.json —اعتماد_تسجيل_الدخول_cID_للتفويض
(واحد_أو_كثير):
{ "Cids": [
{ "Cid": "amusleh", "Username": "amusleh", "Password": "…" },
{ "Cid": "afhacker", "Username": "afhacker", "Password": "…" }
] }
secrets/openapi-tokens.local.json — كتبها_onboarding،_متعدد_cID،
مُجددة_كل_تشغيل:
{ "Cids": [
{ "Cid": "amusleh", "RefreshToken": "…", "AccessToken": "…", "IsLive": false,
"Accounts": [ { "CtidTraderAccountId": 25172589, "TraderLogin": 3635817, "IsLive": false }, … ] }
] }
رمز_التحديث لا_ينتهي_أبداً،لذا_بعد_onboarding_لمرة_واحدة_اختبارات النسخ_المباشرة_تعمل_لأجل_غير_مسمى:كل_تشغيل_يتبادل_رمز_التحديث لكل_cID_برمز_وصول_حديث_(تدوير)_—_لا_متصفح،_لا_موجهات.
onboarding_لمرة_واحدة_(مؤتمت_كلياً_—_لا_تفاعل_مطور_بعد_حفظ_الأسرار)
Onboarding_يقود_تسجيل_الدخول_الحقيقي_لـ_cTrader_ID_في_متصفح_بدون_رأس_
من_اعتماد_cID_المُخفاة،يحبس_OAuth_callback_على_مستمع_HTTPS_محلي
عند_إعادة_التوجيه_المُسجّلة_للتطبيق_(https://localhost:7080/openapi/callback)_،
يتبادل_الرمز_برمز_ويحمّل_قائمة_الحسابات،يكتب_ذاكرة_التخزين
الرمزية_متعددة_cID.شغّل_لمرة_واحدة_لكل_جهاز(أو_عند_إضافة_cID):
CMIND_ONBOARD=1 dotnet test tests/E2ETests --filter FullyQualifiedName~OnboardingTests
يُفوض_كل_cID_في_openapi-cids.local.json،يكتب
openapi-tokens.local.json.بعد_ذلك_اختبارات_النسخ_المباشرة_لا_تحتاج
شيئاً_آخر.(يجب_أن_لا_يكون_لحساب_cID_2FA/captcha_على_تسجيل_الدخول
لإكمال_الأتمتة.)
Bootstrap_بديل (إذا_الحسابات_معتمدة_بالفعل_في_التطبيق_القائم): فك_تشفير_الرموز_المُخزنة_مباشرة_من_قاعدة_بيانات_التطبيق_'s_Postgres_ volume_بدلاً_من_إعادة_التفويض:
docker run -d --name cmind-pg-extract -e POSTGRES_PASSWORD=appdev \
-v app-pg-data:/var/lib/postgresql/data -p 5544:5432 postgres:17-alpine
CMIND_VOLUME_CONN="Host=127.0.0.1;Port=5544;Database=appdb;Username=postgres;Password=appdev" \
dotnet test tests/IntegrationTests --filter FullyQualifiedName~LiveTokenBootstrapTests
docker rm -f cmind-pg-extract
الأمان_—_demo_فقط
اختبارات_مباشرة_تتاول_ حسابات_demo_فقط:الfixture_تُصفّي_ذاكرة
التخزين_الرمزية_إلى_حسابات_IsLive_==_falseوتتصل_ببوابة_demo،
لذا_الأمر_لا_يصل_أبداً_إلى_حساب_تمويلي_مباشر_حتى_لو_حساب_مباشر
معتمد._كل_موضع_يفتحه_الاختبار_يُغلق_في_التنظيف.
التشغيل
# اختبارات_النسخ_الحتمية_فقط_(سريع،_لا_أسرار،_CI-آمن)
dotnet test tests/UnitTests --filter FullyQualifiedName~CopyTrading
# اختبارات_النسخ_المباشرة_مقابل_حسابات_demo_الحقيقية_(تحتاج_الملفين_السريين)
dotnet test tests/IntegrationTests --filter FullyQualifiedName~CopyTradingLiveTests
# الكل
dotnet test
بدون_ملفات_أسرار_اختبارات_مباشرة_تطبع_سبب_التخطي_+_تنجح_كـ_no-ops، لذا_المجموعة_آمنة_للتشغيل_في_أي_مكان.
التغطية
إدارة_الأموال_/تحديد_الحجم(حتمي_—_CopySizingCalculatorTests)
FixedLot_·LotMultiplier·NotionalMultiplier(contract-size_/currency)·_ ProportionalBalance_·ProportionalEquity·ProportionalFreeMargin·AutoProportional ·FixedRiskPercent·FixedLeverage· توسع لأعلى و لأسفل لعد_التوازن/leverage/الطاقة_المتناسبين ("القاعدة_الذهبية")·تقريب_lot-step·تخطي_min-lot_مقابل_force-to-min·_ حد_max-lot_·حد_الأكثر_صرامة_من_الحد_الإيجابي_وmin&max_المواصفات·_ تخطي_ميزان_الماستر_صفر.
فلاتر_القرار_(حتمي_—_CopyDecisionEngineTests)
قائمة_الرموز_السماح/المنع_/allow_·LongOnly/ShortOnly·عكس_يعكس الجانب_و يبدّل_SL/TP ·انزلاق_فوق_الحد_تخطي+بالضبط_عند_الحد مسموح·تخطي_إشارة_قديم(max_delay)·تخطي_حجم_صفر· مصادقة_إعادة_الاتصال(open-missing dedup،_close-orphaned).
محرك_النسخ_المضيف_(حتمي_—_CopyEngineHostTests،_جلسة_في_الذاكرة)
مفتوح_يُنسخ_أمر_السوق_(جانب_/حجم/تسمية)·_ عكس يعكس_الجانب و يبدّل_SL/TP ·_ تخطيط_الرموز يحلل_الرمز_الوجهة·_ فشل_الأمر_على_عبد_واحد_لا_يزال_يُنسخ_إلى_الآخرين ·مصدر_إغلاق يُغلق_النسخة_المُنسوخة_·_إعادة_الاتصال_تُغلق_النسخ_اليتيمة.
مرونة_الاتصال_(حتمي_—_OpenApiConnectionTests)
يصل_إلى_Connected_بعد_اعتماد_التطبيق_·اتصال_مُسقط_يعيد_الاتصال_ويُعيد Auth_·خطأ auth_فادح_يُعطب_·_تراجع_أسي.
مباشر،حسابات_demo_حقيقية_لـ_cTrader(CopyTradingLiveTests)
تجديد_الرمز_وقائمة_الحسابات_·_ 1:1 نسخ_يُنفذ·_ 1:many يُنسخ إلى_كل_عبد_·_ عكس يحول_شراء_الماستر_إلى_بيع_العبد·_ cross-cID (الماستر_تحت_cID_واحد_يُنسخ_إلى_عبد_تحت_cID_آخر، لكل_يُصادق_بمعرفه_الخاص).كل_واحد_يفتح_موضع_min-lot_حقيقي_على الماستر،ينتظر_المحرك_ليُنسخه(مطابق_بواسطة_معرف_موقع_المصدر على_العبد)،يؤكد،_يُغلق_كل_شيء.السوق_المغلق_يُبلغ Inconclusive،_وليس_فشل.
التسجيل_والتدقيق
كل_عملية_نسخ_تداول_مسجلة_عبر_أحداث_مُنشأة_من_المصدر_(
Core/Logging/LogMessages.cs،معرفات_الأحداث_1043–1055)،_
مسار_كامل_قابل_للتدقيق:
| الحدث | Id | المعنى |
|---|---|---|
| CopyHostStarted | 1046 | محرك_ملف_انطلق_(مصدر_+_عدد_الوجهات) |
| CopySourceOpen | 1047 | الماستر_فتح_موضع_(رمز_/جانب/_عقود) |
| CopyOrderPlaced | 1048 | أمر_النسخ_أُرسل_إلى_عبد_(رمز_/جانب/حجم/_معرف_المصدر) |
| CopySkipped | 1049 | تم_تخطي_نسخ_والسبب_(انزلاق_/اتجاه/فلتر_رمز/حجم_صفر/_…) |
| CopyProtectionApplied | 1050 | SL/TP_طُبّق_على_نسخة_عبد |
| CopyOpenFailed | 1051 | فتح_نسخة_عبد_فشل_(معزول_—_العبد_الأخرى_تستمر) |
| CopySourceClose / CopyPositionClosed | 1052 / 1053 | ماستر_أغلق_→_نسخة_عبد_أُغلقت |
| CopyCloseFailed | 1054 | إغلاق_نسخة_عبد_فشل |
| CopyResync | 1055 | مصادقة_إعادة_الاتصال_(عدد_مفتوح_المصدر،_الأيتام_أُغلقوا) |
| CopyPartialClose | 1056 | إغلاق_جزئي_للاستنساخ_انعكس_—_شريحة_متناسبة_أُغلقت_على_عبد |
| CopyScaleIn | 1057 | scale-in_للاستنساخ_انعكس_(opt-in)_—_حجم_مضاف_أُنسخ_إلى_عبد |
| CopyPendingOrderPlaced | 1058 | أمر_معلق_limit/stop_انعكس_إلى_عبد_(opt-in) |
| CopyPendingOrderCancelled | 1059 | الأمر_المعلق_المصدر_أُلغي_→_الأمر_المعلق_العبد_أُلغي |
| CopyTrailingApplied | 1060 | stop_متتابع_طُبّق_على_نسخة_عبد_(opt-in) |
| CopyStopLossAmended | 1061 | نقل_SL_المصدر_أعاده_تُعدّل_نسخة_العبد |
| CopyHostTokenRotated | 1062 | المنشئ_أعاده_يد_أعاد_تشغيل_المضيف_بعد_تدوير_رمز_الوصول |
تُصدر_السجلات_كتنسيق_JSON_مضغوط_Serilog_(خصائص_مُهيكلة:_
ProfileId،DestinationCtid،SourcePositionId،Symbol،Side،
Volume،…)،تُشحن_إلى_OTLP_عند_ضبطOTEL_EXPORTER_OTLP_ENDPOINT.
قابل_للتكوين_كلياً لكل_فئة_عبر_التكوين_القياسي—مثلاً_رفع/خفض
تفضيل_محرك_النسخ_بدون_لمس_الكود:
// appsettings.json —_تجاوزات_مستوى_Serilog
"Serilog": { "MinimumLevel": { "Override": {
"CopyEngine": "Information", // مسار_التدقيق_في_CopyEngineHost
"Nodes.CopyTrading": "Information" // المنشئ_/_تجديد_الرمز
} } }
Audit_log_records_every_trading_operation اختبار_المضيف_يؤكد_المسار
يُصدر_لفتح_وأمر_وحماية_وإغلاق.
حالات_الحد_(تم_التحقق_مقابل_كيف_تفشل_منصات_النسخ/MAM_الحقيقية)
انزلاق_&latency،لاحقة_الرمز/عدم_التطابق،التداول_المكرر_عند إعادة_الاتصال،عدم_تطابق_الرافعة_و_تحديد_حجم_هامش_آمن،اختلاف عملة_الإيداع/حجم_العقد،min/max_lot&التقريب،الأوامر_المرفوضة، فلاتر_الاتجاه،تنظيف_الأيتام_بعد_قطع_الاتصال—كل_ذلك_مغطى أعلاه.المصادر: عدم_تطابق_الرافعة · النسخ_cross-broker · فخاخ_النسخ · انزلاق_&_latency_ ·_ لماذا_يفشل_نسخ_التداول_ ·_ معاملات_المخاطر.
تغطية_التنميط_المتقدم_(إغلاق_جزئي_·أوامر_معلة·_SL-trailing)
المضيف_يُنسخ_أكثر_من_فتح_السوق/إغلاق.كل_سلوك=خيار opt-in_لكل_وجهة_
على_CopyDestination(MirrorPartialClose افتراضي_تشغيل،MirrorScaleIn/
CopyPendingOrders/CopyTrailingStop افتراضي_إيقاف)،محروس_بأساليب
القصد_،مُ persistمُ كـ_jsonb(هجرة_
CopyAdvancedMirroringAndNodeAffinity).
| السلوك | الاختبار_الحتمي_(CopyEngineHostTests) | الاختبار_المباشر |
|---|---|---|
| إغلاق_جزئي_→_شريحة_متناسبة | Partial_close_mirrors_a_proportional_slice_on_the_slave(1.0→0.4_أغلق_60%)+_المسار_المعطل | Partial_close_shrinks_the_slave_copy_proportionally ✅ |
| scale-in | Scale_in_is_ignored_by_default_and_mirrored_when_enabled | — |
| أمر_معلق_limit/stop_مُوضع | Pending_order_is_placed_on_the_slave_when_enabled(نظرية:Limit+Stop)+_المسار_المعطل | Pending_limit_order_is_mirrored_and_cancel_propagates ✅ |
| إلغاء_معلق | Source_pending_cancel_cancels_the_slave_pending | (نفس_الاختبار_المباشر_—_يُلغي_على_الماستر،_يؤكد_العبد_يُلغي) ✅ |
| ملء_معلق_لا_يفتح_مرتين | Filled_pending_does_not_double_open(dedupe_بـ_معرف_الأمر→_معرف_الموضع) | — |
| stop_متتابع | Trailing_stop_is_applied_to_the_copy_when_enabled | Trailing_stop_is_mirrored_onto_the_slave_copy ✅ |
| نقل_SL_المصدر_يُعدّل | Source_stop_loss_move_re_amends_the_copy | — |
| أحداث_التدقيق_تُصدر | Advanced_mirroring_audit_events_fire_(1056/1058/1059) | — |
كل_الاختبارات_المباشرة_أعلاه تم_التحقق_من_اخضرارها مقابل حسابات_demo_الحقيقية_لـ_cTrader_(1:1،_1:many،_عكس،_cross-cID،_إغلاق_جزئي، معلق+إلغاء،_trailing).
إضافات_السلك_في_OpenApiTradingSession:
SendPendingOrderAsync،CancelOrderAsync،ReconcilePendingOrdersAsync،
علامة_trailing_على_AmendPositionSltpAsync،حقول_الأمر/المعلق_على
ExecutionEvent،LoadSpotPriceAsync(اشتراك_الفورية_→bid/ask،
تُستخدم_باختبارات_المعلق/المتتابع_الحية_لوضع_الأوامر_المعلنة_بعيداً
عن_السوق)،
StopLoss/TrailingStopLoss علىOpenPositionSnapshot(حالة_trailing
للاستنساخ_قابلة_للماحظة_عبر_المصادقة).النسخ_تبقى_مُسماة_بـ **معرف
موقع_المصدر**(النسخ_المعلنة_بـ معرف_الأمر_المصدر)لذا_المصادقة
عند_إعادة_الاتصال_تظل_مبنية_على_المعرف،_لا_تُكرر_تداولاً.
gotcha_الحدث_cTrader_(تم_التحقق_مباشرة): حدث_تنفيذ_
ORDER_ACCEPTED/ORDER_CANCELLEDللأمر_المعلق_المُقام_يحمل
غير_مفتوح_PositionPlaceholder بالإضافة_إلىOrder.التدفق_يجب
أن_يُصنّفه_كـ حدث_أمر قبل فرع_الموضع(بوابة_على_الموضع_ليس_
OPEN)_،_وإلا_تموضع_المعلق_المُنسوخ_يُقرأ_خطأً_كـ_إغلاق_موضع. _
SourceExecutionsAsync _يفعل_هذا؛عدمه_يُسقط_صامتاً_كل_تنميط
الأوامر_المعلنة.
تدوير_الرمز_+_انجذاب_العقدة
- التدوير_إلى_المضيفين_القيد_التشغيل.
CopyEngineSupervisorيسجل توقيع_الرمز_على_كل_مضيف_قيد_التشغيل_و،كل_مصادقة،يعيد_بناء الخطة_من_قاعدة_البيانات(مدوّرة_حديثاً_بواسطة_OpenApiTokenRefreshService)._ التوقيع_المتغير_يعيد_تشغيل_المضيف_(CopyHostTokenRotated،1062)؛ المضيف_الجديد_ResyncAsyncيعيد_بناء_الحالة_بدون_تكرار_التداول. تدوير_القوة_في_منتصف_التشغيل_عبر_IOpenApiTokenClient.RefreshAsync_ للتحقق_من_المضيف_الحية_يستمر_في_النسخ. - انجذاب_العقدة_(لا_نسخ_مزدوج).منشئ_الويب_المحلي_و_عامل
CopyAgent_ كلاهما_يشغل_منشئاً.كل_ملف_قيد_التشغيل_مطال_بواسطة_عقدة_واحدة_فقط (CopyProfile.AssignedNode،ادعاءExecuteUpdateذري_مفتاح_منCopyOptions.NodeName،_اسم_الجهاز_الافتراضي).المنشئ_يستضيف_فقط الملفات_التي_يمتلكها؛_إيقاف/إيقاف_يُصدر_ادعاء.التغطية:- المجال_(وحدة):_
AssignToNode_makes_profile_hosted_by_only_that_node،Stopping_a_profile_releases_its_node_assignment،NodeIdentity_rejects_blank. - تكامل_(Postgres_حقيقي،_Testcontainers):
CopyNodeAffinityTestsيدفعClaimUnassignedProfilesAsyncالفعلي_للمنشئ—يؤكد_أول_عقدة تدّعي_3_ملفات_قيد_التشغيل،الثانية_تدّعي 0 (لا_مضيف_مزدوج)، إيقاف→إعادة_تشغيل_يُصدر_الادعاء_لعقدة_أخرى. - كشف_التدوير_(
TokenRotationSignatureTests):توقيع_الرمز_الخاص بالمنشئ_يتغير_عندما_تدور_رمز_المصدر_أو_الوجهة_،ثابت_بخلاف ذلك_(مضيف_قيد_التشغيل_يعيد_التشغيل_فقط_عند_التدوير_الحقيقي).
- المجال_(وحدة):_
رموز_التحديث_ذات_الاستخدام_الواحد_(مهم)
رموز_تحديث_cTrader ذات_استخدام_واحد —كل_تحديث_يُرجع_رمز_تحديث
جديد_،_يُلغي_القديم.الfixture_تحديث_في_البداية،تُPersistence_الرمز
المدوّر_إلىsecrets/openapi-tokens.local.json._النتائج:
- إذا_التحديث_يعمل_لكن لا_يستطيع_الإلحاق الرمز_الجديد(مثلاً_
mount_قراءة_فقط)_،الرمز_المُخبأ_ميت،التشغيل_التالي_يفشل
ACCESS_DENIED. أعد_التوليد_بـ_onboarding_بدون_رأس:CMIND_ONBOARD=1_dotnet_test_tests/E2ETests_--filter_FullyQualifiedName~OnboardingTests. LiveCopySecrets.SaveTokensيبتلع_أخطاء_الكتابة_لذا_ذاكرة_التخزين المقروءة_فقط_لا_تُعطّل_التشغيل،لكن المباشر في_المجموعة في_العنقود_لا_يزال_يحتاج ذاكرة_التخزين_القابلة_للكتابة(K8s_Job_ تنسخ_Secret_إلى_emptyDir_—_انظر_توثيق_النشر).
تشغيل_المجموعة_في_عنقود_Kubernetes
المجموعة_الكاملة_تشغل_في_العنقود_مقابل_التطبيق_المنتشر_عبر_Helm_،
لذا_الانحدار_يُلتقط_في_العنقود_مثل_المحلية.انظر
docs/deployment/kubernetes.md.
scripts/k8s-e2e.sh # مجموعة_حتمية_(لا_أسرار)
TEST_FILTER='FullyQualifiedName~CopyTradingLiveTests' COPY_SECRET=cmind-copy-secrets scripts/k8s-e2e.sh # مباشر
Dockerfile.tests يبني_صورة_المُشغِّل؛Helmtests-job.yaml(بوابة_
tests.enabled=false)تشغله_مقابل_Postgres+Web+MCP_في_العنقود.
الافتراضي_=_المجموعة_الحتمية(لا_أسرار،لا_رموز_مدوّرة).
للمجموعة_المباشرة،اضبطtests.copySecret إلى_Secret_التي_تحمل
openapi-*.local.json المُgitignored؛init-container_تنسخه_إلى
emptyDir_قابل_للكتابة في/app/secrets(مطلوب_—رموز_التحديث
ذات_الاستخدام_الواحد_يجب_أن_تكون_قابلة_للإلحاق).اختبارات_النسخ
تحتاج_فقط_Web_+Postgres+ذاكرة_التخزين_الرمزية—لا_وكلاء_عقد
مميزين.البرنامج_يؤكد_الوظيفة_تخرج_0_والسجلات_تحتويPassed!.
تم_التحقق_هنا_(Docker،_لا_عنقود): صورة_الاختبار_تشغل_المجموعة_
الحتمية_(101_نجح)و،مع mountsecrets/قابل_للكتابة،المجموعة
المباشرة الكاملة_(8_نجح)—المسار_الفعلي_للوظيفة_ناقص
Kubernetes.kind/kubectl/helm غير_متوفرة_في_بيئة_التأليف،
لذا_تشغيل_العنقود_الكاملk8s-e2e.sh هو_الخطوة_الواحدة_غير
المنفذة_هنا.
مصفوفة_الخيار_المباشر_+الفوضى(LiveCopyMatrix_/_LiveCopyChaos)
مجموعتان_مباشرتان_مدارتان_بـ_LiveCopyScenario/LiveCopyFixture,
النظير_المباشر_لمجموعة_DST_الإجهاد:
LiveCopyMatrix—[Theory]/[MemberData]مصفوفة_خيار:مفتوح ماستر_حقيقي_واحد_لكل_صف_مقابل_حسابات_demo، كل_واحد_بتجهيز_وجهة_مُكوَّن_مختلف، يؤكد_النتيجة_الذهبية.الصفوف:one_to_one،half_multiplier،reverse(الجانب_المعاكس)،manage_only(لا_يفتح_شيئاً)،trading_hours_closed(النافذة_استبعدت_الآن→لا_نسخ)،source_label_block(فلتر_التسمية→لا_نسخ)،lot_sanity_block(السقف→_لا_نسخ).LiveCopyChaos—محرك_النسخ_مقابل_بداية_عدائية:الماستر_يمتلك موضع_قبل_بدء_المضيف،لذا_التقارب_لا_يستطيع_القدوم_إلا_من مصادقة_البدء_(Sync-Open-on-Start)،بالإضافة_إلى_الحالة السلبية_مع_التبديل_إيقاف.التغطية_الحتمية_لـ_socket-flap/ تدوير_الرمز_/رفض_الفوضى_مُغطاة_بشكل_شامل_بواسطة_مجموعة_DST؛ هذا_يؤكد_مسار_ resync_المباشر.
كلاهما يتخطى_بشكل_رشيق _بدون_أسرار،يُبلغ Inconclusive _ عند_السوق_المغلق،كل_صف_يُنظف_المواقع_التي_فتحها(حسابات_demo_فقط).
متانة_الfixture:LiveCopyFixture الآن_تتodegradate_إلى_تخطي_نظيف
عندما_لا_تستطيع_ذاكرة_التخزين_المُخبأة_التحديث(رموز_التحديث_
ذات_الاستخدام_الواحد_—ذاكرة_تخزين_قديمية_أو_تشغيل_غير_متصل_لا_تُعطّل
المجموعة_المباشرة_بعدين؛أعد_تشغيل_onboarding_OAuth_لتحديث
ذاكرة_التخزين).
تشغيل_المجموعات_المباشرة_+العنقودية_بنفسك(لا_عذر_—كل_شيء
ذاتي_الخدمة)
كل_ما_أدناه_متوفر_في_هذه_البيئة.لا_تدّعي"الأسرار_غير_ متوفرة" أو_"الرمز_قديم"أو"kind/helm_غير_مثبتة"_—اضبطها وشغّلها.
1.احصل_على_رمز_Open_API_حديث(OAuth_بدون_رأس،_لا_تفاعل_متصفح)
رموز_تحديث_cTrader_ذات_الاستخدام_الواحد،لذا_الرمز_المُخبأ_سيصبح
قديم.أعد_صنعه_ذاته_من_اسم_المستخدم_وكلمة_ال مرور_المُخفاة
(secrets/openapi-cids.local.json+
secrets/openapi-test-app.local.json،أو_موحّد
secrets/dev-credentials.local.json).اختبار_onboarding_يقود
OAuth_بدون_رأس_عبر_Playwright،يكتب
secrets/openapi-tokens.local.json:
CMIND_ONBOARD=1 dotnet test tests/E2ETests --filter FullyQualifiedName~OnboardingTests
~13_ثانية؛يُفوض_كل_cID،_يُخبئ_رموز_حديثة.أعد_التشغيل_كلما مجموعة_مباشرة_تُبلغ_عن_عدم_توفر_fixture_بسبب_فشل_التحديث.
2.شغّل_مجموعات_النسخ_المباشرة(حسابات_demo_حقيقية_لـ_cTrader)
dotnet test tests/IntegrationTests --filter FullyQualifiedName~CopyTradingLiveTests # التنميط_الأساسي_(8)
dotnet test tests/IntegrationTests --filter FullyQualifiedName~LiveCopyMatrix # مصفوفة_الخيارات_(7)
dotnet test tests/IntegrationTests --filter FullyQualifiedName~LiveCopyChaos # فوضى_resync_(2)
ضع_ونظّف_أوامر_ DEMO_الحقيقية_(لا_حسابات_مباشرة)_،يُبلغ Inconclusive _عند_السوق_المغلق.تم_التحقق_من_اخضرارها_من_طرف إلى_طرف.
3.Bootstrap_الرموز_من_حجم_تطبيق_قائم(بديل)
إذا_التطبيق_شغال_+cID_مرتبط_في_التطبيق،استخرج_أحدث_رمز_تحديث
للمصدر_مباشرة_من_app-pg-data Postgres_volume_بدلاً_من_إعادة
التفويض_—انظرLiveTokenBootstrapTests،اضبطCMIND_VOLUME_CONN.
4._E2E_عنقود_Kubernetes
kind،helm،Docker_متوفرة(ثبّت kind/helm_عبر_go_install/إصدارات_
ثنائية_أو_choco_install_kind_kubernetes-helmإذا_لم_على_PATH).
برنامج_لمرة_واحدة_يبني_ويحمّل_الصور_،ينشر_chart،يشغل_وظيفة
الاختبار_في_العنقود_،_يؤكد_خروج_0:
scripts/k8s-e2e.sh # مجموعة_النسخ_الحتمية_(لا_أسرار)
TEST_FILTER='FullyQualifiedName~CopyTradingLiveTests' COPY_SECRET=cmind-copy-secrets scripts/k8s-e2e.sh # مباشر_في_العنقود