~samwhited/xmpp

ref: 12e35d55ff3bb71a6bf93b73c1fbcd789c0064c6 xmpp/styling/fuzz_test.go -rw-r--r-- 2.3 KiB
12e35d55Sam Whited stanza: add Error method on IQ 11 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright 2020 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause
// license that can be found in the LICENSE file.

//+build fuzz

// This tool is meant to excersize the styling code with random documents that
// are likely to contain a high concentration of styling characters.
// This will hopeful tease out any panics that are hidden throughout the code,
// or any places where the output of a token does not exactly match the input
// (due to an off-by-one error causing the output to be truncated, for example).
// No care has been taken to try and make this fast, so it is very slow and does
// not get with the normal tests.

package styling_test

import (
	"bytes"
	"io"
	"math/rand"
	"testing"
	"time"

	"mellium.im/xmpp/styling"
)

// The strings in this list will be selected with a higher probability than
// other random runes to ensure that we add lots of styling directives that will
// tease out any problems with odd combinations of them in the decoder.
var highProbabilityAlphabet = []string{"```", " ", ">", "`", "*", "_", "\n"}

const (
	// The maximum length of generated documents.
	documentLength = 1024

	// The number of documents to generate.
	iterations = 1 << 21

	// An ~1/3 chance of selecting something from the high probability alphabet
	// (which is mostly styling directives).
	probabilityOfDirective = 3
)

func randDoc(size int) []byte {
	var b bytes.Buffer
	for b.Len() < size {
		l := len(highProbabilityAlphabet)
		choice := rand.Intn(l * probabilityOfDirective)
		if choice >= len(highProbabilityAlphabet) {
			b.WriteRune(rune(rand.Uint32()))
			continue
		}
		b.WriteString(highProbabilityAlphabet[choice])
	}
	b.Truncate(size)
	return b.Bytes()
}

func TestFuzz(t *testing.T) {
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < iterations; i++ {
		doc := randDoc(rand.Intn(documentLength))
		d := styling.NewDecoder(bytes.NewReader(doc))
		n := 0
		for {
			tok, err := d.Token()
			if err == io.EOF {
				if n+len(tok.Data) != len(doc) {
					t.Fatalf("Got early EOF at %d for input:\n%v", n, doc)
				}
				break
			}
			if err != nil {
				t.Fatalf("Error decoding: %v\nOriginal bytes:\n%v", err, doc)
				break
			}
			if !bytes.Equal(doc[n:n+len(tok.Data)], tok.Data) {
				t.Fatalf("Output bytes did not equal input bytes at %d for input:\n%v", n, doc)
			}
			n += len(tok.Data)
		}
	}
}