Files
golib/socket/TESTING.md
nabbar 3837f0b2bb Improvements, test & documentatons (2025-12 #1)
[file/bandwidth]
- ADD documentation: add enhanced README and TESTING guidelines
- ADD tests: complete test suites with benchmarks, concurrency, and edge cases

[file/perm]
- ADD documentation: add enhanced README and TESTING guidelines
- ADD tests: complete test suites with benchmarks, concurrency, and edge cases
- ADD function to parse form "rwx-wxr-x" or "-rwx-w-r-x"
- ADD function to ParseFileMode to convert os.FileMode to file.Perm

[file/progress]
- ADD documentation: add enhanced README and TESTING guidelines
- ADD tests: complete test suites with benchmarks, concurrency, and edge cases

[ioutils/...]
- UPDATE documentation: update enhanced README and TESTING guidelines
- UPDATE tests: complete test suites with benchmarks, concurrency, and edge cases

[logger/...]
- UPDATE documentation: update enhanced README and TESTING guidelines
- ADD documentation: add enhanced README and TESTING guidelines for sub
  packages
- UPDATE tests: complete test suites with benchmarks, concurrency, and edge cases
- UPDATE config: remove FileBufferSize from OptionFile (rework hookfile)
- UPDATE fields: expose Store function in interface
- REWORK hookfile: rework package, use aggregator to allow multi write and
  single file
- FIX hookstderr: fix bug with NonColorable
- FIX hookstdout: fix bug with NonColorable
- FIX hookwriter: fix bug with NonColorable

[network/protocol]
- ADD function IsTCP, IsUDP, IsUnixLike to check type of protocol

[runner]
- FIX typo

[socket]
- UPDATE documentation: update enhanced README and TESTING guidelines
- ADD documentation: add enhanced README and TESTING guidelines for sub
  packages
- UPDATE tests: complete test suites with benchmarks, concurrency, and edge cases
- REWORK server: use context compatible io.reader, io.writer, io.closer
  instead of reader / writer
- REWORK server: simplify, optimize server
- REMOVE reader, writer type
- ADD context: add new interface in root socket interface to expose
  context interface that extend context, io reader/writer/closer,
dediacted function to server (IsConnected, ...)
2025-12-02 02:56:20 +01:00

20 KiB

Testing Documentation

License Go Version Tests Assertions Coverage

Comprehensive testing guide for the github.com/nabbar/golib/socket package core interfaces and types.


Table of Contents


Overview

Test Plan

This test suite provides comprehensive validation of the socket package core functionality through:

  1. Functional Testing: Verification of ErrorFilter and ConnState.String()
  2. Constant Validation: Testing of all connection state constants
  3. Value Testing: Verification of DefaultBufferSize and EOL constants
  4. Boundary Testing: Edge cases for error filtering and state strings
  5. Performance Testing: Benchmarking of critical functions

Test Completeness

Coverage Metrics:

  • Code Coverage: 100.0% of statements (target: >80%)
  • Branch Coverage: 100% of conditional branches
  • Function Coverage: 100% of public functions
  • Race Conditions: 0 detected across all scenarios

Test Distribution:

  • 5 unit tests covering all functionality
  • 30+ assertions validating behavior
  • 13 example tests demonstrating usage patterns
  • 4 benchmarks measuring performance
  • Zero flaky tests - all tests are deterministic

Quality Assurance:

  • All tests pass with -race detector enabled
  • All tests pass on Go 1.18 through 1.25
  • Tests run in ~0.004 seconds
  • No external dependencies required for testing

Test Architecture

Test Matrix

Category Files Specs Coverage Priority Dependencies
Core Functions socket_test.go 5 100% Critical None
Examples example_test.go 13 N/A High None
Benchmarks socket_test.go 4 N/A Medium None

Detailed Test Inventory

Test Name File Type Dependencies Priority Expected Outcome Comments
TestErrorFilter socket_test.go Unit None Critical Success Tests all error scenarios
TestConnState_String socket_test.go Unit None Critical Success Tests all state strings
TestConnState_Values socket_test.go Unit None Critical Success Validates constant values
TestDefaultBufferSize socket_test.go Unit None High Success Validates 32KB constant
TestEOL socket_test.go Unit None High Success Validates newline constant
BenchmarkErrorFilter socket_test.go Benchmark None Medium Success Measures filter performance
BenchmarkErrorFilter_Nil socket_test.go Benchmark None Medium Success Measures nil case
BenchmarkErrorFilter_Closed socket_test.go Benchmark None Medium Success Measures closed conn case
BenchmarkConnState_String socket_test.go Benchmark None Medium Success Measures string conversion

Prioritization:

  • Critical: Must pass for release (core functionality)
  • High: Should pass for release (important features)
  • Medium: Nice to have (performance verification)

Test Statistics

Latest Test Run Results:

Total Specs:         5
Passed:              5
Failed:              0
Skipped:             0
Execution Time:      ~0.004 seconds
Coverage:            100.0%
Race Conditions:     0

Test Distribution:

Test Category Count Coverage
Error Handling 1 100%
State Management 3 100%
Constants 2 100%

Example Tests:

Example Count Status
Basic Usage 13 PASS
All examples pass and produce expected output - PASS

Framework & Tools

Testing Frameworks

Standard Go Testing

Why standard testing for this package:

  • Simple functionality: Only two functions and constants to test
  • No complex scenarios: No need for BDD organization
  • Fast execution: <5ms total
  • Clear assertions: Standard testing is sufficient
  • Minimal dependencies: Only standard library

Test Structure:

func TestErrorFilter(t *testing.T) {
    tests := []struct {
        name string
        err  error
        want error
    }{
        // Test cases...
    }
    
    for _, tc := range tests {
        t.Run(tc.name, func(t *testing.T) {
            // Test implementation
        })
    }
}

Example Tests

Purpose: Demonstrate package usage patterns

Benefits:

  • Executable documentation
  • Verified by go test
  • Shown in GoDoc
  • Real-world usage patterns

Reference: See example_test.go


Quick Launch

Prerequisites

# Install Go 1.18 or later
go version  # Should be >= 1.18

# No additional tools required

Running Tests

# Quick test
go test

# Verbose output
go test -v

# With coverage
go test -cover

# Generate coverage report
go test -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html

# Race detection (requires CGO)
CGO_ENABLED=1 go test -race

# Run benchmarks
go test -bench=. -benchmem

# Run examples
go test -v -run Example

Expected Output

$ go test -v

=== RUN   TestErrorFilter
=== RUN   TestErrorFilter/nil_error
=== RUN   TestErrorFilter/closed_connection_error
=== RUN   TestErrorFilter/normal_error
=== RUN   TestErrorFilter/connection_refused
--- PASS: TestErrorFilter (0.00s)
    --- PASS: TestErrorFilter/nil_error (0.00s)
    --- PASS: TestErrorFilter/closed_connection_error (0.00s)
    --- PASS: TestErrorFilter/normal_error (0.00s)
    --- PASS: TestErrorFilter/connection_refused (0.00s)
=== RUN   TestConnState_String
=== RUN   TestConnState_String/Dial_Connection
=== RUN   TestConnState_String/New_Connection
=== RUN   TestConnState_String/Read_Incoming_Stream
=== RUN   TestConnState_String/Close_Incoming_Stream
=== RUN   TestConnState_String/Run_HandlerFunc
=== RUN   TestConnState_String/Write_Outgoing_Steam
=== RUN   TestConnState_String/Close_Outgoing_Stream
=== RUN   TestConnState_String/Close_Connection
=== RUN   TestConnState_String/unknown_connection_state
--- PASS: TestConnState_String (0.00s)
    [9 sub-tests passed]
=== RUN   TestConnState_Values
--- PASS: TestConnState_Values (0.00s)
=== RUN   TestDefaultBufferSize
--- PASS: TestDefaultBufferSize (0.00s)
=== RUN   TestEOL
--- PASS: TestEOL (0.00s)
=== RUN   ExampleConnState
--- PASS: ExampleConnState (0.00s)
=== RUN   ExampleErrorFilter
--- PASS: ExampleErrorFilter (0.00s)
[... 11 more examples ...]
PASS
coverage: 100.0% of statements
ok      github.com/nabbar/golib/socket  0.004s

Coverage

Coverage Report

Overall Coverage: 100.0% (Target: >80%)

Coverage by File:

File Coverage Statements Covered Missed
interface.go 100% 15 15 0
context.go N/A 0 0 0

Functions:

Function Coverage Lines
ConnState.String() 100% 24
ErrorFilter() 100% 7

Why 100% is Achieved:

  • All code paths exercised
  • All branches tested
  • All edge cases covered
  • Unknown state tested
  • Nil error tested
  • Closed connection error tested
  • Normal errors tested

How to Generate:

# Generate coverage
go test -coverprofile=coverage.out

# View in terminal
go tool cover -func=coverage.out

# Generate HTML report
go tool cover -html=coverage.out -o coverage.html

# Open in browser
open coverage.html  # macOS
xdg-open coverage.html  # Linux

Thread Safety Assurance

Race Detector Results: 0 races

$ CGO_ENABLED=1 go test -race

PASS
coverage: 100.0% of statements
ok      github.com/nabbar/golib/socket  0.015s

Why Thread-Safe:

  • No shared state: All functions are stateless
  • Read-only operations: String() and ErrorFilter() only read
  • Pure functions: No side effects
  • Constant values: DefaultBufferSize and EOL are constants

Verified Thread-Safe:

  • ConnState.String() can be called concurrently
  • ErrorFilter() can be called concurrently
  • All constants are immutable

Performance

Performance Report

Function Performance:

Function Time/op Notes
ConnState.String() ~8ns Switch statement, very fast
ErrorFilter(nil) ~3ns Early return
ErrorFilter(closed) ~40ns String contains check
ErrorFilter(other) ~40ns String contains check

Benchmark Results:

$ go test -bench=. -benchmem

BenchmarkConnState_String-8          155,189,350    7.71 ns/op    0 B/op    0 allocs/op
BenchmarkErrorFilter-8               29,418,483     40.8 ns/op    0 B/op    0 allocs/op
BenchmarkErrorFilter_Nil-8           384,293,670    3.11 ns/op    0 B/op    0 allocs/op
BenchmarkErrorFilter_Closed-8        29,201,694     41.1 ns/op    0 B/op    0 allocs/op

Key Observations:

  • Zero allocations: All functions are allocation-free
  • Nanosecond performance: Suitable for hot paths
  • Consistent performance: No performance variance

Test Conditions

Test Environment:

  • Hardware: Varies (local development machines, CI servers)
  • OS: Linux, Darwin, Windows
  • Go Version: 1.18 through 1.25
  • CPU: Multi-core (benchmarks run on single core)

Test Isolation:

  • Each test is independent
  • No shared state between tests
  • No test order dependencies
  • Deterministic results

Performance Limitations

Why No Detailed Benchmarks:

  1. Simple Functions: ConnState.String() and ErrorFilter() are trivial
  2. Negligible Overhead: <100ns per call
  3. Not a Bottleneck: Never performance-critical in real applications
  4. Zero Allocations: No memory optimization needed

Real Performance:


Test Writing

File Organization

socket/
├── socket_test.go           # Unit tests and benchmarks
├── example_test.go          # Example tests (for documentation)
└── doc.go                   # Package documentation

File Naming Convention:

  • *_test.go: Test files
  • example_test.go: Runnable examples

Test Templates

Basic Test Structure

package socket_test

import (
    "fmt"
    "testing"
    
    libsck "github.com/nabbar/golib/socket"
)

func TestFeature(t *testing.T) {
    tests := []struct {
        name string
        // Input fields
        want interface{}
    }{
        {
            name: "descriptive test case name",
            // Test data
        },
    }
    
    for _, tc := range tests {
        t.Run(tc.name, func(t *testing.T) {
            // Arrange
            // Act
            got := featureUnderTest(tc.input)
            
            // Assert
            if got != tc.want {
                t.Errorf("got %v, want %v", got, tc.want)
            }
        })
    }
}

Example Test Structure

package socket_test

import (
    "fmt"
    
    libsck "github.com/nabbar/golib/socket"
)

// ExampleFeature demonstrates feature usage
func ExampleFeature() {
    // Setup
    
    // Usage
    result := libsck.Feature()
    
    // Display result
    fmt.Println(result)
    
    // Output:
    // expected output
}

Benchmark Structure

func BenchmarkFeature(b *testing.B) {
    // Setup
    input := prepareInput()
    
    b.ResetTimer()
    
    for i := 0; i < b.N; i++ {
        _ = featureUnderTest(input)
    }
}

Running New Tests

# Run specific test
go test -run TestFeature -v

# Run specific example
go test -run ExampleFeature -v

# Run specific benchmark
go test -bench=BenchmarkFeature

# Fast validation workflow
go test -run TestFeature && go test -race -run TestFeature

Helper Functions

Test Utilities:

// assertError checks error expectation
func assertError(t *testing.T, got, want error) {
    t.Helper()
    
    if want == nil {
        if got != nil {
            t.Errorf("unexpected error: %v", got)
        }
    } else {
        if got == nil {
            t.Errorf("expected error, got nil")
        } else if got.Error() != want.Error() {
            t.Errorf("got error %v, want %v", got, want)
        }
    }
}

// assertEqual checks value equality
func assertEqual(t *testing.T, got, want interface{}) {
    t.Helper()
    
    if got != want {
        t.Errorf("got %v, want %v", got, want)
    }
}

Best Practices

DO

Write Clear Test Names:

// ✅ Good: Descriptive
func TestErrorFilter_NilError(t *testing.T) {
    // Test implementation
}

// ❌ Bad: Vague
func TestFilter1(t *testing.T) {
    // Test implementation
}

Use Table-Driven Tests:

// ✅ Good: Table-driven
tests := []struct {
    name string
    in   error
    want error
}{
    {"nil error", nil, nil},
    {"closed conn", closedErr, nil},
    {"other error", otherErr, otherErr},
}

for _, tc := range tests {
    t.Run(tc.name, func(t *testing.T) {
        got := ErrorFilter(tc.in)
        assertEqual(t, got, tc.want)
    })
}

Test All Branches:

// ✅ Good: All branches covered
func TestConnState_String(t *testing.T) {
    tests := []struct {
        state ConnState
        want  string
    }{
        {ConnectionDial, "Dial Connection"},
        {ConnectionNew, "New Connection"},
        // ... all states ...
        {ConnState(255), "unknown connection state"},
    }
}

DON'T

Don't Skip Error Checks:

// ❌ Bad: Ignoring errors in tests
func TestFeature(t *testing.T) {
    result, _ := Feature()
}

// ✅ Good: Check all errors
func TestFeature(t *testing.T) {
    result, err := Feature()
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
}

Don't Use Magic Numbers:

// ❌ Bad: Magic numbers
if size != 32768 {
    t.Error("wrong size")
}

// ✅ Good: Use constants
if size != DefaultBufferSize {
    t.Error("wrong size")
}

Troubleshooting

Common Issues

1. Tests Pass Locally But Fail in CI

Problem: Platform-specific behavior differences

Solution: This package is platform-independent. If tests fail in CI:

  • Check Go version compatibility
  • Verify no external dependencies
  • Review CI environment setup

2. Coverage Not 100%

Problem: Missing test cases

Solution:

# View uncovered lines
go tool cover -html=coverage.out

# Identify missing tests
# Add tests for uncovered branches

3. Benchmarks Show High Variance

Problem: System load affecting benchmarks

Solution:

# Run multiple times
go test -bench=. -count=10 -benchmem

# Run with more iterations
go test -bench=. -benchtime=10s

Debug Techniques

1. Verbose Output:

go test -v

2. Run Specific Test:

go test -run TestErrorFilter/nil_error

3. Check Coverage:

go test -coverprofile=coverage.out
go tool cover -html=coverage.out

4. Race Detection:

CGO_ENABLED=1 go test -race -v

Getting Help

GitHub Issues: github.com/nabbar/golib/issues

Documentation:


Reporting Bugs & Vulnerabilities

Bug Report Template

If you encounter a bug, please report it via GitHub Issues using this template:

**Bug Description:**
[A clear and concise description of what the bug is]

**Steps to Reproduce:**
1. [First step]
2. [Second step]
3. [...]

**Expected Behavior**:
[A clear and concise description of what you expected to happen]

**Actual Behavior**:
[What actually happened]

**Code Example**:
[Minimal reproducible example]

**Test Case** (if applicable):
[Paste full test output with -v flag]

**Environment**:
- Go version: `go version`
- OS: Linux/macOS/Windows
- Architecture: amd64/arm64
- Package version: vX.Y.Z or commit hash

**Additional Context**:
[Any other relevant information]

**Logs/Error Messages**:
[Paste error messages or stack traces here]

**Possible Fix:**
[If you have suggestions]

Security Vulnerability Template

⚠️ IMPORTANT: For security vulnerabilities, please DO NOT create a public issue.

Instead, report privately via:

  1. GitHub Security Advisories (preferred)
  2. Email to the maintainer (see footer)

Vulnerability Report Template:

**Vulnerability Type:**
[e.g., Overflow, Race Condition, Memory Leak, Denial of Service]

**Severity:**
[Critical / High / Medium / Low]

**Affected Component:**
[e.g., interface.go, context.go, specific function]

**Affected Versions**:
[e.g., v1.0.0 - v1.2.3]

**Vulnerability Description:**
[Detailed description of the security issue]

**Attack Scenario**:
1. Attacker does X
2. System responds with Y
3. Attacker exploits Z

**Proof of Concept:**
[Minimal code to reproduce the vulnerability]
[DO NOT include actual exploit code]

**Impact**:
- Confidentiality: [High / Medium / Low]
- Integrity: [High / Medium / Low]
- Availability: [High / Medium / Low]

**Proposed Fix** (if known):
[Suggested approach to fix the vulnerability]

**CVE Request**:
[Yes / No / Unknown]

**Coordinated Disclosure**:
[Willing to work with maintainers on disclosure timeline]

Issue Labels

When creating GitHub issues, use these labels:

  • bug: Something isn't working
  • enhancement: New feature or request
  • documentation: Improvements to docs
  • performance: Performance issues
  • test: Test-related issues
  • security: Security vulnerability (private)
  • help wanted: Community help appreciated
  • good first issue: Good for newcomers

Reporting Guidelines

Before Reporting:

  1. Search existing issues to avoid duplicates
  2. Verify the bug with the latest version
  3. Run tests with -race detector
  4. Check if it's a test issue or package issue
  5. Collect all relevant logs and outputs

What to Include:

  • Complete test output (use -v flag)
  • Go version (go version)
  • OS and architecture (go env GOOS GOARCH)
  • Race detector output (if applicable)
  • Coverage report (if relevant)

Response Time:

  • Bugs: Typically reviewed within 48 hours
  • Security: Acknowledged within 24 hours
  • Enhancements: Reviewed as time permits

License: MIT License - See LICENSE file for details
Maintained By: Nicolas JUHEL
Package: github.com/nabbar/golib/socket

AI Transparency: In compliance with EU AI Act Article 50.4: AI assistance was used for testing, documentation, and bug resolution under human supervision. All core functionality is human-designed and validated.