<commit_before>/*
   Implements the Google omaha protocol.

   Omaha is a request/response protocol using XML. Requests are made by
   clients and responses are given by the Omaha server.
   http://code.google.com/p/omaha/wiki/ServerProtocol
*/
package omaha

import (
	"encoding/xml"
)

type Request struct {
	XMLName        xml.Name `xml:"request" datastore:"-"`
	Os             Os       `xml:"os"`
	Apps           []*App   `xml:"app"`
	Protocol       string   `xml:"protocol,attr"`
	Version        string   `xml:"version,attr,omitempty"`
	IsMachine      string   `xml:"ismachine,attr,omitempty"`
	SessionId      string   `xml:"sessionid,attr,omitempty"`
	UserId         string   `xml:"userid,attr,omitempty"`
	InstallSource  string   `xml:"installsource,attr,omitempty"`
	TestSource     string   `xml:"testsource,attr,omitempty"`
	RequestId      string   `xml:"requestid,attr,omitempty"`
	UpdaterVersion string   `xml:"updaterversion,attr,omitempty"`
}

func NewRequest(version string, platform string, sp string, arch string) *Request {
	r := new(Request)
	r.Protocol = "3.0"
	r.Os = Os{Version: version, Platform: platform, Sp: sp, Arch: arch}
	return r
}

func (r *Request) AddApp(id string, version string) *App {
	a := NewApp(id)
	a.Version = version
	r.Apps = append(r.Apps, a)
	return a
}

/* Response
 */
type Response struct {
	XMLName  xml.Name `xml:"response" datastore:"-"`
	DayStart DayStart `xml:"daystart"`
	Apps     []*App   `xml:"app"`
	Protocol string   `xml:"protocol,attr"`
	Server   string   `xml:"server,attr"`
}

func NewResponse(server string) *Response {
	r := &Response{Server: server, Protocol: "3.0"}
	r.DayStart.ElapsedSeconds = "0"
	return r
}

type DayStart struct {
	ElapsedSeconds string `xml:"elapsed_seconds,attr"`
}

func (r *Response) AddApp(id string) *App {
	a := NewApp(id)
	r.Apps = append(r.Apps, a)
	return a
}

type App struct {
	XMLName     xml.Name     `xml:"app" datastore"-"`
	Ping        *Ping        `xml:"ping"`
	UpdateCheck *UpdateCheck `xml:"updatecheck"`
	Events      []*Event     `xml:"event"`
	Id          string       `xml:"appid,attr,omitempty"`
	Version     string       `xml:"version,attr,omitempty"`
	NextVersion string       `xml:"nextversion,attr,omitempty"`
	Lang        string       `xml:"lang,attr,omitempty"`
	Client      string       `xml:"client,attr,omitempty"`
	InstallAge  string       `xml:"installage,attr,omitempty"`
	Track       string       `xml:"track,attr,omitempty"`
	FromTrack   string       `xml:"from_track,attr,omitempty"`
	Status      string       `xml:"status,attr,omitempty"`
}

func NewApp(id string) *App {
	a := &App{Id: id}
	return a
}

func (a *App) AddUpdateCheck() *UpdateCheck {
	a.UpdateCheck = new(UpdateCheck)
	return a.UpdateCheck
}

func (a *App) AddPing() *Ping {
	a.Ping = new(Ping)
	return a.Ping
}

func (a *App) AddEvent() *Event {
	event := new(Event)
	a.Events = append(a.Events, event)
	return event
}

type UpdateCheck struct {
	XMLName             xml.Name  `xml:"updatecheck" datastore:"-"`
	Urls                *Urls     `xml:"urls"`
	Manifest            *Manifest `xml:"manifest"`
	TargetVersionPrefix string    `xml:"targetversionprefix,attr,omitempty"`
	Status              string    `xml:"status,attr,omitempty"`
}

func (u *UpdateCheck) AddUrl(codebase string) *Url {
	if u.Urls == nil {
		u.Urls = new(Urls)
	}
	url := new(Url)
	url.CodeBase = codebase
	u.Urls.Urls = append(u.Urls.Urls, *url)
	return url
}

func (u *UpdateCheck) AddManifest(version string) *Manifest {
	u.Manifest = &Manifest{Version: version}
	return u.Manifest
}

type Ping struct {
	XMLName        xml.Name `xml:"ping" datastore:"-"`
	LastReportDays string   `xml:"r,attr,omitempty"`
	Status         string   `xml:"status,attr,omitempty"`
}

type Os struct {
	XMLName  xml.Name `xml:"os" datastore:"-"`
	Platform string   `xml:"platform,attr,omitempty"`
	Version  string   `xml:"version,attr,omitempty"`
	Sp       string   `xml:"sp,attr,omitempty"`
	Arch     string   `xml:"arch,attr,omitempty"`
}

func NewOs(platform string, version string, sp string, arch string) *Os {
	o := &Os{Version: version, Platform: platform, Sp: sp, Arch: arch}
	return o
}

type Event struct {
	XMLName         xml.Name `xml:"event" datastore:"-"`
	Type            string   `xml:"eventtype,attr,omitempty"`
	Result          string   `xml:"eventresult,attr,omitempty"`
	PreviousVersion string   `xml:"previousversion,attr,omitempty"`
}

type Urls struct {
	XMLName xml.Name `xml:"urls" datastore:"-"`
	Urls    []Url    `xml:"url"`
}

type Url struct {
	XMLName  xml.Name `xml:"url" datastore:"-"`
	CodeBase string   `xml:"codebase,attr"`
}

type Manifest struct {
	XMLName  xml.Name `xml:"manifest" datastore:"-"`
	Packages Packages `xml:"packages"`
	Actions  Actions  `xml:"actions"`
	Version  string   `xml:"version,attr"`
}

type Packages struct {
	XMLName  xml.Name  `xml:"packages" datastore:"-"`
	Packages []Package `xml:"package"`
}

type Package struct {
	XMLName  xml.Name `xml:"package" datastore:"-"`
	Hash     string   `xml:"hash,attr"`
	Name     string   `xml:"name,attr"`
	Size     string   `xml:"size,attr"`
	Required bool     `xml:"required,attr"`
}

func (m *Manifest) AddPackage(hash string, name string, size string, required bool) *Package {
	p := &Package{Hash: hash, Name: name, Size: size, Required: required}
	m.Packages.Packages = append(m.Packages.Packages, *p)
	return p
}

type Actions struct {
	XMLName xml.Name  `xml:"actions" datastore:"-"`
	Actions []*Action `xml:"action"`
}

type Action struct {
	XMLName xml.Name `xml:"action" datastore:"-"`
	Event   string   `xml:"event,attr"`

	// Extensions added by update_engine
	ChromeOSVersion       string `xml:"ChromeOSVersion,attr"`
	Sha256                string `xml:"sha256,attr"`
	NeedsAdmin            bool   `xml:"needsadmin,attr"`
	IsDelta               bool   `xml:"IsDelta,attr"`
	DisablePayloadBackoff bool   `xml:"DisablePayloadBackoff,attr,omitempty"`
	MetadataSignatureRsa  string `xml:"MetadataSignatureRsa,attr,omitempty"`
	MetadataSize          string `xml:"MetadataSize,attr,omitempty"`
	Deadline              string `xml:"deadline,attr,omitempty"`
}

func (m *Manifest) AddAction(event string) *Action {
	a := &Action{Event: event}
	m.Actions.Actions = append(m.Actions.Actions, a)
	return a
}

var EventTypes = map[int]string{
	0:   "unknown",
	1:   "download complete",
	2:   "install complete",
	3:   "update complete",
	4:   "uninstall",
	5:   "download started",
	6:   "install started",
	9:   "new application install started",
	10:  "setup started",
	11:  "setup finished",
	12:  "update application started",
	13:  "update download started",
	14:  "update download finished",
	15:  "update installer started",
	16:  "setup update begin",
	17:  "setup update complete",
	20:  "register product complete",
	30:  "OEM install first check",
	40:  "app-specific command started",
	41:  "app-specific command ended",
	100: "setup failure",
	102: "COM server failure",
	103: "setup update failure",
}

var EventResults = map[int]string{
	0:  "error",
	1:  "success",
	2:  "success reboot",
	3:  "success restart browser",
	4:  "cancelled",
	5:  "error installer MSI",
	6:  "error installer other",
	7:  "noupdate",
	8:  "error installer system",
	9:  "update deferred",
	10: "handoff error",
}
<commit_msg>chore(omaha): group the update engine extensions together<commit_after>/*
   Implements the Google omaha protocol.

   Omaha is a request/response protocol using XML. Requests are made by
   clients and responses are given by the Omaha server.
   http://code.google.com/p/omaha/wiki/ServerProtocol
*/
package omaha

import (
	"encoding/xml"
)

type Request struct {
	XMLName        xml.Name `xml:"request" datastore:"-"`
	Os             Os       `xml:"os"`
	Apps           []*App   `xml:"app"`
	Protocol       string   `xml:"protocol,attr"`
	Version        string   `xml:"version,attr,omitempty"`
	IsMachine      string   `xml:"ismachine,attr,omitempty"`
	SessionId      string   `xml:"sessionid,attr,omitempty"`
	UserId         string   `xml:"userid,attr,omitempty"`
	InstallSource  string   `xml:"installsource,attr,omitempty"`
	TestSource     string   `xml:"testsource,attr,omitempty"`
	RequestId      string   `xml:"requestid,attr,omitempty"`
	UpdaterVersion string   `xml:"updaterversion,attr,omitempty"`
}

func NewRequest(version string, platform string, sp string, arch string) *Request {
	r := new(Request)
	r.Protocol = "3.0"
	r.Os = Os{Version: version, Platform: platform, Sp: sp, Arch: arch}
	return r
}

func (r *Request) AddApp(id string, version string) *App {
	a := NewApp(id)
	a.Version = version
	r.Apps = append(r.Apps, a)
	return a
}

/* Response
 */
type Response struct {
	XMLName  xml.Name `xml:"response" datastore:"-"`
	DayStart DayStart `xml:"daystart"`
	Apps     []*App   `xml:"app"`
	Protocol string   `xml:"protocol,attr"`
	Server   string   `xml:"server,attr"`
}

func NewResponse(server string) *Response {
	r := &Response{Server: server, Protocol: "3.0"}
	r.DayStart.ElapsedSeconds = "0"
	return r
}

type DayStart struct {
	ElapsedSeconds string `xml:"elapsed_seconds,attr"`
}

