Testing Files Generator
Українська

Як зробити пошкоджений файл для тестів

Валідатор, якому показували лише здорові файли, насправді не перевірений. Ось як отримати файл, навмисно зіпсований, що виходить точно такого розміру, який ви просите, і несе маніфест із вказівкою, що ваша система має з ним зробити.

Коротка відповідь

tfg generate --format png --size 2mb --damage zero-head --out ./out записує PNG рівно в 2097152 байти, перші байти якого нулі, а маніфест поруч фіксує, що ваша система має його відхилити.

Звичайний шлях

Чому файл, зіпсований вручну, - поганий тест

Зазвичай беруть шістнадцятковий редактор, скрипт, що перевертає кілька випадкових байтів, або вкорочують файл через head чи truncate. Один раз це працює, а потім коштує дорого:

Що ви отримуєте

Пошкоджений файл лишається потрібного розміру

Файл створюється як зазвичай і псується потім, дорогою на диск. Він зберігає заданий розмір, а та сама команда знову записує ті самі байти.

tfg generate --format png --size 2mb --damage zero-head --out ./out
tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken

Налаштування пишуться після двокрапки. Параметр можна повторювати, а пошкодження застосовуються в тому порядку, в якому ви їх записали. Це працює з кожним із 26 форматів.

Що він уміє

Які бувають пошкодження?

Це список, який друкує програма, прочитаний із неї під час збирання цієї сторінки. tfg damage друкує той самий список, а tfg damage <id> каже, що приймає одне з них.

Пошкодження Що воно робить із байтами Найменший файл Налаштування
zero-head Перезаписує перші байти файлу нулями, не змінюючи його довжину. Більшість програм читання дивляться спочатку туди, тому це пошкодження помічає майже все. 8 bytes

zero-head записує нулі поверх початку файлу. Більшість програм читання дивляться спочатку туди, на сигнатуру й заголовок, які кажуть, що це за файл, тому помічає майже будь-яка. У простого тексту та журналів сигнатури немає, і їх теж відхиляють, бо послідовність нульових байтів не є текстом. Менше ніж чотири байти - і в деяких форматів виходить пошкодження, на яке не скаржиться жодна програма читання, тому налаштування починається з чотирьох.

Що каже маніфест

Маніфест, який каже, що має статися

Кожен пошкоджений файл отримує запис про те, що ваша система має його відхилити, а поруч записано пошкодження:

"expected": {
  "outcome": "reject",
  "reason": "content_malformed",
  "confidence": "certain"
},
"damage": [
  {
    "type": "zero-head",
    "settings": {
      "bytes": "8"
    }
  }
]

Два запити відхиляються, перш ніж щось буде записано, бо кожен залишив би на диску файл, який маніфест описує хибно:

У рецепті

Здорові й зламані файли за один запуск

Покладіть обидва види в один рецепт, і маніфест несе очікування для кожного файлу, тож тесту не потрібен список, який файл який:

version: 1
targets:
  - id: healthy
    format: pdf
    size: 1mb
    expected: accept
  - id: broken
    format: pdf
    size: 1mb
    damage:
      - zero-head

У тесті

Перетворюємо це на тест

Тест читає маніфест і перевіряє, що сталося те, що було заявлено. Список імен файлів йому не потрібен:

import json, os

directory = "healthy-and-broken"
manifest = json.load(open(os.path.join(directory, "manifest.json")))

for entry in manifest["files"]:
    response = upload(os.path.join(directory, entry["path"]))
    if entry["expected"]["outcome"] == "reject":
        assert not response.ok
    else:
        assert response.ok

Гарна відмова - це чиста відмова. Повідомлення, що каже, що було не так, - та відповідь, яка вам потрібна. Помилка сервера, зависання або наполовину збережений файл - той дефект, заради якого цей тест і існує.

Далі

Куди йти звідси