~ubuntu-branches/ubuntu/vivid/juju-core/vivid-updates

« back to all changes in this revision

Viewing changes to src/gopkg.in/juju/charm.v4/testing/mockstore.go

  • Committer: Package Import Robot
  • Author(s): Curtis C. Hovey
  • Date: 2015-09-29 19:43:29 UTC
  • mfrom: (47.1.4 wily-proposed)
  • Revision ID: package-import@ubuntu.com-20150929194329-9y496tbic30hc7vp
Tags: 1.24.6-0ubuntu1~15.04.1
Backport of 1.24.6 from wily. (LP: #1500916, #1497087)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2012, 2013 Canonical Ltd.
2
 
// Licensed under the AGPLv3, see LICENCE file for details.
3
 
 
4
 
package testing
5
 
 
6
 
import (
7
 
        "bytes"
8
 
        "encoding/json"
9
 
        "io"
10
 
        "net"
11
 
        "net/http"
12
 
        "os"
13
 
        "strconv"
14
 
        "strings"
15
 
 
16
 
        "github.com/juju/loggo"
17
 
        "github.com/juju/utils"
18
 
        gc "gopkg.in/check.v1"
19
 
 
20
 
        "gopkg.in/juju/charm.v4"
21
 
)
22
 
 
23
 
var logger = loggo.GetLogger("juju.charm.testing.mockstore")
24
 
 
25
 
// MockStore provides a mock charm store implementation useful when testing.
26
 
type MockStore struct {
27
 
        mux                     *http.ServeMux
28
 
        listener                net.Listener
29
 
        archiveBytes            []byte
30
 
        archiveSha256           string
31
 
        Downloads               []*charm.URL
32
 
        DownloadsNoStats        []*charm.URL
33
 
        Authorizations          []string
34
 
        Metadata                []string
35
 
        InfoRequestCount        int
36
 
        InfoRequestCountNoStats int
37
 
        DefaultSeries           string
38
 
 
39
 
        charms map[string]int
40
 
}
41
 
 
42
 
// NewMockStore creates a mock charm store containing the specified charms.
43
 
func NewMockStore(c *gc.C, repo *Repo, charms map[string]int) *MockStore {
44
 
        s := &MockStore{charms: charms, DefaultSeries: "precise"}
45
 
        f, err := os.Open(repo.CharmArchivePath(c.MkDir(), "dummy"))
46
 
        c.Assert(err, gc.IsNil)
47
 
        defer f.Close()
48
 
        buf := &bytes.Buffer{}
49
 
        s.archiveSha256, _, err = utils.ReadSHA256(io.TeeReader(f, buf))
50
 
        c.Assert(err, gc.IsNil)
51
 
        s.archiveBytes = buf.Bytes()
52
 
        c.Assert(err, gc.IsNil)
53
 
        s.mux = http.NewServeMux()
54
 
        s.mux.HandleFunc("/charm-info", s.serveInfo)
55
 
        s.mux.HandleFunc("/charm-event", s.serveEvent)
56
 
        s.mux.HandleFunc("/charm/", s.serveCharm)
57
 
        lis, err := net.Listen("tcp", "127.0.0.1:0")
58
 
        c.Assert(err, gc.IsNil)
59
 
        s.listener = lis
60
 
        go http.Serve(s.listener, s)
61
 
        return s
62
 
}
63
 
 
64
 
// Close closes the mock store's socket.
65
 
func (s *MockStore) Close() {
66
 
        s.listener.Close()
67
 
}
68
 
 
69
 
// Address returns the URL used to make requests to the mock store.
70
 
func (s *MockStore) Address() string {
71
 
        return "http://" + s.listener.Addr().String()
72
 
}
73
 
 
74
 
// UpdateStoreRevision sets the revision of the specified charm to rev.
75
 
func (s *MockStore) UpdateStoreRevision(ch string, rev int) {
76
 
        s.charms[ch] = rev
77
 
}
78
 
 
79
 
// ServeHTTP implements http.ServeHTTP
80
 
func (s *MockStore) ServeHTTP(w http.ResponseWriter, r *http.Request) {
81
 
        s.mux.ServeHTTP(w, r)
82
 
}
83
 
 
84
 
func (s *MockStore) serveInfo(w http.ResponseWriter, r *http.Request) {
85
 
        if metadata := r.Header.Get("Juju-Metadata"); metadata != "" {
86
 
                s.Metadata = append(s.Metadata, metadata)
87
 
                logger.Infof("Juju metadata: " + metadata)
88
 
        }
89
 
 
90
 
        r.ParseForm()
91
 
        if r.Form.Get("stats") == "0" {
92
 
                s.InfoRequestCountNoStats += 1
93
 
        } else {
94
 
                s.InfoRequestCount += 1
95
 
        }
96
 
 
97
 
        response := map[string]*charm.InfoResponse{}
98
 
        for _, url := range r.Form["charms"] {
99
 
                cr := &charm.InfoResponse{}
100
 
                response[url] = cr
101
 
                charmURL, err := charm.ParseURL(url)
102
 
                if err == charm.ErrUnresolvedUrl {
103
 
                        ref, err := charm.ParseReference(url)
104
 
                        if err != nil {
105
 
                                panic(err)
106
 
                        }
107
 
                        charmURL, err = ref.URL(s.DefaultSeries)
108
 
                        if err != nil {
109
 
                                panic(err)
110
 
                        }
111
 
                }
112
 
                switch charmURL.Name {
113
 
                case "borken":
114
 
                        cr.Errors = append(cr.Errors, "badness")
115
 
                case "terracotta":
116
 
                        cr.Errors = append(cr.Errors, "cannot get revision")
117
 
                case "unwise":
118
 
                        cr.Warnings = append(cr.Warnings, "foolishness")
119
 
                        fallthrough
120
 
                default:
121
 
                        if rev, ok := s.charms[charmURL.WithRevision(-1).String()]; ok {
122
 
                                if charmURL.Revision == -1 {
123
 
                                        cr.Revision = rev
124
 
                                } else {
125
 
                                        cr.Revision = charmURL.Revision
126
 
                                }
127
 
                                cr.Sha256 = s.archiveSha256
128
 
                                cr.CanonicalURL = charmURL.String()
129
 
                        } else {
130
 
                                cr.Errors = append(cr.Errors, "entry not found")
131
 
                        }
132
 
                }
133
 
        }
134
 
        data, err := json.Marshal(response)
135
 
        if err != nil {
136
 
                panic(err)
137
 
        }
138
 
        w.Header().Set("Content-Type", "application/json")
139
 
        _, err = w.Write(data)
140
 
        if err != nil {
141
 
                panic(err)
142
 
        }
143
 
}
144
 
 
145
 
func (s *MockStore) serveEvent(w http.ResponseWriter, r *http.Request) {
146
 
        r.ParseForm()
147
 
        response := map[string]*charm.EventResponse{}
148
 
        for _, url := range r.Form["charms"] {
149
 
                digest := ""
150
 
                if i := strings.Index(url, "@"); i >= 0 {
151
 
                        digest = url[i+1:]
152
 
                        url = url[:i]
153
 
                }
154
 
                er := &charm.EventResponse{}
155
 
                response[url] = er
156
 
                if digest != "" && digest != "the-digest" {
157
 
                        er.Kind = "not-found"
158
 
                        er.Errors = []string{"entry not found"}
159
 
                        continue
160
 
                }
161
 
                charmURL := charm.MustParseURL(url)
162
 
                switch charmURL.Name {
163
 
                case "borken":
164
 
                        er.Kind = "publish-error"
165
 
                        er.Errors = append(er.Errors, "badness")
166
 
                case "unwise":
167
 
                        er.Warnings = append(er.Warnings, "foolishness")
168
 
                        fallthrough
169
 
                default:
170
 
                        if rev, ok := s.charms[charmURL.WithRevision(-1).String()]; ok {
171
 
                                er.Kind = "published"
172
 
                                er.Revision = rev
173
 
                                er.Digest = "the-digest"
174
 
                        } else {
175
 
                                er.Kind = "not-found"
176
 
                                er.Errors = []string{"entry not found"}
177
 
                        }
178
 
                }
179
 
        }
180
 
        data, err := json.Marshal(response)
181
 
        if err != nil {
182
 
                panic(err)
183
 
        }
184
 
        w.Header().Set("Content-Type", "application/json")
185
 
        _, err = w.Write(data)
186
 
        if err != nil {
187
 
                panic(err)
188
 
        }
189
 
}
190
 
 
191
 
func (s *MockStore) serveCharm(w http.ResponseWriter, r *http.Request) {
192
 
        charmURL := charm.MustParseURL("cs:" + r.URL.Path[len("/charm/"):])
193
 
 
194
 
        r.ParseForm()
195
 
        if r.Form.Get("stats") == "0" {
196
 
                s.DownloadsNoStats = append(s.DownloadsNoStats, charmURL)
197
 
        } else {
198
 
                s.Downloads = append(s.Downloads, charmURL)
199
 
        }
200
 
 
201
 
        if auth := r.Header.Get("Authorization"); auth != "" {
202
 
                s.Authorizations = append(s.Authorizations, auth)
203
 
        }
204
 
 
205
 
        w.Header().Set("Connection", "close")
206
 
        w.Header().Set("Content-Type", "application/octet-stream")
207
 
        w.Header().Set("Content-Length", strconv.Itoa(len(s.archiveBytes)))
208
 
        _, err := w.Write(s.archiveBytes)
209
 
        if err != nil {
210
 
                panic(err)
211
 
        }
212
 
}