chaoswriter

package module
v0.0.1-alpha.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 25, 2025 License: Unlicense Imports: 11 Imported by: 0

README

ChaosWriter

ChaosWriter is a lightweight Go library for simulating flaky data streams. It wraps an io.Writer to inject chaos by applying rate limiting, dynamic rate fluctuations, random delays, and controlled bit-level corruption. This makes it ideal for testing error handling, simulating unreliable network conditions, or fuzzing applications.

Features

  • Rate Limiting: Limit write speed to a specified bytes-per-second.
  • Dynamic Rate Fluctuations: Simulate variable network conditions.
  • Random Delays: Introduce random write delays.
  • Bit-level Corruption: Optionally corrupt a percentage of the data bits.
  • Fuzzing Support: Optionally process strings with a built-in fuzzer.

Installation

Use go get to install ChaosWriter:

go get github.com/toxyl/chaoswriter

Usage

ChaosWriter can be used in several ways. Below are three examples demonstrating how to integrate ChaosWriter into your project.

Example 1: Basic Usage with Fuzzing
package main

import (
	"fmt"
	"os"
	"time"

	"github.com/toxyl/chaoswriter"
)

func main() {
	// Create a ChaosWriter with:
	// - A rate of 10 bytes per second with ±90% fluctuation,
	// - A 10% chance of corruption per chunk,
	// - 10% of bits corrupted in affected chunks,
	// - 0-10ms random delay per write.
	cw := chaoswriter.New(10, 0.9, 0.10, 0.10, 10*time.Millisecond, os.Stdout)

	// Process the string with fuzzing and write it out.
	n, _ := cw.Write(
		"This is a test to see how much corruption will occur.\n"+
			"First we are writing a known text, so we can judge the chaos effects.\n"+
			"Then we'll print 10 bytes of random data: [$randBytes:10]\n"+
			"And finally we'll print a fuzzed text, such as a random UUID: [#UUID] or a random hash: [#32]",
		true,
	)

	fmt.Printf("\n\nTotal bytes written: %d\n", n)
}
Example 2: Using the Package-Level Write Function
package main

import (
	"fmt"
	"os"
	"time"

	"github.com/toxyl/chaoswriter"
)

func main() {
	n, _ := chaoswriter.Write(
		os.Stdout, // Target writer
		"This is a test to see how much corruption will occur.\n"+
			"First we are writing a known text, so we can judge the chaos effects.\n"+
			"Then we'll print 10 bytes of random data: [$randBytes:10]\n"+
			"And finally we'll print a fuzzed text, such as a random UUID: [#UUID] or a random hash: [#32]",
		true,    // Process string with fuzzer
		10, 0.9, // Rate limit: 10B/s with ±90% fluctuation
		0.10, 0.10, // Corruption: 10% chance per chunk, 10% corruption intensity
		10*time.Millisecond, // 0-10ms random delay per write
	)

	fmt.Printf("\n\nTotal bytes written: %d\n", n)
}
Example 3: Command-Line Tool
package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"github.com/toxyl/chaoswriter"
)

func main() {
	// Define command-line flags for ChaosWriter options.
	fuzz := flag.Bool("fuzz", false, "Enable fuzzing of the input string before writing")
	rateBytesSec := flag.Float64("rate", 1024, "Rate limit in bytes per second")
	rateFluctuation := flag.Float64("fluctuation", 0.1, "Rate fluctuation as a fraction (0-1)")
	corruptionProbability := flag.Float64("corruptionProbability", 0.0, "Probability of corruption (0-1)")
	corruptionIntensity := flag.Float64("corruptionIntensity", 0.0, "Intensity of corruption as a fraction of bits (0-1)")
	delayStr := flag.String("delay", "0s", "Maximum random delay (e.g., 100ms, 1s)")

	flag.Parse()

	// Ensure the required positional arguments (input string and target) are provided.
	args := flag.Args()
	if len(args) < 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s [options] <string> <target>\n", os.Args[0])
		flag.PrintDefaults()
		os.Exit(1)
	}
	inputStr := args[0]
	target := args[1]

	// Parse the maximum random delay.
	maxDelay, err := time.ParseDuration(*delayStr)
	if err != nil {
		log.Fatalf("Invalid delay value: %v", err)
	}

	// Determine the writer: if target is "-", use stdout; otherwise, create the file.
	var writer io.Writer
	if target == "-" {
		writer = os.Stdout
	} else {
		file, err := os.Create(target)
		if err != nil {
			log.Fatalf("Failed to create target file: %v", err)
		}
		defer file.Close()
		writer = file
	}

	// Write the string with chaos injection using the package-level Write function.
	written, err := chaoswriter.Write(
		writer,
		inputStr,
		*fuzz,
		*rateBytesSec,
		*rateFluctuation,
		*corruptionProbability,
		*corruptionIntensity,
		maxDelay,
	)
	if err != nil {
		log.Fatalf("Error writing data: %v", err)
	}

	fmt.Printf("Successfully wrote %d bytes to %s\n", written, target)
}

Fuzzer Support

When the fuzzing option is enabled (by passing true as the fuzz parameter), ChaosWriter processes the input string through a built-in fuzzer. The fuzzer replaces specific tokens in the string with dynamically generated values. It supports the following tokens:

