<commit_before>package mock

import (
	"context"
	"net/http"
	"strconv"
	"time"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"

	"zvelo.io/msg"
	"zvelo.io/msg/status"
)

type ContextOption func(*result)

func WithCategories(val ...msg.Category) ContextOption {
	return func(r *result) {
		if len(val) == 0 {
			return
		}

		if r.ResponseDataset == nil {
			r.ResponseDataset = &msg.DataSet{}
		}

		if r.ResponseDataset.Categorization == nil {
			r.ResponseDataset.Categorization = &msg.DataSet_Categorization{}
		}

		r.ResponseDataset.Categorization.Value = val
	}
}

func WithMalicious(val ...msg.Category) ContextOption {
	return func(r *result) {
		if r.ResponseDataset == nil {
			r.ResponseDataset = &msg.DataSet{}
		}

		if r.ResponseDataset.Malicious == nil {
			r.ResponseDataset.Malicious = &msg.DataSet_Malicious{}
		}

		r.ResponseDataset.Malicious.Category = val
	}
}

func WithLanguage(val string) ContextOption {
	return func(r *result) {
		if r.ResponseDataset == nil {
			r.ResponseDataset = &msg.DataSet{}
		}

		if r.ResponseDataset.Language == nil {
			r.ResponseDataset.Language = &msg.DataSet_Language{}
		}

		r.ResponseDataset.Language.Code = val
	}
}

func WithCompleteAfter(val time.Duration) ContextOption {
	return func(r *result) {
		r.CompleteAfter = val
	}
}

func WithFetchCode(val int32) ContextOption {
	return func(r *result) {
		if r.QueryStatus == nil {
			r.QueryStatus = &msg.QueryStatus{}
		}

		r.QueryStatus.FetchCode = val
	}
}

func WithLocation(val string) ContextOption {
	return func(r *result) {
		if r.QueryStatus == nil {
			r.QueryStatus = &msg.QueryStatus{}
		}

		r.QueryStatus.Location = val
	}
}

func WithError(c codes.Code, str string) ContextOption {
	return func(r *result) {
		if r.QueryStatus == nil {
			r.QueryStatus = &msg.QueryStatus{}
		}

		r.QueryStatus.Error = status.New(c, str).Proto()
	}
}

const (
	headerCategory          = "zvelo-mock-category"
	headerMaliciousCategory = "zvelo-mock-malicious-category"
	headerLanguageCode      = "zvelo-mock-language"
	headerCompleteAfter     = "zvelo-mock-complete-after"
	headerFetchCode         = "zvelo-mock-fetch-code"
	headerLocation          = "zvelo-mock-location"
	headerErrorCode         = "zvelo-mock-error-code"
	headerErrorMessage      = "zvelo-mock-error-message"
)

func QueryContext(ctx context.Context, opts ...ContextOption) context.Context {
	var r result
	for _, opt := range opts {
		opt(&r)
	}

	var pairs []string

	if ds := r.ResponseDataset; ds != nil {
		if c := ds.Categorization; c != nil {
			for _, cat := range c.Value {
				pairs = append(pairs, headerCategory, cat.String())
			}
		}

		if m := ds.Malicious; m != nil {
			for _, cat := range m.Category {
				pairs = append(pairs, headerMaliciousCategory, cat.String())
			}
		}

		if l := ds.Language; l != nil {
			pairs = append(pairs, headerLanguageCode, l.Code)
		}
	}

	if r.CompleteAfter > 0 {
		pairs = append(pairs, headerCompleteAfter, r.CompleteAfter.String())
	}

	if qs := r.QueryStatus; qs != nil {
		if qs.FetchCode != 0 {
			pairs = append(pairs, headerFetchCode, strconv.Itoa(int(qs.FetchCode)))
		}

		if qs.Location != "" {
			pairs = append(pairs, headerLocation, qs.Location)
		}

		if e := qs.Error; e != nil {
			if e.Code != 0 {
				pairs = append(pairs, headerErrorCode, strconv.Itoa(int(e.Code)))
			}

			if e.Message != "" {
				pairs = append(pairs, headerErrorMessage, e.Message)
			}
		}
	}

	md := metadata.Pairs(pairs...)

	if cmd, ok := metadata.FromOutgoingContext(ctx); ok {
		md = metadata.Join(cmd, md)
	}

	return metadata.NewOutgoingContext(ctx, md)
}

func mdGet(md metadata.MD, key string) string {
	if md == nil {
		return ""
	}
	v := md[key]
	if len(v) == 0 {
		return ""
	}
	return v[0]
}

func parseOpts(ctx context.Context, url string, content bool, ds []msg.DataSetType, r *result) error {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil
	}

	for _, t := range ds {
		switch msg.DataSetType(t) {
		case msg.CATEGORIZATION:
			if r.ResponseDataset == nil {
				r.ResponseDataset = &msg.DataSet{}
			}

			r.ResponseDataset.Categorization = &msg.DataSet_Categorization{}

			if categoryNames, ok := md[headerCategory]; ok {
				categories := make([]msg.Category, len(categoryNames))
				for i, categoryName := range categoryNames {
					categories[i] = msg.ParseCategory(categoryName)
				}

				WithCategories(categories...)(r)
			}
		case msg.MALICIOUS:
			if r.ResponseDataset == nil {
				r.ResponseDataset = &msg.DataSet{}
			}

			r.ResponseDataset.Malicious = &msg.DataSet_Malicious{}

			if categoryNames, ok := md[headerMaliciousCategory]; ok {
				categories := make([]msg.Category, len(categoryNames))
				for i, categoryName := range categoryNames {
					categories[i] = msg.ParseCategory(categoryName)
				}

				WithMalicious(categories...)(r)
			}
		case msg.ECHO:
			if r.ResponseDataset == nil {
				r.ResponseDataset = &msg.DataSet{}
			}

			r.ResponseDataset.Echo = &msg.DataSet_Echo{Url: url}
		case msg.LANGUAGE:
			if r.ResponseDataset == nil {
				r.ResponseDataset = &msg.DataSet{}
			}

			r.ResponseDataset.Language = &msg.DataSet_Language{}

			if langCodes, ok := md[headerLanguageCode]; ok && len(langCodes) > 0 {
				r.ResponseDataset.Language.Code = langCodes[0]
			}
		}
	}

	if s := mdGet(md, headerCompleteAfter); s != "" {
		d, err := time.ParseDuration(s)
		if err != nil {
			return err
		}

		WithCompleteAfter(d)(r)
	}

	if c := mdGet(md, headerFetchCode); c != "" {
		code, err := strconv.ParseInt(c, 10, 32)
		if err != nil {
			return err
		}

		WithFetchCode(int32(code))(r)
	} else if !content {
		WithFetchCode(http.StatusOK)(r)
	}

	if l := mdGet(md, headerLocation); l != "" {
		WithLocation(l)(r)
	}

	var errorCode codes.Code
	if c := mdGet(md, headerErrorCode); c != "" {
		code, err := strconv.ParseUint(c, 10, 32)
		if err != nil {
			return err
		}

		errorCode = codes.Code(code)
	}

	errorMsg := mdGet(md, headerErrorMessage)

	if errorCode != 0 || errorMsg != "" {
		WithError(errorCode, errorMsg)(r)
	}

	return nil
}
<commit_msg>lint fix<commit_after>package mock

import (
	"context"
	"net/http"
	"strconv"
	"time"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"

	"zvelo.io/msg"
	"zvelo.io/msg/status"
)

type ContextOption func(*result)

func WithCategories(val ...msg.Category) ContextOption {
	return func(r *result) {
		if len(val) == 0 {
			return
		}

		if r.ResponseDataset == nil {
			r.ResponseDataset = &msg.DataSet{}
		}

		if r.ResponseDataset.Categorization == nil {
			r.ResponseDataset.Categorization = &msg.DataSet_Categorization{}
		}

		r.ResponseDataset.Categorization.Value = val
	}
}

func WithMalicious(val ...msg.Category) ContextOption {
	return func(r *result) {
		if r.ResponseDataset == nil {
			r.ResponseDataset = &msg.DataSet{}
		}

		if r.ResponseDataset.Malicious == nil {
			r.ResponseDataset.Malicious = &msg.DataSet_Malicious{}
		}

		r.ResponseDataset.Malicious.Category = val
	}
}

func WithLanguage(val string) ContextOption {
	return func(r *result) {
		if r.ResponseDataset == nil {
			r.ResponseDataset = &msg.DataSet{}
		}

		if r.ResponseDataset.Language == nil {
			r.ResponseDataset.Language = &msg.DataSet_Language{}
		}

		r.ResponseDataset.Language.Code = val
	}
}

func WithCompleteAfter(val time.Duration) ContextOption {
	return func(r *result) {
		r.CompleteAfter = val
	}
}

func WithFetchCode(val int32) ContextOption {
	return func(r *result) {
		if r.QueryStatus == nil {
			r.QueryStatus = &msg.QueryStatus{}
		}

		r.QueryStatus.FetchCode = val
	}
}

func WithLocation(val string) ContextOption {
	return func(r *result) {
		if r.QueryStatus == nil {
			r.QueryStatus = &msg.QueryStatus{}
		}

		r.QueryStatus.Location = val
	}
}

func WithError(c codes.Code, str string) ContextOption {
	return func(r *result) {
		if r.QueryStatus == nil {
			r.QueryStatus = &msg.QueryStatus{}
		}

		r.QueryStatus.Error = status.New(c, str).Proto()
	}
}

const (
	headerCategory          = "zvelo-mock-category"
	headerMaliciousCategory = "zvelo-mock-malicious-category"
	headerLanguageCode      = "zvelo-mock-language"
	headerCompleteAfter     = "zvelo-mock-complete-after"
	headerFetchCode         = "zvelo-mock-fetch-code"
	headerLocation          = "zvelo-mock-location"
	headerErrorCode         = "zvelo-mock-error-code"
	headerErrorMessage      = "zvelo-mock-error-message"
)

func QueryContext(ctx context.Context, opts ...ContextOption) context.Context {
	var r result
	for _, opt := range opts {
		opt(&r)
	}

	var pairs []string

	if ds := r.ResponseDataset; ds != nil {
		if c := ds.Categorization; c != nil {
			for _, cat := range c.Value {
				pairs = append(pairs, headerCategory, cat.String())
			}
		}

		if m := ds.Malicious; m != nil {
			for _, cat := range m.Category {
				pairs = append(pairs, headerMaliciousCategory, cat.String())
			}
		}

		if l := ds.Language; l != nil {
			pairs = append(pairs, headerLanguageCode, l.Code)
		}
	}

	if r.CompleteAfter > 0 {
		pairs = append(pairs, headerCompleteAfter, r.CompleteAfter.String())
	}

	if qs := r.QueryStatus; qs != nil {
		if qs.FetchCode != 0 {
			pairs = append(pairs, headerFetchCode, strconv.Itoa(int(qs.FetchCode)))
		}

		if qs.Location != "" {
			pairs = append(pairs, headerLocation, qs.Location)
		}

		if e := qs.Error; e != nil {
			if e.Code != 0 {
				pairs = append(pairs, headerErrorCode, strconv.Itoa(int(e.Code)))
			}

			if e.Message != "" {
				pairs = append(pairs, headerErrorMessage, e.Message)
			}
		}
	}

	md := metadata.Pairs(pairs...)

	if cmd, ok := metadata.FromOutgoingContext(ctx); ok {
		md = metadata.Join(cmd, md)
	}

	return metadata.NewOutgoingContext(ctx, md)
}

func mdGet(md metadata.MD, key string) string {
	if md == nil {
		return ""
	}
	v := md[key]
	if len(v) == 0 {
		return ""
	}
	return v[0]
}

func parseOpts(ctx context.Context, url string, content bool, ds []msg.DataSetType, r *result) error {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil
	}

	for _, t := range ds {
		switch t {
		case msg.CATEGORIZATION:
			if r.ResponseDataset == nil {
				r.ResponseDataset = &msg.DataSet{}
			}

			r.ResponseDataset.Categorization = &msg.DataSet_Categorization{}

			if categoryNames, ok := md[headerCategory]; ok {
				categories := make([]msg.Category, len(categoryNames))
				for i, categoryName := range categoryNames {
					categories[i] = msg.ParseCategory(categoryName)
				}

				WithCategories(categories...)(r)
			}
		case msg.MALICIOUS:
			if r.ResponseDataset == nil {
				r.ResponseDataset = &msg.DataSet{}
			}

			r.ResponseDataset.Malicious = &msg.DataSet_Malicious{}

			if categoryNames, ok := md[headerMaliciousCategory]; ok {
				categories := make([]msg.Category, len(categoryNames))
				for i, categoryName := range categoryNames {
					categories[i] = msg.ParseCategory(categoryName)
				}

				WithMalicious(categories...)(r)
			}
		case msg.ECHO:
			if r.ResponseDataset == nil {
				r.ResponseDataset = &msg.DataSet{}
			}

			r.ResponseDataset.Echo = &msg.DataSet_Echo{Url: url}
		case msg.LANGUAGE:
			if r.ResponseDataset == nil {
				r.ResponseDataset = &msg.DataSet{}
			}

			r.ResponseDataset.Language = &msg.DataSet_Language{}

			if langCodes, ok := md[headerLanguageCode]; ok && len(langCodes) > 0 {
				r.ResponseDataset.Language.Code = langCodes[0]
			}
		}
	}

	if s := mdGet(md, headerCompleteAfter); s != "" {
		d, err := time.ParseDuration(s)
		if err != nil {
			return err
		}

		WithCompleteAfter(d)(r)
	}

	if c := mdGet(md, headerFetchCode); c != "" {
		code, err := strconv.ParseInt(c, 10, 32)
		if err != nil {
			return err
		}

		WithFetchCode(int32(code))(r)
	} else if !content {
		WithFetchCode(http.StatusOK)(r)
	}

	if l := mdGet(md, headerLocation); l != "" {
		WithLocation(l)(r)
	}

	var errorCode codes.Code
	if c := mdGet(md, headerErrorCode); c != "" {
		code, err := strconv.ParseUint(c, 10, 32)
		if err != nil {
			return err
		}

		errorCode = codes.Code(code)
	}

	errorMsg := mdGet(md, headerErrorMessage)

	if errorCode != 0 || errorMsg != "" {
		WithError(errorCode, errorMsg)(r)
	}

	return nil
}
<|endoftext|>