func (r *Response) AddApp(id string) *App {
	a := NewApp(id)
	r.Apps = append(r.Apps, a)
	return a
}

type App struct {
	XMLName     xml.Name     `xml:"app" datastore"-"`
	Ping        *Ping        `xml:"ping"`
	UpdateCheck *UpdateCheck `xml:"updatecheck"`
	Events      []*Event     `xml:"event"`
	Id          string       `xml:"appid,attr,omitempty"`
	Version     string       `xml:"version,attr,omitempty"`
	NextVersion string       `xml:"nextversion,attr,omitempty"`
	Lang        string       `xml:"lang,attr,omitempty"`
	Client      string       `xml:"client,attr,omitempty"`
	InstallAge  string       `xml:"installage,attr,omitempty"`
	Status      string       `xml:"status,attr,omitempty"`

	// update engine extensions
	Track       string       `xml:"track,attr,omitempty"`
	FromTrack   string       `xml:"from_track,attr,omitempty"`
}

func NewApp(id string) *App {
	a := &App{Id: id}
	return a
}

func (a *App) AddUpdateCheck() *UpdateCheck {
	a.UpdateCheck = new(UpdateCheck)
	return a.UpdateCheck
}

func (a *App) AddPing() *Ping {
	a.Ping = new(Ping)
	return a.Ping
}

func (a *App) AddEvent() *Event {
	event := new(Event)
	a.Events = append(a.Events, event)
	return event
}

type UpdateCheck struct {
	XMLName             xml.Name  `xml:"updatecheck" datastore:"-"`
	Urls                *Urls     `xml:"urls"`
	Manifest            *Manifest `xml:"manifest"`
	TargetVersionPrefix string    `xml:"targetversionprefix,attr,omitempty"`
	Status              string    `xml:"status,attr,omitempty"`
}

func (u *UpdateCheck) AddUrl(codebase string) *Url {
	if u.Urls == nil {
		u.Urls = new(Urls)
	}
	url := new(Url)
	url.CodeBase = codebase
	u.Urls.Urls = append(u.Urls.Urls, *url)
	return url
}

func (u *UpdateCheck) AddManifest(version string) *Manifest {
	u.Manifest = &Manifest{Version: version}
	return u.Manifest
}

type Ping struct {
	XMLName        xml.Name `xml:"ping" datastore:"-"`
	LastReportDays string   `xml:"r,attr,omitempty"`
	Status         string   `xml:"status,attr,omitempty"`
}

type Os struct {
	XMLName  xml.Name `xml:"os" datastore:"-"`
	Platform string   `xml:"platform,attr,omitempty"`
	Version  string   `xml:"version,attr,omitempty"`
	Sp       string   `xml:"sp,attr,omitempty"`
	Arch     string   `xml:"arch,attr,omitempty"`
}

func NewOs(platform string, version string, sp string, arch string) *Os {
	o := &Os{Version: version, Platform: platform, Sp: sp, Arch: arch}
	return o
}

type Event struct {
	XMLName         xml.Name `xml:"event" datastore:"-"`
	Type            string   `xml:"eventtype,attr,omitempty"`
	Result          string   `xml:"eventresult,attr,omitempty"`
	PreviousVersion string   `xml:"previousversion,attr,omitempty"`
}

type Urls struct {
	XMLName xml.Name `xml:"urls" datastore:"-"`
	Urls    []Url    `xml:"url"`
}

type Url struct {
	XMLName  xml.Name `xml:"url" datastore:"-"`
	CodeBase string   `xml:"codebase,attr"`
}

type Manifest struct {
	XMLName  xml.Name `xml:"manifest" datastore:"-"`
	Packages Packages `xml:"packages"`
	Actions  Actions  `xml:"actions"`
	Version  string   `xml:"version,attr"`
}

type Packages struct {
	XMLName  xml.Name  `xml:"packages" datastore:"-"`
	Packages []Package `xml:"package"`
}

type Package struct {
	XMLName  xml.Name `xml:"package" datastore:"-"`
	Hash     string   `xml:"hash,attr"`
	Name     string   `xml:"name,attr"`
	Size     string   `xml:"size,attr"`
	Required bool     `xml:"required,attr"`
}

func (m *Manifest) AddPackage(hash string, name string, size string, required bool) *Package {
	p := &Package{Hash: hash, Name: name, Size: size, Required: required}
	m.Packages.Packages = append(m.Packages.Packages, *p)
	return p
}

type Actions struct {
	XMLName xml.Name  `xml:"actions" datastore:"-"`
	Actions []*Action `xml:"action"`
}

type Action struct {
	XMLName xml.Name `xml:"action" datastore:"-"`
	Event   string   `xml:"event,attr"`

	// Extensions added by update_engine
	ChromeOSVersion       string `xml:"ChromeOSVersion,attr"`
	Sha256                string `xml:"sha256,attr"`
	NeedsAdmin            bool   `xml:"needsadmin,attr"`
	IsDelta               bool   `xml:"IsDelta,attr"`
	DisablePayloadBackoff bool   `xml:"DisablePayloadBackoff,attr,omitempty"`
	MetadataSignatureRsa  string `xml:"MetadataSignatureRsa,attr,omitempty"`
	MetadataSize          string `xml:"MetadataSize,attr,omitempty"`
	Deadline              string `xml:"deadline,attr,omitempty"`
}

func (m *Manifest) AddAction(event string) *Action {
	a := &Action{Event: event}
	m.Actions.Actions = append(m.Actions.Actions, a)
	return a
}

var EventTypes = map[int]string{
	0:   "unknown",
	1:   "download complete",
	2:   "install complete",
	3:   "update complete",
	4:   "uninstall",
	5:   "download started",
	6:   "install started",
	9:   "new application install started",
	10:  "setup started",
	11:  "setup finished",
	12:  "update application started",
	13:  "update download started",
	14:  "update download finished",
	15:  "update installer started",
	16:  "setup update begin",
	17:  "setup update complete",
	20:  "register product complete",
	30:  "OEM install first check",
	40:  "app-specific command started",
	41:  "app-specific command ended",
	100: "setup failure",
	102: "COM server failure",
	103: "setup update failure",
}

var EventResults = map[int]string{
	0:  "error",
	1:  "success",
	2:  "success reboot",
	3:  "success restart browser",
	4:  "cancelled",
	5:  "error installer MSI",
	6:  "error installer other",
	7:  "noupdate",
	8:  "error installer system",
	9:  "update deferred",
	10: "handoff error",
}
<|endoftext|>


<commit_before>package goose

import (
	"code.google.com/p/go.net/html"
	"github.com/PuerkitoBio/goquery"
)

type parser struct{}

func NewParser() *parser {
	return &parser{}
}

func (this *parser) dropTag(selection *goquery.Selection) {
	selection.Each(func(i int, s *goquery.Selection) {
		node := s.Get(0)
		node.Data = s.Text()
		node.Type = html.TextNode
	})
}

func (this *parser) indexOfAttribute(selection *goquery.Selection, attr string) int {
	node := selection.Get(0)
	for i, a := range node.Attr {
		if a.Key == attr {
			return i
		}
	}
	return -1
}

func (this *parser) delAttr(selection *goquery.Selection, attr string) {
	idx := this.indexOfAttribute(selection, attr)
	if idx > -1 {
		node := selection.Get(0)
		node.Attr = append(node.Attr[:idx], node.Attr[idx+1:]...)
	}
}

func (this *parser) getElementsByTags(div *goquery.Selection, tags []string) *goquery.Selection {
	selection := new(goquery.Selection)
	for _, tag := range tags {
		selections := div.Find(tag)
		if selections != nil {
			selection = selection.Union(selections)
		}
	}
	return selection
}

func (this *parser) clear(selection *goquery.Selection) {
	selection.Nodes = make([]*html.Node, 0)
}

func (this *parser) removeNode(selection *goquery.Selection) {
	if selection != nil {
		node := selection.Get(0)
		if node != nil && node.Parent != nil {
			node.Parent.RemoveChild(node)
		}
	}
}

func (this *parser) name(selector string, selection *goquery.Selection) string {
	value, exists := selection.Attr(selector)
	if exists {
		return value
	}
	return ""
}

func (this *parser) setAttr(selection *goquery.Selection, attr string, value string) {
	node := selection.Get(0)

	for _, a := range node.Attr {
		if a.Key == attr {
			a.Val = value
			return
		}
	}
	attrs := make([]html.Attribute, len(node.Attr)+1)
	for i, a := range node.Attr {
		attrs[i+1] = a
	}
	newAttr := new(html.Attribute)
	newAttr.Key = attr
	newAttr.Val = value
	attrs[0] = *newAttr
	node.Attr = attrs
}
<commit_msg>Fixed setAttr<commit_after>package goose

import (
	"code.google.com/p/go.net/html"
	"github.com/PuerkitoBio/goquery"
)

type parser struct{}

func NewParser() *parser {
	return &parser{}
}

func (this *parser) dropTag(selection *goquery.Selection) {
	selection.Each(func(i int, s *goquery.Selection) {
		node := s.Get(0)
		node.Data = s.Text()
		node.Type = html.TextNode
	})
}

func (this *parser) indexOfAttribute(selection *goquery.Selection, attr string) int {
	node := selection.Get(0)
	for i, a := range node.Attr {
		if a.Key == attr {
			return i
		}
	}
	return -1
}

func (this *parser) delAttr(selection *goquery.Selection, attr string) {
	idx := this.indexOfAttribute(selection, attr)
	if idx > -1 {
		node := selection.Get(0)
		node.Attr = append(node.Attr[:idx], node.Attr[idx+1:]...)
	}
}

func (this *parser) getElementsByTags(div *goquery.Selection, tags []string) *goquery.Selection {
	selection := new(goquery.Selection)
	for _, tag := range tags {
		selections := div.Find(tag)
		if selections != nil {
			selection = selection.Union(selections)
		}
	}
	return selection
}

func (this *parser) clear(selection *goquery.Selection) {
	selection.Nodes = make([]*html.Node, 0)
}

func (this *parser) removeNode(selection *goquery.Selection) {
	if selection != nil {
		node := selection.Get(0)
		if node != nil && node.Parent != nil {
			node.Parent.RemoveChild(node)
		}
	}
}

func (this *parser) name(selector string, selection *goquery.Selection) string {
	value, exists := selection.Attr(selector)
	if exists {
		return value
	}
	return ""
}

