1package random_bugs
2
3import (
4 "math/rand"
5 "strings"
6 "time"
7
8 "github.com/icrowley/fake"
9
10 "github.com/MichaelMure/git-bug/bug"
11 "github.com/MichaelMure/git-bug/identity"
12 "github.com/MichaelMure/git-bug/repository"
13)
14
15type opsGenerator func(bug.Interface, identity.Interface, int64)
16
17type Options struct {
18 BugNumber int
19 PersonNumber int
20 MinOp int
21 MaxOp int
22}
23
24func DefaultOptions() Options {
25 return Options{
26 BugNumber: 15,
27 PersonNumber: 5,
28 MinOp: 3,
29 MaxOp: 20,
30 }
31}
32
33func FillRepo(repo repository.ClockedRepo, bugNumber int) {
34 FillRepoWithSeed(repo, bugNumber, time.Now().UnixNano())
35}
36
37func FillRepoWithSeed(repo repository.ClockedRepo, bugNumber int, seed int64) {
38 options := DefaultOptions()
39 options.BugNumber = bugNumber
40
41 CommitRandomBugsWithSeed(repo, options, seed)
42}
43
44func CommitRandomBugs(repo repository.ClockedRepo, opts Options) {
45 CommitRandomBugsWithSeed(repo, opts, time.Now().UnixNano())
46}
47
48func CommitRandomBugsWithSeed(repo repository.ClockedRepo, opts Options, seed int64) {
49 generateRandomPersons(repo, opts.PersonNumber)
50
51 bugs := generateRandomBugsWithSeed(opts, seed)
52
53 for _, b := range bugs {
54 err := b.Commit(repo)
55 if err != nil {
56 panic(err)
57 }
58 }
59}
60
61func generateRandomBugsWithSeed(opts Options, seed int64) []*bug.Bug {
62 rand.Seed(seed)
63 fake.Seed(seed)
64
65 // At the moment git-bug has a risk of hash collision is simple
66 // operation (like open/close) are made with the same timestamp.
67 // As a temporary workaround, we use here an strictly increasing
68 // timestamp
69 timestamp := time.Now().Unix()
70
71 opsGenerators := []opsGenerator{
72 comment,
73 comment,
74 title,
75 labels,
76 open,
77 close,
78 }
79
80 result := make([]*bug.Bug, opts.BugNumber)
81
82 for i := 0; i < opts.BugNumber; i++ {
83 addedLabels = []string{}
84
85 b, _, err := bug.Create(
86 randomPerson(),
87 time.Now().Unix(),
88 fake.Sentence(),
89 paragraphs(),
90 )
91
92 if err != nil {
93 panic(err)
94 }
95
96 nOps := opts.MinOp
97
98 if opts.MaxOp > opts.MinOp {
99 nOps += rand.Intn(opts.MaxOp - opts.MinOp)
100 }
101
102 for j := 0; j < nOps; j++ {
103 index := rand.Intn(len(opsGenerators))
104 opsGenerators[index](b, randomPerson(), timestamp)
105 timestamp++
106 }
107
108 result[i] = b
109 }
110
111 return result
112}
113
114func person(repo repository.RepoClock) (*identity.Identity, error) {
115 return identity.NewIdentity(repo, fake.FullName(), fake.EmailAddress())
116}
117
118var persons []*identity.Identity
119
120func generateRandomPersons(repo repository.ClockedRepo, n int) {
121 persons = make([]*identity.Identity, n)
122 for i := range persons {
123 p, err := person(repo)
124 if err != nil {
125 panic(err)
126 }
127 err = p.Commit(repo)
128 if err != nil {
129 panic(err)
130 }
131 persons[i] = p
132 }
133}
134
135func randomPerson() identity.Interface {
136 index := rand.Intn(len(persons))
137 return persons[index]
138}
139
140func paragraphs() string {
141 p := fake.Paragraphs()
142 return strings.Replace(p, "\t", "\n\n", -1)
143}
144
145func comment(b bug.Interface, p identity.Interface, timestamp int64) {
146 _, _ = bug.AddComment(b, p, timestamp, paragraphs())
147}
148
149func title(b bug.Interface, p identity.Interface, timestamp int64) {
150 _, _ = bug.SetTitle(b, p, timestamp, fake.Sentence())
151}
152
153func open(b bug.Interface, p identity.Interface, timestamp int64) {
154 _, _ = bug.Open(b, p, timestamp)
155}
156
157func close(b bug.Interface, p identity.Interface, timestamp int64) {
158 _, _ = bug.Close(b, p, timestamp)
159}
160
161var addedLabels []string
162
163func labels(b bug.Interface, p identity.Interface, timestamp int64) {
164 var removed []string
165 nbRemoved := rand.Intn(3)
166 for nbRemoved > 0 && len(addedLabels) > 0 {
167 index := rand.Intn(len(addedLabels))
168 removed = append(removed, addedLabels[index])
169 addedLabels[index] = addedLabels[len(addedLabels)-1]
170 addedLabels = addedLabels[:len(addedLabels)-1]
171 nbRemoved--
172 }
173
174 var added []string
175 nbAdded := rand.Intn(3)
176 for i := 0; i < nbAdded; i++ {
177 label := fake.Word()
178 added = append(added, label)
179 addedLabels = append(addedLabels, label)
180 }
181
182 // ignore error
183 // if the randomisation produce no changes, no op
184 // is added to the bug
185 _, _, _ = bug.ChangeLabels(b, p, timestamp, added, removed)
186}