<commit_before><commit_msg>using conv.Constant to map basic lit<commit_after><|endoftext|>


<commit_before>// Copyright 2013 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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
// are signed messages attesting to the validity of a certificate for a small
// period of time. This is used to manage revocation for X.509 certificates.
package ocsp

import (
	"crypto"
	_ "crypto/sha1"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/asn1"
	"math/big"
	"time"
)

var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})

// These are internal structures that reflect the ASN.1 structure of an OCSP
// response. See RFC 2560, section 4.2.

const (
	ocspSuccess       = 0
	ocspMalformed     = 1
	ocspInternalError = 2
	ocspTryLater      = 3
	ocspSigRequired   = 4
	ocspUnauthorized  = 5
)

type certID struct {
	HashAlgorithm pkix.AlgorithmIdentifier
	NameHash      []byte
	IssuerKeyHash []byte
	SerialNumber  *big.Int
}

type responseASN1 struct {
	Status   asn1.Enumerated
	Response responseBytes `asn1:"explicit,tag:0"`
}

type responseBytes struct {
	ResponseType asn1.ObjectIdentifier
	Response     []byte
}

type basicResponse struct {
	TBSResponseData    responseData
	SignatureAlgorithm pkix.AlgorithmIdentifier
	Signature          asn1.BitString
	Certificates       []asn1.RawValue `asn1:"explicit,tag:0,optional"`
}

type responseData struct {
	Raw           asn1.RawContent
	Version       int              `asn1:"optional,default:1,explicit,tag:0"`
	RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"`
	KeyHash       []byte           `asn1:"optional,explicit,tag:2"`
	ProducedAt    time.Time
	Responses     []singleResponse
}

type singleResponse struct {
	CertID     certID
	Good       asn1.Flag   `asn1:"explicit,tag:0,optional"`
	Revoked    revokedInfo `asn1:"explicit,tag:1,optional"`
	Unknown    asn1.Flag   `asn1:"explicit,tag:2,optional"`
	ThisUpdate time.Time
	NextUpdate time.Time `asn1:"explicit,tag:0,optional"`
}

type revokedInfo struct {
	RevocationTime time.Time
	Reason         int `asn1:"explicit,tag:0,optional"`
}

var (
	oidSignatureMD2WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
	oidSignatureMD5WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
	oidSignatureSHA1WithRSA     = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
	oidSignatureSHA256WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
	oidSignatureSHA384WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
	oidSignatureSHA512WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
	oidSignatureDSAWithSHA1     = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
	oidSignatureDSAWithSHA256   = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
	oidSignatureECDSAWithSHA1   = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
	oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
	oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
	oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
)

// TODO(agl): this is taken from crypto/x509 and so should probably be exported
// from crypto/x509 or crypto/x509/pkix.
func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
	switch {
	case oid.Equal(oidSignatureMD2WithRSA):
		return x509.MD2WithRSA
	case oid.Equal(oidSignatureMD5WithRSA):
		return x509.MD5WithRSA
	case oid.Equal(oidSignatureSHA1WithRSA):
		return x509.SHA1WithRSA
	case oid.Equal(oidSignatureSHA256WithRSA):
		return x509.SHA256WithRSA
	case oid.Equal(oidSignatureSHA384WithRSA):
		return x509.SHA384WithRSA
	case oid.Equal(oidSignatureSHA512WithRSA):
		return x509.SHA512WithRSA
	case oid.Equal(oidSignatureDSAWithSHA1):
		return x509.DSAWithSHA1
	case oid.Equal(oidSignatureDSAWithSHA256):
		return x509.DSAWithSHA256
	case oid.Equal(oidSignatureECDSAWithSHA1):
		return x509.ECDSAWithSHA1
	case oid.Equal(oidSignatureECDSAWithSHA256):
		return x509.ECDSAWithSHA256
	case oid.Equal(oidSignatureECDSAWithSHA384):
		return x509.ECDSAWithSHA384
	case oid.Equal(oidSignatureECDSAWithSHA512):
		return x509.ECDSAWithSHA512
	}
	return x509.UnknownSignatureAlgorithm
}

// This is the exposed reflection of the internal OCSP structures.

const (
	// Good means that the certificate is valid.
	Good = iota
	// Revoked means that the certificate has been deliberately revoked.
	Revoked = iota
	// Unknown means that the OCSP responder doesn't know about the certificate.
	Unknown = iota
	// ServerFailed means that the OCSP responder failed to process the request.
	ServerFailed = iota
)

// Response represents an OCSP response. See RFC 2560.
type Response struct {
	// Status is one of {Good, Revoked, Unknown, ServerFailed}
	Status                                        int
	SerialNumber                                  *big.Int
	ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
	RevocationReason                              int
	Certificate                                   *x509.Certificate
	// TBSResponseData contains the raw bytes of the signed response. If
	// Certificate is nil then this can be used to verify Signature.
	TBSResponseData    []byte
	Signature          []byte
	SignatureAlgorithm x509.SignatureAlgorithm
}

// CheckSignatureFrom checks that the signature in resp is a valid signature
// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
// the OCSP response contained an intermediate certificate that created the
// signature. That signature is checked by ParseResponse and only
// resp.Certificate remains to be validated.
func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
	return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
}

// ParseError results from an invalid OCSP response.
type ParseError string

func (p ParseError) Error() string {
	return string(p)
}

// ParseResponse parses an OCSP response in DER form. It only supports
// responses for a single certificate. If the response contains a certificate
// then the signature over the response is checked. Invalid signatures or parse
// failures will result in a ParseError.
func ParseResponse(bytes []byte) (*Response, error) {
	var resp responseASN1
	rest, err := asn1.Unmarshal(bytes, &resp)
	if err != nil {
		return nil, err
	}
	if len(rest) > 0 {
		return nil, ParseError("trailing data in OCSP response")
	}

	ret := new(Response)
	if resp.Status != ocspSuccess {
		ret.Status = ServerFailed
		return ret, nil
	}

	if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
		return nil, ParseError("bad OCSP response type")
	}

	var basicResp basicResponse
	rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
	if err != nil {
		return nil, err
	}

	if len(basicResp.Certificates) > 1 {
		return nil, ParseError("OCSP response contains bad number of certificates")
	}

	if len(basicResp.TBSResponseData.Responses) != 1 {
		return nil, ParseError("OCSP response contains bad number of responses")
	}

	ret.TBSResponseData = basicResp.TBSResponseData.Raw
	ret.Signature = basicResp.Signature.RightAlign()
	ret.SignatureAlgorithm = getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm)

	if len(basicResp.Certificates) > 0 {
		ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
		if err != nil {
			return nil, err
		}

		if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
			return nil, ParseError("bad OCSP signature")
		}
	}

	r := basicResp.TBSResponseData.Responses[0]

	ret.SerialNumber = r.CertID.SerialNumber

	switch {
	case bool(r.Good):
		ret.Status = Good
	case bool(r.Unknown):
		ret.Status = Unknown
	default:
		ret.Status = Revoked
		ret.RevokedAt = r.Revoked.RevocationTime
		ret.RevocationReason = r.Revoked.Reason
	}

	ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
	ret.ThisUpdate = r.ThisUpdate
	ret.NextUpdate = r.NextUpdate

	return ret, nil
}

// https://tools.ietf.org/html/rfc2560#section-4.1.1
type ocspRequest struct {
	TBSRequest tbsRequest
}

type tbsRequest struct {
	Version     int `asn1:"explicit,tag:0,default:0"`
	RequestList []request
}

type request struct {
	Cert certID
}

// RequestOptions contains options for constructing OCSP requests.
type RequestOptions struct {
	// Hash contains the hash function that should be used when
	// constructing the OCSP request.
	Hash crypto.Hash
}

func (opts *RequestOptions) hash() crypto.Hash {
	if opts == nil {
		// SHA-1 is nearly universally used in OCSP.
		return crypto.SHA1
	}
	return opts.Hash
}

// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If
// opts is nil then sensible defaults are used.
func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
	hashFunc := opts.hash()

	// OCSP seems to be the only place where these raw hash identifiers are
	// used. I took the following from
	// http://msdn.microsoft.com/en-us/library/ff635603.aspx
	var hashOID asn1.ObjectIdentifier
	switch hashFunc {
	case crypto.SHA1:
		hashOID = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
	case crypto.SHA256:
		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1})
	case crypto.SHA384:
		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2})
	case crypto.SHA512:
		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3})
	default:
		return nil, x509.ErrUnsupportedAlgorithm
	}

	if !hashFunc.Available() {
		return nil, x509.ErrUnsupportedAlgorithm
	}
	h := opts.hash().New()

	var publicKeyInfo struct {
		Algorithm pkix.AlgorithmIdentifier
		PublicKey asn1.BitString
	}
	if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
		return nil, err
	}

	h.Write(publicKeyInfo.PublicKey.RightAlign())
	issuerKeyHash := h.Sum(nil)

	h.Reset()
	h.Write(issuer.RawSubject)
	issuerNameHash := h.Sum(nil)

	return asn1.Marshal(ocspRequest{
		tbsRequest{
			Version: 0,
			RequestList: []request{
				{
					Cert: certID{
						pkix.AlgorithmIdentifier{
							Algorithm:  hashOID,
							Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
						},
						issuerNameHash,
						issuerKeyHash,
						cert.SerialNumber,
					},
				},
			},
		},
	})
}
<commit_msg>go.crypto/ocsp: make the zero value of RequestOptions valid and documented.<commit_after>// Copyright 2013 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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
// are signed messages attesting to the validity of a certificate for a small
// period of time. This is used to manage revocation for X.509 certificates.
package ocsp

import (
	"crypto"
	_ "crypto/sha1"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/asn1"
	"math/big"
	"time"
)

var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})

// These are internal structures that reflect the ASN.1 structure of an OCSP
// response. See RFC 2560, section 4.2.

const (
	ocspSuccess       = 0
	ocspMalformed     = 1
	ocspInternalError = 2
	ocspTryLater      = 3
	ocspSigRequired   = 4
	ocspUnauthorized  = 5
)

type certID struct {
	HashAlgorithm pkix.AlgorithmIdentifier
	NameHash      []byte
	IssuerKeyHash []byte
	SerialNumber  *big.Int
}

type responseASN1 struct {
	Status   asn1.Enumerated
	Response responseBytes `asn1:"explicit,tag:0"`
}

type responseBytes struct {
	ResponseType asn1.ObjectIdentifier
	Response     []byte
}

type basicResponse struct {
	TBSResponseData    responseData
	SignatureAlgorithm pkix.AlgorithmIdentifier
	Signature          asn1.BitString
	Certificates       []asn1.RawValue `asn1:"explicit,tag:0,optional"`
}

type responseData struct {
	Raw           asn1.RawContent
	Version       int              `asn1:"optional,default:1,explicit,tag:0"`
	RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"`
	KeyHash       []byte           `asn1:"optional,explicit,tag:2"`
	ProducedAt    time.Time
	Responses     []singleResponse
}

type singleResponse struct {
	CertID     certID
	Good       asn1.Flag   `asn1:"explicit,tag:0,optional"`
	Revoked    revokedInfo `asn1:"explicit,tag:1,optional"`
	Unknown    asn1.Flag   `asn1:"explicit,tag:2,optional"`
	ThisUpdate time.Time
	NextUpdate time.Time `asn1:"explicit,tag:0,optional"`
}

type revokedInfo struct {
	RevocationTime time.Time
	Reason         int `asn1:"explicit,tag:0,optional"`
}

var (
	oidSignatureMD2WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
	oidSignatureMD5WithRSA      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
	oidSignatureSHA1WithRSA     = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
	oidSignatureSHA256WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
	oidSignatureSHA384WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
	oidSignatureSHA512WithRSA   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
	oidSignatureDSAWithSHA1     = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
	oidSignatureDSAWithSHA256   = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 4, 3, 2}
	oidSignatureECDSAWithSHA1   = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
	oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
	oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
	oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
)