func (this *parser) setAttr(selection *goquery.Selection, attr string, value string) {
	node := selection.Get(0)
	attrs := make([]html.Attribute, 0)
	for _, a := range node.Attr {
		if a.Key != attr {
			newAttr := new(html.Attribute)
			newAttr.Key = a.Key
			newAttr.Val = a.Val
			attrs = append(attrs, *newAttr)
		}
	}
	newAttr := new(html.Attribute)
	newAttr.Key = attr
	newAttr.Val = value
	attrs = append(attrs, *newAttr)
	node.Attr = attrs
}
<|endoftext|>


<commit_before>// Copyright 2011 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 http_test

import (
	"bytes"
	"io"
	"io/ioutil"
	"log"
	. "net/http"
	"net/http/httptest"
	"strconv"
	"testing"
)

var sniffTests = []struct {
	desc        string
	data        []byte
	contentType string
}{
	// Some nonsense.
	{"Empty", []byte{}, "text/plain; charset=utf-8"},
	{"Binary", []byte{1, 2, 3}, "application/octet-stream"},

	{"HTML document #1", []byte(`<HtMl><bOdY>blah blah blah</body></html>`), "text/html; charset=utf-8"},
	{"HTML document #2", []byte(`<HTML></HTML>`), "text/html; charset=utf-8"},
	{"HTML document #3 (leading whitespace)", []byte(`   <!DOCTYPE HTML>...`), "text/html; charset=utf-8"},
	{"HTML document #4 (leading CRLF)", []byte("\r\n<html>..."), "text/html; charset=utf-8"},

	{"Plain text", []byte(`This is not HTML. It has ☃ though.`), "text/plain; charset=utf-8"},

	{"XML", []byte("\n<?xml!"), "text/xml; charset=utf-8"},

	// Image types.
	{"GIF 87a", []byte(`GIF87a`), "image/gif"},
	{"GIF 89a", []byte(`GIF89a...`), "image/gif"},

	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
	//{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
	//{"MP4 audio", []byte("\x00\x00\x00\x20ftypM4A \x00\x00\x00\x00M4A mp42isom\x00\x00\x00\x00"), "audio/mp4"},
}

func TestDetectContentType(t *testing.T) {
	for _, tt := range sniffTests {
		ct := DetectContentType(tt.data)
		if ct != tt.contentType {
			t.Errorf("%v: DetectContentType = %q, want %q", tt.desc, ct, tt.contentType)
		}
	}
}

func TestServerContentType(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		i, _ := strconv.Atoi(r.FormValue("i"))
		tt := sniffTests[i]
		n, err := w.Write(tt.data)
		if n != len(tt.data) || err != nil {
			log.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt.desc, tt.data, n, err, len(tt.data))
		}
	}))
	defer ts.Close()

	for i, tt := range sniffTests {
		resp, err := Get(ts.URL + "/?i=" + strconv.Itoa(i))
		if err != nil {
			t.Errorf("%v: %v", tt.desc, err)
			continue
		}
		if ct := resp.Header.Get("Content-Type"); ct != tt.contentType {
			t.Errorf("%v: Content-Type = %q, want %q", tt.desc, ct, tt.contentType)
		}
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			t.Errorf("%v: reading body: %v", tt.desc, err)
		} else if !bytes.Equal(data, tt.data) {
			t.Errorf("%v: data is %q, want %q", tt.desc, data, tt.data)
		}
		resp.Body.Close()
	}
}

func TestContentTypeWithCopy(t *testing.T) {
	const (
		input    = "\n<html>\n\t<head>\n"
		expected = "text/html; charset=utf-8"
	)

	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		// Use io.Copy from a bytes.Buffer to trigger ReadFrom.
		buf := bytes.NewBuffer([]byte(input))
		n, err := io.Copy(w, buf)
		if int(n) != len(input) || err != nil {
			t.Fatalf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
		}
	}))
	defer ts.Close()

	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if ct := resp.Header.Get("Content-Type"); ct != expected {
		t.Errorf("Content-Type = %q, want %q", ct, expected)
	}
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Errorf("reading body: %v", err)
	} else if !bytes.Equal(data, []byte(input)) {
		t.Errorf("data is %q, want %q", data, input)
	}
	resp.Body.Close()
}
<commit_msg>net/http: use t.Errorf from alternate goroutine in test.<commit_after>// Copyright 2011 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 http_test

import (
	"bytes"
	"io"
	"io/ioutil"
	"log"
	. "net/http"
	"net/http/httptest"
	"strconv"
	"testing"
)

var sniffTests = []struct {
	desc        string
	data        []byte
	contentType string
}{
	// Some nonsense.
	{"Empty", []byte{}, "text/plain; charset=utf-8"},
	{"Binary", []byte{1, 2, 3}, "application/octet-stream"},

	{"HTML document #1", []byte(`<HtMl><bOdY>blah blah blah</body></html>`), "text/html; charset=utf-8"},
	{"HTML document #2", []byte(`<HTML></HTML>`), "text/html; charset=utf-8"},
	{"HTML document #3 (leading whitespace)", []byte(`   <!DOCTYPE HTML>...`), "text/html; charset=utf-8"},
	{"HTML document #4 (leading CRLF)", []byte("\r\n<html>..."), "text/html; charset=utf-8"},

	{"Plain text", []byte(`This is not HTML. It has ☃ though.`), "text/plain; charset=utf-8"},

	{"XML", []byte("\n<?xml!"), "text/xml; charset=utf-8"},

	// Image types.
	{"GIF 87a", []byte(`GIF87a`), "image/gif"},
	{"GIF 89a", []byte(`GIF89a...`), "image/gif"},

	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
	//{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
	//{"MP4 audio", []byte("\x00\x00\x00\x20ftypM4A \x00\x00\x00\x00M4A mp42isom\x00\x00\x00\x00"), "audio/mp4"},
}

func TestDetectContentType(t *testing.T) {
	for _, tt := range sniffTests {
		ct := DetectContentType(tt.data)
		if ct != tt.contentType {
			t.Errorf("%v: DetectContentType = %q, want %q", tt.desc, ct, tt.contentType)
		}
	}
}

func TestServerContentType(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		i, _ := strconv.Atoi(r.FormValue("i"))
		tt := sniffTests[i]
		n, err := w.Write(tt.data)
		if n != len(tt.data) || err != nil {
			log.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt.desc, tt.data, n, err, len(tt.data))
		}
	}))
	defer ts.Close()

	for i, tt := range sniffTests {
		resp, err := Get(ts.URL + "/?i=" + strconv.Itoa(i))
		if err != nil {
			t.Errorf("%v: %v", tt.desc, err)
			continue
		}
		if ct := resp.Header.Get("Content-Type"); ct != tt.contentType {
			t.Errorf("%v: Content-Type = %q, want %q", tt.desc, ct, tt.contentType)
		}
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			t.Errorf("%v: reading body: %v", tt.desc, err)
		} else if !bytes.Equal(data, tt.data) {
			t.Errorf("%v: data is %q, want %q", tt.desc, data, tt.data)
		}
		resp.Body.Close()
	}
}

func TestContentTypeWithCopy(t *testing.T) {
	const (
		input    = "\n<html>\n\t<head>\n"
		expected = "text/html; charset=utf-8"
	)

	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		// Use io.Copy from a bytes.Buffer to trigger ReadFrom.
		buf := bytes.NewBuffer([]byte(input))
		n, err := io.Copy(w, buf)
		if int(n) != len(input) || err != nil {
			t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
		}
	}))
	defer ts.Close()

	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if ct := resp.Header.Get("Content-Type"); ct != expected {
		t.Errorf("Content-Type = %q, want %q", ct, expected)
	}
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Errorf("reading body: %v", err)
	} else if !bytes.Equal(data, []byte(input)) {
		t.Errorf("data is %q, want %q", data, input)
	}
	resp.Body.Close()
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package client

import (
	"bytes"
	"text/template"

	"github.com/Masterminds/sprig"
	"github.com/kubernetes/helm/pkg/format"
	"github.com/kubernetes/helm/pkg/kubectl"
)

// Installer is capable of installing DM into Kubernetes.
//
// See InstallYAML.
type Installer struct {
	// TODO: At some point we could transform these from maps to structs.

	// Expandybird params are used to render the expandybird manifest.
	Expandybird map[string]interface{}
	// Resourcifier params are used to render the resourcifier manifest.
	Resourcifier map[string]interface{}
	// Manager params are used to render the manager manifest.
	Manager map[string]interface{}
}

// NewInstaller creates a new Installer.
func NewInstaller() *Installer {
	return &Installer{
		Expandybird:  map[string]interface{}{},
		Resourcifier: map[string]interface{}{},
		Manager:      map[string]interface{}{},
	}
}

// Install uses kubectl to install the base DM.
//
// Returns the string output received from the operation, and an error if the
// command failed.
func (i *Installer) Install(runner kubectl.Runner) (string, error) {
	b, err := i.expand()
	if err != nil {
		return "", err
	}

	o, err := runner.Create(b)
	return string(o), err
}

func (i *Installer) expand() ([]byte, error) {
	var b bytes.Buffer
	t := template.Must(template.New("manifest").Funcs(sprig.TxtFuncMap()).Parse(InstallYAML))
	err := t.Execute(&b, i)
	return b.Bytes(), err
}

// IsInstalled checks whether DM has been installed.
func IsInstalled(runner kubectl.Runner) bool {
	// Basically, we test "all-or-nothing" here: if this returns without error
	// we know that we have both the namespace and the manager API server.
	out, err := runner.GetByKind("rc", "manager-rc", "helm")
	if err != nil {
		format.Err("Installation not found: %s %s", out, err)
		return false
	}
	return true
}

