🇬🇧 English | 🇺🇦 Українська
9. Тестування¶
Розділ про те, як перевірити плагін і як перевірити власну інтеграцію з ним.
Автотести плагіна¶
Плагін постачається з набором тестів у модулі S3CompatibleStorageTests. Модуль має тип
DeveloperTool: він збирається для редактора й для Development-конфігурацій і ніколи не
потрапляє в Shipping-збірку.
Запуск із редактора¶
Window → Test Automation, фільтр S3.
Запуск із командного рядка¶
UnrealEditor-Cmd YourProject.uproject \
-ExecCmds="Automation RunTests S3.;Quit" \
-unattended -nopause -nullrhi -abslog=/tmp/s3tests.log
Звузьте фільтр, щоб запустити менше: Automation RunTests S3.SigV4.
Якщо шлях до проєкту містить пробіл, передавайте його звичайним аргументом у лапках оболонки. Не додавайте лапки всередину самого аргументу — рушій квотує аргументи сам, і подвійні лапки призводять до того, що проєкт не відкривається зовсім, а запуск повідомляє «No automation tests matched».
Що покривають тести¶
94 офлайнові тести, без мережі й повністю детерміновано:
| Група | Про що |
|---|---|
S3.Crypto.* |
SHA-256 і HMAC проти опублікованих контрольних векторів |
S3.SigV4.* |
Побудова підпису проти незалежної реалізації тієї самої специфікації |
S3.UriEncode.* |
Кодування за RFC 3986, зокрема символи поза базовою площиною |
S3.RequestBuilder.* |
Побудова адрес, обидва стилі адресації, кодування рівно один раз |
S3.Xml.* |
Розбір відповідей, сутності, простори імен |
S3.Headers.* |
ETag, Content-Range, метадані користувача |
S3.Result.*, S3.Diagnostics.* |
Класифікація помилок і діагностичні підказки |
S3.Retry.* |
Розклад повторів і те, що повторюється, а що ні |
S3.Credentials.* |
Провайдери, ланцюжок, оновлення ключів, зашифроване сховище, коли ключ скидається після відмови, а коли ні |
S3.Config.* |
Пресети провайдерів, обчислення адрес, санітизація параметрів передавання |
S3.LocalPath.* |
Розгортання відносного Local File Path проти кореня проєкту |
S3.Download.*, S3.ChunkedDownload.* |
Зчитування у файл, ретраї, побайтовий прогрес, збирання діапазонів |
S3.Multipart.*, S3.Cancel.* |
Багаточастинне завантаження: усі частини рівно по разу, коректна поведінка при відмові частини, скасування — зокрема реальний DELETE-аборт у провайдера, а не просто мовчазна зупинка |
S3.ResumeUpload.* |
Відновлення перерваного завантаження: пропуск уже надісланих частин, відмова відновлювати змінений файл |
S3.ResumeDownload.* |
Відновлення перерваного зчитування: продовження з .s3part замість повторного тягнення, перезапуск на зміненому об'єкті, відмова склеїти дві версії — зокрема тоді, коли провайдер ігнорує If-Match або віддає весь об'єкт замість діапазону |
S3.BatchDelete.* |
Розбиття на пачки по 1000 ключів, часткові відмови, порожній список |
S3.Copy.* |
Кодування джерела в x-amz-copy-source, пізня відмова у тілі відповіді на статус 200 |
S3.DeleteBucket.* |
Видалення адресується самому бакетові, а не ключу в ньому; непорожній бакет відхиляється кодом BucketNotEmpty із підказкою, що робити далі |
S3.Tags.*, S3.Lifecycle.* |
Теги об'єктів і правила життєвого циклу: читання, запис, «немає правил» — це не помилка |
S3.TextBytes.* |
String To UTF-8 Bytes / UTF-8 Bytes To String |
S3.Profile.* |
S3 Storage Profile: побудова конфігурації, джерело облікових даних, редакторські ключі |
S3.Subsystem.* |
Кешування іменованих клієнтів підсистемою |
S3.Live.* |
Наскрізний цикл проти справжнього сервісу — див. нижче |
Наскрізні тести проти справжнього сервісу¶
Група S3.Live.* пропускається й вважається успішною, якщо не задано змінних оточення —
тож звичайний запуск лишається офлайновим і швидким.
export S3_TEST_PROVIDER=MinIO
export S3_TEST_ENDPOINT=http://localhost:9000
export S3_TEST_BUCKET=my-test-bucket
export S3_TEST_ACCESS_KEY=...
export S3_TEST_SECRET_KEY=...
export S3_TEST_REGION=us-east-1 # необов'язково
UnrealEditor-Cmd YourProject.uproject \
-ExecCmds="Automation RunTests S3.Live;Quit" \
-unattended -nopause -nullrhi
Облікові дані читаються лише зі змінних оточення: у репозиторії плагіна їх немає й бути не може.
Дев'ять тестів. Вісім — проти того самого бакета (S3_TEST_BUCKET); CreateAndDeleteBucket
— проти свого власного, створеного й видаленого просто для цього тесту, тож для нього
потрібні права на створення й видалення бакетів на рівні акаунта, не лише на рівні одного
бакета:
| Тест | Що перевіряє |
|---|---|
S3.Live.RoundTrip |
Запис, зчитування, метадані, діапазонний запит, перелік і пакетне видалення — з ключем, що містить пробіл, амперсанд, кирилицю й плюс. Саме такий ключ виявляє помилки кодування адрес і XML-сутностей, яких офлайновий тест довести не може |
S3.Live.MultipartUploadRoundTrip |
Файл, більший за поріг частини, справді йде кількома UploadPart, а не одним PutObject |
S3.Live.MultipartCancelAbortsAtProvider |
Скасування посеред завантаження справді шле AbortMultipartUpload і не лишає частин у провайдера |
S3.Live.CopyObjectRoundTrip |
Копіювання на боці сервера |
S3.Live.TagsRoundTrip |
Теги: запис, читання, видалення |
S3.Live.BucketLifecycleRoundTrip |
Правила життєвого циклу: запис, читання, видалення |
S3.Live.PresignedUrlRoundTrip |
Підписане посилання, яке справді працює для звичайного HTTP-клієнта, що нічого не знає про підпис плагіна |
S3.Live.ResumeInterruptedDownload |
Продовження зчитування проти справжнього провайдера — і те, що переписаний об'єкт змушує почати спочатку, а не дописатися до старого хвоста. Офлайновий тест цього довести не може: він перевіряє код проти підробки, яка з ним заздалегідь згодна, тоді як If-Match на діапазонному GET кожен із шести провайдерів реалізує самостійно |
S3.Live.CreateAndDeleteBucket |
Створення бакета, видалення порожнього, відмова видалити непорожній із кодом BucketNotEmpty і зрозумілою підказкою, видалення після спорожнення |
S3.Live.BucketLifecycleRoundTripзамінює весь набір правил бакета, а наприкінці видаляє його зовсім — так само, якSet Bucket Lifecycle/Delete Bucket Lifecycleі мають поводитися. Не запускайте цей тест проти бакета, у якого вже є правила життєвого циклу, які вам потрібні.
S3.Live.CreateAndDeleteBucketреально створює й видаляє бакет у вашому акаунті. На провайдері з обмеженим ключем (наприклад, application key B2, заскоуплений на один бакет) тест впаде наS3 Create Bucketз403 AccessDenied— це про права ключа, не про плагін. На Wasabi акаунт може додатково заблокувати сам крок видалення функцією безпеки «Security Contacts», навіть для щойно створеного порожнього бакета — див. 8. Провайдери → Wasabi. В обох випадках раніше створений бакет може лишитися в акаунті й піде на прибирання вручну.
Не всі тести прибирають за собою: S3.Live.RoundTrip видаляє все, що створив, навіть коли
крок посередині не вдався, а решта свідомо лишають кілька невеликих об'єктів під префіксом
ue-plugin-tests/ — щоб результат можна було подивитися в консолі провайдера. Для одноразової
перевірки це зручно; для регулярного прогону в CI варто або прибирати такий префікс окремим
кроком, або просто зважати, що бакет поступово накопичує тестове сміття.
Живе тестування у вашому власному проєкті¶
S3.Live.* існує не лише для розробки самого плагіна. Це найшвидший спосіб довести собі,
що плагін справді працює з вашим власним провайдером, обліковим записом і бакетом — раніше,
ніж ви покладетеся на нього у грі. У вас практично напевно інша адреса, інші ключі й інша
політика доступу, ніж у будь-якому середовищі, яке перевірили автори плагіна.
Механізм — той самий: змінні оточення з таблиці вище, спрямовані на ваш сервіс замість
MinIO. Модуль S3CompatibleStorageTests приїжджає разом із повним вихідним кодом плагіна,
тож нічого додатково встановлювати не треба.
Крок за кроком¶
Якщо раніше так не робили — усе відбувається в одному вікні терміналу, кроки одразу за одним.
1. Відкрийте термінал.
macOS: Cmd + Space, наберіть «Terminal». Windows: «Пуск» → «PowerShell».
2. Задайте змінні оточення — вставте й натисніть Enter. Вони діють лише в цьому вікні: закриєте його — доведеться вводити знову.
export S3_TEST_PROVIDER=MinIO
export S3_TEST_ENDPOINT=http://localhost:9000
export S3_TEST_BUCKET=my-test-bucket
export S3_TEST_ACCESS_KEY=...
export S3_TEST_SECRET_KEY=...
export S3_TEST_REGION=us-east-1
У Windows PowerShell синтаксис інший — кожен рядок замінюється на
$env:S3_TEST_PROVIDER = "MinIO".
3. У тому самому вікні запустіть тести, підставивши свої реальні шляхи до UnrealEditor-Cmd
рушія та до .uproject свого проєкту:
"/шлях/до/Engine/Binaries/Mac/UnrealEditor-Cmd" \
"/шлях/до/YourProject.uproject" \
-ExecCmds="Automation RunTests S3.Live;Quit" \
-unattended -nopause -nullrhi -abslog=/tmp/s3livetests.log
Це займає секунди-хвилини — залежно від того, скільки тестів у групі S3.Live і наскільки
швидко відповідає ваш провайдер.
4. Прочитайте результат. У самому терміналі пролітає багато службових рядків рушія, тож найпростіше відфільтрувати:
grep -E "Test Completed|LogDemoS3:" /tmp/s3livetests.log
Або відкрити файл цілком: cat /tmp/s3livetests.log, чи очима через Finder — Cmd + Shift + G,
увести /tmp (тека прихована за замовчуванням, звичайним подвійним кліком у неї не потрапити).
/tmpне гарантовано переживає перезавантаження машини. Якщо лог потрібен надовго — вкажіть-abslogу свою домашню теку замість/tmp, наприклад-abslog=/Users/you/Desktop/s3livetests.log.
Кілька практичних порад:
- Використовуйте одноразовий чи тестовий бакет, не той, де лежать справжні дані. Тести пишуть, читають і видаляють об'єкти по-справжньому — проти реального облікового запису, не проти симуляції.
- Ключам потрібні права на все, що ви хочете перевірити. Ключ лише на читання не пройде
S3.Live.RoundTripузагалі; ключ без права наPutBucketLifecycleConfigurationне пройдеS3.Live.BucketLifecycleRoundTrip, хоча решта тестів відпрацюють. Це не збій плагіна — це саме те, що мала показати перевірка: чи вистачає прав для того, що ви плануєте робити. - Звужуйте фільтр, якщо потрібен не весь набір:
Automation RunTests S3.Live.RoundTripзапустить лише базовий цикл, без багаточастинного завантаження, тегів чи правил життєвого циклу. - Cloudflare R2 не реалізує
ListBuckets, а деякі провайдери не підтримують сам механізм скасування багаточастинного завантаження в очікуваний спосіб — якщо один тест не пройшов, а решта зелені, дивіться повідомлення помилки:Diagnostic Hintтам так само працює, як і в результаті звичайної операції.
Як перевірити власну інтеграцію¶
Найшвидший спосіб¶
Project Settings → Plugins → S3 Compatible Storage → Run Round Trip Check.
Запис, зчитування, звірка байтів і видалення — тим самим кодом, яким працюватиме зібрана гра. Якщо ця кнопка зелена, конфігурація робоча.
Що варто перевірити у своєму проєкті¶
| Сценарій | Навіщо |
|---|---|
Файл, більший за Multipart Part Size Bytes |
Багаточастинний шлях відрізняється від звичайного |
| Скасування посеред передавання | Переконайтеся, що інтерфейс коректно відкочується |
| Помилковий ключ або бакет | Подивіться, що ваш код показує користувачеві при відмові |
| Обрив мережі під час передавання | Вимкніть Wi-Fi на середині великого завантаження |
| Ключ із пробілами й нелатинськими символами | Якщо імена об'єктів походять від користувача |
Останній пункт варто перевірити обов'язково, якщо ключі складаються з введених користувачем назв: помилки кодування проявляються не одразу й виглядають як «підпис не збігається», що відводить пошук зовсім не туди.
Підміна транспорту у власних тестах¶
Якщо ви пишете автотести для свого коду й не хочете, щоб вони ходили в мережу, підмініть транспорт клієнта:
Client->SetHttpTransport(MyFakeTransport);
Достатньо реалізувати IDemoS3HttpTransport — один метод. Далі ваш код працюватиме через
плагін, а відповіді ви задаватимете самі.
Логи для розбору¶
Log LogDemoS3 Verbose // по рядку на запит
Log LogDemoS3 VeryVerbose // ще й підписані заголовки
Секрет у логи не потрапляє за жодної багатослівності.
Далі: 10. Сценарії розгортання