maintner: process a github new issue mutation, start of tests
Change-Id: I92b9d5b8ddce6b48ede67e5d5ec97c1a07d17e06
Reviewed-on: https://go-review.googlesource.com/36901
Reviewed-by: Kevin Burke <kev@inburke.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/maintner/maintner.go b/maintner/maintner.go
index f342af7..973a629 100644
--- a/maintner/maintner.go
+++ b/maintner/maintner.go
@@ -23,7 +23,7 @@
// ... TODO
mu sync.RWMutex
- githubIssues map[githubRepo]map[int]*githubIssue // repo -> num -> issue
+ githubIssues map[githubRepo]map[int32]*githubIssue // repo -> num -> issue
githubUsers map[int64]*githubUser
}
@@ -34,8 +34,8 @@
// githubUser represents a github user.
// It is a subset of https://developer.github.com/v3/users/#get-a-single-user
type githubUser struct {
- ID int64
- Username string // what Github calls "Login"
+ ID int64
+ Login string
}
// githubIssue represents a github issue.
@@ -88,8 +88,67 @@
// TODO: more...
}
+func (c *Corpus) repoKey(owner, repo string) githubRepo {
+ if owner == "" || repo == "" {
+ return ""
+ }
+ // TODO: avoid garbage, use interned strings? profile later
+ // once we have gigabytes of mutation logs to slurp at
+ // start-up. (The same thing mattered for Camlistore start-up
+ // time at least)
+ return githubRepo(owner + "/" + repo)
+}
+
+func (c *Corpus) getGithubUser(pu *maintpb.GithubUser) *githubUser {
+ if pu == nil {
+ return nil
+ }
+ if u := c.githubUsers[pu.Id]; u != nil {
+ if pu.Login != "" && pu.Login != u.Login {
+ u.Login = pu.Login
+ }
+ return u
+ }
+ if c.githubUsers == nil {
+ c.githubUsers = make(map[int64]*githubUser)
+ }
+ u := &githubUser{
+ ID: pu.Id,
+ Login: pu.Login,
+ }
+ c.githubUsers[pu.Id] = u
+ return u
+}
+
func (c *Corpus) processGithubIssueMutation(m *maintpb.GithubIssueMutation) {
- // TODO: ...
+ k := c.repoKey(m.Owner, m.Repo)
+ if k == "" {
+ // TODO: errors? return false? skip for now.
+ return
+ }
+ if m.Number == 0 {
+ return
+ }
+ issueMap, ok := c.githubIssues[k]
+ if !ok {
+ if c.githubIssues == nil {
+ c.githubIssues = make(map[githubRepo]map[int32]*githubIssue)
+ }
+ issueMap = make(map[int32]*githubIssue)
+ c.githubIssues[k] = issueMap
+ }
+ gi, ok := issueMap[m.Number]
+ if !ok {
+ gi = &githubIssue{
+ Number: m.Number,
+ User: c.getGithubUser(m.User),
+ }
+ issueMap[m.Number] = gi
+ }
+ if m.Body != "" {
+ gi.Body = m.Body
+ }
+ // TODO: times, etc.
}
// PopulateFromServer populates the corpus from a maintnerd server.
diff --git a/maintner/maintner_test.go b/maintner/maintner_test.go
new file mode 100644
index 0000000..aeb671a
--- /dev/null
+++ b/maintner/maintner_test.go
@@ -0,0 +1,60 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package maintner
+
+import (
+ "reflect"
+ "testing"
+
+ "golang.org/x/build/maintner/maintpb"
+)
+
+type mutationTest struct {
+ corpus Corpus
+ want Corpus
+}
+
+func (mt mutationTest) test(t *testing.T, muts ...*maintpb.Mutation) {
+ c := mt.corpus
+ for _, m := range muts {
+ c.processMutationLocked(m)
+ }
+ if !reflect.DeepEqual(c, mt.want) {
+ t.Errorf("corpus mismatch\n got: %#v\nwant: %#v", c, mt.want)
+ }
+}
+
+func TestProcessMutation_Github_NewIssue(t *testing.T) {
+ mutationTest{
+ want: Corpus{
+ githubUsers: map[int64]*githubUser{
+ 100: &githubUser{
+ Login: "gopherbot",
+ ID: 100,
+ },
+ },
+ githubIssues: map[githubRepo]map[int32]*githubIssue{
+ "golang/go": map[int32]*githubIssue{
+ 3: &githubIssue{
+ Number: 3,
+ User: &githubUser{ID: 100, Login: "gopherbot"},
+ Body: "some body",
+ },
+ },
+ },
+ },
+ }.test(t, &maintpb.Mutation{
+ GithubIssue: &maintpb.GithubIssueMutation{
+ Owner: "golang",
+ Repo: "go",
+ Number: 3,
+ User: &maintpb.GithubUser{
+ Login: "gopherbot",
+ Id: 100,
+ },
+ Body: "some body",
+ },
+ })
+}