// InstallYAML is the installation YAML for DM.
const InstallYAML = `
######################################################################
# Copyright 2015 The Kubernetes Authors All rights reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
######################################################################

---
apiVersion: v1
kind: Namespace
metadata:
  labels:
    app: helm
    name: helm-namespace
  name: helm
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: helm
    name: expandybird-service
  name: expandybird-service
  namespace: helm
spec:
  ports:
  - name: expandybird
    port: 8081
    targetPort: 8080
  selector:
    app: helm
    name: expandybird
---
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    app: helm
    name: expandybird-rc
  name: expandybird-rc
  namespace: helm
spec:
  replicas: 2
  selector:
    app: helm
    name: expandybird
  template:
    metadata:
      labels:
        app: helm
        name: expandybird
    spec:
      containers:
      - env: []
        image: {{default "gcr.io/kubernetes-helm/expandybird:v1.2.1" .Expandybird.Image}}
        name: expandybird
        ports:
        - containerPort: 8080
          name: expandybird
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: helm
    name: resourcifier-service
  name: resourcifier-service
  namespace: helm
spec:
  ports:
  - name: resourcifier
    port: 8082
    targetPort: 8080
  selector:
    app: helm
    name: resourcifier
---
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    app: helm
    name: resourcifier-rc
  name: resourcifier-rc
  namespace: helm
spec:
  replicas: 2
  selector:
    app: helm
    name: resourcifier
  template:
    metadata:
      labels:
        app: helm
        name: resourcifier
    spec:
      containers:
      - env: []
        image: {{ default "gcr.io/kubernetes-helm/resourcifier:v1.2.1" .Resourcifier.Image }}
        name: resourcifier
        ports:
        - containerPort: 8080
          name: resourcifier
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: helm
    name: manager-service
  name: manager-service
  namespace: helm
spec:
  ports:
  - name: manager
    port: 8080
    targetPort: 8080
  selector:
    app: helm
    name: manager
---
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    app: helm
    name: manager-rc
  name: manager-rc
  namespace: helm
spec:
  replicas: 1
  selector:
    app: helm
    name: manager
  template:
    metadata:
      labels:
        app: helm
        name: manager
    spec:
      containers:
      - env: []
        image: {{ default "gcr.io/kubernetes-helm/manager:v1.2.1" .Manager.Image }}
        name: manager
        ports:
        - containerPort: 8080
          name: manager
`
<commit_msg>Change server image default tag from v1.2.1 to latest<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package client

import (
	"bytes"
	"text/template"

	"github.com/Masterminds/sprig"
	"github.com/kubernetes/helm/pkg/format"
	"github.com/kubernetes/helm/pkg/kubectl"
)

// Installer is capable of installing DM into Kubernetes.
//
// See InstallYAML.
type Installer struct {
	// TODO: At some point we could transform these from maps to structs.

	// Expandybird params are used to render the expandybird manifest.
	Expandybird map[string]interface{}
	// Resourcifier params are used to render the resourcifier manifest.
	Resourcifier map[string]interface{}
	// Manager params are used to render the manager manifest.
	Manager map[string]interface{}
}

// NewInstaller creates a new Installer.
func NewInstaller() *Installer {
	return &Installer{
		Expandybird:  map[string]interface{}{},
		Resourcifier: map[string]interface{}{},
		Manager:      map[string]interface{}{},
	}
}

// Install uses kubectl to install the base DM.
//
// Returns the string output received from the operation, and an error if the
// command failed.
func (i *Installer) Install(runner kubectl.Runner) (string, error) {
	b, err := i.expand()
	if err != nil {
		return "", err
	}

	o, err := runner.Create(b)
	return string(o), err
}

func (i *Installer) expand() ([]byte, error) {
	var b bytes.Buffer
	t := template.Must(template.New("manifest").Funcs(sprig.TxtFuncMap()).Parse(InstallYAML))
	err := t.Execute(&b, i)
	return b.Bytes(), err
}

// IsInstalled checks whether DM has been installed.
func IsInstalled(runner kubectl.Runner) bool {
	// Basically, we test "all-or-nothing" here: if this returns without error
	// we know that we have both the namespace and the manager API server.
	out, err := runner.GetByKind("rc", "manager-rc", "helm")
	if err != nil {
		format.Err("Installation not found: %s %s", out, err)
		return false
	}
	return true
}

// InstallYAML is the installation YAML for DM.
const InstallYAML = `
######################################################################
# Copyright 2015 The Kubernetes Authors All rights reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
######################################################################

---
apiVersion: v1
kind: Namespace
metadata:
  labels:
    app: helm
    name: helm-namespace
  name: helm
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: helm
    name: expandybird-service
  name: expandybird-service
  namespace: helm
spec:
  ports:
  - name: expandybird
    port: 8081
    targetPort: 8080
  selector:
    app: helm
    name: expandybird
---
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    app: helm
    name: expandybird-rc
  name: expandybird-rc
  namespace: helm
spec:
  replicas: 2
  selector:
    app: helm
    name: expandybird
  template:
    metadata:
      labels:
        app: helm
        name: expandybird
    spec:
      containers:
      - env: []
        image: {{default "gcr.io/kubernetes-helm/expandybird:latest" .Expandybird.Image}}
        name: expandybird
        ports:
        - containerPort: 8080
          name: expandybird
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: helm
    name: resourcifier-service
  name: resourcifier-service
  namespace: helm
spec:
  ports:
  - name: resourcifier
    port: 8082
    targetPort: 8080
  selector:
    app: helm
    name: resourcifier
---
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    app: helm
    name: resourcifier-rc
  name: resourcifier-rc
  namespace: helm
spec:
  replicas: 2
  selector:
    app: helm
    name: resourcifier
  template:
    metadata:
      labels:
        app: helm
        name: resourcifier
    spec:
      containers:
      - env: []
        image: {{ default "gcr.io/kubernetes-helm/resourcifier:latest" .Resourcifier.Image }}
        name: resourcifier
        ports:
        - containerPort: 8080
          name: resourcifier
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: helm
    name: manager-service
  name: manager-service
  namespace: helm
spec:
  ports:
  - name: manager
    port: 8080
    targetPort: 8080
  selector:
    app: helm
    name: manager
---
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    app: helm
    name: manager-rc
  name: manager-rc
  namespace: helm
spec:
  replicas: 1
  selector:
    app: helm
    name: manager
  template:
    metadata:
      labels:
        app: helm
        name: manager
    spec:
      containers:
      - env: []
        image: {{ default "gcr.io/kubernetes-helm/manager:latest" .Manager.Image }}
        name: manager
        ports:
        - containerPort: 8080
          name: manager
`
<|endoftext|>


<commit_before>/*

	boardgame-util is a comprehensive CLI tool to help administer projects
	built with boardgame. All of its substantive functionality is implemented
	in sub-libraries in lib/, which can be used directly if necessary.

	The canonical help documentation is provided by `boardgame-util help`.

*/
package main

import (
	"os"
	"strings"
)

func main() {
	mainImpl(os.Args)
}

func mainImpl(args []string) {
	b := &BoardgameUtil{}

	setupParents(b, nil, nil)

	defer b.Cleanup()

	cmd := b.WritCommand()

	path, positional, err := cmd.Decode(args[1:])

	if err != nil {
		path.Last().ExitHelp(err)
	}

	subcommandObj := selectSubcommandObject(b, strings.Split(path.String(), " "))

	if subcommandObj == nil {
		panic("BUG: one of the subcommands didn't enumerate all subcommands")
	}

	subcommandObj.Run(path, positional)

}
<commit_msg>BoardgameUtil.Cleanup is called now when program is canceled via sigterm, so when you Ctrl-C the serve command it deletes the temp dir. Part of #655.<commit_after>/*

	boardgame-util is a comprehensive CLI tool to help administer projects
	built with boardgame. All of its substantive functionality is implemented
	in sub-libraries in lib/, which can be used directly if necessary.

	The canonical help documentation is provided by `boardgame-util help`.

*/
package main

import (
	"os"
	"os/signal"
	"strings"
	"syscall"
)

func main() {
	mainImpl(os.Args)
}

func mainImpl(args []string) {
	b := &BoardgameUtil{}

	setupParents(b, nil, nil)

	defer b.Cleanup()

	//Make sure that even if we get exited early we still clean up.
	c := make(chan os.Signal, 1)

	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)

	go func() {
		<-c
		b.Cleanup()
		os.Exit(1)
	}()

	cmd := b.WritCommand()

	path, positional, err := cmd.Decode(args[1:])

	if err != nil {
		path.Last().ExitHelp(err)
	}

	subcommandObj := selectSubcommandObject(b, strings.Split(path.String(), " "))

	if subcommandObj == nil {
		panic("BUG: one of the subcommands didn't enumerate all subcommands")
	}

	subcommandObj.Run(path, positional)

}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package generators

import (
	"fmt"
	"io"
	"path/filepath"
	"strings"

	"k8s.io/gengo/args"
	"k8s.io/gengo/generator"
	"k8s.io/gengo/namer"
	"k8s.io/gengo/types"

	"k8s.io/code-generator/cmd/client-gen/generators/util"
	clientgentypes "k8s.io/code-generator/cmd/client-gen/types"

	"github.com/golang/glog"
)

// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
	pluralExceptions := map[string]string{
		"Endpoints": "Endpoints",
	}
	return namer.NameSystems{
		"public":             namer.NewPublicNamer(0),
		"private":            namer.NewPrivateNamer(0),
		"raw":                namer.NewRawNamer("", nil),
		"publicPlural":       namer.NewPublicPluralNamer(pluralExceptions),
		"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
		"lowercaseSingular":  &lowercaseSingularNamer{},
	}
}

// lowercaseSingularNamer implements Namer
type lowercaseSingularNamer struct{}

// Name returns t's name in all lowercase.
func (n *lowercaseSingularNamer) Name(t *types.Type) string {
	return strings.ToLower(t.Name.Name)
}

// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
	return "public"
}

// generatedBy returns information about the arguments used to invoke
// lister-gen.
func generatedBy() string {
	return fmt.Sprintf("\n// This file was automatically generated by lister-gen\n\n")
}

// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
	boilerplate, err := arguments.LoadGoBoilerplate()
	if err != nil {
		glog.Fatalf("Failed loading boilerplate: %v", err)
	}

	boilerplate = append(boilerplate, []byte(generatedBy())...)

	var packageList generator.Packages
	for _, inputDir := range arguments.InputDirs {
		p := context.Universe.Package(inputDir)

		objectMeta, internal, err := objectMetaForPackage(p)
		if err != nil {
			glog.Fatal(err)
		}
		if objectMeta == nil {
			// no types in this package had genclient
			continue
		}

		var gv clientgentypes.GroupVersion
		var internalGVPkg string

		if internal {
			lastSlash := strings.LastIndex(p.Path, "/")
			if lastSlash == -1 {
				glog.Fatalf("error constructing internal group version for package %q", p.Path)
			}
			gv.Group = clientgentypes.Group(p.Path[lastSlash+1:])
			internalGVPkg = p.Path
		} else {
			parts := strings.Split(p.Path, "/")
			gv.Group = clientgentypes.Group(parts[len(parts)-2])
			gv.Version = clientgentypes.Version(parts[len(parts)-1])

			internalGVPkg = strings.Join(parts[0:len(parts)-1], "/")
		}

		// If there's a comment of the form "// +groupName=somegroup" or
		// "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the
		// group when generating.
		if override := types.ExtractCommentTags("+", p.DocComments)["groupName"]; override != nil {
			gv.Group = clientgentypes.Group(strings.SplitN(override[0], ".", 2)[0])
		}

		var typesToGenerate []*types.Type
		for _, t := range p.Types {
			tags := util.MustParseClientGenTags(t.SecondClosestCommentLines)
			if !tags.GenerateClient || !tags.HasVerb("list") || !tags.HasVerb("get") {
				continue
			}
			typesToGenerate = append(typesToGenerate, t)
		}
		if len(typesToGenerate) == 0 {
			continue
		}
		orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
		typesToGenerate = orderer.OrderTypes(typesToGenerate)

		packagePath := filepath.Join(arguments.OutputPackagePath, strings.ToLower(gv.Group.NonEmpty()), strings.ToLower(gv.Version.NonEmpty()))
		packageList = append(packageList, &generator.DefaultPackage{
			PackageName: strings.ToLower(gv.Version.NonEmpty()),
			PackagePath: packagePath,
			HeaderText:  boilerplate,
			GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
				generators = append(generators, &expansionGenerator{
					DefaultGen: generator.DefaultGen{
						OptionalName: "expansion_generated",
					},
					packagePath: filepath.Join(arguments.OutputBase, packagePath),
					types:       typesToGenerate,
				})

				for _, t := range typesToGenerate {
					generators = append(generators, &listerGenerator{
						DefaultGen: generator.DefaultGen{
							OptionalName: strings.ToLower(t.Name.Name),
						},
						outputPackage:  arguments.OutputPackagePath,
						groupVersion:   gv,
						internalGVPkg:  internalGVPkg,
						typeToGenerate: t,
						imports:        generator.NewImportTracker(),
						objectMeta:     objectMeta,
					})
				}
				return generators
			},
			FilterFunc: func(c *generator.Context, t *types.Type) bool {
				tags := util.MustParseClientGenTags(t.SecondClosestCommentLines)
				return tags.GenerateClient && tags.HasVerb("list") && tags.HasVerb("get")
			},
		})
	}

	return packageList
}

// objectMetaForPackage returns the type of ObjectMeta used by package p.
func objectMetaForPackage(p *types.Package) (*types.Type, bool, error) {
	generatingForPackage := false
	for _, t := range p.Types {
		// filter out types which dont have genclient.
		if !util.MustParseClientGenTags(t.SecondClosestCommentLines).GenerateClient {
			continue
		}
		generatingForPackage = true
		for _, member := range t.Members {
			if member.Name == "ObjectMeta" {
				return member.Type, isInternal(member), nil
			}
		}
	}
	if generatingForPackage {
		return nil, false, fmt.Errorf("unable to find ObjectMeta for any types in package %s", p.Path)
	}
	return nil, false, nil
}

// isInternal returns true if the tags for a member do not contain a json tag
func isInternal(m types.Member) bool {
	return !strings.Contains(m.Tags, "json")
}

// listerGenerator produces a file of listers for a given GroupVersion and
// type.
type listerGenerator struct {
	generator.DefaultGen
	outputPackage  string
	groupVersion   clientgentypes.GroupVersion
	internalGVPkg  string
	typeToGenerate *types.Type
	imports        namer.ImportTracker
	objectMeta     *types.Type
}

var _ generator.Generator = &listerGenerator{}

func (g *listerGenerator) Filter(c *generator.Context, t *types.Type) bool {
	return t == g.typeToGenerate
}

func (g *listerGenerator) Namers(c *generator.Context) namer.NameSystems {
	return namer.NameSystems{
		"raw": namer.NewRawNamer(g.outputPackage, g.imports),
	}
}

func (g *listerGenerator) Imports(c *generator.Context) (imports []string) {
	imports = append(imports, g.imports.ImportLines()...)
	imports = append(imports, "k8s.io/apimachinery/pkg/api/errors")
	imports = append(imports, "k8s.io/apimachinery/pkg/labels")
	// for Indexer
	imports = append(imports, "k8s.io/client-go/tools/cache")
	return
}

func (g *listerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
	sw := generator.NewSnippetWriter(w, c, "$", "$")

	glog.V(5).Infof("processing type %v", t)
	m := map[string]interface{}{
		"Resource":   c.Universe.Function(types.Name{Package: t.Name.Package, Name: "Resource"}),
		"type":       t,
		"objectMeta": g.objectMeta,
	}

	tags, err := util.ParseClientGenTags(t.SecondClosestCommentLines)
	if err != nil {
		return err
	}

	if tags.NonNamespaced {
		sw.Do(typeListerInterface_NonNamespaced, m)
	} else {
		sw.Do(typeListerInterface, m)
	}

	sw.Do(typeListerStruct, m)
	sw.Do(typeListerConstructor, m)
	sw.Do(typeLister_List, m)

	if tags.NonNamespaced {
		sw.Do(typeLister_NonNamespacedGet, m)
		return sw.Error()
	}

	sw.Do(typeLister_NamespaceLister, m)
	sw.Do(namespaceListerInterface, m)
	sw.Do(namespaceListerStruct, m)
	sw.Do(namespaceLister_List, m)
	sw.Do(namespaceLister_Get, m)

	return sw.Error()
}

var typeListerInterface = `
// $.type|public$Lister helps list $.type|publicPlural$.
type $.type|public$Lister interface {
	// List lists all $.type|publicPlural$ in the indexer.
	List(selector labels.Selector) (ret []*$.type|raw$, err error)
	// $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$.
	$.type|publicPlural$(namespace string) $.type|public$NamespaceLister
	$.type|public$ListerExpansion
}
`

var typeListerInterface_NonNamespaced = `
// $.type|public$Lister helps list $.type|publicPlural$.
type $.type|public$Lister interface {
	// List lists all $.type|publicPlural$ in the indexer.
	List(selector labels.Selector) (ret []*$.type|raw$, err error)
	// Get retrieves the $.type|public$ from the index for a given name.
	Get(name string) (*$.type|raw$, error)
	$.type|public$ListerExpansion
}
`

var typeListerStruct = `
// $.type|private$Lister implements the $.type|public$Lister interface.
type $.type|private$Lister struct {
	indexer cache.Indexer
}
`

var typeListerConstructor = `
// New$.type|public$Lister returns a new $.type|public$Lister.
func New$.type|public$Lister(indexer cache.Indexer) $.type|public$Lister {
	return &$.type|private$Lister{indexer: indexer}
}
`

var typeLister_List = `
// List lists all $.type|publicPlural$ in the indexer.
func (s *$.type|private$Lister) List(selector labels.Selector) (ret []*$.type|raw$, err error) {
	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
		ret = append(ret, m.(*$.type|raw$))
	})
	return ret, err
}
`

var typeLister_NamespaceLister = `
// $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$.
func (s *$.type|private$Lister) $.type|publicPlural$(namespace string) $.type|public$NamespaceLister {
	return $.type|private$NamespaceLister{indexer: s.indexer, namespace: namespace}
}
`

var typeLister_NonNamespacedGet = `
// Get retrieves the $.type|public$ from the index for a given name.
func (s *$.type|private$Lister) Get(name string) (*$.type|raw$, error) {
  key := &$.type|raw${ObjectMeta: $.objectMeta|raw${Name: name}}
  obj, exists, err := s.indexer.Get(key)
  if err != nil {
    return nil, err
  }
  if !exists {
    return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
  }
  return obj.(*$.type|raw$), nil
}
`

var namespaceListerInterface = `
// $.type|public$NamespaceLister helps list and get $.type|publicPlural$.
type $.type|public$NamespaceLister interface {
	// List lists all $.type|publicPlural$ in the indexer for a given namespace.
	List(selector labels.Selector) (ret []*$.type|raw$, err error)
	// Get retrieves the $.type|public$ from the indexer for a given namespace and name.
	Get(name string) (*$.type|raw$, error)
	$.type|public$NamespaceListerExpansion
}
`

var namespaceListerStruct = `
// $.type|private$NamespaceLister implements the $.type|public$NamespaceLister
// interface.
type $.type|private$NamespaceLister struct {
	indexer cache.Indexer
	namespace string
}
`

var namespaceLister_List = `
// List lists all $.type|publicPlural$ in the indexer for a given namespace.
func (s $.type|private$NamespaceLister) List(selector labels.Selector) (ret []*$.type|raw$, err error) {
	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
		ret = append(ret, m.(*$.type|raw$))
	})
	return ret, err
}
`

var namespaceLister_Get = `
// Get retrieves the $.type|public$ from the indexer for a given namespace and name.
func (s $.type|private$NamespaceLister) Get(name string) (*$.type|raw$, error) {
	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
	if err != nil {
		return nil, err
	}
	if !exists {
		return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
	}
	return obj.(*$.type|raw$), nil
}
`
<commit_msg>Use GetByKey() in typeLister_NonNamespacedGet<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package generators

import (
	"fmt"
	"io"
	"path/filepath"
	"strings"

	"k8s.io/gengo/args"
	"k8s.io/gengo/generator"
	"k8s.io/gengo/namer"
	"k8s.io/gengo/types"

	"k8s.io/code-generator/cmd/client-gen/generators/util"
	clientgentypes "k8s.io/code-generator/cmd/client-gen/types"

	"github.com/golang/glog"
)

// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
	pluralExceptions := map[string]string{
		"Endpoints": "Endpoints",
	}
	return namer.NameSystems{
		"public":             namer.NewPublicNamer(0),
		"private":            namer.NewPrivateNamer(0),
		"raw":                namer.NewRawNamer("", nil),
		"publicPlural":       namer.NewPublicPluralNamer(pluralExceptions),
		"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
		"lowercaseSingular":  &lowercaseSingularNamer{},
	}
}

// lowercaseSingularNamer implements Namer
type lowercaseSingularNamer struct{}

// Name returns t's name in all lowercase.
func (n *lowercaseSingularNamer) Name(t *types.Type) string {
	return strings.ToLower(t.Name.Name)
}

// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
	return "public"
}

// generatedBy returns information about the arguments used to invoke
// lister-gen.
func generatedBy() string {
	return fmt.Sprintf("\n// This file was automatically generated by lister-gen\n\n")
}

// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
	boilerplate, err := arguments.LoadGoBoilerplate()
	if err != nil {
		glog.Fatalf("Failed loading boilerplate: %v", err)
	}

	boilerplate = append(boilerplate, []byte(generatedBy())...)

	var packageList generator.Packages
	for _, inputDir := range arguments.InputDirs {
		p := context.Universe.Package(inputDir)

		objectMeta, internal, err := objectMetaForPackage(p)
		if err != nil {
			glog.Fatal(err)
		}
		if objectMeta == nil {
			// no types in this package had genclient
			continue
		}

		var gv clientgentypes.GroupVersion
		var internalGVPkg string

		if internal {
			lastSlash := strings.LastIndex(p.Path, "/")
			if lastSlash == -1 {
				glog.Fatalf("error constructing internal group version for package %q", p.Path)
			}
			gv.Group = clientgentypes.Group(p.Path[lastSlash+1:])
			internalGVPkg = p.Path
		} else {
			parts := strings.Split(p.Path, "/")
			gv.Group = clientgentypes.Group(parts[len(parts)-2])
			gv.Version = clientgentypes.Version(parts[len(parts)-1])

			internalGVPkg = strings.Join(parts[0:len(parts)-1], "/")
		}

		// If there's a comment of the form "// +groupName=somegroup" or
		// "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the
		// group when generating.
		if override := types.ExtractCommentTags("+", p.DocComments)["groupName"]; override != nil {
			gv.Group = clientgentypes.Group(strings.SplitN(override[0], ".", 2)[0])
		}

		var typesToGenerate []*types.Type
		for _, t := range p.Types {
			tags := util.MustParseClientGenTags(t.SecondClosestCommentLines)
			if !tags.GenerateClient || !tags.HasVerb("list") || !tags.HasVerb("get") {
				continue
			}
			typesToGenerate = append(typesToGenerate, t)
		}
		if len(typesToGenerate) == 0 {
			continue
		}
		orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
		typesToGenerate = orderer.OrderTypes(typesToGenerate)

		packagePath := filepath.Join(arguments.OutputPackagePath, strings.ToLower(gv.Group.NonEmpty()), strings.ToLower(gv.Version.NonEmpty()))
		packageList = append(packageList, &generator.DefaultPackage{
			PackageName: strings.ToLower(gv.Version.NonEmpty()),
			PackagePath: packagePath,
			HeaderText:  boilerplate,
			GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
				generators = append(generators, &expansionGenerator{
					DefaultGen: generator.DefaultGen{
						OptionalName: "expansion_generated",
					},
					packagePath: filepath.Join(arguments.OutputBase, packagePath),
					types:       typesToGenerate,
				})

				for _, t := range typesToGenerate {
					generators = append(generators, &listerGenerator{
						DefaultGen: generator.DefaultGen{
							OptionalName: strings.ToLower(t.Name.Name),
						},
						outputPackage:  arguments.OutputPackagePath,
						groupVersion:   gv,
						internalGVPkg:  internalGVPkg,
						typeToGenerate: t,
						imports:        generator.NewImportTracker(),
						objectMeta:     objectMeta,
					})
				}
				return generators
			},
			FilterFunc: func(c *generator.Context, t *types.Type) bool {
				tags := util.MustParseClientGenTags(t.SecondClosestCommentLines)
				return tags.GenerateClient && tags.HasVerb("list") && tags.HasVerb("get")
			},
		})
	}

	return packageList
}

// objectMetaForPackage returns the type of ObjectMeta used by package p.
func objectMetaForPackage(p *types.Package) (*types.Type, bool, error) {
	generatingForPackage := false
	for _, t := range p.Types {
		// filter out types which dont have genclient.
		if !util.MustParseClientGenTags(t.SecondClosestCommentLines).GenerateClient {
			continue
		}
		generatingForPackage = true
		for _, member := range t.Members {
			if member.Name == "ObjectMeta" {
				return member.Type, isInternal(member), nil
			}
		}
	}
	if generatingForPackage {
		return nil, false, fmt.Errorf("unable to find ObjectMeta for any types in package %s", p.Path)
	}
	return nil, false, nil
}

// isInternal returns true if the tags for a member do not contain a json tag
func isInternal(m types.Member) bool {
	return !strings.Contains(m.Tags, "json")
}

// listerGenerator produces a file of listers for a given GroupVersion and
// type.
type listerGenerator struct {
	generator.DefaultGen
	outputPackage  string
	groupVersion   clientgentypes.GroupVersion
	internalGVPkg  string
	typeToGenerate *types.Type
	imports        namer.ImportTracker
	objectMeta     *types.Type
}

var _ generator.Generator = &listerGenerator{}

func (g *listerGenerator) Filter(c *generator.Context, t *types.Type) bool {
	return t == g.typeToGenerate
}

func (g *listerGenerator) Namers(c *generator.Context) namer.NameSystems {
	return namer.NameSystems{
		"raw": namer.NewRawNamer(g.outputPackage, g.imports),
	}
}

func (g *listerGenerator) Imports(c *generator.Context) (imports []string) {
	imports = append(imports, g.imports.ImportLines()...)
	imports = append(imports, "k8s.io/apimachinery/pkg/api/errors")
	imports = append(imports, "k8s.io/apimachinery/pkg/labels")
	// for Indexer
	imports = append(imports, "k8s.io/client-go/tools/cache")
	return
}

func (g *listerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
	sw := generator.NewSnippetWriter(w, c, "$", "$")

	glog.V(5).Infof("processing type %v", t)
	m := map[string]interface{}{
		"Resource":   c.Universe.Function(types.Name{Package: t.Name.Package, Name: "Resource"}),
		"type":       t,
		"objectMeta": g.objectMeta,
	}

	tags, err := util.ParseClientGenTags(t.SecondClosestCommentLines)
	if err != nil {
		return err
	}

	if tags.NonNamespaced {
		sw.Do(typeListerInterface_NonNamespaced, m)
	} else {
		sw.Do(typeListerInterface, m)
	}

	sw.Do(typeListerStruct, m)
	sw.Do(typeListerConstructor, m)
	sw.Do(typeLister_List, m)

	if tags.NonNamespaced {
		sw.Do(typeLister_NonNamespacedGet, m)
		return sw.Error()
	}

	sw.Do(typeLister_NamespaceLister, m)
	sw.Do(namespaceListerInterface, m)
	sw.Do(namespaceListerStruct, m)
	sw.Do(namespaceLister_List, m)
	sw.Do(namespaceLister_Get, m)

	return sw.Error()
}

var typeListerInterface = `
// $.type|public$Lister helps list $.type|publicPlural$.
type $.type|public$Lister interface {
	// List lists all $.type|publicPlural$ in the indexer.
	List(selector labels.Selector) (ret []*$.type|raw$, err error)
	// $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$.
	$.type|publicPlural$(namespace string) $.type|public$NamespaceLister
	$.type|public$ListerExpansion
}
`

var typeListerInterface_NonNamespaced = `
// $.type|public$Lister helps list $.type|publicPlural$.
type $.type|public$Lister interface {
	// List lists all $.type|publicPlural$ in the indexer.
	List(selector labels.Selector) (ret []*$.type|raw$, err error)
	// Get retrieves the $.type|public$ from the index for a given name.
	Get(name string) (*$.type|raw$, error)
	$.type|public$ListerExpansion
}
`

var typeListerStruct = `
// $.type|private$Lister implements the $.type|public$Lister interface.
type $.type|private$Lister struct {
	indexer cache.Indexer
}
`

var typeListerConstructor = `
// New$.type|public$Lister returns a new $.type|public$Lister.
func New$.type|public$Lister(indexer cache.Indexer) $.type|public$Lister {
	return &$.type|private$Lister{indexer: indexer}
}
`

var typeLister_List = `
// List lists all $.type|publicPlural$ in the indexer.
func (s *$.type|private$Lister) List(selector labels.Selector) (ret []*$.type|raw$, err error) {
	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
		ret = append(ret, m.(*$.type|raw$))
	})
	return ret, err
}
`

var typeLister_NamespaceLister = `
// $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$.
func (s *$.type|private$Lister) $.type|publicPlural$(namespace string) $.type|public$NamespaceLister {
	return $.type|private$NamespaceLister{indexer: s.indexer, namespace: namespace}
}
`

var typeLister_NonNamespacedGet = `
// Get retrieves the $.type|public$ from the index for a given name.
func (s *$.type|private$Lister) Get(name string) (*$.type|raw$, error) {
  obj, exists, err := s.indexer.GetByKey(name)
  if err != nil {
    return nil, err
  }
  if !exists {
    return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
  }
  return obj.(*$.type|raw$), nil
}
`

var namespaceListerInterface = `
// $.type|public$NamespaceLister helps list and get $.type|publicPlural$.
type $.type|public$NamespaceLister interface {
	// List lists all $.type|publicPlural$ in the indexer for a given namespace.
	List(selector labels.Selector) (ret []*$.type|raw$, err error)
	// Get retrieves the $.type|public$ from the indexer for a given namespace and name.
	Get(name string) (*$.type|raw$, error)
	$.type|public$NamespaceListerExpansion
}
`

var namespaceListerStruct = `
// $.type|private$NamespaceLister implements the $.type|public$NamespaceLister
// interface.
type $.type|private$NamespaceLister struct {
	indexer cache.Indexer
	namespace string
}
`

var namespaceLister_List = `
// List lists all $.type|publicPlural$ in the indexer for a given namespace.
func (s $.type|private$NamespaceLister) List(selector labels.Selector) (ret []*$.type|raw$, err error) {
	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
		ret = append(ret, m.(*$.type|raw$))
	})
	return ret, err
}
`

var namespaceLister_Get = `
// Get retrieves the $.type|public$ from the indexer for a given namespace and name.
func (s $.type|private$NamespaceLister) Get(name string) (*$.type|raw$, error) {
	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
	if err != nil {
		return nil, err
	}
	if !exists {
		return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
	}
	return obj.(*$.type|raw$), nil
}
`
<|endoftext|>


<commit_before>package jsonez

import (
	"errors"
	"fmt"
	"math"
	"strings"
	"unicode"
)

/*
 * JSON types
 */
const (
	JSON_BOOL = iota
	JSON_NULL
	JSON_INT
	JSON_DOUBLE
	JSON_STRING
	JSON_ARRAY
	JSON_OBJECT
)

var errorOffset int = -1

