Hone logo
Hone
Problems

Implementing Coverage-Guided Fuzzing in Jest for Robust TypeScript Functions

This challenge focuses on integrating coverage-guided fuzzing into a Jest testing suite for a TypeScript function. The goal is to automatically discover edge cases and potential bugs in your code by generating diverse inputs based on code coverage, ensuring a more robust and reliable codebase.

Problem Description

Your task is to instrument a given TypeScript function and its Jest tests to incorporate coverage-guided fuzzing. This involves setting up a fuzzer that intelligently generates inputs for your function, aiming to maximize code coverage and uncover unexpected behaviors or crashes. You will need to adapt existing Jest tests or create new ones that work seamlessly with the fuzzing framework.

Key Requirements:

  1. Function Under Test: You will be provided with a simple, yet potentially buggy, TypeScript function that takes a specific type of input.
  2. Jest Test Suite: You will be given a basic Jest test suite for this function.
  3. Coverage-Guided Fuzzing Integration: Implement coverage-guided fuzzing using a suitable JavaScript/TypeScript fuzzing library (e.g., jazzer.js, american-fuzzy-loop).
  4. Input Generation: The fuzzer should generate inputs dynamically, aiming to explore different code paths within the function.
  5. Test Execution: The generated inputs should be passed to the function under test within the Jest environment.
  6. Reporting: The fuzzing process should provide some form of reporting on uncovered code paths or detected crashes/errors.

Expected Behavior:

  • The fuzzer should run for a specified duration or number of iterations.
  • During execution, it should attempt to reach new lines of code in the function under test.
  • If the fuzzer encounters an input that causes the function to throw an uncaught error or crash, this should be flagged.
  • Ideally, the fuzzer should attempt to identify and report inputs that achieve high code coverage.

Edge Cases to Consider:

  • Empty or null/undefined inputs.
  • Extremely long or complex inputs.
  • Inputs with unusual character sets or data types.
  • Inputs that trigger boundary conditions or error handling logic.

Examples

Let's consider a hypothetical parseConfig function.

Example 1: Valid Input

// Function under test (simplified)
function parseConfig(configString: string | null | undefined): Record<string, any> {
  if (configString === null || configString === undefined || configString.trim() === '') {
    return {};
  }
  try {
    return JSON.parse(configString);
  } catch (e) {
    throw new Error('Invalid JSON format');
  }
}

// Jest test (example)
test('should parse a valid JSON string', () => {
  const validJson = '{"port": 8080, "host": "localhost"}';
  expect(parseConfig(validJson)).toEqual({ port: 8080, host: 'localhost' });
});

Example 2: Empty Input

// Jest test (example)
test('should return an empty object for null input', () => {
  expect(parseConfig(null)).toEqual({});
});

Example 3: Invalid JSON Input (potential fuzzing target)

// Jest test (example)
test('should throw an error for invalid JSON', () => {
  const invalidJson = '{ "port": 8080, "host": '; // Incomplete JSON
  expect(() => parseConfig(invalidJson)).toThrow('Invalid JSON format');
});

When fuzzing, the fuzzer might generate inputs like:

  • '{"user": "Alice", "age": "30"'} (malformed JSON, might trigger the catch block)
  • '{"very_long_key_that_is_extremely_long_and_might_cause_performance_issues_or_buffer_overflows_in_a_real_scenario": 123}' (tests handling of large strings)
  • '' (empty string, already covered by existing tests but fuzzer might rediscover)
  • '[' (invalid JSON)

Constraints

  • Fuzzing Duration: The fuzzing process should be configurable to run for a minimum of 5 minutes or a minimum of 10,000 iterations, whichever comes first.
  • Input Format: The fuzzer should generate string inputs.
  • Performance: The fuzzing overhead should not significantly degrade the execution time of typical Jest tests.
  • Fuzzing Library: You may use any established JavaScript/TypeScript fuzzing library that supports coverage guidance.

Notes

  • Fuzzing often requires a dedicated setup and integration with your build process. For this challenge, focus on the core integration within a single project structure.
  • Consider how the fuzzer's output (e.g., crashing inputs) can be captured and potentially saved for later debugging.
  • The primary goal is to demonstrate the process of integrating coverage-guided fuzzing with Jest, not necessarily to find a critical bug in a provided function (though that would be a bonus!).
  • Think about how you'll define the "corpus" or initial set of inputs for the fuzzer.
Loading editor...
typescript