प्रतिनिधि इंटरव्यू विषय

कोडिंग इंटरव्यू: Go फ़ज़ की विफलताओं को रिग्रेशन कॉर्पस में कैसे बदलें?

कोडिंगकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक इनपुट पार्सर के लिए Go फ़ज़ टेस्ट डिज़ाइन करें। एक सीड कॉर्पस से शुरुआत करें, इनवेरिएंट बताएं, और समझाएं कि कैसे एक मिनिमाइज़ किया गया फ़ेलिंग इनपुट सामान्य go test के तहत एक रिग्रेशन टेस्ट बन जाता है।

प्रश्न और उपयुक्त परिदृश्य

आप एक Go इनपुट पार्सर को मेंटेन करते हैं जो प्रोडक्शन में कभी-कभी Unicode, ट्रंकेटेड बाइट्स, या अत्यधिक लंबाई देखता है। समझाएं कि testing.F फ़ज़ टारगेट कैसे डिज़ाइन करें, सीड्स कैसे चुनें, सटीक आउटपुट अज्ञात होने पर प्रॉपर्टीज़ को कैसे व्यक्त करें, और फिक्स के बाद विफलता को रिग्रेशन के रूप में कैसे सुरक्षित रखें।

यह बैकएंड, इंफ्रास्ट्रक्चर और टेस्ट-टूलिंग भूमिकाओं के लिए उपयुक्त है। Microsoft का तकनीकी-साक्षात्कार मार्गदर्शन स्पष्ट रूप से टेस्टिंग, सीमाओं और सुरक्षा प्रभावों का मूल्यांकन करता है; Amazon का SDE मार्गदर्शन प्रोग्रामिंग और कोर सॉफ़्टवेयर विषयों को सूचीबद्ध करता है। साक्षात्कार का संकेत इंजीनियरिंग लूप है, न कि किसी कमांड को याद रखना।

साक्षात्कारकर्ता क्या परीक्षण कर रहा है

  • उदाहरण-परीक्षण के अपेक्षित मानों को फ़ज़-परीक्षण की प्रॉपर्टीज़ से अलग करना।
  • बिना किसी बाहरी साइड इफ़ेक्ट के एक तेज़ टारगेट चुनना।
  • सीड कॉर्पस, कवरेज गाइडेंस, मिनिमाइज़ेशन और रीप्ले की व्याख्या करना।
  • अमान्य UTF-8, खाली इनपुट, बड़े आकार के इनपुट और संसाधन सीमाओं को संभालना।
  • खोज, निदान, मरम्मत, पुनः चलाने और कमिट किए गए कॉर्पस को जोड़ना।

एक कमज़ोर उत्तर कहता है "रैंडम इनपुट जनरेट करें।" एक मजबूत उत्तर इनवेरिएंट, कमांड, विफलता पथ और CI विभाजन का नाम देता है।

उत्तर देने से पहले स्पष्टीकरण

  1. क्या पार्सर इनपुट string, []byte, या कई फ़ील्ड्स हैं? यह फ़ज़ तर्कों और कॉर्पस एन्कोडिंग को निर्धारित करता है।
  2. कौन से अमान्य इनपुट अपेक्षित त्रुटियां हैं? एक त्रुटि अनुबंध (error contract) असर्शन को बदल देता है।
  3. प्रति-कॉल संसाधन बजट क्या है? एक धीमा इनपुट सेवा से इनकार (denial-of-service) का संकेत हो सकता है।
  4. क्या हम पैनिक, सिमेंटिक बग या कम्पैटिबिलिटी रिग्रेशन की तलाश कर रहे हैं? प्रत्येक को अलग-अलग प्रॉपर्टीज़ और सीड्स की आवश्यकता होती है।

30-सेकंड का उत्तर ढांचा

मैं एक जांचने योग्य प्रॉपर्टी के साथ शुरुआत करता हूं, जैसे कि "पार्सिंग के बाद एन्कोडिंग समान संरचना को बनाए रखती है" या "अमान्य इनपुट एक नियंत्रित त्रुटि लौटाता है।" मैं f.Add के साथ वास्तविक सीमा मामले जोड़ता हूं, फिर f.Fuzz को तेज़, नियतात्मक (deterministic) और सीमित रखता हूं। सामान्य go test सीड्स और सहेजी गई विफलताओं को चलाता है; एक अलग CI जॉब समय बजट के साथ go test -fuzz चलाता है। Go एक फ़ेलिंग इनपुट को testdata/fuzz/<name> में छोटा (minimize) कर देता है। मूल कारण को ठीक करने के बाद, मैं उस इनपुट को फिर से चलाता हूं, पूरा टेस्ट सुइट चलाता हूं, और कॉर्पस को कमिट करता हूं ताकि खोज एक रिग्रेशन बाधा बन जाए।