// TODO(agl): this is taken from crypto/x509 and so should probably be exported
// from crypto/x509 or crypto/x509/pkix.
func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
	switch {
	case oid.Equal(oidSignatureMD2WithRSA):
		return x509.MD2WithRSA
	case oid.Equal(oidSignatureMD5WithRSA):
		return x509.MD5WithRSA
	case oid.Equal(oidSignatureSHA1WithRSA):
		return x509.SHA1WithRSA
	case oid.Equal(oidSignatureSHA256WithRSA):
		return x509.SHA256WithRSA
	case oid.Equal(oidSignatureSHA384WithRSA):
		return x509.SHA384WithRSA
	case oid.Equal(oidSignatureSHA512WithRSA):
		return x509.SHA512WithRSA
	case oid.Equal(oidSignatureDSAWithSHA1):
		return x509.DSAWithSHA1
	case oid.Equal(oidSignatureDSAWithSHA256):
		return x509.DSAWithSHA256
	case oid.Equal(oidSignatureECDSAWithSHA1):
		return x509.ECDSAWithSHA1
	case oid.Equal(oidSignatureECDSAWithSHA256):
		return x509.ECDSAWithSHA256
	case oid.Equal(oidSignatureECDSAWithSHA384):
		return x509.ECDSAWithSHA384
	case oid.Equal(oidSignatureECDSAWithSHA512):
		return x509.ECDSAWithSHA512
	}
	return x509.UnknownSignatureAlgorithm
}

// This is the exposed reflection of the internal OCSP structures.

const (
	// Good means that the certificate is valid.
	Good = iota
	// Revoked means that the certificate has been deliberately revoked.
	Revoked = iota
	// Unknown means that the OCSP responder doesn't know about the certificate.
	Unknown = iota
	// ServerFailed means that the OCSP responder failed to process the request.
	ServerFailed = iota
)

// Response represents an OCSP response. See RFC 2560.
type Response struct {
	// Status is one of {Good, Revoked, Unknown, ServerFailed}
	Status                                        int
	SerialNumber                                  *big.Int
	ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
	RevocationReason                              int
	Certificate                                   *x509.Certificate
	// TBSResponseData contains the raw bytes of the signed response. If
	// Certificate is nil then this can be used to verify Signature.
	TBSResponseData    []byte
	Signature          []byte
	SignatureAlgorithm x509.SignatureAlgorithm
}

// CheckSignatureFrom checks that the signature in resp is a valid signature
// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
// the OCSP response contained an intermediate certificate that created the
// signature. That signature is checked by ParseResponse and only
// resp.Certificate remains to be validated.
func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
	return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
}

// ParseError results from an invalid OCSP response.
type ParseError string

func (p ParseError) Error() string {
	return string(p)
}

// ParseResponse parses an OCSP response in DER form. It only supports
// responses for a single certificate. If the response contains a certificate
// then the signature over the response is checked. Invalid signatures or parse
// failures will result in a ParseError.
func ParseResponse(bytes []byte) (*Response, error) {
	var resp responseASN1
	rest, err := asn1.Unmarshal(bytes, &resp)
	if err != nil {
		return nil, err
	}
	if len(rest) > 0 {
		return nil, ParseError("trailing data in OCSP response")
	}

	ret := new(Response)
	if resp.Status != ocspSuccess {
		ret.Status = ServerFailed
		return ret, nil
	}

	if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
		return nil, ParseError("bad OCSP response type")
	}

	var basicResp basicResponse
	rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
	if err != nil {
		return nil, err
	}

	if len(basicResp.Certificates) > 1 {
		return nil, ParseError("OCSP response contains bad number of certificates")
	}

	if len(basicResp.TBSResponseData.Responses) != 1 {
		return nil, ParseError("OCSP response contains bad number of responses")
	}

	ret.TBSResponseData = basicResp.TBSResponseData.Raw
	ret.Signature = basicResp.Signature.RightAlign()
	ret.SignatureAlgorithm = getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm)

	if len(basicResp.Certificates) > 0 {
		ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
		if err != nil {
			return nil, err
		}

		if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
			return nil, ParseError("bad OCSP signature")
		}
	}

	r := basicResp.TBSResponseData.Responses[0]

	ret.SerialNumber = r.CertID.SerialNumber

	switch {
	case bool(r.Good):
		ret.Status = Good
	case bool(r.Unknown):
		ret.Status = Unknown
	default:
		ret.Status = Revoked
		ret.RevokedAt = r.Revoked.RevocationTime
		ret.RevocationReason = r.Revoked.Reason
	}

	ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
	ret.ThisUpdate = r.ThisUpdate
	ret.NextUpdate = r.NextUpdate

	return ret, nil
}

// https://tools.ietf.org/html/rfc2560#section-4.1.1
type ocspRequest struct {
	TBSRequest tbsRequest
}

type tbsRequest struct {
	Version     int `asn1:"explicit,tag:0,default:0"`
	RequestList []request
}

type request struct {
	Cert certID
}

// RequestOptions contains options for constructing OCSP requests.
type RequestOptions struct {
	// Hash contains the hash function that should be used when
	// constructing the OCSP request. If zero, SHA-1 will be used.
	Hash crypto.Hash
}

func (opts *RequestOptions) hash() crypto.Hash {
	if opts == nil || opts.Hash == 0 {
		// SHA-1 is nearly universally used in OCSP.
		return crypto.SHA1
	}
	return opts.Hash
}

// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If
// opts is nil then sensible defaults are used.
func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
	hashFunc := opts.hash()

	// OCSP seems to be the only place where these raw hash identifiers are
	// used. I took the following from
	// http://msdn.microsoft.com/en-us/library/ff635603.aspx
	var hashOID asn1.ObjectIdentifier
	switch hashFunc {
	case crypto.SHA1:
		hashOID = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
	case crypto.SHA256:
		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1})
	case crypto.SHA384:
		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2})
	case crypto.SHA512:
		hashOID = asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3})
	default:
		return nil, x509.ErrUnsupportedAlgorithm
	}

	if !hashFunc.Available() {
		return nil, x509.ErrUnsupportedAlgorithm
	}
	h := opts.hash().New()

	var publicKeyInfo struct {
		Algorithm pkix.AlgorithmIdentifier
		PublicKey asn1.BitString
	}
	if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
		return nil, err
	}

	h.Write(publicKeyInfo.PublicKey.RightAlign())
	issuerKeyHash := h.Sum(nil)

	h.Reset()
	h.Write(issuer.RawSubject)
	issuerNameHash := h.Sum(nil)

	return asn1.Marshal(ocspRequest{
		tbsRequest{
			Version: 0,
			RequestList: []request{
				{
					Cert: certID{
						pkix.AlgorithmIdentifier{
							Algorithm:  hashOID,
							Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
						},
						issuerNameHash,
						issuerKeyHash,
						cert.SerialNumber,
					},
				},
			},
		},
	})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"golang.org/x/crypto/ssh"
	"io"
	"io/ioutil"
	"net"
	"strconv"
	"time"
)

/**
 * L left/local  -   SshProxy   -    R Right/Remote
 *
 * LocalSSH  - The listening side of tihs application
 * RemoteSSH - The connection with the server that contains and provides the actual data
 * Client    - The client that connects with this application
 *
 */

func main() {
	listener, err := net.Listen("tcp", "0.0.0.0:2022")
	if err != nil {
		panic("failed to listen for connection")
	}
	for {
		lnConn, err := listener.Accept()
		if err != nil {
			panic("failed to accept incoming connection")
		}
		go handleLocalSshConn(lnConn)
	}
}

func handleLocalSshConn(lnConn net.Conn) {
	defer func() {
		return
		if r := recover(); r != nil {
			fmt.Println("Recovered in f", r)
		}
	}()

	var rClient *ssh.Client
	lConfig := getLocalSshConfig(&rClient)
	lConn, lChans, lReqs, err := ssh.NewServerConn(lnConn, lConfig)
	if rClient == nil {
		return
	}
	defer lConn.Close()
	if err != nil {
		panic("failed to handshake")
	}
	go ssh.DiscardRequests(lReqs)
	defer rClient.Close()

	for newChannel := range lChans {
		if newChannel.ChannelType() != "session" {
			newChannel.Reject(ssh.UnknownChannelType, "unknown channel type: "+newChannel.ChannelType())
			continue
		}
		lChannel, lRequests, err := newChannel.Accept()
		if err != nil {
			panic("could not accept channel.")
		}

		rChannel, rRequests, err := rClient.OpenChannel(newChannel.ChannelType(), nil)
		if err != nil {
			panic("Failed to create session: " + err.Error())
		}

		go func(lChannel, rChannel ssh.Channel) {
			defer func() {
				return
				if r := recover(); r != nil {
					fmt.Println("Recovered in f", r)
				}
			}()
			defer rChannel.Close()
			defer lChannel.Close()

			for {
				select {
				case lRequest, ok := <-lRequests:
					if !ok {
						return
					}
					if err := pipeRequests(lRequest, rChannel); err != nil {
						fmt.Println("Error: " + err.Error())
						continue
					}
				case rRequest, ok := <-rRequests:
					if !ok {
						return
					}
					if err := pipeRequests(rRequest, lChannel); err != nil {
						fmt.Println("Error: " + err.Error())
						continue
					}
				}
			}
		}(lChannel, rChannel)

		time.Sleep(50 * time.Millisecond)
		pipe := func(dst io.Writer, src io.Reader) {
			bytes, err := io.Copy(dst, src)
			if err != nil {
				fmt.Println(err.Error())
			}

			fmt.Println("Bytes exchanged: ", bytes)
			rChannel.CloseWrite()
			lChannel.CloseWrite()
		}

		go pipe(rChannel, lChannel)
		go pipe(lChannel, rChannel)
	}
}

func getLocalSshConfig(rClient **ssh.Client) *ssh.ServerConfig {
	config := &ssh.ServerConfig{
		ServerVersion: "SSH-2.0-SshReverseProxy",
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			if c.User() == "dolf" {
				var err error
				*rClient, err = getRemoteSshClient("localhost", "2222", c.User(), string(pass))
				if err != nil {
					return nil, fmt.Errorf("password rejected for %q: %s", c.User(), err)
				}
				return nil, nil
			}
			return nil, fmt.Errorf("Unknown user %q", c.User())
		},
	}

	privateBytes, err := ioutil.ReadFile("id_rsa")
	if err != nil {
		panic("Failed to load private key")
	}

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil {
		panic("Failed to parse private key")
	}

	config.AddHostKey(private)
	return config
}

func getRemoteSshClient(host, portStr, user, password string) (*ssh.Client, error) {
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
	}
	port, err := strconv.ParseInt(portStr, 10, 64)
	if err != nil {
		panic("Port must be an integer")
	}

	conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", host, port), config)
	if err != nil {
		return nil, fmt.Errorf("unable to connect: " + err.Error())
	}

	return conn, nil
}

func pipeRequests(req *ssh.Request, channel ssh.Channel) error {
	if string(req.Type) != "subsystem" && string(req.Type) != "exit-status" {
		req.Reply(false, nil)
		return fmt.Errorf("Ignoring unsupported request type: %s", string(req.Type))
	}
	reply, err := channel.SendRequest(req.Type, req.WantReply, req.Payload)
	if err != nil {
		return err
	}
	if req.WantReply {
		req.Reply(reply, nil)
	}

	return nil
}
<commit_msg>Make code less fugly<commit_after>package main

import (
	"fmt"
	"golang.org/x/crypto/ssh"
	"io"
	"io/ioutil"
	"net"
	"strconv"
	"time"
)

/**
 * L left/local  -   SshProxy   -    R Right/Remote
 *
 * LocalSSH  - The listening side of tihs application
 * RemoteSSH - The connection with the server that contains and provides the actual data
 * Client    - The client that connects with this application
 *
 */

func main() {
	listener, err := net.Listen("tcp", "0.0.0.0:2022")
	if err != nil {
		panic("failed to listen for connection")
	}
	for {
		lnConn, err := listener.Accept()
		if err != nil {
			panic("failed to accept incoming connection")
		}
		go handleLocalSshConn(lnConn)
	}
}

func handleLocalSshConn(lnConn net.Conn) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered from panic: ", r)
		}
	}()

	var rClient *ssh.Client
	lConfig := getLocalSshConfig(&rClient)
	lConn, lChans, lReqs, err := ssh.NewServerConn(lnConn, lConfig)
	if err != nil {
		panic("Handshake failed " + err.Error())
	}
	defer lConn.Close()
	defer rClient.Close()

	go ssh.DiscardRequests(lReqs)

	for newChannel := range lChans {
		handleChannel(newChannel, rClient)
	}
}

func handleChannel(newChannel ssh.NewChannel, rClient *ssh.Client) {
	if newChannel.ChannelType() != "session" {
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type: "+newChannel.ChannelType())
		return
	}
	lChannel, lRequests, err := newChannel.Accept()
	if err != nil {
		panic("could not accept channel.")
	}

	rChannel, rRequests, err := rClient.OpenChannel(newChannel.ChannelType(), nil)
	if err != nil {
		panic("Failed to create session: " + err.Error())
	}

	go pipeRequests(lChannel, rChannel, lRequests, rRequests)

	time.Sleep(50 * time.Millisecond)
	pipe := func(dst io.Writer, src io.Reader) {
		bytes, err := io.Copy(dst, src)
		if err != nil {
			fmt.Println(err.Error())
		}

		fmt.Println("Bytes exchanged: ", bytes)
		rChannel.CloseWrite()
		lChannel.CloseWrite()
	}

	go pipe(rChannel, lChannel)
	go pipe(lChannel, rChannel)
}