/*
 * GoJSON structure
 */
type GoJSON struct {
	/**
	 * Pointers to walk array/object chains
	 */
	next, prev *GoJSON

	/**
	 * Child item of the current object
	 */
	child *GoJSON

	/** JSON type */
	Jsontype int

	/**
	 * Valstr will be set when
	 *type is JSON_STRING
	 */
	Valstr string

	/**
	 * Valint will be set when type
	 * is JSON_INT
	 */
	Valint int

	/**
	 * valuenum will be set when
	 * type is JSON_DOUBLE
	 */
	Valdouble float64

	/**
	 * Valbool will be set when
	 * type is JSON_BOOL
	 */
	Valbool bool

	/**
	 * JSON Key
	 */
	Key string
}

/**
 * Functions related to parsing a JSON string
 */

/**
 * nextToken finds the next token
 */
func nextToken(input []byte) []byte {
	for i, c := range input {
		if unicode.IsSpace(rune(c)) || c == '\'' {
			continue
		} else {
			return input[i:]
		}
	}

	return []byte{}
}

/**
 * Function to parse a string
 */
func parseString(cur *GoJSON, input []byte) ([]byte, error) {
	var offset int

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if input[0] != '"' {
		errorStr := fmt.Sprintf("%s: Not a valid string in input %s", funcName(), string(input))
		return nil, errors.New(errorStr)
	}

	for i := range input {
		if i > 0 && input[i] == '"' {
			break
		} else {
			offset++
		}
	}

	cur.Jsontype = JSON_STRING
	cur.Valstr = strings.Trim(string(input[1:offset]), " ")

	return input[offset+1:], nil
}

/**
 * Function to parse a number
 */
func parseNumber(cur *GoJSON, input []byte) ([]byte, error) {
	var n, sign, scale float64
	var subscale, signsubscale, offset int
	var isDouble bool = false

	sign = 1
	subscale = 0
	signsubscale = 1

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if input[offset] == '-' {
		sign = -1
		offset++
	}

	if unicode.IsDigit(rune(input[offset])) == false {
		errorStr := fmt.Sprintf("%s: Not a valid number in input %s", funcName(), string(input))
		return nil, errors.New(errorStr)
	}

	for {
		if input[offset] == '0' {
			offset++
		} else {
			break
		}
	}

	for {
		if unicode.IsDigit(rune(input[offset])) == true {
			n = (n * 10.0) + float64(input[offset]-'0')
			offset++
		} else {
			break
		}
	}

	if input[offset] == '.' && unicode.IsDigit(rune(input[offset+1])) == true {
		offset++
		isDouble = true

		for {
			if unicode.IsDigit(rune(input[offset])) == true {
				n = (n * 10.0) + float64(input[offset]-'0')
				offset++
				scale--
			} else {
				break
			}
		}
	}

	if input[offset] == 'e' || input[offset] == 'E' {
		offset++
		isDouble = true

		if input[offset] == '-' {
			signsubscale = -1
		}
		offset++

		for {
			if unicode.IsDigit(rune(input[offset])) == true {
				subscale = (subscale * 10) + int(input[offset]-'0')
				offset++
			} else {
				break
			}
		}
	}

	n = sign * n * math.Pow(10.0, scale+float64(subscale)*float64(signsubscale))

	if isDouble == true {
		cur.Valdouble = n
		cur.Jsontype = JSON_DOUBLE
	} else {
		cur.Valint = int(n)
		cur.Jsontype = JSON_INT
	}

	return input[offset:], nil
}

/**
 * Function to parse an array
 */