चरण-दर-चरण गहरा उत्तर

1. किसी प्रॉपर्टी से शुरुआत करें, अपेक्षित उत्तर से नहीं

पार्सर के लिए, राउंड-ट्रिप प्रॉपर्टी का उपयोग करें: सामान्यीकरण के बाद Encode(Parse(x)) को x का प्रतिनिधित्व करना चाहिए। स्ट्रिंग ट्रांसफ़ॉर्म के लिए, आइडेंटपोटेंस, लंबाई संरक्षण, या UTF-8 वैधता का उपयोग करें। निर्दिष्ट सामान्यीकरण की अनुमति दें; बाइट लेआउट को अनुबंध समझने की भूल न करें।

2. एक सीमित फ़ज़ टारगेट बनाएं

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)
        }
    })
}

f.Add प्रकार और क्रम कॉलबैक से मेल खाना चाहिए। टारगेट को फ़ाइलें नहीं लिखनी चाहिए, नेटवर्क कॉल नहीं करनी चाहिए, या समय पर निर्भर नहीं होना चाहिए; अन्यथा समानांतर फ़ज़िंग गैर-पुनरुत्पादनीय (non-reproducible) विफलताएं पैदा करती है।

3. व्यावसायिक सीमाओं को सीड करें

सीड्स में प्रोटोकॉल संस्करण, खाली मान, डुप्लिकेट फ़ील्ड, गैर-ASCII टेक्स्ट, ट्रंकेशन और सैनिटाइज़ किए गए प्रोडक्शन नमूने शामिल होने चाहिए। Go सामान्य परीक्षणों के दौरान सीड्स चलाता है, इसलिए प्रत्येक सीड सस्ता और स्थिर होना चाहिए।

4. निष्पादन मोड को विभाजित करें

कमिट करने से पहले, सीड्स की जांच करने के लिए go test -run=FuzzParseRoundTrip चलाएं। एक समर्पित जॉब go test -fuzz=FuzzParseRoundTrip -fuzztime=10s चला सकता है। समय ध्वज (time flag) अन्वेषण को सीमित करता है; प्रोडक्शन कोड के बजाय CI समानांतरता और पैकेज बजट का प्रबंधन करता है।

5. मिनिमाइज़ किए गए इनपुट को दोबारा चलाएं और निदान करें

Go ऐसे इनपुट को छोटा करता है जो अभी भी विफलता को ट्रिगर करता है और इसे testdata/fuzz/FuzzParseRoundTrip/ के तहत लिखता है। go test -run=FuzzParseRoundTrip/<id> के साथ दोबारा चलाएं, फिर मूल कारण को वर्गीकृत करें: असर्शन, पैनिक, संसाधन थकावट, या परीक्षण गैर-नियतिवाद (nondeterminism)। नमूने को बग की व्याख्या करनी चाहिए, न कि एक अपारदर्शी ब्लॉब होना चाहिए।

6. फिक्स को स्थायी बनाएं

फिक्स के बाद विफलता को दोबारा चलाएं, फिर सभी go test चलाएं। सहेजी गई विफलताएं बिना -fuzz के भी चलती हैं, इसलिए कॉर्पस को कमिट करने से पहले रहस्यों (secrets), रिडेक्शन और आकार सीमाओं के लिए इसकी समीक्षा करें।

7. फ़ज़ की गुणवत्ता मापें

यदि कवरेज बढ़ना बंद हो जाता है, तो केवल अवधि बढ़ाने के बजाय संरचित सीड्स जोड़ें या जनरेशन में सुधार करें। बार-बार होने वाले टाइमआउट विफलताओं के लिए छोटे इनपुट या महंगे पथों के अलगाव की आवश्यकता होती है; उन्हें प्रदर्शन दोष के रूप में मानें। गिरती हुई खोज दर शुद्धता का प्रमाण नहीं है।

उच्च-गुणवत्ता वाला नमूना उत्तर

