Topik wawancara representatif

Wawancara Koding: Bagaimana cara mengubah kegagalan fuzzing Go menjadi korpus regresi?

CodingSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Rancang uji fuzz Go untuk parser input. Mulailah dengan seed corpus, nyatakan invarian, dan jelaskan bagaimana input gagal yang telah diminimalkan menjadi uji regresi di bawah go test biasa.

Pertanyaan dan skenario yang cocok

Anda mengelola parser input Go yang sesekali menerima Unicode, bita terpotong, atau panjang ekstrem di produksi. Jelaskan cara merancang target fuzz testing.F, memilih seed, mengekspresikan properti saat output pasti tidak diketahui, dan mempertahankan kegagalan sebagai regresi setelah perbaikan.

Ini cocok untuk peran backend, infrastruktur, dan test-tooling. Panduan wawancara teknis Microsoft secara eksplisit mengevaluasi pengujian, batasan, dan implikasi keamanan; panduan SDE Amazon mencantumkan topik pemrograman dan perangkat lunak inti. Sinyal wawancara yang dicari adalah siklus rekayasa (engineering loop), bukan menghafal perintah.

Apa yang sedang diuji oleh pewawancara

  • Membedakan nilai yang diharapkan pada pengujian contoh dari properti pengujian fuzz.
  • Memilih target yang cepat tanpa efek samping eksternal.
  • Menjelaskan seed corpus, panduan cakupan (coverage guidance), minimisasi, dan pemutaran ulang (replay).
  • Menangani UTF-8 yang tidak valid, input kosong, input berukuran terlalu besar, dan batas sumber daya.
  • Menghubungkan penemuan, diagnosis, perbaikan, eksekusi ulang, dan korpus yang di-commit.

Jawaban yang lemah mengatakan "menghasilkan input acak." Jawaban yang kuat menyebutkan invarian, perintah, jalur kegagalan, dan pemisahan CI.

Klarifikasi sebelum menjawab

  1. Apakah input parser berupa string, []byte, atau beberapa bidang? Ini menentukan argumen fuzz dan pengodean korpus.
  2. Input tidak valid mana yang merupakan kesalahan yang diharapkan? Kontrak kesalahan mengubah asersi.
  3. Berapa anggaran sumber daya per pemanggilan? Input yang lambat bisa menjadi sinyal penolakan layanan (denial-of-service).
  4. Apakah kita mencari panic, bug semantik, atau regresi kompatibilitas? Masing-masing membutuhkan properti dan seed yang berbeda.

Kerangka jawaban 30 detik

Saya mulai dengan properti yang dapat diperiksa, seperti "pengodean setelah parsing mempertahankan struktur yang sama" atau "input yang tidak valid mengembalikan kesalahan yang terkontrol." Saya menambahkan kasus batas nyata dengan f.Add, lalu menjaga f.Fuzz tetap cepat, deterministik, dan terbatas. go test biasa menjalankan seed dan kegagalan yang tersimpan; pekerjaan CI terpisah menjalankan go test -fuzz dengan anggaran waktu. Go meminimalkan input yang gagal menjadi testdata/fuzz/<name>. Setelah memperbaiki akar penyebabnya, saya memutar ulang input tersebut, menjalankan seluruh rangkaian pengujian, dan melakukan commit pada korpus sehingga penemuan tersebut menjadi batasan regresi.

Jawaban mendalam langkah demi langkah

1. Mulai dengan sebuah properti, bukan jawaban yang diharapkan

Untuk sebuah parser, gunakan properti round-trip: Encode(Parse(x)) harus merepresentasikan x setelah normalisasi. Untuk transformasi string, gunakan idempoten, preservasi panjang, atau validitas UTF-8. Izinkan normalisasi yang ditentukan; jangan salah mengartikan tata letak bita sebagai kontrak.

2. Bangun target fuzz yang berbatas

go
func FuzzParseRoundTrip(f *testing.F) {
    f.Add([]byte("name=alice"))
    f.Add([]byte{})
    f.Fuzz(func(t *testing.T, input []byte) {
        t.Helper()
        if len(input) > 1<<20 {
            t.Skip()
        }
        got, err := Parse(input)
        if err != nil {
            return
        }
        again, err := Parse(Encode(got))
        if err != nil || !Equal(got, again) {
            t.Fatalf("round trip failed: %v", err)
        }
    })
}

Tipe dan urutan f.Add harus cocok dengan callback. Target tidak boleh menulis file, memanggil jaringan, atau bergantung pada waktu; jika tidak, fuzzing paralel akan menghasilkan kegagalan yang tidak dapat direproduksi.

3. Berikan seed untuk batasan bisnis

Seed harus mencakup versi protokol, nilai kosong, bidang duplikat, teks non-ASCII, pemotongan, dan sampel produksi yang telah disanitasi. Go menjalankan seed selama pengujian biasa, jadi setiap seed harus ringan dan stabil.

4. Pisahkan mode eksekusi