func getLocalSshConfig(rClient **ssh.Client) *ssh.ServerConfig {
	config := &ssh.ServerConfig{
		ServerVersion: "SSH-2.0-SshReverseProxy",
		PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
			if c.User() == "dolf" {
				var err error
				*rClient, err = getRemoteSshClient("localhost", "2222", c.User(), string(pass))
				if err != nil {
					return nil, fmt.Errorf("password rejected for %q: %s", c.User(), err)
				}
				return nil, nil
			}
			return nil, fmt.Errorf("Unknown user %q", c.User())
		},
	}

	privateBytes, err := ioutil.ReadFile("id_rsa")
	if err != nil {
		panic("Failed to load private key")
	}

	private, err := ssh.ParsePrivateKey(privateBytes)
	if err != nil {
		panic("Failed to parse private key")
	}

	config.AddHostKey(private)
	return config
}

func getRemoteSshClient(host, portStr, user, password string) (*ssh.Client, error) {
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
	}
	port, err := strconv.ParseInt(portStr, 10, 64)
	if err != nil {
		panic("Port must be an integer")
	}

	conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", host, port), config)
	if err != nil {
		return nil, fmt.Errorf("unable to connect: " + err.Error())
	}

	return conn, nil
}

func pipeRequests(lChannel, rChannel ssh.Channel, lRequests, rRequests <-chan *ssh.Request) {
	defer func() {
		return
		if r := recover(); r != nil {
			fmt.Println("Recovered in f", r)
		}
	}()
	defer rChannel.Close()
	defer lChannel.Close()

	for {
		select {
		case lRequest, ok := <-lRequests:
			if !ok {
				return
			}
			if err := forwardRequest(lRequest, rChannel); err != nil {
				fmt.Println("Error: " + err.Error())
				continue
			}
		case rRequest, ok := <-rRequests:
			if !ok {
				return
			}
			if err := forwardRequest(rRequest, lChannel); err != nil {
				fmt.Println("Error: " + err.Error())
				continue
			}
		}
	}
}

func forwardRequest(req *ssh.Request, channel ssh.Channel) error {
	if string(req.Type) != "subsystem" && string(req.Type) != "exit-status" {
		req.Reply(false, nil)
		return fmt.Errorf("Ignoring unsupported request type: %s", string(req.Type))
	}
	reply, err := channel.SendRequest(req.Type, req.WantReply, req.Payload)
	if err != nil {
		return err
	}
	if req.WantReply {
		req.Reply(reply, nil)
	}

	return nil
}
<|endoftext|>


<commit_before>package nyaafeeds

// rss support
// validation done according to spec here:
//    http://cyber.law.harvard.edu/rss/rss.html

import (
	"encoding/xml"
	"fmt"
	"strconv"
	"time"

	"github.com/gorilla/feeds"
)

// private wrapper around the RssFeed which gives us the <rss>..</rss> xml
type rssFeedXML struct {
	XMLName  xml.Name `xml:"rss"`
	Version  string   `xml:"version,attr"`
	Encoding string   `xml:"encoding,attr"`
	Channel  *RssFeed `xml:"channel,omitempty"`
	Caps     *RssCaps `xml:"caps,omitempty"`
}

type RssImage struct {
	XMLName xml.Name `xml:"image"`
	URL     string   `xml:"url"`
	Title   string   `xml:"title"`
	Link    string   `xml:"link"`
	Width   int      `xml:"width,omitempty"`
	Height  int      `xml:"height,omitempty"`
}

type RssTextInput struct {
	XMLName     xml.Name `xml:"textInput"`
	Title       string   `xml:"title"`
	Description string   `xml:"description"`
	Name        string   `xml:"name"`
	Link        string   `xml:"link"`
}

type RssFeed struct {
	XMLName        xml.Name `xml:"channel"`
	Title          string   `xml:"title"`       // required
	Link           string   `xml:"link"`        // required
	Description    string   `xml:"description"` // required
	Language       string   `xml:"language,omitempty"`
	Copyright      string   `xml:"copyright,omitempty"`
	ManagingEditor string   `xml:"managingEditor,omitempty"` // Author used
	WebMaster      string   `xml:"webMaster,omitempty"`
	PubDate        string   `xml:"pubDate,omitempty"`       // created or updated
	LastBuildDate  string   `xml:"lastBuildDate,omitempty"` // updated used
	Category       string   `xml:"category,omitempty"`
	Generator      string   `xml:"generator,omitempty"`
	Docs           string   `xml:"docs,omitempty"`
	Cloud          string   `xml:"cloud,omitempty"`
	TTL            int      `xml:"ttl,omitempty"`
	Rating         string   `xml:"rating,omitempty"`
	SkipHours      string   `xml:"skipHours,omitempty"`
	SkipDays       string   `xml:"skipDays,omitempty"`
	Image          *RssImage
	TextInput      *RssTextInput
	Items          []*RssItem
}

type RssItem struct {
	XMLName     xml.Name     `xml:"item"`
	Title       string       `xml:"title"`       // required
	Link        string       `xml:"link"`        // required
	Description string       `xml:"description"` // required
	Author      string       `xml:"author,omitempty"`
	Category    *RssCategory `xml:"category,omitempty"`
	Comments    string       `xml:"comments,omitempty"`
	Enclosure   *RssEnclosure
	GUID        string      `xml:"guid,omitempty"`    // Id used
	PubDate     string      `xml:"pubDate,omitempty"` // created or updated
	Source      string      `xml:"source,omitempty"`
	Torrent     *RssTorrent `xml:"torrent,omitempty"`
	Torznab     *RssTorznab `xml:"torznab,omitempty"`
}

type RssCaps struct {
	XMLName      xml.Name         `xml:"caps"`
	Server       *RssServer       `xml:"server,omitempty"`
	Limits       *RssLimits       `xml:"limits,omitempty"`
	Registration *RssRegistration `xml:"registration,omitempty"`
	Searching    *RssSearching    `xml:"searching,omitempty"`
	Categories   *RssCategories   `xml:"categories,omitempty"`
}

type RssServer struct {
	XMLName   xml.Name `xml:"server"`
	Xmlns     string   `xml:"xmlns,attr"`
	Version   string   `xml:"version,attr"`
	Title     string   `xml:"title,attr"`
	Strapline string   `xml:"strapline,attr"`
	Email     string   `xml:"email,attr"`
	URL       string   `xml:"url,attr"`
	Image     string   `xml:"image,attr"`
}

type RssLimits struct {
	XMLName xml.Name `xml:"limits"`
	Max     string   `xml:"limits,attr"`
	Default string   `xml:"default,attr"`
}

type RssRegistration struct {
	XMLName   xml.Name `xml:"registration"`
	Available string   `xml:"available,attr"`
	Open      string   `xml:"open,attr"`
}

type RssSearching struct {
	XMLName     xml.Name   `xml:"searching"`
	Search      *RssSearch `xml:"search,omitempty"`
	TvSearch    *RssSearch `xml:"tv-search,omitempty"`
	MovieSearch *RssSearch `xml:"movie-search,omitempty"`
}

type RssSearch struct {
	Available       string `xml:"available,attr"`
	SupportedParams string `xml:"supportedParams,attr,omitempty"`
}

type RssCategories struct {
	XMLName  xml.Name `xml:"categories"`
	Category []*RssCategoryTorznab
}

type RssCategoryTorznab struct {
	XMLName     xml.Name `xml:"category"`
	ID          string   `xml:"id,attr"`
	Name        string   `xml:"name,attr"`
	Subcat      []*RssSubCat
	Description string `xml:"description,attr,omitempty"`
}

type RssSubCat struct {
	XMLName     xml.Name `xml:"subcat"`
	ID          string   `xml:"id"`
	Name        string   `xml:"name"`
	Description string   `xml:"description,omitempty"`
}

type RssTorrent struct {
	XMLName       xml.Name `xml:"torrent"`
	Xmlns         string   `xml:"xmlns,attr"`
	FileName      string   `xml:"fileName,omitempty"`
	ContentLength string   `xml:"contentLength,omitempty"`
	InfoHash      string   `xml:"infoHash,omitempty"`
	MagnetURI     string   `xml:"magnetUri,omitempty"`
}

type RssTorznab struct {
	XMLName              xml.Name `xml:"torznab"`
	Xmlns                string   `xml:"xmlns,attr"`
	Type                 string   `xml:"type,omitempty"`
	Size                 string   `xml:"size,omitempty"`
	Files                string   `xml:"files,omitempty"`
	Grabs                string   `xml:"grabs,omitempty"`
	Tvdbid               string   `xml:"tvdbid,omitempty"`
	Rageid               string   `xml:"rageid,omitempty"`
	Tvmazeid             string   `xml:"tvmazeid,omitempty"`
	Imdb                 string   `xml:"imdb,omitempty"`
	BannerURL            string   `xml:"bannerurl,omitempty"`
	Infohash             string   `xml:"infohash,omitempty"`
	MagnetURL            string   `xml:"magneturl,omitempty"`
	Seeders              string   `xml:"seeders,omitempty"`
	Leechers             string   `xml:"leechers,omitempty"`
	Peers                string   `xml:"peers,omitempty"`
	SeedType             string   `xml:"seedtype,omitempty"`
	MinimumRatio         string   `xml:"minimumratio,omitempty"`
	MinimumSeedTime      string   `xml:"minimumseedtime,omitempty"`
	DownloadVolumeFactor string   `xml:"downloadvolumefactor,omitempty"`
	UploadVolumeFactor   string   `xml:"uploadvolumefactor,omitempty"`
}

// RssCategory is a category for rss item
type RssCategory struct {
	XMLName xml.Name `xml:"category"`
	Domain  string   `xml:"domain"`
}

type RssEnclosure struct {
	//RSS 2.0 <enclosure url="http://example.com/file.mp3" length="123456789" type="audio/mpeg" />
	XMLName xml.Name `xml:"enclosure"`
	URL     string   `xml:"url,attr"`
	Length  string   `xml:"length,attr"`
	Type    string   `xml:"type,attr"`
}

type Rss struct {
	*feeds.Feed
}

// create a new RssItem with a generic Item struct's data
func newRssItem(i *feeds.Item) *RssItem {
	item := &RssItem{
		Title:       i.Title,
		Link:        i.Link.Href,
		Description: i.Description,
		GUID:        i.Id,
		PubDate:     anyTimeFormat(time.RFC1123Z, i.Created, i.Updated),
	}

	intLength, err := strconv.ParseInt(i.Link.Length, 10, 64)

	if err == nil && (intLength > 0 || i.Link.Type != "") {
		item.Enclosure = &RssEnclosure{URL: i.Link.Href, Type: i.Link.Type, Length: i.Link.Length}
	}
	if i.Author != nil {
		item.Author = i.Author.Name
	}
	return item
}

// returns the first non-zero time formatted as a string or ""
func anyTimeFormat(format string, times ...time.Time) string {
	for _, t := range times {
		if !t.IsZero() {
			return t.Format(format)
		}
	}
	return ""
}

// RssFeed : create a new RssFeed with a generic Feed struct's data
func (r *Rss) RssFeed() *RssFeed {
	pub := anyTimeFormat(time.RFC1123Z, r.Created, r.Updated)
	build := anyTimeFormat(time.RFC1123Z, r.Updated)
	author := ""
	if r.Author != nil {
		author = r.Author.Email
		if len(r.Author.Name) > 0 {
			author = fmt.Sprintf("%s (%s)", r.Author.Email, r.Author.Name)
		}
	}

	channel := &RssFeed{
		Title:          r.Title,
		Link:           r.Link.Href,
		Description:    r.Description,
		ManagingEditor: author,
		PubDate:        pub,
		LastBuildDate:  build,
		Copyright:      r.Copyright,
	}
	for _, i := range r.Items {
		channel.Items = append(channel.Items, newRssItem(i))
	}
	return channel
}

// FeedXml : return an XML-Ready object for an Rss object
func (r *Rss) FeedXml() interface{} {
	// only generate version 2.0 feeds for now
	return r.RssFeed().FeedXml()

}

// FeedXml : return an XML-ready object for an RssFeed object
func (r *RssFeed) FeedXml() interface{} {
	return &rssFeedXML{Version: "2.0", Encoding: "UTF-8", Channel: r}
}

// FeedXml : return an XML-ready object for an RssFeed object
func (r *RssCaps) FeedXml() interface{} {
	return &rssFeedXML{Version: "2.0", Encoding: "UTF-8", Caps: r}
}
<commit_msg>Forgot subcat have attr not tags<commit_after>package nyaafeeds

// rss support
// validation done according to spec here:
//    http://cyber.law.harvard.edu/rss/rss.html

import (
	"encoding/xml"
	"fmt"
	"strconv"
	"time"

	"github.com/gorilla/feeds"
)

// private wrapper around the RssFeed which gives us the <rss>..</rss> xml
type rssFeedXML struct {
	XMLName  xml.Name `xml:"rss"`
	Version  string   `xml:"version,attr"`
	Encoding string   `xml:"encoding,attr"`
	Channel  *RssFeed `xml:"channel,omitempty"`
	Caps     *RssCaps `xml:"caps,omitempty"`
}

type RssImage struct {
	XMLName xml.Name `xml:"image"`
	URL     string   `xml:"url"`
	Title   string   `xml:"title"`
	Link    string   `xml:"link"`
	Width   int      `xml:"width,omitempty"`
	Height  int      `xml:"height,omitempty"`
}

type RssTextInput struct {
	XMLName     xml.Name `xml:"textInput"`
	Title       string   `xml:"title"`
	Description string   `xml:"description"`
	Name        string   `xml:"name"`
	Link        string   `xml:"link"`
}

type RssFeed struct {
	XMLName        xml.Name `xml:"channel"`
	Title          string   `xml:"title"`       // required
	Link           string   `xml:"link"`        // required
	Description    string   `xml:"description"` // required
	Language       string   `xml:"language,omitempty"`
	Copyright      string   `xml:"copyright,omitempty"`
	ManagingEditor string   `xml:"managingEditor,omitempty"` // Author used
	WebMaster      string   `xml:"webMaster,omitempty"`
	PubDate        string   `xml:"pubDate,omitempty"`       // created or updated
	LastBuildDate  string   `xml:"lastBuildDate,omitempty"` // updated used
	Category       string   `xml:"category,omitempty"`
	Generator      string   `xml:"generator,omitempty"`
	Docs           string   `xml:"docs,omitempty"`
	Cloud          string   `xml:"cloud,omitempty"`
	TTL            int      `xml:"ttl,omitempty"`
	Rating         string   `xml:"rating,omitempty"`
	SkipHours      string   `xml:"skipHours,omitempty"`
	SkipDays       string   `xml:"skipDays,omitempty"`
	Image          *RssImage
	TextInput      *RssTextInput
	Items          []*RssItem
}

type RssItem struct {
	XMLName     xml.Name     `xml:"item"`
	Title       string       `xml:"title"`       // required
	Link        string       `xml:"link"`        // required
	Description string       `xml:"description"` // required
	Author      string       `xml:"author,omitempty"`
	Category    *RssCategory `xml:"category,omitempty"`
	Comments    string       `xml:"comments,omitempty"`
	Enclosure   *RssEnclosure
	GUID        string      `xml:"guid,omitempty"`    // Id used
	PubDate     string      `xml:"pubDate,omitempty"` // created or updated
	Source      string      `xml:"source,omitempty"`
	Torrent     *RssTorrent `xml:"torrent,omitempty"`
	Torznab     *RssTorznab `xml:"torznab,omitempty"`
}

type RssCaps struct {
	XMLName      xml.Name         `xml:"caps"`
	Server       *RssServer       `xml:"server,omitempty"`
	Limits       *RssLimits       `xml:"limits,omitempty"`
	Registration *RssRegistration `xml:"registration,omitempty"`
	Searching    *RssSearching    `xml:"searching,omitempty"`
	Categories   *RssCategories   `xml:"categories,omitempty"`
}

type RssServer struct {
	XMLName   xml.Name `xml:"server"`
	Xmlns     string   `xml:"xmlns,attr"`
	Version   string   `xml:"version,attr"`
	Title     string   `xml:"title,attr"`
	Strapline string   `xml:"strapline,attr"`
	Email     string   `xml:"email,attr"`
	URL       string   `xml:"url,attr"`
	Image     string   `xml:"image,attr"`
}

type RssLimits struct {
	XMLName xml.Name `xml:"limits"`
	Max     string   `xml:"limits,attr"`
	Default string   `xml:"default,attr"`
}

type RssRegistration struct {
	XMLName   xml.Name `xml:"registration"`
	Available string   `xml:"available,attr"`
	Open      string   `xml:"open,attr"`
}

type RssSearching struct {
	XMLName     xml.Name   `xml:"searching"`
	Search      *RssSearch `xml:"search,omitempty"`
	TvSearch    *RssSearch `xml:"tv-search,omitempty"`
	MovieSearch *RssSearch `xml:"movie-search,omitempty"`
}

type RssSearch struct {
	Available       string `xml:"available,attr"`
	SupportedParams string `xml:"supportedParams,attr,omitempty"`
}

type RssCategories struct {
	XMLName  xml.Name `xml:"categories"`
	Category []*RssCategoryTorznab
}

type RssCategoryTorznab struct {
	XMLName     xml.Name `xml:"category"`
	ID          string   `xml:"id,attr"`
	Name        string   `xml:"name,attr"`
	Subcat      []*RssSubCat
	Description string `xml:"description,attr,omitempty"`
}

type RssSubCat struct {
	XMLName     xml.Name `xml:"subcat"`
	ID          string   `xml:"id,attr"`
	Name        string   `xml:"name,attr"`
	Description string   `xml:"description,attr,omitempty"`
}

type RssTorrent struct {
	XMLName       xml.Name `xml:"torrent"`
	Xmlns         string   `xml:"xmlns,attr"`
	FileName      string   `xml:"fileName,omitempty"`
	ContentLength string   `xml:"contentLength,omitempty"`
	InfoHash      string   `xml:"infoHash,omitempty"`
	MagnetURI     string   `xml:"magnetUri,omitempty"`
}

type RssTorznab struct {
	XMLName              xml.Name `xml:"torznab"`
	Xmlns                string   `xml:"xmlns,attr"`
	Type                 string   `xml:"type,omitempty"`
	Size                 string   `xml:"size,omitempty"`
	Files                string   `xml:"files,omitempty"`
	Grabs                string   `xml:"grabs,omitempty"`
	Tvdbid               string   `xml:"tvdbid,omitempty"`
	Rageid               string   `xml:"rageid,omitempty"`
	Tvmazeid             string   `xml:"tvmazeid,omitempty"`
	Imdb                 string   `xml:"imdb,omitempty"`
	BannerURL            string   `xml:"bannerurl,omitempty"`
	Infohash             string   `xml:"infohash,omitempty"`
	MagnetURL            string   `xml:"magneturl,omitempty"`
	Seeders              string   `xml:"seeders,omitempty"`
	Leechers             string   `xml:"leechers,omitempty"`
	Peers                string   `xml:"peers,omitempty"`
	SeedType             string   `xml:"seedtype,omitempty"`
	MinimumRatio         string   `xml:"minimumratio,omitempty"`
	MinimumSeedTime      string   `xml:"minimumseedtime,omitempty"`
	DownloadVolumeFactor string   `xml:"downloadvolumefactor,omitempty"`
	UploadVolumeFactor   string   `xml:"uploadvolumefactor,omitempty"`
}

// RssCategory is a category for rss item
type RssCategory struct {
	XMLName xml.Name `xml:"category"`
	Domain  string   `xml:"domain"`
}

type RssEnclosure struct {
	//RSS 2.0 <enclosure url="http://example.com/file.mp3" length="123456789" type="audio/mpeg" />
	XMLName xml.Name `xml:"enclosure"`
	URL     string   `xml:"url,attr"`
	Length  string   `xml:"length,attr"`
	Type    string   `xml:"type,attr"`
}

type Rss struct {
	*feeds.Feed
}

// create a new RssItem with a generic Item struct's data
func newRssItem(i *feeds.Item) *RssItem {
	item := &RssItem{
		Title:       i.Title,
		Link:        i.Link.Href,
		Description: i.Description,
		GUID:        i.Id,
		PubDate:     anyTimeFormat(time.RFC1123Z, i.Created, i.Updated),
	}

	intLength, err := strconv.ParseInt(i.Link.Length, 10, 64)

	if err == nil && (intLength > 0 || i.Link.Type != "") {
		item.Enclosure = &RssEnclosure{URL: i.Link.Href, Type: i.Link.Type, Length: i.Link.Length}
	}
	if i.Author != nil {
		item.Author = i.Author.Name
	}
	return item
}

// returns the first non-zero time formatted as a string or ""
func anyTimeFormat(format string, times ...time.Time) string {
	for _, t := range times {
		if !t.IsZero() {
			return t.Format(format)
		}
	}
	return ""
}

// RssFeed : create a new RssFeed with a generic Feed struct's data
func (r *Rss) RssFeed() *RssFeed {
	pub := anyTimeFormat(time.RFC1123Z, r.Created, r.Updated)
	build := anyTimeFormat(time.RFC1123Z, r.Updated)
	author := ""
	if r.Author != nil {
		author = r.Author.Email
		if len(r.Author.Name) > 0 {
			author = fmt.Sprintf("%s (%s)", r.Author.Email, r.Author.Name)
		}
	}

	channel := &RssFeed{
		Title:          r.Title,
		Link:           r.Link.Href,
		Description:    r.Description,
		ManagingEditor: author,
		PubDate:        pub,
		LastBuildDate:  build,
		Copyright:      r.Copyright,
	}
	for _, i := range r.Items {
		channel.Items = append(channel.Items, newRssItem(i))
	}
	return channel
}

// FeedXml : return an XML-Ready object for an Rss object
func (r *Rss) FeedXml() interface{} {
	// only generate version 2.0 feeds for now
	return r.RssFeed().FeedXml()

}

// FeedXml : return an XML-ready object for an RssFeed object
func (r *RssFeed) FeedXml() interface{} {
	return &rssFeedXML{Version: "2.0", Encoding: "UTF-8", Channel: r}
}

// FeedXml : return an XML-ready object for an RssFeed object
func (r *RssCaps) FeedXml() interface{} {
	return &rssFeedXML{Version: "2.0", Encoding: "UTF-8", Caps: r}
}
<|endoftext|>


<commit_before>// Copyright 2012 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 (
	"runtime"
	"testing"
)

type I1 interface {
	Method1()
}

type I2 interface {
	Method1()
	Method2()
}

type TS uint16
type TM uintptr
type TL [2]uintptr

func (TS) Method1() {}
func (TS) Method2() {}
func (TM) Method1() {}
func (TM) Method2() {}
func (TL) Method1() {}
func (TL) Method2() {}

var (
	e  interface{}
	e_ interface{}
	i1 I1
	i2 I2
	ts TS
	tm TM
	tl TL
	ok bool
)

// Issue 9370
func TestCmpIfaceConcreteAlloc(t *testing.T) {
	if runtime.Compiler != "gc" {
		t.Skip("skipping on non-gc compiler")
	}

	n := testing.AllocsPerRun(1, func() {
		_ = e == ts
		_ = i1 == ts
		_ = e == 1
	})

	if n > 0 {
		t.Fatalf("iface cmp allocs=%v; want 0", n)
	}
}

func BenchmarkEqEfaceConcrete(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = e == ts
	}
}

func BenchmarkEqIfaceConcrete(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = i1 == ts
	}
}

func BenchmarkNeEfaceConcrete(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = e != ts
	}
}

func BenchmarkNeIfaceConcrete(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = i1 != ts
	}
}

func BenchmarkConvT2ESmall(b *testing.B) {
	for i := 0; i < b.N; i++ {
		e = ts
	}
}

func BenchmarkConvT2EUintptr(b *testing.B) {
	for i := 0; i < b.N; i++ {
		e = tm
	}
}

func BenchmarkConvT2ELarge(b *testing.B) {
	for i := 0; i < b.N; i++ {
		e = tl
	}
}

func BenchmarkConvT2ISmall(b *testing.B) {
	for i := 0; i < b.N; i++ {
		i1 = ts
	}
}

func BenchmarkConvT2IUintptr(b *testing.B) {
	for i := 0; i < b.N; i++ {
		i1 = tm
	}
}

func BenchmarkConvT2ILarge(b *testing.B) {
	for i := 0; i < b.N; i++ {
		i1 = tl
	}
}

func BenchmarkConvI2E(b *testing.B) {
	i2 = tm
	for i := 0; i < b.N; i++ {
		e = i2
	}
}

func BenchmarkConvI2I(b *testing.B) {
	i2 = tm
	for i := 0; i < b.N; i++ {
		i1 = i2
	}
}

func BenchmarkAssertE2T(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		tm = e.(TM)
	}
}

func BenchmarkAssertE2TLarge(b *testing.B) {
	e = tl
	for i := 0; i < b.N; i++ {
		tl = e.(TL)
	}
}

func BenchmarkAssertE2I(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		i1 = e.(I1)
	}
}

func BenchmarkAssertI2T(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		tm = i1.(TM)
	}
}

func BenchmarkAssertI2I(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		i2 = i1.(I2)
	}
}

func BenchmarkAssertI2E(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		e = i1.(interface{})
	}
}

func BenchmarkAssertE2E(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		e_ = e
	}
}

func BenchmarkAssertE2T2(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		tm, ok = e.(TM)
	}
}

func BenchmarkAssertE2T2Blank(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		_, ok = e.(TM)
	}
}

func BenchmarkAssertI2E2(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		e, ok = i1.(interface{})
	}
}

func BenchmarkAssertI2E2Blank(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		_, ok = i1.(interface{})
	}
}