मैं फ़ज़िंग को एक पुनरुत्पादनीय प्रॉपर्टी के इर्द-गिर्द परिभाषित करता हूं, न कि प्रत्येक रैंडम इनपुट के लिए अपेक्षित व्यावसायिक परिणाम के इर्द-गिर्द। एक पार्सर के लिए, मान्य इनपुट को पार्स होना चाहिए और उसी संरचना में पुन: एन्कोड होना चाहिए; अमान्य इनपुट को एक नियंत्रित त्रुटि लौटानी चाहिए और कभी भी पैनिक नहीं होना चाहिए। मैं खाली इनपुट, अधिकतम स्वीकृत आकार, डुप्लिकेट फ़ील्ड, Unicode और सैनिटाइज़ किए गए प्रोडक्शन मामलों को सीड करता हूं। टारगेट सीमित और साइड-इफ़ेक्ट मुक्त है। डेवलपर्स go test -run=FuzzX चलाते हैं; CI एक निश्चित -fuzztime के साथ अन्वेषण करता है। जब Go एक मिनिमाइज़ की गई विफलता लिखता है, तो मैं इसे फिर से चलाता हूं, मूल कारण की पहचान करता हूं, कार्यान्वयन को ठीक करता हूं, सामान्य परीक्षण और फ़ज़िंग चलाता हूं, और testdata/fuzz/FuzzX को कमिट करता हूं। इस प्रकार एक खोज प्रत्येक परिवर्तन पर एक रिग्रेशन जांच बन जाती है।

सामान्य गलतियाँ

  • फ़ज़िंग को रैंडम लोड मानना → कोई ऑरेकल मौजूद नहीं है → पहले एक इनवेरिएंट और त्रुटि अनुबंध परिभाषित करें।
  • टारगेट से किसी लाइव सेवा को कॉल करना → नेटवर्क और स्थिति विफलताओं को अस्थिर (flaky) बनाते हैं → एक नियतात्मक नकली (deterministic fake) का उपयोग करें।
  • सहेजी गई विफलताओं को केवल फ़ज़ मोड में चलाना → फिक्स रिग्र्रेस हो सकते हैं → उन्हें testdata/fuzz में रखें।
  • असीमित इनपुट स्वीकार करना → एक मामला बजट की खपत करता है → एक सीमा लागू करें और छोड़े गए मामलों को रिकॉर्ड करें।
  • प्रत्येक जनरेट किए गए मामले को कमिट करना → रिपॉजिटरी में शोर और वृद्धि → उन मामलों को रखें जो बग को पुनरुत्पादित करते हैं या प्रमुख शाखाओं को कवर करते हैं।

अनुवर्ती प्रश्न और उत्तर

क्या राउंड-ट्रिप असर्शन बहुत सख्त है जब पार्सिंग इनपुट को सामान्यीकृत (normalize) करती है?

हाँ। सामान्यीकृत ASTs या फ़ील्ड सेट की तुलना करें और बताएं कि कौन से क्रम, व्हाइटस्पेस, या केस अंतर जानबूझकर अनदेखा किए जाते हैं।

क्या उपयोगकर्ता के रहस्य (secrets) वाले फ़ेलिंग नमूने को कमिट किया जा सकता है?

नहीं। क्रेडेंशियल्स और व्यक्तिगत डेटा की जांच करें, रिडैक्ट करें, और सत्यापित करें कि रिडैक्ट किया गया नमूना अभी भी विफल होता है। यदि इसे सुरक्षित रूप से कमिट नहीं किया जा सकता है, तो नियंत्रित आंतरिक पुनरुत्पादन बनाए रखें और एक सिंथेटिक समकक्ष सबमिट करें।

CI बजट पांच मिनट है। फ़ज़िंग को कैसे समायोजित किया जाना चाहिए?

प्रत्येक बिल्ड पर सीड्स और ज्ञात विफलताओं को चलाएं। समय, पैकेज और संसाधनों द्वारा अन्वेषण को सीमित करें; चुपचाप छोड़ने के बजाय टाइमआउट रिकॉर्ड करें।

आप कैसे बता सकते हैं कि फ़ज़ टेस्ट ख़राब है?

मिनिमाइज़ किए गए मामले को दोबारा चलाएं और वैश्विक स्थिति, यादृच्छिकता (randomness), और गोरूटीन टाइमिंग का निरीक्षण करें। फिर एक नियतात्मक यूनिट टेस्ट लिखें; यदि यह अस्थिर है, तो प्रोडक्शन कोड से पहले अलगाव को ठीक करें।

क्या एकाधिक टारगेट एक कॉर्पस साझा कर सकते हैं?

रूपांतरण तर्क केवल तभी साझा करें जब इनपुट प्रारूप और सिमेंटिक्स मेल खाते हों। अलग-अलग निर्देशिकाएं और इनवेरिएंट रखें ताकि एक टारगेट का कॉर्पस दूसरे के कवरेज अंतर को छुपा न सके।

सार्वजनिक स्रोत

संबंधित प्रश्न

संबंधित इंटरव्यू टूल

कोडिंग प्रॉम्प्ट के लिए स्क्रीनशॉट का उपयोग करें

समस्या को कैप्चर करें, फिर क्रम से प्रतिबंधों (constraints), समाधान, कोड, एज केस और जटिलता पर काम करें।

टूल देखें