UUIDs and Hashes
  • [#UUID]
    Generates a random UUID (e.g., xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx).
  • [#56]
    Generates a random 56-character hash.
Random Numbers
  • [i:6]
    Random integer with a 6-character length (zero-padded).
  • [f:6.2]
    Random float with a 6-character integer part and a 2-character fractional part.
  • [10:500]
    Random integer between 10 and 500 (inclusive, can include negative values).
  • [0.5:5.5]
    Random float between 0.5 and 5.5 (inclusive, can include negative values).
Random Strings
  • [sl:6]
    Random lowercase string with 6 characters (a-z).
  • [su:6]
    Random uppercase string with 6 characters (A-Z).
  • [s:6]
    Random mixed-case string with 6 characters (a-z, A-Z).
  • [al:6]
    Random lowercase alphanumeric string with 6 characters (a-z, 0-9).
  • [au:6]
    Random uppercase alphanumeric string with 6 characters (A-Z, 0-9).
  • [a:6]
    Random mixed-case alphanumeric string with 6 characters (a-z, A-Z, 0-9).
Lists and Ranges
  • [10..500]
    Generates a comma-separated list of all integers from 10 to 500 (inclusive).
  • [a,b,c]
    Randomly selects a value from the given list.
Bytes
  • [$randBytes:n]
    Generates n random bytes.
Data Encoding
  • [bin:data]
    Encodes data as binary.
  • [b32:data]
    Encodes data as Base32.
  • [b64:data]
    Encodes data as Base64.
  • [b85:data]
    Encodes data as Base85.
  • [hex:data]
    Encodes data as hexadecimal.
  • [url:data]
    Encodes data as URL (percent-encoding).

This flexible token replacement system allows you to easily inject dynamic, randomized data into your output streams.

API Overview

ChaosWriter
  • New
    Creates a new ChaosWriter instance that wraps an io.Writer with the following configuration:

    • rateBytesSec: Base rate limit in bytes per second (a minimum value of 0.0001 is enforced).
    • rateFluctuation: Maximum fluctuation fraction (0 to 1) applied to the base rate.
    • corruptionProbability: Likelihood (0 to 1) that a write operation will corrupt data.
    • corruptionIntensity: Fraction (0 to 1) of bits to corrupt when corruption occurs.
    • maxRandomDelay: Maximum random delay applied before each write.
    • w: The underlying io.Writer to wrap.
  • Write
    Writes a string to the underlying writer, applying rate limiting, random delays, and optional bit-level corruption. If fuzzing is enabled, the string is first processed through the built-in fuzzer.

  • Package-Level Write Function
    A convenience function that wraps the creation of a ChaosWriter and writes a string with chaos injection directly.

License

This project is licensed under the UNLICENSE.

Documentation

Overview

Package chaoswriter provides a writer that injects chaos into data streams.

It wraps an io.Writer to perform rate-limited writes with optional random delays, dynamic rate fluctuations, and controlled bit-level corruption. This package is useful for testing error handling, simulating unreliable network conditions, or fuzzing.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Write

func Write(w io.Writer, str string, fuzz bool, rateBytesSec, rateFluctuation, corruptionProbability, corruptionIntensity float64, maxRandomDelay time.Duration) (int, error)

Write writes the given string to the provided writer using a ChaosWriter. It applies rate limiting, optional random delays, and potential bit-level corruption.

The fuzz parameter controls whether the input string is processed through the fuzzer before writing. The rateBytesSec parameter sets the base rate limit in bytes per second, and rateFluctuation specifies the maximum variation in the rate. The corruptionProbability and corruptionIntensity control the likelihood and extent of bit-level corruption, respectively. maxRandomDelay specifies the maximum random delay to apply before writing.

It returns the number of bytes written and any error encountered.

Types

type ChaosWriter

type ChaosWriter struct {
	// contains filtered or unexported fields
}

ChaosWriter is a writer that injects chaos into data streams. It wraps an underlying io.Writer and modifies data writes by applying rate limiting, random delays, dynamic rate fluctuations, and controlled bit-level corruption. This type can be used to simulate unreliable network conditions or to test error handling and fuzzing mechanisms.

func New

func New(rateBytesSec, rateFluctuation, corruptionProbability, corruptionIntensity float64, maxRandomDelay time.Duration, w io.Writer) *ChaosWriter

New returns a new ChaosWriter that wraps the provided io.Writer. The ChaosWriter is configured to perform rate-limited writes with optional delays and bit-level corruption.

Parameters:

rateBytesSec:       Base rate limit in bytes per second (a minimum value of 0.0001 is enforced).
rateFluctuation:    Fraction (0 to 1) that determines the maximum deviation from the base rate.
corruptionProbability: Probability (0 to 1) that a write operation will apply bit-level corruption.
corruptionIntensity: Fraction (0 to 1) representing the proportion of bits to corrupt when corruption occurs.
maxRandomDelay:     Maximum duration for additional random delay applied before writes.
w:                  The underlying io.Writer to wrap.

It returns a pointer to a ChaosWriter instance.

func (*ChaosWriter) Write

func (cw *ChaosWriter) Write(str string, fuzz bool) (int, error)

Write writes the given string to the underlying writer with chaos injection applied. If the fuzz parameter is true, the input string is processed through the fuzzer before writing. The method introduces a random delay (up to the configured maximum) and may apply rate-limited writing with bit-level corruption to simulate chaotic conditions.

It returns the number of bytes written and any error encountered.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL