Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: appengine/cmd/dm/deps/common_test.go

Issue 1537883002: Initial distributor implementation (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@master
Patch Set: self review Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package deps 5 package deps
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 9
10 "github.com/golang/protobuf/proto" 10 "github.com/golang/protobuf/proto"
11 "github.com/luci/gae/service/datastore" 11 "github.com/luci/gae/service/datastore"
12 "github.com/luci/gae/service/datastore/dumper"
13 "github.com/luci/luci-go/appengine/cmd/dm/distributor/fake"
12 "github.com/luci/luci-go/appengine/cmd/dm/model" 14 "github.com/luci/luci-go/appengine/cmd/dm/model"
15 "github.com/luci/luci-go/appengine/cmd/dm/mutate"
16 "github.com/luci/luci-go/appengine/tumble"
13 dm "github.com/luci/luci-go/common/api/dm/service/v1" 17 dm "github.com/luci/luci-go/common/api/dm/service/v1"
14 "github.com/luci/luci-go/common/clock"
15 "github.com/luci/luci-go/common/cryptorand"
16 . "github.com/luci/luci-go/common/testing/assertions"
17 . "github.com/smartystreets/goconvey/convey" 18 . "github.com/smartystreets/goconvey/convey"
18 "golang.org/x/net/context" 19 "golang.org/x/net/context"
19 ) 20 )
20 21
21 func ensureQuest(c context.Context, name string, aids ...uint32) string { 22 func testSetup() (ttest *tumble.Testing, c context.Context, dist *fake.Distribut or, s testDepsServer) {
22 » desc := &dm.Quest_Desc{ 23 » ttest, c, dist, reg := fake.Setup(mutate.FinishExecutionFn)
23 » » DistributorConfigName: "foof", 24 » s = testDepsServer{newDecoratedDeps(reg)}
24 » » JsonPayload: fmt.Sprintf(`{"name": "%s"}`, name), 25 » return
25 » } 26 }
26 » q, err := model.NewQuest(c, desc) 27
27 » So(err, ShouldBeNil) 28 type testDepsServer struct {
28 » qsts, err := newDecoratedDeps().EnsureGraphData(c, &dm.EnsureGraphDataRe q{ 29 » dm.DepsServer
30 }
31
32 func (s testDepsServer) ensureQuest(c context.Context, name string, aids ...uint 32) string {
33 » desc := fake.QuestDesc(name)
34 » q := model.NewQuest(c, desc)
35 » qsts, err := s.EnsureGraphData(c, &dm.EnsureGraphDataReq{
29 Quest: []*dm.Quest_Desc{desc}, 36 Quest: []*dm.Quest_Desc{desc},
30 Attempts: dm.NewAttemptList(map[string][]uint32{q.ID: aids}), 37 Attempts: dm.NewAttemptList(map[string][]uint32{q.ID: aids}),
31 }) 38 })
32 So(err, ShouldBeNil) 39 So(err, ShouldBeNil)
33 for qid := range qsts.Result.Quests { 40 for qid := range qsts.Result.Quests {
34 So(qid, ShouldEqual, q.ID) 41 So(qid, ShouldEqual, q.ID)
35 return qid 42 return qid
36 } 43 }
37 panic("impossible") 44 panic("impossible")
38 } 45 }
39 46
40 func mkToken(c context.Context) []byte { 47 func dumpDatastore(c context.Context) {
41 » rtok := make([]byte, 32) 48 » ds := datastore.Get(c)
42 » _, err := cryptorand.Read(c, rtok) 49 » snap := ds.Testable().TakeIndexSnapshot()
43 » if err != nil { 50 » ds.Testable().CatchupIndexes()
44 » » panic(err) 51 » defer ds.Testable().SetIndexSnapshot(snap)
45 » } 52
46 » return rtok 53 » fmt.Println("dumping datastore")
54 » dumper.Config{
55 » » PropFilters: dumper.PropFilterMap{
56 » » » {"Quest", "Desc"}: func(prop datastore.Property) string {
57 » » » » desc := &dm.Quest_Desc{}
58 » » » » if err := proto.Unmarshal(prop.Value().([]byte), desc); err != nil {
59 » » » » » panic(err)
60 » » » » }
61 » » » » return desc.String()
62 » » » },
63 » » » {"Attempt", "State"}: func(prop datastore.Property) stri ng {
64 » » » » return dm.Attempt_State(int32(prop.Value().(int6 4))).String()
65 » » » },
66 » » » {"Execution", "State"}: func(prop datastore.Property) st ring {
67 » » » » return dm.Execution_State(int32(prop.Value().(in t64))).String()
68 » » » },
69 » » },
70 » }.Query(c, nil)
47 } 71 }
48
49 func execute(c context.Context, aid *dm.Attempt_ID) *dm.Execution_Auth {
50 // takes an NeedsExecution attempt, and moves it to Executing
51 rtok := mkToken(c)
52 ret := &dm.Execution_Auth{Token: rtok}
53
54 err := datastore.Get(c).RunInTransaction(func(c context.Context) error {
55 ds := datastore.Get(c)
56 atmpt := &model.Attempt{ID: *aid}
57 if err := ds.Get(atmpt); err != nil {
58 panic(err)
59 }
60
61 atmpt.CurExecution++
62 atmpt.MustModifyState(c, dm.Attempt_EXECUTING)
63
64 ret.Id = dm.NewExecutionID(atmpt.ID.Quest, atmpt.ID.Id, atmpt.Cu rExecution)
65
66 So(ds.PutMulti([]interface{}{atmpt, &model.Execution{
67 ID: atmpt.CurExecution,
68 Created: clock.Now(c),
69 State: dm.Execution_SCHEDULED,
70 Attempt: ds.KeyForObj(atmpt),
71 Token: rtok,
72 }}), ShouldBeNil)
73 return nil
74 }, nil)
75 So(err, ShouldBeNil)
76 return ret
77 }
78
79 func activate(c context.Context, auth *dm.Execution_Auth) *dm.Execution_Auth {
80 newTok := mkToken(c)
81 _, err := newDecoratedDeps().ActivateExecution(c, &dm.ActivateExecutionR eq{
82 Auth: auth, ExecutionToken: newTok})
83 So(err, ShouldBeNil)
84 return &dm.Execution_Auth{Id: auth.Id, Token: newTok}
85 }
86
87 func depOn(c context.Context, fromAuth *dm.Execution_Auth, to ...*dm.Attempt_ID) {
88 req := &dm.EnsureGraphDataReq{
89 ForExecution: fromAuth,
90 Attempts: dm.NewAttemptList(nil),
91 }
92 req.Attempts.AddAIDs(to...)
93
94 rsp, err := newDecoratedDeps().EnsureGraphData(c, req)
95 if err != nil {
96 panic(err)
97 }
98 So(rsp.ShouldHalt, ShouldBeTrue)
99 }
100
101 func purgeTimestamps(gd *dm.GraphData) {
102 for _, q := range gd.Quests {
103 if q.GetData().GetCreated() != nil {
104 q.Data.Created = nil
105 }
106 for _, a := range q.GetAttempts() {
107 if a.Data != nil {
108 a.Data.Created = nil
109 a.Data.Modified = nil
110 if ne := a.Data.GetNeedsExecution(); ne != nil {
111 ne.Pending = nil
112 } else if fi := a.Data.GetFinished(); fi != nil {
113 fi.Expiration = nil
114 }
115 }
116 for _, e := range a.Executions {
117 if e.Data != nil {
118 e.Data.Created = nil
119 }
120 }
121 }
122 }
123 }
124
125 func WalkShouldReturn(c context.Context, keepTimestamps ...bool) func(request in terface{}, expect ...interface{}) string {
126 kt := len(keepTimestamps) > 0 && keepTimestamps[0]
127
128 normalize := func(gd *dm.GraphData) *dm.GraphData {
129 data, err := proto.Marshal(gd)
130 if err != nil {
131 panic(err)
132 }
133 So(err, ShouldBeNil)
134 ret := &dm.GraphData{}
135 if err := proto.Unmarshal(data, ret); err != nil {
136 panic(err)
137 }
138 if !kt {
139 purgeTimestamps(ret)
140 }
141 return ret
142 }
143
144 return func(request interface{}, expect ...interface{}) string {
145 r := request.(*dm.WalkGraphReq)
146 e := expect[0].(*dm.GraphData)
147 ret, err := newDecoratedDeps().WalkGraph(c, r)
148 if nilExpect := ShouldErrLike(err, nil); nilExpect != "" {
149 return nilExpect
150 }
151 return ShouldResemble(normalize(ret), e)
152 }
153 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698