func BenchmarkAssertE2E2(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		e_, ok = e.(interface{})
	}
}

func BenchmarkAssertE2E2Blank(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		_, ok = e.(interface{})
	}
}

func TestNonEscapingConvT2E(t *testing.T) {
	m := make(map[interface{}]bool)
	m[42] = true
	if !m[42] {
		t.Fatalf("42 is not present in the map")
	}
	if m[0] {
		t.Fatalf("0 is present in the map")
	}

	n := testing.AllocsPerRun(1000, func() {
		if m[0] {
			t.Fatalf("0 is present in the map")
		}
	})
	if n != 0 {
		t.Fatalf("want 0 allocs, got %v", n)
	}
}

func TestNonEscapingConvT2I(t *testing.T) {
	m := make(map[I1]bool)
	m[TM(42)] = true
	if !m[TM(42)] {
		t.Fatalf("42 is not present in the map")
	}
	if m[TM(0)] {
		t.Fatalf("0 is present in the map")
	}

	n := testing.AllocsPerRun(1000, func() {
		if m[TM(0)] {
			t.Fatalf("0 is present in the map")
		}
	})
	if n != 0 {
		t.Fatalf("want 0 allocs, got %v", n)
	}
}
<commit_msg>runtime: disable allocations test on gccgo<commit_after>// Copyright 2012 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 (
	"runtime"
	"testing"
)

type I1 interface {
	Method1()
}

type I2 interface {
	Method1()
	Method2()
}

type TS uint16
type TM uintptr
type TL [2]uintptr

func (TS) Method1() {}
func (TS) Method2() {}
func (TM) Method1() {}
func (TM) Method2() {}
func (TL) Method1() {}
func (TL) Method2() {}

var (
	e  interface{}
	e_ interface{}
	i1 I1
	i2 I2
	ts TS
	tm TM
	tl TL
	ok bool
)

// Issue 9370
func TestCmpIfaceConcreteAlloc(t *testing.T) {
	if runtime.Compiler != "gc" {
		t.Skip("skipping on non-gc compiler")
	}

	n := testing.AllocsPerRun(1, func() {
		_ = e == ts
		_ = i1 == ts
		_ = e == 1
	})

	if n > 0 {
		t.Fatalf("iface cmp allocs=%v; want 0", n)
	}
}

func BenchmarkEqEfaceConcrete(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = e == ts
	}
}

func BenchmarkEqIfaceConcrete(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = i1 == ts
	}
}

func BenchmarkNeEfaceConcrete(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = e != ts
	}
}

func BenchmarkNeIfaceConcrete(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = i1 != ts
	}
}

func BenchmarkConvT2ESmall(b *testing.B) {
	for i := 0; i < b.N; i++ {
		e = ts
	}
}

func BenchmarkConvT2EUintptr(b *testing.B) {
	for i := 0; i < b.N; i++ {
		e = tm
	}
}

func BenchmarkConvT2ELarge(b *testing.B) {
	for i := 0; i < b.N; i++ {
		e = tl
	}
}

func BenchmarkConvT2ISmall(b *testing.B) {
	for i := 0; i < b.N; i++ {
		i1 = ts
	}
}

func BenchmarkConvT2IUintptr(b *testing.B) {
	for i := 0; i < b.N; i++ {
		i1 = tm
	}
}

func BenchmarkConvT2ILarge(b *testing.B) {
	for i := 0; i < b.N; i++ {
		i1 = tl
	}
}

func BenchmarkConvI2E(b *testing.B) {
	i2 = tm
	for i := 0; i < b.N; i++ {
		e = i2
	}
}

func BenchmarkConvI2I(b *testing.B) {
	i2 = tm
	for i := 0; i < b.N; i++ {
		i1 = i2
	}
}

func BenchmarkAssertE2T(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		tm = e.(TM)
	}
}

func BenchmarkAssertE2TLarge(b *testing.B) {
	e = tl
	for i := 0; i < b.N; i++ {
		tl = e.(TL)
	}
}

func BenchmarkAssertE2I(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		i1 = e.(I1)
	}
}

func BenchmarkAssertI2T(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		tm = i1.(TM)
	}
}

func BenchmarkAssertI2I(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		i2 = i1.(I2)
	}
}

func BenchmarkAssertI2E(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		e = i1.(interface{})
	}
}

func BenchmarkAssertE2E(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		e_ = e
	}
}

func BenchmarkAssertE2T2(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		tm, ok = e.(TM)
	}
}

func BenchmarkAssertE2T2Blank(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		_, ok = e.(TM)
	}
}

func BenchmarkAssertI2E2(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		e, ok = i1.(interface{})
	}
}

func BenchmarkAssertI2E2Blank(b *testing.B) {
	i1 = tm
	for i := 0; i < b.N; i++ {
		_, ok = i1.(interface{})
	}
}

func BenchmarkAssertE2E2(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		e_, ok = e.(interface{})
	}
}

func BenchmarkAssertE2E2Blank(b *testing.B) {
	e = tm
	for i := 0; i < b.N; i++ {
		_, ok = e.(interface{})
	}
}

func TestNonEscapingConvT2E(t *testing.T) {
	if runtime.Compiler == "gccgo" {
		t.Skip("does not work on gccgo without better escape analysis")
	}

	m := make(map[interface{}]bool)
	m[42] = true
	if !m[42] {
		t.Fatalf("42 is not present in the map")
	}
	if m[0] {
		t.Fatalf("0 is present in the map")
	}

	n := testing.AllocsPerRun(1000, func() {
		if m[0] {
			t.Fatalf("0 is present in the map")
		}
	})
	if n != 0 {
		t.Fatalf("want 0 allocs, got %v", n)
	}
}

func TestNonEscapingConvT2I(t *testing.T) {
	if runtime.Compiler == "gccgo" {
		t.Skip("does not work on gccgo without better escape analysis")
	}

	m := make(map[I1]bool)
	m[TM(42)] = true
	if !m[TM(42)] {
		t.Fatalf("42 is not present in the map")
	}
	if m[TM(0)] {
		t.Fatalf("0 is present in the map")
	}

	n := testing.AllocsPerRun(1000, func() {
		if m[TM(0)] {
			t.Fatalf("0 is present in the map")
		}
	})
	if n != 0 {
		t.Fatalf("want 0 allocs, got %v", n)
	}
}
<|endoftext|>


<commit_before>package util

import (
	"os"
	"strings"
	"testing"
)

func TestGetPathPaths(t *testing.T) {
	dirPath, fileName, absPath := GetPathParts("/bin/sh")
	if dirPath != "/bin" {
		t.Fail()
	}
	if fileName != "sh" {
		t.Fail()
	}
	if absPath != "/bin/sh" {
		t.Fail()
	}
}

func TestGetThisPathParts(t *testing.T) {
	dirPath, fileName, absPath := GetThisPathParts()
	if !strings.Contains(dirPath,
		"github.com/codedellemc/dvdcli/util/_test") {
		t.Fail()
	}
	if fileName != "util.test" {
		t.Fail()
	}
	if !strings.Contains(absPath,
		"github.com/codedellemc/dvdcli/util/_test/util.test") {
		t.Fail()
	}
}

func TestPrintVersion(t *testing.T) {
	PrintVersion(os.Stdout)
}
<commit_msg>Fix failing util test<commit_after>package util

import (
	"os"
	"strings"
	"testing"
)

func TestGetPathPaths(t *testing.T) {
	dirPath, fileName, absPath := GetPathParts("/bin/sh")
	if dirPath != "/bin" {
		t.Fail()
	}
	if fileName != "sh" {
		t.Fail()
	}
	if absPath != "/bin/sh" {
		t.Fail()
	}
}

func TestGetThisPathParts(t *testing.T) {
	t.Skip()
	dirPath, fileName, absPath := GetThisPathParts()
	t.Logf("dirPath=%s, fileName=%s, absPath=%s\n", dirPath, fileName, absPath)
	if !strings.Contains(dirPath,
		"github.com/rexray/dvdcli/util/_test") {
		t.Fail()
	}
	if fileName != "util.test" {
		t.Fail()
	}
	if !strings.Contains(absPath,
		"github.com/rexray/dvdcli/util/_test/util.test") {
		t.Fail()
	}
}

func TestPrintVersion(t *testing.T) {
	PrintVersion(os.Stdout)
}
<|endoftext|>


<commit_before>package util

import (
	"testing"
	"time"

	"github.com/stretchr/testify/suite"
)

type Suite struct {
	suite.Suite
}

func (suite *Suite) TestNewTimePeriod() {
	timezone, err := time.LoadLocation("Australia/Brisbane")
	suite.Require().NoError(err)

	for _, tt := range []struct {
		from     time.Time
		to       time.Time
		expected TimePeriod
	}{
		// when it's already normalized
		{
			time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
			time.Date(0, 0, 0, 16, 04, 05, 06, time.UTC),
			TimePeriod{
				From: time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
				To:   time.Date(0, 0, 0, 16, 04, 05, 06, time.UTC),
			},
		},
		// it normalizes to very first day
		{
			time.Date(1869, 9, 24, 15, 04, 05, 06, time.UTC),
			time.Date(1869, 9, 24, 16, 04, 05, 06, time.UTC),
			TimePeriod{
				From: time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
				To:   time.Date(0, 0, 0, 16, 04, 05, 06, time.UTC),
			},
		},
		// it ignores the timezone
		{
			time.Date(1869, 9, 24, 15, 04, 05, 06, timezone),
			time.Date(1869, 9, 24, 16, 04, 05, 06, timezone),
			TimePeriod{
				From: time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
				To:   time.Date(0, 0, 0, 16, 04, 05, 06, time.UTC),
			},
		},
	} {
		suite.Equal(tt.expected, NewTimePeriod(tt.from, tt.to))
	}
}

func (suite *Suite) TestTimePeriodIncludes() {
	atTheMoment := NewTimePeriod(
		time.Now().Add(-1*time.Minute),
		time.Now().Add(+1*time.Minute),
	)
	midnight := NewTimePeriod(
		time.Date(1869, 9, 23, 23, 00, 00, 00, time.UTC),
		time.Date(1869, 9, 24, 01, 00, 00, 00, time.UTC),
	)
	now := time.Now()

	for _, tt := range []struct {
		pointInTime time.Time
		timeOfDay   TimePeriod
		expected    bool
	}{
		// it's included
		{
			now,
			atTheMoment,
			true,
		},
		// it's one day before
		{
			now.Add(-24 * time.Hour),
			atTheMoment,
			true,
		},
		// it's one day after
		{
			now.Add(+24 * time.Hour),
			atTheMoment,
			true,
		},
		// it's just before
		{
			now.Add(-2 * time.Minute),
			atTheMoment,
			false,
		},
		// it's just after
		{
			now.Add(+2 * time.Minute),
			atTheMoment,
			false,
		},
		// it's slightly inside before day switch
		{
			time.Date(1869, 9, 23, 23, 30, 00, 00, time.UTC),
			midnight,
			true,
		},
		// it's slightly inside after day switch
		{
			time.Date(1869, 9, 24, 00, 30, 00, 00, time.UTC),
			midnight,
			true,
		},
		// it's just before
		{
			time.Date(1869, 9, 23, 22, 30, 00, 00, time.UTC),
			midnight,
			false,
		},
		// it's just after
		{
			time.Date(1869, 9, 24, 01, 30, 00, 00, time.UTC),
			midnight,
			false,
		},
		// it's exactly matching a point in time
		{
			now,
			TimePeriod{From: TimeOfDay(now), To: TimeOfDay(now)},
			true,
		},
		// it's right after exactly matching a point in time
		{
			now.Add(+1 * time.Second),
			TimePeriod{From: TimeOfDay(now), To: TimeOfDay(now)},
			false,
		},
		// it's right before exactly matching a point in time
		{
			now.Add(-1 * time.Second),
			TimePeriod{From: TimeOfDay(now), To: TimeOfDay(now)},
			false,
		},
	} {
		suite.Equal(tt.expected, tt.timeOfDay.Includes(tt.pointInTime))
	}
}

func (suite *Suite) TestTimePeriodString() {
	for _, tt := range []struct {
		given    TimePeriod
		expected string
	}{
		// empty time period
		{
			TimePeriod{},
			"00:00-00:00",
		},
		// simple time period
		{
			TimePeriod{
				From: time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
				To:   time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
			},
			"08:00-16:00",
		},
		// time period across days
		{
			TimePeriod{
				From: time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
				To:   time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
			},
			"16:00-08:00",
		},
	} {
		suite.Equal(tt.expected, tt.given.String())
	}
}

func (suite *Suite) TestTimeOfDay() {
	timezone, err := time.LoadLocation("Australia/Brisbane")
	suite.Require().NoError(err)

	for _, tt := range []struct {
		pointInTime time.Time
		expected    time.Time
	}{
		// strips of any day information
		{
			time.Date(1869, 9, 24, 15, 04, 05, 06, time.UTC),
			time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
		},
		// it normalizes to UTC timezone
		{
			time.Date(1869, 9, 24, 15, 04, 05, 06, timezone),
			time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
		},
	} {
		suite.Equal(tt.expected, TimeOfDay(tt.pointInTime))
	}
}