Sebelum commit, jalankan go test -run=FuzzParseRoundTrip untuk memeriksa seed. Pekerjaan khusus dapat menjalankan go test -fuzz=FuzzParseRoundTrip -fuzztime=10s. Flag waktu membatasi eksplorasi; CI mengelola paralelisme dan anggaran paket daripada kode produksi.

5. Putar ulang dan diagnosis input yang diminimalkan

Go meminimalkan input yang masih memicu kegagalan dan menulisnya di bawah testdata/fuzz/FuzzParseRoundTrip/. Putar ulang dengan go test -run=FuzzParseRoundTrip/<id>, lalu klasifikasikan akar penyebabnya: asersi, panic, kehabisan sumber daya, atau nondeterminisme pengujian. Sampel harus menjelaskan bug tersebut, bukan menjadi blob yang buram.

6. Buat perbaikan permanen

Putar ulang kegagalan setelah perbaikan, lalu jalankan semua go test. Kegagalan yang tersimpan juga berjalan tanpa -fuzz, jadi tinjau korpus untuk rahasia, redaksi, dan batas ukuran sebelum melakukan commit.

7. Ukur kualitas fuzz

Jika cakupan berhenti tumbuh, tambahkan seed terstruktur atau tingkatkan pembuatan daripada hanya menambah durasi. Kegagalan timeout yang sering memerlukan input yang lebih kecil atau isolasi jalur yang mahal; perlakukan hal tersebut sebagai cacat performa. Tingkat penemuan yang menurun bukanlah bukti kebenaran.

Contoh jawaban berkualitas tinggi

Saya mendefinisikan fuzzing di sekitar properti yang dapat direproduksi, bukan hasil bisnis yang diharapkan untuk setiap input acak. Untuk sebuah parser, input yang valid harus dapat di-parse dan dienkode ulang ke struktur yang sama; input yang tidak valid harus mengembalikan kesalahan yang terkontrol dan tidak boleh panic. Saya memberikan seed untuk input kosong, ukuran maksimum yang diterima, bidang duplikat, Unicode, dan kasus produksi yang disanitasi. Targetnya terbatas dan bebas dari efek samping. Pengembang menjalankan go test -run=FuzzX; CI mengeksplorasi dengan -fuzztime yang tetap. Ketika Go menulis kegagalan yang diminimalkan, saya memutar ulangnya, mengidentifikasi akar penyebabnya, memperbaiki implementasi, menjalankan pengujian biasa dan fuzzing, lalu melakukan commit pada testdata/fuzz/FuzzX. Satu penemuan kemudian menjadi pemeriksaan regresi pada setiap perubahan.

Kesalahan umum

  • Memperlakukan fuzzing sebagai beban acak → tidak ada oracle → tentukan invarian dan kontrak kesalahan terlebih dahulu.
  • Memanggil layanan langsung dari target → jaringan dan status membuat kegagalan menjadi tidak stabil (flaky) → gunakan fake yang deterministik.
  • Menjalankan kegagalan yang tersimpan hanya dalam mode fuzz → perbaikan dapat mengalami regresi → simpan di testdata/fuzz.
  • Menerima input tanpa batas → satu kasus menghabiskan anggaran → terapkan batas dan catat yang dilewati.
  • Melakukan commit pada setiap kasus yang dihasilkan → kebisingan dan pembengkakan repositori → simpan kasus yang mereproduksi bug atau mencakup cabang utama.

Pertanyaan lanjutan dan tanggapan

Apakah asersi round-trip terlalu ketat ketika parsing menormalisasi input?

Ya. Bandingkan AST yang dinormalisasi atau kumpulan bidang dan nyatakan perbedaan pengurutan, spasi kosong, atau huruf besar/kecil mana yang sengaja diabaikan.

Bisakah sampel gagal yang berisi rahasia pengguna di-commit?

Tidak. Periksa kredensial dan data pribadi, lakukan redaksi, dan verifikasi bahwa sampel yang diredaksi masih gagal. Jika tidak dapat di-commit dengan aman, pertahankan reproduksi internal yang terkontrol dan kirimkan padanan sintetis.

Anggaran CI adalah lima menit. Bagaimana fuzzing harus disesuaikan?

Jalankan seed dan kegagalan yang diketahui pada setiap build. Batasi eksplorasi berdasarkan waktu, paket, dan sumber daya; catat timeout alih-alih melewatinya secara diam-diam.

Bagaimana Anda tahu apakah uji fuzz rusak?

Putar ulang kasus yang diminimalkan dan periksa status global, keacakan, dan waktu goroutine. Kemudian tulis uji unit deterministik; jika tidak stabil, perbaiki isolasi sebelum kode produksi.

Bisakah beberapa target berbagi korpus?

Bagikan logika konversi hanya jika format input dan semantik cocok. Pisahkan direktori dan invarian sehingga korpus satu target tidak dapat menyembunyikan celah cakupan target lainnya.

Sumber publik

Pertanyaan terkait

Alat wawancara terkait

Gunakan Tangkapan Layar untuk perintah coding

Ambil tangkapan layar soal, lalu telusuri batasan, solusi, kode, edge case, dan kompleksitas secara berurutan.

Lihat alat