github.com/richardwilkes/toolbox@v1.121.0/txt/natural_sort_test.go (about)

     1  // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the Mozilla Public
     4  // License, version 2.0. If a copy of the MPL was not distributed with
     5  // this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  //
     7  // This Source Code Form is "Incompatible With Secondary Licenses", as
     8  // defined by the Mozilla Public License, version 2.0.
     9  
    10  package txt_test
    11  
    12  import (
    13  	"flag"
    14  	"fmt"
    15  	"math/rand/v2"
    16  	"strconv"
    17  	"testing"
    18  
    19  	"github.com/richardwilkes/toolbox/atexit"
    20  	"github.com/richardwilkes/toolbox/check"
    21  	"github.com/richardwilkes/toolbox/txt"
    22  )
    23  
    24  var benchSet []string
    25  
    26  func TestMain(m *testing.M) {
    27  	flag.Parse()
    28  	if f := flag.Lookup("test.bench"); f != nil && f.Value.String() != "" {
    29  		initBenchSet()
    30  	}
    31  	atexit.Exit(m.Run())
    32  }
    33  
    34  func TestNaturalLess(t *testing.T) {
    35  	testset := []struct {
    36  		s1              string
    37  		s2              string
    38  		caseInsensitive bool
    39  		less            bool
    40  	}{
    41  		{"0", "00", false, true},
    42  		{"00", "0", false, false},
    43  		{"aa", "ab", false, true},
    44  		{"ab", "abc", false, true},
    45  		{"abc", "ad", false, true},
    46  		{"ab1", "ab2", false, true},
    47  		{"ab1c", "ab1c", false, false},
    48  		{"ab12", "abc", false, true},
    49  		{"ab2a", "ab10", false, true},
    50  		{"a0001", "a0000001", false, true},
    51  		{"a10", "abcdefgh2", false, true},
    52  		{"аб2аб", "аб10аб", false, true},
    53  		{"2аб", "3аб", false, true},
    54  		{"a1b", "a01b", false, true},
    55  		{"a01b", "a1b", false, false},
    56  		{"ab01b", "ab010b", false, true},
    57  		{"ab010b", "ab01b", false, false},
    58  		{"a01b001", "a001b01", false, true},
    59  		{"a001b01", "a01b001", false, false},
    60  		{"a1", "a1x", false, true},
    61  		{"1ax", "1b", false, true},
    62  		{"1b", "1ax", false, false},
    63  		{"082", "83", false, true},
    64  		{"083a", "9a", false, false},
    65  		{"9a", "083a", false, true},
    66  		{"a123", "A0123", true, true},
    67  		{"A123", "a0123", true, true},
    68  		{"ab010b", "ab01B", true, false},
    69  		{"1.12.34", "1.2", false, false},
    70  		{"1.2.34", "1.11.11", false, true},
    71  	}
    72  	for _, v := range testset {
    73  		check.Equal(t, v.less, txt.NaturalLess(v.s1, v.s2, v.caseInsensitive), fmt.Sprintf("%q < %q", v.s1, v.s2))
    74  	}
    75  }
    76  
    77  func BenchmarkStdStringLess(b *testing.B) {
    78  	for i := 0; i < b.N; i++ {
    79  		for j := range benchSet {
    80  			_ = benchSet[j] < benchSet[(j+1)%len(benchSet)]
    81  		}
    82  	}
    83  }
    84  
    85  func BenchmarkNaturalLess(b *testing.B) {
    86  	for i := 0; i < b.N; i++ {
    87  		for j := range benchSet {
    88  			_ = txt.NaturalLess(benchSet[j], benchSet[(j+1)%len(benchSet)], false)
    89  		}
    90  	}
    91  }
    92  
    93  func BenchmarkNaturalLessCaseInsensitive(b *testing.B) {
    94  	for i := 0; i < b.N; i++ {
    95  		for j := range benchSet {
    96  			_ = txt.NaturalLess(benchSet[j], benchSet[(j+1)%len(benchSet)], true)
    97  		}
    98  	}
    99  }
   100  
   101  func initBenchSet() {
   102  	rnd := rand.New(rand.NewPCG(22, 1967)) //nolint:gosec // Use of weak prng is fine here
   103  	benchSet = make([]string, 20000)
   104  	for i := range benchSet {
   105  		strlen := rnd.IntN(6) + 3
   106  		numlen := rnd.IntN(3) + 1
   107  		numpos := rnd.IntN(strlen + 1)
   108  		var num string
   109  		for j := 0; j < numlen; j++ {
   110  			num += strconv.Itoa(rnd.IntN(10))
   111  		}
   112  		var str string
   113  		for j := 0; j < strlen+1; j++ {
   114  			if j == numpos {
   115  				str += num
   116  			} else {
   117  				str += string(rune('a' + rnd.IntN(16)))
   118  			}
   119  		}
   120  		benchSet[i] = str
   121  	}
   122  }