func (suite *Suite) TestParseWeekdays() {
	for _, tt := range []struct {
		given    string
		expected []time.Weekday
	}{
		// empty string
		{
			"",
			[]time.Weekday{},
		},
		// single weekday
		{
			"sat",
			[]time.Weekday{time.Saturday},
		},
		// multiple weekdays
		{
			"sat,sun",
			[]time.Weekday{time.Saturday, time.Sunday},
		},
		// case-insensitive
		{
			"SaT,SUn",
			[]time.Weekday{time.Saturday, time.Sunday},
		},
		// ignore whitespace
		{
			" sat , sun ",
			[]time.Weekday{time.Saturday, time.Sunday},
		},
		// ignore unknown weekdays
		{
			"sat,unknown,sun",
			[]time.Weekday{time.Saturday, time.Sunday},
		},
		// deal with all kinds at the same time
		{
			"Fri, sat ,,,,  ,foobar,tue",
			[]time.Weekday{time.Friday, time.Saturday, time.Tuesday},
		},
	} {
		suite.Equal(tt.expected, ParseWeekdays(tt.given))
	}
}

func (suite *Suite) TestParseTimePeriods() {
	for _, tt := range []struct {
		given    string
		expected []TimePeriod
	}{
		// empty time period string
		{
			"",
			[]TimePeriod{},
		},
		// single range string
		{
			"08:00-16:00",
			[]TimePeriod{
				{
					From: time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
				},
			},
		},
		// multiple ranges string
		{
			"08:00-16:00,20:00-22:00",
			[]TimePeriod{
				{
					From: time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
				},
				{
					From: time.Date(0, 0, 0, 20, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 22, 0, 0, 0, time.UTC),
				},
			},
		},
		// string containing whitespace
		{
			" 08:00 - 16:00 ,, , 20:00 - 22:00 ",
			[]TimePeriod{
				{
					From: time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
				},
				{
					From: time.Date(0, 0, 0, 20, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 22, 0, 0, 0, time.UTC),
				},
			},
		},
	} {
		timePeriods, err := ParseTimePeriods(tt.given)
		suite.Require().NoError(err)

		suite.Equal(tt.expected, timePeriods)
	}
}

func (suite *Suite) TestParseDates() {
	for _, tt := range []struct {
		given    string
		expected []time.Time
	}{
		// empty string
		{
			"",
			[]time.Time{},
		},
		// single date
		{
			"Apr 1",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
			},
		},
		// single date leaving out the space
		{
			"Apr1",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
			},
		},
		// multiple dates
		{
			"Apr 1,Dec 24",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
				time.Date(0, 12, 24, 0, 0, 0, 0, time.UTC),
			},
		},
		// case-insensitive
		{
			"apr 1,dEc 24",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
				time.Date(0, 12, 24, 0, 0, 0, 0, time.UTC),
			},
		},
		// ignore whitespace
		{
			" apr 1 , dec 24 ",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
				time.Date(0, 12, 24, 0, 0, 0, 0, time.UTC),
			},
		},
		// deal with all kinds at the same time
		{
			",Apr 1, dEc 24 ,,,,  ,jun08,,",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
				time.Date(0, 12, 24, 0, 0, 0, 0, time.UTC),
				time.Date(0, 6, 8, 0, 0, 0, 0, time.UTC),
			},
		},
	} {
		days, err := ParseDays(tt.given)
		suite.Require().NoError(err)

		suite.Equal(tt.expected, days)
	}
}

func (suite *Suite) TestFormatDays() {
	for _, tt := range []struct {
		given    []time.Time
		expected []string
	}{
		{
			[]time.Time{
				time.Date(1869, 9, 24, 15, 04, 05, 06, time.UTC),
			},
			[]string{"Sep24"},
		}, {
			[]time.Time{
				time.Date(1869, 9, 24, 15, 04, 05, 06, time.UTC),
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
			},
			[]string{"Sep24", "Apr 1"},
		},
	} {
		suite.Equal(tt.expected, FormatDays(tt.given))
	}
}

func (suite *Suite) TestNewNamespace() {
	namespace := NewNamespace("name")

	suite.Equal("name", namespace.Name)
	suite.Equal("name", namespace.Labels["env"])
}

func TestSuite(t *testing.T) {
	suite.Run(t, new(Suite))
}
<commit_msg>chore: add test for NewPod helper function<commit_after>package util

import (
	"testing"
	"time"

	"github.com/stretchr/testify/suite"
)

type Suite struct {
	suite.Suite
}

func (suite *Suite) TestNewTimePeriod() {
	timezone, err := time.LoadLocation("Australia/Brisbane")
	suite.Require().NoError(err)

	for _, tt := range []struct {
		from     time.Time
		to       time.Time
		expected TimePeriod
	}{
		// when it's already normalized
		{
			time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
			time.Date(0, 0, 0, 16, 04, 05, 06, time.UTC),
			TimePeriod{
				From: time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
				To:   time.Date(0, 0, 0, 16, 04, 05, 06, time.UTC),
			},
		},
		// it normalizes to very first day
		{
			time.Date(1869, 9, 24, 15, 04, 05, 06, time.UTC),
			time.Date(1869, 9, 24, 16, 04, 05, 06, time.UTC),
			TimePeriod{
				From: time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
				To:   time.Date(0, 0, 0, 16, 04, 05, 06, time.UTC),
			},
		},
		// it ignores the timezone
		{
			time.Date(1869, 9, 24, 15, 04, 05, 06, timezone),
			time.Date(1869, 9, 24, 16, 04, 05, 06, timezone),
			TimePeriod{
				From: time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
				To:   time.Date(0, 0, 0, 16, 04, 05, 06, time.UTC),
			},
		},
	} {
		suite.Equal(tt.expected, NewTimePeriod(tt.from, tt.to))
	}
}

func (suite *Suite) TestTimePeriodIncludes() {
	atTheMoment := NewTimePeriod(
		time.Now().Add(-1*time.Minute),
		time.Now().Add(+1*time.Minute),
	)
	midnight := NewTimePeriod(
		time.Date(1869, 9, 23, 23, 00, 00, 00, time.UTC),
		time.Date(1869, 9, 24, 01, 00, 00, 00, time.UTC),
	)
	now := time.Now()

	for _, tt := range []struct {
		pointInTime time.Time
		timeOfDay   TimePeriod
		expected    bool
	}{
		// it's included
		{
			now,
			atTheMoment,
			true,
		},
		// it's one day before
		{
			now.Add(-24 * time.Hour),
			atTheMoment,
			true,
		},
		// it's one day after
		{
			now.Add(+24 * time.Hour),
			atTheMoment,
			true,
		},
		// it's just before
		{
			now.Add(-2 * time.Minute),
			atTheMoment,
			false,
		},
		// it's just after
		{
			now.Add(+2 * time.Minute),
			atTheMoment,
			false,
		},
		// it's slightly inside before day switch
		{
			time.Date(1869, 9, 23, 23, 30, 00, 00, time.UTC),
			midnight,
			true,
		},
		// it's slightly inside after day switch
		{
			time.Date(1869, 9, 24, 00, 30, 00, 00, time.UTC),
			midnight,
			true,
		},
		// it's just before
		{
			time.Date(1869, 9, 23, 22, 30, 00, 00, time.UTC),
			midnight,
			false,
		},
		// it's just after
		{
			time.Date(1869, 9, 24, 01, 30, 00, 00, time.UTC),
			midnight,
			false,
		},
		// it's exactly matching a point in time
		{
			now,
			TimePeriod{From: TimeOfDay(now), To: TimeOfDay(now)},
			true,
		},
		// it's right after exactly matching a point in time
		{
			now.Add(+1 * time.Second),
			TimePeriod{From: TimeOfDay(now), To: TimeOfDay(now)},
			false,
		},
		// it's right before exactly matching a point in time
		{
			now.Add(-1 * time.Second),
			TimePeriod{From: TimeOfDay(now), To: TimeOfDay(now)},
			false,
		},
	} {
		suite.Equal(tt.expected, tt.timeOfDay.Includes(tt.pointInTime))
	}
}

func (suite *Suite) TestTimePeriodString() {
	for _, tt := range []struct {
		given    TimePeriod
		expected string
	}{
		// empty time period
		{
			TimePeriod{},
			"00:00-00:00",
		},
		// simple time period
		{
			TimePeriod{
				From: time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
				To:   time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
			},
			"08:00-16:00",
		},
		// time period across days
		{
			TimePeriod{
				From: time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
				To:   time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
			},
			"16:00-08:00",
		},
	} {
		suite.Equal(tt.expected, tt.given.String())
	}
}

func (suite *Suite) TestTimeOfDay() {
	timezone, err := time.LoadLocation("Australia/Brisbane")
	suite.Require().NoError(err)

	for _, tt := range []struct {
		pointInTime time.Time
		expected    time.Time
	}{
		// strips of any day information
		{
			time.Date(1869, 9, 24, 15, 04, 05, 06, time.UTC),
			time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
		},
		// it normalizes to UTC timezone
		{
			time.Date(1869, 9, 24, 15, 04, 05, 06, timezone),
			time.Date(0, 0, 0, 15, 04, 05, 06, time.UTC),
		},
	} {
		suite.Equal(tt.expected, TimeOfDay(tt.pointInTime))
	}
}

func (suite *Suite) TestParseWeekdays() {
	for _, tt := range []struct {
		given    string
		expected []time.Weekday
	}{
		// empty string
		{
			"",
			[]time.Weekday{},
		},
		// single weekday
		{
			"sat",
			[]time.Weekday{time.Saturday},
		},
		// multiple weekdays
		{
			"sat,sun",
			[]time.Weekday{time.Saturday, time.Sunday},
		},
		// case-insensitive
		{
			"SaT,SUn",
			[]time.Weekday{time.Saturday, time.Sunday},
		},
		// ignore whitespace
		{
			" sat , sun ",
			[]time.Weekday{time.Saturday, time.Sunday},
		},
		// ignore unknown weekdays
		{
			"sat,unknown,sun",
			[]time.Weekday{time.Saturday, time.Sunday},
		},
		// deal with all kinds at the same time
		{
			"Fri, sat ,,,,  ,foobar,tue",
			[]time.Weekday{time.Friday, time.Saturday, time.Tuesday},
		},
	} {
		suite.Equal(tt.expected, ParseWeekdays(tt.given))
	}
}

func (suite *Suite) TestParseTimePeriods() {
	for _, tt := range []struct {
		given    string
		expected []TimePeriod
	}{
		// empty time period string
		{
			"",
			[]TimePeriod{},
		},
		// single range string
		{
			"08:00-16:00",
			[]TimePeriod{
				{
					From: time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
				},
			},
		},
		// multiple ranges string
		{
			"08:00-16:00,20:00-22:00",
			[]TimePeriod{
				{
					From: time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
				},
				{
					From: time.Date(0, 0, 0, 20, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 22, 0, 0, 0, time.UTC),
				},
			},
		},
		// string containing whitespace
		{
			" 08:00 - 16:00 ,, , 20:00 - 22:00 ",
			[]TimePeriod{
				{
					From: time.Date(0, 0, 0, 8, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 16, 0, 0, 0, time.UTC),
				},
				{
					From: time.Date(0, 0, 0, 20, 0, 0, 0, time.UTC),
					To:   time.Date(0, 0, 0, 22, 0, 0, 0, time.UTC),
				},
			},
		},
	} {
		timePeriods, err := ParseTimePeriods(tt.given)
		suite.Require().NoError(err)

		suite.Equal(tt.expected, timePeriods)
	}
}

func (suite *Suite) TestParseDates() {
	for _, tt := range []struct {
		given    string
		expected []time.Time
	}{
		// empty string
		{
			"",
			[]time.Time{},
		},
		// single date
		{
			"Apr 1",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
			},
		},
		// single date leaving out the space
		{
			"Apr1",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
			},
		},
		// multiple dates
		{
			"Apr 1,Dec 24",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
				time.Date(0, 12, 24, 0, 0, 0, 0, time.UTC),
			},
		},
		// case-insensitive
		{
			"apr 1,dEc 24",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
				time.Date(0, 12, 24, 0, 0, 0, 0, time.UTC),
			},
		},
		// ignore whitespace
		{
			" apr 1 , dec 24 ",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
				time.Date(0, 12, 24, 0, 0, 0, 0, time.UTC),
			},
		},
		// deal with all kinds at the same time
		{
			",Apr 1, dEc 24 ,,,,  ,jun08,,",
			[]time.Time{
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
				time.Date(0, 12, 24, 0, 0, 0, 0, time.UTC),
				time.Date(0, 6, 8, 0, 0, 0, 0, time.UTC),
			},
		},
	} {
		days, err := ParseDays(tt.given)
		suite.Require().NoError(err)

		suite.Equal(tt.expected, days)
	}
}

func (suite *Suite) TestFormatDays() {
	for _, tt := range []struct {
		given    []time.Time
		expected []string
	}{
		{
			[]time.Time{
				time.Date(1869, 9, 24, 15, 04, 05, 06, time.UTC),
			},
			[]string{"Sep24"},
		}, {
			[]time.Time{
				time.Date(1869, 9, 24, 15, 04, 05, 06, time.UTC),
				time.Date(0, 4, 1, 0, 0, 0, 0, time.UTC),
			},
			[]string{"Sep24", "Apr 1"},
		},
	} {
		suite.Equal(tt.expected, FormatDays(tt.given))
	}
}

