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