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

การปฏิเสธที่ดีคือการปฏิเสธที่สะอาด ข้อความที่บอกว่าผิดตรงไหนคือคำตอบที่คุณต้องการ ส่วนข้อผิดพลาดของเซิร์ฟเวอร์ การค้าง หรือไฟล์ที่บันทึกไว้ครึ่งเดียวคือข้อบกพร่องที่การทดสอบนี้มีไว้หา

ถัดไป

จากตรงนี้ไปไหนต่อ