func (suite *Suite) TestNewPod() {
	pod := NewPod("namespace", "name", "phase")

	suite.Equal("v1", pod.APIVersion)
	suite.Equal("Pod", pod.Kind)
	suite.Equal("namespace", pod.Namespace)
	suite.Equal("name", pod.Name)
	suite.Equal("name", pod.Labels["app"])
	suite.Equal("name", pod.Annotations["chaos"])
	suite.Equal("/api/v1/namespaces/namespace/pods/name", pod.SelfLink)
	suite.EqualValues("phase", pod.Status.Phase)
}

func (suite *Suite) TestNewNamespace() {
	namespace := NewNamespace("name")

	suite.Equal("name", namespace.Name)
	suite.Equal("name", namespace.Labels["env"])
}

func TestSuite(t *testing.T) {
	suite.Run(t, new(Suite))
}
<|endoftext|>


<commit_before>package models

import (
	"github.com/eirka/eirka-libs/db"
	"time"
)

// NewModel holds the parameters from the request and also the key for the cache
type StatisticsModel struct {
	Ib     uint
	Result StatisticsType
}

type StatisticsType struct {
	Labels []time.Time `json:"labels"`
	Series []Series    `json:"series"`
}

type Series struct {
	Name string `json:"name"`
	Data []uint `json:"data"`
}

// Get will gather the information from the database and return it as JSON serialized data
func (i *StatisticsModel) Get() (err error) {

	// Initialize response header
	response := StatisticsType{}

	visitors := Series{
		Name: "Visitors",
	}

	hits := Series{
		Name: "Hits",
	}

	// Get Database handle
	dbase, err := db.GetDb()
	if err != nil {
		return
	}

	ps1, err := dbase.Prepare(`SELECT (now() - interval ? hour) as time,
    COUNT(DISTINCT request_ip) as visitors, COUNT(request_itemkey) as hits
    FROM analytics
    WHERE request_time BETWEEN (now() - interval ? hour) AND (now() - interval ? hour) AND ib_id = ?`)
	if err != nil {
		return
	}
	defer ps1.Close()

	// loop through every two hours
	for hour := 2; hour <= 24; hour++ {
		if hour%2 == 0 {

			var label time.Time
			var visitor_count, hit_count uint

			// period minus two hours
			previous := (hour - 2)

			err := ps1.QueryRow(hour, hour, previous, i.Ib).Scan(&label, &visitor_count, &hit_count)
			if err != nil {
				return err
			}

			response.Labels = append(response.Labels, label)
			visitors.Data = append(visitors.Data, visitor_count)
			hits.Data = append(hits.Data, hit_count)

		}
	}

	response.Series = append(response.Series, visitors, hits)

	// This is the data we will serialize
	i.Result = response

	return

}
<commit_msg>reverse stats order<commit_after>package models

import (
	"github.com/eirka/eirka-libs/db"
	"time"
)

// NewModel holds the parameters from the request and also the key for the cache
type StatisticsModel struct {
	Ib     uint
	Result StatisticsType
}

type StatisticsType struct {
	Labels []time.Time `json:"labels"`
	Series []Series    `json:"series"`
}

type Series struct {
	Name string `json:"name"`
	Data []uint `json:"data"`
}

// Get will gather the information from the database and return it as JSON serialized data
func (i *StatisticsModel) Get() (err error) {

	// Initialize response header
	response := StatisticsType{}

	visitors := Series{
		Name: "Visitors",
	}

	hits := Series{
		Name: "Hits",
	}

	// Get Database handle
	dbase, err := db.GetDb()
	if err != nil {
		return
	}

	ps1, err := dbase.Prepare(`SELECT (now() - interval ? hour) as time,
    COUNT(DISTINCT request_ip) as visitors, COUNT(request_itemkey) as hits
    FROM analytics
    WHERE request_time BETWEEN (now() - interval ? hour) AND (now() - interval ? hour) AND ib_id = ?`)
	if err != nil {
		return
	}
	defer ps1.Close()

	// loop through every two hours
	for hour := 24; hour >= 2; hour-- {
		if hour%2 == 0 {

			var label time.Time
			var visitor_count, hit_count uint

			// period minus two hours
			previous := (hour - 2)

			err := ps1.QueryRow(hour, hour, previous, i.Ib).Scan(&label, &visitor_count, &hit_count)
			if err != nil {
				return err
			}

			response.Labels = append(response.Labels, label)
			visitors.Data = append(visitors.Data, visitor_count)
			hits.Data = append(hits.Data, hit_count)

		}
	}

	response.Series = append(response.Series, visitors, hits)

	// This is the data we will serialize
	i.Result = response

	return

}
<|endoftext|>


<commit_before>package models

type User struct {
	User_id        int     `json:"user_id"`
	User_name      string  `json:"user_name"`
	user_pass      string  `json:"user_pass"`
	User_type      string  `json:"user_type"`
	User_mobile    string  `json:"user_mobile"`
	Add_time  	   string  `json:"add_time"`
}

type  Users []User<commit_msg>fix bugs<commit_after>package models

type User struct {
	User_id        int     `json:"user_id"`
	User_name      string  `json:"user_name"`
	User_type      string  `json:"user_type"`
	User_mobile    string  `json:"user_mobile"`
	Add_time  	   string  `json:"add_time"`
}

type  Users []User<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io"
	"os"
	"regexp"

	"github.com/bborbe/log"
)

var logger = log.DefaultLogger

const SIZE = 10

func main() {
	logger.SetLevelThreshold(log.ERROR)
	defer logger.Close()
	logger.Debug("started")
	err := grepUrls()
	if err != nil {
		logger.Fatal(err)
	}
	logger.Debug("finished")
}

func grepUrls() error {
	contentBuffer := bytes.NewBuffer(nil)
	io.Copy(contentBuffer, os.Stdin)
	re := regexp.MustCompile("(https?://[^,'\" \\?&;]+)")
	result := re.FindAll(contentBuffer.Bytes(), -1)
	for _, match := range result {
		os.Stdout.Write(match)
		os.Stdout.WriteString("\n")
	}
	return nil
}
<commit_msg>use linkparser<commit_after>package main

import (
	"bytes"
	"io"
	"os"

	"github.com/bborbe/crawler/linkparser"
	"github.com/bborbe/log"
)

var logger = log.DefaultLogger

const SIZE = 10

func main() {
	logger.SetLevelThreshold(log.ERROR)
	defer logger.Close()
	logger.Debug("started")
	err := grepUrls()
	if err != nil {
		logger.Fatal(err)
	}
	logger.Debug("finished")
}

func grepUrls() error {
	contentBuffer := bytes.NewBuffer(nil)
	io.Copy(contentBuffer, os.Stdin)

	l := linkparser.New()
	links := l.Parse(string(contentBuffer.Bytes()))
	for match := range links {
		os.Stdout.WriteString(match)
		os.Stdout.WriteString("\n")
	}

	return nil
}
<|endoftext|>


<commit_before>/**
 * Minecraft Forge
 * Copyright (c) 2016.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation version 2.1
 * of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package util

import (
	"bytes"
	"encoding/json"
	"github.com/fatih/color"
	"fmt"
	"os"
)

type LauncherJson struct {
	Java struct {
		Lzma struct {
			Sha1 string `json:"sha1"`
			URL  string `json:"url"`
		} `json:"lzma"`
		Sha1 string `json:"sha1"`
	} `json:"java"`
	Osx struct {
		Arch64 struct {
			Jdk struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jdk"`
			Jre struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jre"`
		} `json:"64"`
		Apphash      string `json:"apphash"`
		Applink      string `json:"applink"`
		Downloadhash string `json:"downloadhash"`
	} `json:"osx"`
	Windows struct {
		Arch32 struct {
			Jdk struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jdk"`
			Jre struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jre"`
		} `json:"32"`
		Arch64 struct {
			Jdk struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jdk"`
			Jre struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jre"`
		} `json:"64"`
		Apphash string `json:"apphash"`
		Applink string `json:"applink"`
	} `json:"windows"`
}

var ljString = StringFromWebJson("http://launchermeta.mojang.com/mc-staging/launcher.json")
var buf = bytes.NewBufferString(ljString)

func GetJreInfo() (string, string, string, string) {

	var ljObj LauncherJson

	err := json.NewDecoder(buf).Decode(&ljObj)
	if err != nil {
		panic(err)
	}

	var platform string
	var arch string
	var version string
	var url string

	switch GetThisPlatform() {
	case "windows":
		platform = "windows"
		if GetThisArch() == "amd64" {
			arch = "64"
			version = ljObj.Windows.Arch64.Jre.Version
			url = ljObj.Windows.Arch64.Jre.URL
		} else if GetThisArch() == "386" {
			arch = "32"
			version = ljObj.Windows.Arch32.Jre.Version
			url = ljObj.Windows.Arch32.Jre.URL
		} else {
			color.Red("UNABLE TO DETERMINE ARCHITECTURE NOW SHUTTING DOWN")
			os.Exit(2)
		}
	case "darwin":
		platform = "osx"
		arch = "64"
		version = ljObj.Osx.Arch64.Jre.Version
		url = ljObj.Osx.Arch64.Jre.URL
	case "linux":
		color.Red("Sorry Mojang has not build a JRE for this platfrom please update to your java " +
			"go to http://openjdk.java.net/install/ or " +
			"http://www.oracle.com/technetwork/java/javase/downloads/index.html to download the latest java.")
		os.Exit(3)
	}

	return platform, arch, version, url
}

func GetJREVersion() string {
	_, _, version, _ := GetJreInfo()
	return version
}

func GetLauncherUrl() string {
	var ljObj LauncherJson

	err := json.NewDecoder(buf).Decode(&ljObj)
	if err != nil {
		fmt.Println(err)
	}

	return ljObj.Java.Lzma.URL
}
<commit_msg>Think I fixed the version issue<commit_after>/**
 * Minecraft Forge
 * Copyright (c) 2016.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation version 2.1
 * of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package util

import (
	"bytes"
	"encoding/json"
	"github.com/fatih/color"
	"fmt"
	"os"
	"strconv"
)

type LauncherJson struct {
	Java struct {
		Lzma struct {
			Sha1 string `json:"sha1"`
			URL  string `json:"url"`
		} `json:"lzma"`
		Sha1 string `json:"sha1"`
	} `json:"java"`
	Osx struct {
		Arch64 struct {
			Jdk struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jdk"`
			Jre struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jre"`
		} `json:"64"`
		Apphash      string `json:"apphash"`
		Applink      string `json:"applink"`
		Downloadhash string `json:"downloadhash"`
	} `json:"osx"`
	Windows struct {
		Arch32 struct {
			Jdk struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jdk"`
			Jre struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jre"`
		} `json:"32"`
		Arch64 struct {
			Jdk struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jdk"`
			Jre struct {
				Sha1    string `json:"sha1"`
				URL     string `json:"url"`
				Version string `json:"version"`
			} `json:"jre"`
		} `json:"64"`
		Apphash string `json:"apphash"`
		Applink string `json:"applink"`
	} `json:"windows"`
}

var ljString = StringFromWebJson("http://launchermeta.mojang.com/mc-staging/launcher.json")
var buf = bytes.NewBufferString(ljString)

func GetJreInfo() (string, string, string, string) {

	var ljObj LauncherJson

	err := json.NewDecoder(buf).Decode(&ljObj)
	if err != nil {
		panic(err)
	}

	var platform string
	var arch string
	var version string
	var url string

	switch GetThisPlatform() {
	case "windows":
		platform = "windows"
		if GetThisArch() == "amd64" {
			arch = "64"
			version = ljObj.Windows.Arch64.Jre.Version
			url = ljObj.Windows.Arch64.Jre.URL
		} else if GetThisArch() == "386" {
			arch = "32"
			version = ljObj.Windows.Arch32.Jre.Version
			url = ljObj.Windows.Arch32.Jre.URL
		} else {
			color.Red("UNABLE TO DETERMINE ARCHITECTURE NOW SHUTTING DOWN")
			os.Exit(2)
		}
	case "darwin":
		platform = "osx"
		arch = "64"
		version = ljObj.Osx.Arch64.Jre.Version
		url = ljObj.Osx.Arch64.Jre.URL
	case "linux":
		color.Red("Sorry Mojang has not build a JRE for this platfrom please update to your java " +
			"go to http://openjdk.java.net/install/ or " +
			"http://www.oracle.com/technetwork/java/javase/downloads/index.html to download the latest java.")
		os.Exit(3)
	}

	return platform, arch, strconv.Itoa(version), url
}

func GetJREVersion() string {
	_, _, version, _ := GetJreInfo()
	return version
}

func GetLauncherUrl() string {
	var ljObj LauncherJson

	err := json.NewDecoder(buf).Decode(&ljObj)
	if err != nil {
		fmt.Println(err)
	}

	return ljObj.Java.Lzma.URL
}
<|endoftext|>