fix: replace string(rune()) with strconv.Itoa in tests (bd-fmc)
Also updated CONFIG.md to clarify mass delete threshold requires >5 issues (bd-in6).
The string(rune('0'+i)) pattern produces incorrect characters when i >= 10.
Changed to strconv.Itoa(i) for reliable conversion.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/steveyegge/beads/internal/storage/sqlite"
|
||||
@@ -42,9 +43,9 @@ func TestExportIntegrityAfterJSONLTruncation(t *testing.T) {
|
||||
var allIssues []*types.Issue
|
||||
for i := 1; i <= numIssues; i++ {
|
||||
issue := &types.Issue{
|
||||
ID: "bd-" + string(rune('0'+i)),
|
||||
Title: "Test issue " + string(rune('0'+i)),
|
||||
Description: "Description " + string(rune('0'+i)),
|
||||
ID: "bd-" + strconv.Itoa(i),
|
||||
Title: "Test issue " + strconv.Itoa(i),
|
||||
Description: "Description " + strconv.Itoa(i),
|
||||
Status: types.StatusOpen,
|
||||
Priority: 1,
|
||||
IssueType: types.TypeTask,
|
||||
@@ -276,8 +277,8 @@ func TestMultipleExportsStayConsistent(t *testing.T) {
|
||||
var issues []*types.Issue
|
||||
for i := 1; i <= 5; i++ {
|
||||
issue := &types.Issue{
|
||||
ID: "bd-" + string(rune('0'+i)),
|
||||
Title: "Issue " + string(rune('0'+i)),
|
||||
ID: "bd-" + strconv.Itoa(i),
|
||||
Title: "Issue " + strconv.Itoa(i),
|
||||
Status: types.StatusOpen,
|
||||
Priority: 1,
|
||||
IssueType: types.TypeTask,
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -215,7 +216,7 @@ func TestStaleIssuesWithLimit(t *testing.T) {
|
||||
for i := 1; i <= 5; i++ {
|
||||
updatedAt := oldTime.Add(time.Duration(i) * time.Hour) // Slightly different times for sorting
|
||||
issue := &types.Issue{
|
||||
ID: "test-stale-limit-" + string(rune('0'+i)),
|
||||
ID: "test-stale-limit-" + strconv.Itoa(i),
|
||||
Title: "Stale issue",
|
||||
Status: types.StatusOpen,
|
||||
Priority: 1,
|
||||
@@ -231,7 +232,7 @@ func TestStaleIssuesWithLimit(t *testing.T) {
|
||||
// Update timestamps directly in DB using datetime() function
|
||||
db := s.UnderlyingDB()
|
||||
for i := 1; i <= 5; i++ {
|
||||
id := "test-stale-limit-" + string(rune('0'+i))
|
||||
id := "test-stale-limit-" + strconv.Itoa(i)
|
||||
// Make each slightly different (40 days ago + i hours)
|
||||
_, err := db.ExecContext(ctx, "UPDATE issues SET updated_at = datetime('now', '-40 days', '+' || ? || ' hours') WHERE id = ?", i, id)
|
||||
if err != nil {
|
||||
|
||||
@@ -187,7 +187,7 @@ Configuration keys use dot-notation namespaces to organize settings:
|
||||
- `export.write_manifest` - Write .manifest.json with export metadata (default: false)
|
||||
- `auto_export.error_policy` - Override error policy for auto-exports (default: `best-effort`)
|
||||
- `sync.branch` - Name of the dedicated sync branch for beads data (see docs/PROTECTED_BRANCHES.md)
|
||||
- `sync.require_confirmation_on_mass_delete` - Require interactive confirmation before pushing when >50% of issues vanish during a merge (default: `false`)
|
||||
- `sync.require_confirmation_on_mass_delete` - Require interactive confirmation before pushing when >50% of issues vanish during a merge AND more than 5 issues existed before (default: `false`)
|
||||
|
||||
### Integration Namespaces
|
||||
|
||||
@@ -336,7 +336,8 @@ Controls for the sync branch workflow (see docs/PROTECTED_BRANCHES.md):
|
||||
bd config set sync.branch beads-metadata
|
||||
|
||||
# Enable mass deletion protection (optional, default: false)
|
||||
# When enabled, if >50% of issues vanish during a merge, bd sync will:
|
||||
# When enabled, if >50% of issues vanish during a merge AND more than 5
|
||||
# issues existed before the merge, bd sync will:
|
||||
# 1. Show forensic info about vanished issues
|
||||
# 2. Prompt for confirmation before pushing
|
||||
bd config set sync.require_confirmation_on_mass_delete "true"
|
||||
|
||||
@@ -2,6 +2,7 @@ package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
@@ -289,7 +290,7 @@ func TestDeepHierarchyCacheCorrectness(t *testing.T) {
|
||||
var issues []*types.Issue
|
||||
for i := 0; i < 4; i++ {
|
||||
issue := &types.Issue{
|
||||
Title: "Level " + string(rune('0'+i)),
|
||||
Title: "Level " + strconv.Itoa(i),
|
||||
Status: types.StatusOpen,
|
||||
Priority: 1,
|
||||
IssueType: types.TypeEpic,
|
||||
|
||||
@@ -2,6 +2,7 @@ package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
@@ -143,7 +144,7 @@ func TestGetIssueCommentsOrdering(t *testing.T) {
|
||||
|
||||
// Add comments with identifiable ordering
|
||||
for i := 1; i <= 5; i++ {
|
||||
text := "Comment " + string(rune('0'+i))
|
||||
text := "Comment " + strconv.Itoa(i)
|
||||
_, err := store.AddIssueComment(ctx, issue.ID, "alice", text)
|
||||
if err != nil {
|
||||
t.Fatalf("AddIssueComment failed: %v", err)
|
||||
@@ -162,7 +163,7 @@ func TestGetIssueCommentsOrdering(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := 0; i < len(comments); i++ {
|
||||
expectedText := "Comment " + string(rune('0'+i+1))
|
||||
expectedText := "Comment " + strconv.Itoa(i+1)
|
||||
if comments[i].Text != expectedText {
|
||||
t.Errorf("Comment %d: expected text %s, got %s", i, expectedText, comments[i].Text)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -112,9 +113,9 @@ func BenchmarkCheckEligibility(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func generateID(b testing.TB, prefix string, n int) string{
|
||||
func generateID(b testing.TB, prefix string, n int) string {
|
||||
b.Helper()
|
||||
return prefix + string(rune('0'+n/10)) + string(rune('0'+n%10))
|
||||
return prefix + strconv.Itoa(n)
|
||||
}
|
||||
|
||||
func setupBenchDB(tb testing.TB) (*SQLiteStorage, func()) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
@@ -415,7 +416,7 @@ func TestDetectCyclesLongCycle(t *testing.T) {
|
||||
issues := make([]*types.Issue, cycleLength)
|
||||
for i := 0; i < cycleLength; i++ {
|
||||
issues[i] = &types.Issue{
|
||||
Title: "Issue " + string(rune('0'+i)),
|
||||
Title: "Issue " + strconv.Itoa(i),
|
||||
Status: types.StatusOpen,
|
||||
Priority: 1,
|
||||
IssueType: types.TypeTask,
|
||||
|
||||
Reference in New Issue
Block a user