func parseArray(cur *GoJSON, input []byte) ([]byte, error) {
	var child, sibling *GoJSON

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if input[0] != '[' {
		errorStr := fmt.Sprintf("%s: Not a valid array in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}

	cur.Jsontype = JSON_ARRAY
	input = nextToken(input[1:])

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Could not find any valid JSON", funcName())
		return []byte{}, errors.New(errorStr)
	}

	/*
	 * Check if the array is empty
	 */
	if input[0] == ']' {
		return input[1:], nil
	}

	/*
	 * Allocate memory for the child to
	 * continue processing
	 */
	cur.child = new(GoJSON)
	child = cur.child
	input, err := parseValue(child, nextToken(input))

	if err != nil {
		return []byte{}, err
	}

	input = nextToken(input)

	if len(input) == 0 {
		return []byte{}, nil
	}

	/*
	 * Continue processing the array and add the
	 * child entries to this parent GoJSON object
	 */
	for {
		if input[0] == ',' {
			sibling = new(GoJSON)
			child.next = sibling
			sibling.prev = child
			child = sibling

			input, err = parseValue(child, nextToken(input[1:]))

			if err != nil {
				return []byte{}, err
			}

			input = nextToken(input)

			if len(input) == 0 {
				return []byte{}, nil
			}
		} else {
			break
		}
	}

	if input[0] == ']' {
		return input[1:], nil
	} else {
		errorStr := fmt.Sprintf("%s: Incomplete/Malformed array in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}
}

/**
 * Function to parse an object
 */
func parseObject(cur *GoJSON, input []byte) ([]byte, error) {
	var child, sibling *GoJSON

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if input[0] != '{' {
		errorStr := fmt.Sprintf("%s: Not a valid object", funcName())
		return []byte{}, errors.New(errorStr)
	}

	cur.Jsontype = JSON_OBJECT
	input = nextToken(input[1:])

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Could not find any valid JSON in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}

	/*
	 * Check if the object is empty
	 */
	if input[0] == '}' {
		return input[1:], nil
	}

	/*
	 * Allocate memory for the child to
	 * continue processing
	 */
	cur.child = new(GoJSON)
	child = cur.child
	input, err := parseString(child, nextToken(input))

	if err != nil {
		return []byte{}, err
	}

	child.Key = child.Valstr
	child.Valstr = ""

	/*
	 * Fetch the location of ':' after the object key
	 */
	input = nextToken(input)
	if len(input) == 0 {
		return []byte{}, nil
	}

	if input[0] != ':' {
		errorStr := fmt.Sprintf("%s: Malformed object in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}

	input, err = parseValue(child, nextToken(input[1:]))

	if err != nil {
		return []byte{}, err
	}

	if input[0] != ',' {
		input = nextToken(input)

		if len(input) == 0 {
			return []byte{}, nil
		}
	}

	/*
	 * Continue processing the object and add the
	 * child entries to this parent GoJSON object
	 */
	for {
		if input[0] == ',' {
			sibling = new(GoJSON)
			child.next = sibling
			sibling.prev = child
			child = sibling

			input, err = parseString(child, nextToken(input[1:]))

			if err != nil {
				return []byte{}, err
			}

			child.Key = child.Valstr
			child.Valstr = ""

			/*
			 * Fetch the location of ':' after the object key
			 */
			input = nextToken(input)
			if len(input) == 0 {
				return []byte{}, nil
			}

			if input[0] != ':' {
				errorStr := fmt.Sprintf("%s: Malformed object in input %s", funcName(), string(input))
				return []byte{}, errors.New(errorStr)
			}

			input, err = parseValue(child, nextToken(input[1:]))

			if err != nil {
				return []byte{}, err
			}

			if input[0] != ',' {
				input = nextToken(input)

				if len(input) == 0 {
					return []byte{}, nil
				}
			}

		} else {
			break
		}
	}

	if input[0] == '}' {
		return input[1:], nil
	} else {
		errorStr := fmt.Sprintf("%s: Incomplete/Malformed object in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}
}

/**
 * Function to parse the current token
 */
func parseValue(cur *GoJSON, input []byte) ([]byte, error) {
	input = nextToken(input)
	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if strings.Compare(string(input[:4]), "null") == 0 {
		cur.Jsontype = JSON_NULL
		return input[4:], nil
	}

	if strings.Compare(string(input[:5]), "false") == 0 {
		cur.Jsontype = JSON_BOOL
		cur.Valbool = false
		return input[5:], nil
	}

	if strings.Compare(string(input[:4]), "true") == 0 {
		cur.Jsontype = JSON_BOOL
		cur.Valbool = true
		return input[4:], nil
	}

	if input[0] >= '0' && input[0] <= '9' {
		return parseNumber(cur, input)
	}

	switch input[0] {
	case '"':
		return parseString(cur, input)

	case '-':
		return parseNumber(cur, input)

	case '[':
		return parseArray(cur, input)

	case '{':
		return parseObject(cur, input)

	}

	errorStr := fmt.Sprintf("%s: Parsing Error", funcName())
	return []byte{}, errors.New(errorStr)
}

/*
 * Function to begin processing the string input
 * as a byte sequence
 */
func GoJSONParse(input []byte) (*GoJSON, error) {
	var g *GoJSON

	g = new(GoJSON)

	input = nextToken(input)

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Could not find any valid JSON in input %s", funcName(), string(input))
		return nil, errors.New(errorStr)
	}

	_, err := parseValue(g, input)

	if err != nil {
		errorStr := fmt.Sprintf("%s: JSON Parse failed with error %s ", funcName(), err)
		return nil, errors.New(errorStr)
	}

	return g, nil
}
<commit_msg>Changes next, prev and child pointers to be exposed externally.<commit_after>package jsonez

import (
	"errors"
	"fmt"
	"math"
	"strings"
	"unicode"
)

/*
 * JSON types
 */
const (
	JSON_BOOL = iota
	JSON_NULL
	JSON_INT
	JSON_DOUBLE
	JSON_STRING
	JSON_ARRAY
	JSON_OBJECT
)

var errorOffset int = -1

/*
 * GoJSON structure
 */
type GoJSON struct {
	/**
	 * Pointers to walk array/object chains
	 */
	Next, Prev *GoJSON

	/**
	 * Child item of the current object
	 */
	Child *GoJSON

	/** JSON type */
	Jsontype int

	/**
	 * Valstr will be set when
	 *type is JSON_STRING
	 */
	Valstr string

	/**
	 * Valint will be set when type
	 * is JSON_INT
	 */
	Valint int

	/**
	 * valuenum will be set when
	 * type is JSON_DOUBLE
	 */
	Valdouble float64

	/**
	 * Valbool will be set when
	 * type is JSON_BOOL
	 */
	Valbool bool

	/**
	 * JSON Key
	 */
	Key string
}

/**
 * Functions related to parsing a JSON string
 */

/**
 * nextToken finds the next token
 */
func nextToken(input []byte) []byte {
	for i, c := range input {
		if unicode.IsSpace(rune(c)) || c == '\'' {
			continue
		} else {
			return input[i:]
		}
	}

	return []byte{}
}

/**
 * Function to parse a string
 */
func parseString(cur *GoJSON, input []byte) ([]byte, error) {
	var offset int

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if input[0] != '"' {
		errorStr := fmt.Sprintf("%s: Not a valid string in input %s", funcName(), string(input))
		return nil, errors.New(errorStr)
	}

	for i := range input {
		if i > 0 && input[i] == '"' {
			break
		} else {
			offset++
		}
	}

	cur.Jsontype = JSON_STRING
	cur.Valstr = strings.Trim(string(input[1:offset]), " ")

	return input[offset+1:], nil
}

/**
 * Function to parse a number
 */
func parseNumber(cur *GoJSON, input []byte) ([]byte, error) {
	var n, sign, scale float64
	var subscale, signsubscale, offset int
	var isDouble bool = false

	sign = 1
	subscale = 0
	signsubscale = 1

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if input[offset] == '-' {
		sign = -1
		offset++
	}

	if unicode.IsDigit(rune(input[offset])) == false {
		errorStr := fmt.Sprintf("%s: Not a valid number in input %s", funcName(), string(input))
		return nil, errors.New(errorStr)
	}

	for {
		if input[offset] == '0' {
			offset++
		} else {
			break
		}
	}

	for {
		if unicode.IsDigit(rune(input[offset])) == true {
			n = (n * 10.0) + float64(input[offset]-'0')
			offset++
		} else {
			break
		}
	}

	if input[offset] == '.' && unicode.IsDigit(rune(input[offset+1])) == true {
		offset++
		isDouble = true

		for {
			if unicode.IsDigit(rune(input[offset])) == true {
				n = (n * 10.0) + float64(input[offset]-'0')
				offset++
				scale--
			} else {
				break
			}
		}
	}

	if input[offset] == 'e' || input[offset] == 'E' {
		offset++
		isDouble = true

		if input[offset] == '-' {
			signsubscale = -1
		}
		offset++

		for {
			if unicode.IsDigit(rune(input[offset])) == true {
				subscale = (subscale * 10) + int(input[offset]-'0')
				offset++
			} else {
				break
			}
		}
	}

	n = sign * n * math.Pow(10.0, scale+float64(subscale)*float64(signsubscale))

	if isDouble == true {
		cur.Valdouble = n
		cur.Jsontype = JSON_DOUBLE
	} else {
		cur.Valint = int(n)
		cur.Jsontype = JSON_INT
	}

	return input[offset:], nil
}

/**
 * Function to parse an array
 */
func parseArray(cur *GoJSON, input []byte) ([]byte, error) {
	var child, sibling *GoJSON

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if input[0] != '[' {
		errorStr := fmt.Sprintf("%s: Not a valid array in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}

	cur.Jsontype = JSON_ARRAY
	input = nextToken(input[1:])

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Could not find any valid JSON", funcName())
		return []byte{}, errors.New(errorStr)
	}

	/*
	 * Check if the array is empty
	 */
	if input[0] == ']' {
		return input[1:], nil
	}

	/*
	 * Allocate memory for the child to
	 * continue processing
	 */
	cur.child = new(GoJSON)
	child = cur.child
	input, err := parseValue(child, nextToken(input))

	if err != nil {
		return []byte{}, err
	}

	input = nextToken(input)

	if len(input) == 0 {
		return []byte{}, nil
	}

	/*
	 * Continue processing the array and add the
	 * child entries to this parent GoJSON object
	 */
	for {
		if input[0] == ',' {
			sibling = new(GoJSON)
			child.next = sibling
			sibling.prev = child
			child = sibling

			input, err = parseValue(child, nextToken(input[1:]))

			if err != nil {
				return []byte{}, err
			}

			input = nextToken(input)

			if len(input) == 0 {
				return []byte{}, nil
			}
		} else {
			break
		}
	}

	if input[0] == ']' {
		return input[1:], nil
	} else {
		errorStr := fmt.Sprintf("%s: Incomplete/Malformed array in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}
}

/**
 * Function to parse an object
 */
func parseObject(cur *GoJSON, input []byte) ([]byte, error) {
	var child, sibling *GoJSON

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if input[0] != '{' {
		errorStr := fmt.Sprintf("%s: Not a valid object", funcName())
		return []byte{}, errors.New(errorStr)
	}

	cur.Jsontype = JSON_OBJECT
	input = nextToken(input[1:])

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Could not find any valid JSON in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}

	/*
	 * Check if the object is empty
	 */
	if input[0] == '}' {
		return input[1:], nil
	}

	/*
	 * Allocate memory for the child to
	 * continue processing
	 */
	cur.child = new(GoJSON)
	child = cur.child
	input, err := parseString(child, nextToken(input))

	if err != nil {
		return []byte{}, err
	}

	child.Key = child.Valstr
	child.Valstr = ""

	/*
	 * Fetch the location of ':' after the object key
	 */
	input = nextToken(input)
	if len(input) == 0 {
		return []byte{}, nil
	}

	if input[0] != ':' {
		errorStr := fmt.Sprintf("%s: Malformed object in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}

	input, err = parseValue(child, nextToken(input[1:]))

	if err != nil {
		return []byte{}, err
	}

	if input[0] != ',' {
		input = nextToken(input)

		if len(input) == 0 {
			return []byte{}, nil
		}
	}

	/*
	 * Continue processing the object and add the
	 * child entries to this parent GoJSON object
	 */
	for {
		if input[0] == ',' {
			sibling = new(GoJSON)
			child.next = sibling
			sibling.prev = child
			child = sibling

			input, err = parseString(child, nextToken(input[1:]))

			if err != nil {
				return []byte{}, err
			}

			child.Key = child.Valstr
			child.Valstr = ""

			/*
			 * Fetch the location of ':' after the object key
			 */
			input = nextToken(input)
			if len(input) == 0 {
				return []byte{}, nil
			}

			if input[0] != ':' {
				errorStr := fmt.Sprintf("%s: Malformed object in input %s", funcName(), string(input))
				return []byte{}, errors.New(errorStr)
			}

			input, err = parseValue(child, nextToken(input[1:]))

			if err != nil {
				return []byte{}, err
			}

			if input[0] != ',' {
				input = nextToken(input)

				if len(input) == 0 {
					return []byte{}, nil
				}
			}

		} else {
			break
		}
	}

	if input[0] == '}' {
		return input[1:], nil
	} else {
		errorStr := fmt.Sprintf("%s: Incomplete/Malformed object in input %s", funcName(), string(input))
		return []byte{}, errors.New(errorStr)
	}
}

/**
 * Function to parse the current token
 */
func parseValue(cur *GoJSON, input []byte) ([]byte, error) {
	input = nextToken(input)
	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Byte slice is empty", funcName())
		return []byte{}, errors.New(errorStr)
	}

	if strings.Compare(string(input[:4]), "null") == 0 {
		cur.Jsontype = JSON_NULL
		return input[4:], nil
	}

	if strings.Compare(string(input[:5]), "false") == 0 {
		cur.Jsontype = JSON_BOOL
		cur.Valbool = false
		return input[5:], nil
	}

	if strings.Compare(string(input[:4]), "true") == 0 {
		cur.Jsontype = JSON_BOOL
		cur.Valbool = true
		return input[4:], nil
	}

	if input[0] >= '0' && input[0] <= '9' {
		return parseNumber(cur, input)
	}

	switch input[0] {
	case '"':
		return parseString(cur, input)

	case '-':
		return parseNumber(cur, input)

	case '[':
		return parseArray(cur, input)

	case '{':
		return parseObject(cur, input)

	}

	errorStr := fmt.Sprintf("%s: Parsing Error", funcName())
	return []byte{}, errors.New(errorStr)
}

/*
 * Function to begin processing the string input
 * as a byte sequence
 */
func GoJSONParse(input []byte) (*GoJSON, error) {
	var g *GoJSON

	g = new(GoJSON)

	input = nextToken(input)

	if len(input) == 0 {
		errorStr := fmt.Sprintf("%s: Could not find any valid JSON in input %s", funcName(), string(input))
		return nil, errors.New(errorStr)
	}

	_, err := parseValue(g, input)

	if err != nil {
		errorStr := fmt.Sprintf("%s: JSON Parse failed with error %s ", funcName(), err)
		return nil, errors.New(errorStr)
	}

	return g, nil
}
<|endoftext|>


<commit_before>// Copyright 2011 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 runtime_test

import "testing"

const N = 20

func BenchmarkAppend(b *testing.B) {
	b.StopTimer()
	x := make([]int, 0, N)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		x = x[0:0]
		for j := 0; j < N; j++ {
			x = append(x, j)
		}
	}
}

func BenchmarkAppendSpecialCase(b *testing.B) {
	b.StopTimer()
	x := make([]int, 0, N)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		x = x[0:0]
		for j := 0; j < N; j++ {
			if len(x) < cap(x) {
				x = x[:len(x)+1]
				x[len(x)-1] = j
			} else {
				x = append(x, j)
			}
		}
	}
}

var x = make([]int, 0, 10)

func f() int {
	x[:1][0] = 3
	return 2
}

func TestSideEffectOrder(t *testing.T) {
	x = append(x, 1, f())
	if x[0] != 1 || x[1] != 2 {
		t.Error("append failed: ", x[0], x[1])
	}
}
<commit_msg>runtime: make TestSideEffectOrder work twice<commit_after>// Copyright 2011 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 runtime_test

import "testing"

const N = 20

func BenchmarkAppend(b *testing.B) {
	b.StopTimer()
	x := make([]int, 0, N)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		x = x[0:0]
		for j := 0; j < N; j++ {
			x = append(x, j)
		}
	}
}

func BenchmarkAppendSpecialCase(b *testing.B) {
	b.StopTimer()
	x := make([]int, 0, N)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		x = x[0:0]
		for j := 0; j < N; j++ {
			if len(x) < cap(x) {
				x = x[:len(x)+1]
				x[len(x)-1] = j
			} else {
				x = append(x, j)
			}
		}
	}
}

var x []int

func f() int {
	x[:1][0] = 3
	return 2
}

func TestSideEffectOrder(t *testing.T) {
	x = make([]int, 0, 10)
	x = append(x, 1, f())
	if x[0] != 1 || x[1] != 2 {
		t.Error("append failed: ", x[0], x[1])
	}
}
<|endoftext|>