github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/tsearch/random.go (about)

     1  // Copyright 2022 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package tsearch
    12  
    13  import (
    14  	"math/rand"
    15  	"strconv"
    16  	"strings"
    17  )
    18  
    19  var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    20  
    21  // RandomTSVector returns a random TSVector for testing.
    22  func RandomTSVector(rng *rand.Rand) TSVector {
    23  	for {
    24  		nTerms := 1 + rng.Intn(10)
    25  		var b strings.Builder
    26  		for i := 0; i < nTerms; i++ {
    27  			l := make([]byte, 1+rng.Intn(10))
    28  			for i := range l {
    29  				l[i] = alphabet[rng.Intn(len(alphabet))]
    30  			}
    31  			b.Write(l)
    32  			if rng.Intn(2) == 0 {
    33  				b.WriteString(":")
    34  				for j := 0; j < 1+rng.Intn(5); j++ {
    35  					if j > 0 {
    36  						b.WriteString(",")
    37  					}
    38  					b.WriteString(strconv.Itoa(rng.Intn(1000)))
    39  					// Write a random "weight" from a-d.
    40  					b.WriteByte(byte('a' + rng.Intn('d'-'a')))
    41  				}
    42  			}
    43  			b.WriteByte(' ')
    44  		}
    45  		vec, err := ParseTSVector(b.String())
    46  		if err != nil {
    47  			continue
    48  		}
    49  		return vec
    50  	}
    51  }
    52  
    53  // RandomTSQuery returns a random TSQuery for testing.
    54  func RandomTSQuery(rng *rand.Rand) TSQuery {
    55  	// TODO(jordan): add parenthesis grouping to the random query generator
    56  	nTerms := 1 + rng.Intn(5)
    57  	for {
    58  		var sb strings.Builder
    59  		for i := 0; i < nTerms; i++ {
    60  			l := make([]byte, 1+rng.Intn(10))
    61  			for i := range l {
    62  				l[i] = alphabet[rng.Intn(len(alphabet))]
    63  			}
    64  			if rng.Intn(4) == 0 {
    65  				// Make it a negation query!
    66  				sb.WriteString("!")
    67  			}
    68  			sb.Write(l)
    69  			sb.WriteString(" ")
    70  			if i < nTerms-1 {
    71  				infixOp := rng.Intn(3)
    72  				var opstr string
    73  				switch infixOp {
    74  				case 0:
    75  					opstr = "&"
    76  				case 1:
    77  					opstr = "|"
    78  				case 2:
    79  					opstr = "<->"
    80  				}
    81  				sb.WriteString(opstr)
    82  				sb.WriteString(" ")
    83  			}
    84  		}
    85  
    86  		query, err := ParseTSQuery(sb.String())
    87  		if err != nil {
    88  			continue
    89  		}
    90  		return query
    91  	}
    92  }