• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

freeeve / tinykvs / 21101887097

17 Jan 2026 10:31PM UTC coverage: 70.948% (+2.3%) from 68.627%
21101887097

push

github

freeeve
test: add comprehensive fuzz testing

Shell fuzz tests:
- FuzzShellOrderBy: ORDER BY clause parsing
- FuzzShellBinaryFunctions: uint64_be, fnv64, byte, hex literals
- FuzzShellAggregations: count, sum, avg, min, max functions
- FuzzShellNestedFields: nested record field access
- FuzzShellHexValues: hex literal INSERT/SELECT

Core library fuzz tests:
- FuzzDecodeMsgpack: msgpack decoding (with OOM protection)
- FuzzRecordValueEncode: record encoding round-trip
- FuzzStoreOperations: basic store put/get/delete
- FuzzPrefixCompare: key prefix operations

Bug fixes found by fuzzing:
- Fix slice bounds panic in ParseOrderBy with malformed input

3 of 5 new or added lines in 1 file covered. (60.0%)

5358 of 7552 relevant lines covered (70.95%)

427871.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.63
/cmd/tinykvs/shell_sort.go
1
package main
2

3
import (
4
        "sort"
5
        "strconv"
6
        "strings"
7
)
8

9
// SortOrder represents a single ORDER BY column
10
type SortOrder struct {
11
        Field      string // "k" for key, or field name like "ttl", "v.name"
12
        Descending bool
13
}
14

15
// SortableRows wraps rows for sorting with ORDER BY
16
type SortableRows struct {
17
        Headers []string
18
        Rows    [][]string
19
        Orders  []SortOrder
20
}
21

22
func (s *SortableRows) Len() int {
10✔
23
        return len(s.Rows)
10✔
24
}
10✔
25

26
func (s *SortableRows) Swap(i, j int) {
7✔
27
        s.Rows[i], s.Rows[j] = s.Rows[j], s.Rows[i]
7✔
28
}
7✔
29

30
func (s *SortableRows) Less(i, j int) bool {
22✔
31
        for _, order := range s.Orders {
46✔
32
                colIdx := s.findColumn(order.Field)
24✔
33
                if colIdx < 0 {
36✔
34
                        continue
12✔
35
                }
36

37
                valI := s.Rows[i][colIdx]
12✔
38
                valJ := s.Rows[j][colIdx]
12✔
39

12✔
40
                cmp := compareValues(valI, valJ)
12✔
41
                if cmp == 0 {
12✔
42
                        continue
×
43
                }
44

45
                if order.Descending {
18✔
46
                        return cmp > 0
6✔
47
                }
6✔
48
                return cmp < 0
6✔
49
        }
50
        return false
10✔
51
}
52

53
func (s *SortableRows) findColumn(field string) int {
24✔
54
        // Normalize field name
24✔
55
        field = strings.TrimPrefix(field, "v.")
24✔
56
        field = strings.ToLower(field)
24✔
57

24✔
58
        for i, h := range s.Headers {
64✔
59
                if strings.ToLower(h) == field {
52✔
60
                        return i
12✔
61
                }
12✔
62
        }
63
        return -1
12✔
64
}
65

66
// compareValues compares two string values, attempting numeric comparison first
67
func compareValues(a, b string) int {
12✔
68
        // Try numeric comparison first
12✔
69
        numA, errA := strconv.ParseFloat(a, 64)
12✔
70
        numB, errB := strconv.ParseFloat(b, 64)
12✔
71
        if errA == nil && errB == nil {
14✔
72
                if numA < numB {
3✔
73
                        return -1
1✔
74
                } else if numA > numB {
3✔
75
                        return 1
1✔
76
                }
1✔
77
                return 0
×
78
        }
79

80
        // Fall back to string comparison
81
        if a < b {
10✔
82
                return -1
×
83
        } else if a > b {
20✔
84
                return 1
10✔
85
        }
10✔
86
        return 0
×
87
}
88

89
// SortRows sorts rows according to the ORDER BY clauses
90
func SortRows(headers []string, rows [][]string, orders []SortOrder) {
10✔
91
        if len(orders) == 0 || len(rows) == 0 {
10✔
92
                return
×
93
        }
×
94

95
        sortable := &SortableRows{
10✔
96
                Headers: headers,
10✔
97
                Rows:    rows,
10✔
98
                Orders:  orders,
10✔
99
        }
10✔
100
        sort.Stable(sortable)
10✔
101
}
102

103
// ParseOrderBy extracts ORDER BY clauses from SQL
104
// Returns the modified SQL (with ORDER BY removed) and the sort orders
105
func ParseOrderBy(sql string) (string, []SortOrder) {
419✔
106
        lower := strings.ToLower(sql)
419✔
107
        idx := strings.LastIndex(lower, " order by ")
419✔
108
        if idx == -1 {
828✔
109
                return sql, nil
409✔
110
        }
409✔
111

112
        // Bounds check - index from lowercase string must be valid for original
113
        startIdx := idx + len(" order by ")
10✔
114
        if startIdx > len(sql) || idx > len(sql) {
10✔
NEW
115
                return sql, nil
×
NEW
116
        }
×
117

118
        orderPart := sql[startIdx:]
10✔
119
        sql = sql[:idx]
10✔
120

10✔
121
        // Remove any trailing LIMIT clause from orderPart
10✔
122
        limitIdx := strings.Index(strings.ToLower(orderPart), " limit ")
10✔
123
        if limitIdx != -1 {
12✔
124
                // Put LIMIT back on the main SQL
2✔
125
                sql = sql + orderPart[limitIdx:]
2✔
126
                orderPart = orderPart[:limitIdx]
2✔
127
        }
2✔
128

129
        // Parse order columns
130
        var orders []SortOrder
10✔
131
        parts := strings.Split(orderPart, ",")
10✔
132
        for _, part := range parts {
21✔
133
                part = strings.TrimSpace(part)
11✔
134
                if part == "" {
11✔
135
                        continue
×
136
                }
137

138
                order := SortOrder{}
11✔
139
                tokens := strings.Fields(part)
11✔
140
                if len(tokens) >= 1 {
22✔
141
                        order.Field = tokens[0]
11✔
142
                }
11✔
143
                if len(tokens) >= 2 {
19✔
144
                        if strings.ToUpper(tokens[1]) == "DESC" {
14✔
145
                                order.Descending = true
6✔
146
                        }
6✔
147
                }
148
                orders = append(orders, order)
11✔
149
        }
150

151
        return sql, orders
10✔
152
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc