<commit_before>package gaerecords

import (
	"os"
	"fmt"
	"reflect"
	"appengine"
	"appengine/datastore"
)

// Represents a single model. A model is a class of data.
//  // create a new model for 'people'
//  people := NewModel("people")
type Model struct {

	// Event that gets triggered after a record has been created.
	// Useful for initializing Records.
	//
	//   Args[0] - The *Record that has been created
	AfterNew Event

	// Event that gets triggered after a record of this kind has been
	// found.  Useful for any processing of records after they have been loaded.
	// For any operations that cause multiple finds (i.e. All()) this event
	// will be triggered for each record.
	//
	//   Args[0] - The *Record that has been found.
	//
	AfterFind Event

	// Event that gets triggered before a record is deleted. The Args will
	// always contain the ID of the record being deleted, and depending on the
	// operation, the second argument could be the *Record itself.
	//
	// Setting Cancel to true will cancel the delete operation.
	//
	//   Args[0] - ID (int64) of the record that is about to be deleted.
	//   Args[1] - *Record to be deleted (if available)
	//
	BeforeDelete Event

	// Event that gets triggered after a record has been deleted by ID. The Args will
	// always contain the ID of the record being deleted, and depending on the
	// operation, the second argument could be the *Record itself.
	///
	// The EventContext is the same one that was passed to BeforeDelete.
	//
	//   Args[0] - ID (int64) of the record that was just deleted.
	//   Args[1] - *Record that was deleted (if available)
	//
	AfterDelete Event

	// Event that gets triggered before a record gets Put into the datastore.
	// Use Args[0].(*Record).IsPersisted() to find out whether the record is being
	// saved or updated.
	//
	// Setting Cancel to true will prevent the record from being Put
	//
	//   Args[0] - The *Record that is about to be Put
	//
	BeforePut Event

	// Event that gets triggered after a record has been Put.
	// The EventContext is the same one that was passed to BeforePut.
	//
	//   Args[0] - The *Record that was just Put
	//
	AfterPut Event

	// Event that gets triggered after a record field has been changed
	// using one of the Set*() methods.
	//
	//   Args[0] - The record that changed
	//   Args[1] - The key of the field that changed
	//   Args[2] - The new value of the field
	//   Args[3] - The old value of the field (or nil if it's a new field)
	OnChanged Event

	// internal string holding the 'type' of this model,
	// or the kind of data this model works with
	recordType string

	// internal storage of appengine context to use for this model.
	specificAppengineContext appengine.Context
}

// Creates a new model for data classified by the specified recordType.
//
// For example, the following code creates a new Model called 'people':
//
//   people := NewModel("people")
func NewModel(recordType string) *Model {

	model := new(Model)

	model.recordType = recordType

	return model

}

// Creates a new record of this type.
//   people := NewModel("people")
//   person1 := people.New()
//   person2 := people.New()
func (m *Model) New() *Record {
	return NewRecord(m)
}

// Gets the record type of the model as a string.  This is the string you specify
// when calling NewModel(string) and is used as the Kind in the datasource keys.
func (m *Model) RecordType() string {
	return m.recordType
}

// Gets a human readable string representation of this model.
func (m *Model) String() string {
	return fmt.Sprintf("{Model:%v}", m.RecordType())
}

/*
	AppEngine Context
	----------------------------------------------------------------------
*/

// Gets the appengine.Context to use for datastore interactions for this model.
// If a specific one has been provided (via Model.SetAppEngineContext()) that
// context is used, otherwise the global AppEngineContext object is returned.
func (m *Model) AppEngineContext() appengine.Context {

	// do we have a specific model context?
	if m.specificAppengineContext == nil {

		// use the global one
		return AppEngineContext

	}

	// use the specific one
	return m.specificAppengineContext

}

// Tells this model to use the specified appengine.Context instead of the global
// AppEngineContext object for its interactions with the datastore.
func (m *Model) SetAppEngineContext(context appengine.Context) *Model {

	// set the context
	m.specificAppengineContext = context

	// chain
	return m
}

// Tells this model to use the global AppEngineContext object for its interactions with the datastore,
// instead of one provided by Model.SetAppEngineContext().
func (m *Model) UseGlobalAppEngineContext() *Model {

	// set the model specific context to nil so it uses the
	// global one when Model.AppEngineContext() is called.
	m.SetAppEngineContext(nil)

	// chain
	return m
}

/*
	Persistence
	----------------------------------------------------------------------
*/

// Finds the record of this type with the specified id.
//  people := NewModel("people")
//  firstPerson := people.Find(1)
//
// Raises events:
//   Model.AfterFind with Args(record)
func (m *Model) Find(id int64) (*Record, os.Error) {

	key := m.NewKeyWithID(id)

	var record *Record = new(Record)

	err := datastore.Get(m.AppEngineContext(), key, datastore.PropertyLoadSaver(record))

	if err == nil {

		// setup the record object
		record.configureRecord(m, key)

		// raise the AfterFind event on the model
		m.AfterFind.Trigger(record)

		// return the record
		return record, nil

	}

	return nil, err

}

// Finds all records of this type.
//   people := NewModel("people")
//   everyone := people.All()
//
// Raises events for each record:
//   Model.AfterFind with Args(record)
func (m *Model) All() ([]*Record, os.Error) {
	return m.FindByQuery(m.NewQuery())
}

// Deletes a single record of this type.  Returns nil if successful, otherwise
// the datastore error that was returned.
//   people := NewModel("people")
//   people.Delete(1)
//
// Raises events:
//   Model.BeforeDelete with Args(id, nil)
//   Model.AfterDelete with Args(id, nil)
// Note: The Record will not be passed to the events.
func (m *Model) Delete(id int64) os.Error {

	// trigger the BeforeDeleteByID event
	context := m.BeforeDelete.Trigger(id, nil)

	if !context.Cancel {

		err := datastore.Delete(m.AppEngineContext(), m.NewKeyWithID(id))

		if err == nil {

			// trigger the AfterDeleteByID event
			m.AfterDelete.TriggerWithContext(context)

		}

		// return the error
		return err

	}

	return ErrOperationCancelledByEventCallback

}

/*
	Queries
	----------------------------------------------------------------------
*/

// Creates a new datastore.Query for accessing records represented
// by the model.  For advanced use only.  Consider instead one of the
// Find* methods.
func (m *Model) NewQuery() *datastore.Query {
	return datastore.NewQuery(m.RecordType())
}

// Finds Records handled by this Model.
//
// Returns an array of records as the first argument,
// or an error as the second return argument.
//
// The queryOrFunc argument may be one of:
//
//   *datastore.Query
// The specified query will be used to find records.
//   func(*datastore.Query)
// A new query will be created and the specified function will be
// used to further configure the query.
//
// Example:
//  model := NewModel("people")
//  women, err := model.FindByQuery(func(q *datastore.Query){
//	  q.Filter("sex=", "male")
//  })
func (m *Model) FindByQuery(queryOrFunc interface{}) ([]*Record, os.Error) {

	var query *datastore.Query

	if reflect.TypeOf(queryOrFunc).Kind() == reflect.Func {

		// create a new query
		query = m.NewQuery()

		// ask the func to configure the query
		queryOrFunc.(func(*datastore.Query))(query)

	} else {

		// just use the query
		query = queryOrFunc.(*datastore.Query)

	}

	var records []*Record
	keys, err := query.GetAll(m.AppEngineContext(), &records)

	if err == nil {

		// update the key for each loaded record
		for index, record := range records {
			record.configureRecord(m, keys[index])
			m.AfterFind.Trigger(record)
		}

		return records, nil

	}

	return nil, err

}

/*
	datastore.Keys
	----------------------------------------------------------------------
*/

// Creates a new datastore Key for this kind of record.
func (m *Model) NewKey() *datastore.Key {
	return datastore.NewIncompleteKey(m.AppEngineContext(), m.recordType, nil)
}

// Creates a new datastore Key for this kind of record with the specified ID.
func (m *Model) NewKeyWithID(id int64) *datastore.Key {
	return datastore.NewKey(m.AppEngineContext(), m.recordType, "", int64(id), nil)
}
<commit_msg>model comment tidyup<commit_after>package gaerecords

import (
	"os"
	"fmt"
	"reflect"
	"appengine"
	"appengine/datastore"
)

// Represents a single model. A model is a class of data.
//  // create a new model for 'people'
//  people := NewModel("people")
type Model struct {

	// Event that gets triggered after a record has been created.
	// Useful for initializing Records.
	//
	//   Args[0] - The *Record that has been created
	//
	AfterNew Event

	// Event that gets triggered after a record of this kind has been
	// found.  Useful for any processing of records after they have been loaded.
	// For any operations that cause multiple finds (i.e. All()) this event
	// will be triggered for each record.
	//
	//   Args[0] - The *Record that has been found.
	//
	AfterFind Event

	// Event that gets triggered before a record is deleted. The Args will
	// always contain the ID of the record being deleted, and depending on the
	// operation, the second argument could be the *Record itself.
	//
	// Setting Cancel to true will cancel the delete operation.
	//
	//   Args[0] - ID (int64) of the record that is about to be deleted.
	//   Args[1] - *Record to be deleted (if available)
	//
	BeforeDelete Event

	// Event that gets triggered after a record has been deleted by ID. The Args will
	// always contain the ID of the record being deleted, and depending on the
	// operation, the second argument could be the *Record itself.
	///
	// The EventContext is the same one that was passed to BeforeDelete.
	//
	//   Args[0] - ID (int64) of the record that was just deleted.
	//   Args[1] - *Record that was deleted (if available)
	//
	AfterDelete Event

	// Event that gets triggered before a record gets Put into the datastore.
	// Use Args[0].(*Record).IsPersisted() to find out whether the record is being
	// saved or updated.
	//
	// Setting Cancel to true will prevent the record from being Put
	//
	//   Args[0] - The *Record that is about to be Put
	//
	BeforePut Event

	// Event that gets triggered after a record has been Put.
	// The EventContext is the same one that was passed to BeforePut.
	//
	//   Args[0] - The *Record that was just Put
	//
	AfterPut Event

	// Event that gets triggered after a record field has been changed
	// using one of the Set*() methods.
	//
	//   Args[0] - The record that changed
	//   Args[1] - The key of the field that changed
	//   Args[2] - The new value of the field
	//   Args[3] - The old value of the field (or nil if it's a new field)
	//
	OnChanged Event

	// internal string holding the 'type' of this model,
	// or the kind of data this model works with
	recordType string

	// internal storage of appengine context to use for this model.
	specificAppengineContext appengine.Context
}

// Creates a new model for data classified by the specified recordType.
//
// For example, the following code creates a new Model called 'people':
//
//   people := NewModel("people")
func NewModel(recordType string) *Model {

	model := new(Model)

	model.recordType = recordType

	return model

}

// Creates a new record of this type.
//   people := NewModel("people")
//   person1 := people.New()
//   person2 := people.New()
func (m *Model) New() *Record {
	return NewRecord(m)
}

// Gets the record type of the model as a string.  This is the string you specify
// when calling NewModel(string) and is used as the Kind in the datasource keys.
func (m *Model) RecordType() string {
	return m.recordType
}

// Gets a human readable string representation of this model.
func (m *Model) String() string {
	return fmt.Sprintf("{Model:%v}", m.RecordType())
}

/*
	AppEngine Context
	----------------------------------------------------------------------
*/

// Gets the appengine.Context to use for datastore interactions for this model.
// If a specific one has been provided (via Model.SetAppEngineContext()) that
// context is used, otherwise the global AppEngineContext object is returned.
func (m *Model) AppEngineContext() appengine.Context {

	// do we have a specific model context?
	if m.specificAppengineContext == nil {

		// use the global one
		return AppEngineContext

	}

	// use the specific one
	return m.specificAppengineContext

}

// Tells this model to use the specified appengine.Context instead of the global
// AppEngineContext object for its interactions with the datastore.
func (m *Model) SetAppEngineContext(context appengine.Context) *Model {

	// set the context
	m.specificAppengineContext = context

	// chain
	return m
}

// Tells this model to use the global AppEngineContext object for its interactions with the datastore,
// instead of one provided by Model.SetAppEngineContext().
func (m *Model) UseGlobalAppEngineContext() *Model {

	// set the model specific context to nil so it uses the
	// global one when Model.AppEngineContext() is called.
	m.SetAppEngineContext(nil)

	// chain
	return m
}

/*
	Persistence
	----------------------------------------------------------------------
*/

// Finds the record of this type with the specified id.
//  people := NewModel("people")
//  firstPerson := people.Find(1)
//
// Raises events:
//   Model.AfterFind with Args(record)
func (m *Model) Find(id int64) (*Record, os.Error) {

	key := m.NewKeyWithID(id)

	var record *Record = new(Record)

	err := datastore.Get(m.AppEngineContext(), key, datastore.PropertyLoadSaver(record))

	if err == nil {

		// setup the record object
		record.configureRecord(m, key)

		// raise the AfterFind event on the model
		m.AfterFind.Trigger(record)

		// return the record
		return record, nil

	}

	return nil, err

}

// Finds all records of this type.
//   people := NewModel("people")
//   everyone := people.All()
//
// Raises events for each record:
//   Model.AfterFind with Args(record)
func (m *Model) All() ([]*Record, os.Error) {
	return m.FindByQuery(m.NewQuery())
}

// Deletes a single record of this type.  Returns nil if successful, otherwise
// the datastore error that was returned.
//   people := NewModel("people")
//   people.Delete(1)
//
// Raises events:
//   Model.BeforeDelete with Args(id, nil)
//   Model.AfterDelete with Args(id, nil)
// Note: The Record will not be passed to the events.
func (m *Model) Delete(id int64) os.Error {

	// trigger the BeforeDeleteByID event
	context := m.BeforeDelete.Trigger(id, nil)

	if !context.Cancel {

		err := datastore.Delete(m.AppEngineContext(), m.NewKeyWithID(id))

		if err == nil {

			// trigger the AfterDeleteByID event
			m.AfterDelete.TriggerWithContext(context)

		}

		// return the error
		return err

	}

	return ErrOperationCancelledByEventCallback

}

/*
	Queries
	----------------------------------------------------------------------
*/

// Creates a new datastore.Query for accessing records represented
// by the model.  For advanced use only.  Consider instead one of the
// Find* methods.
func (m *Model) NewQuery() *datastore.Query {
	return datastore.NewQuery(m.RecordType())
}

// Finds Records handled by this Model.
//
// Returns an array of records as the first argument,
// or an error as the second return argument.
//
// The queryOrFunc argument may be one of:
//
//   *datastore.Query
// The specified query will be used to find records.
//   func(*datastore.Query)
// A new query will be created and the specified function will be
// used to further configure the query.
//
// Example:
//  model := NewModel("people")
//  women, err := model.FindByQuery(func(q *datastore.Query){
//	  q.Filter("sex=", "male")
//  })
func (m *Model) FindByQuery(queryOrFunc interface{}) ([]*Record, os.Error) {

	var query *datastore.Query

	if reflect.TypeOf(queryOrFunc).Kind() == reflect.Func {

		// create a new query
		query = m.NewQuery()

		// ask the func to configure the query
		queryOrFunc.(func(*datastore.Query))(query)

	} else {

		// just use the query
		query = queryOrFunc.(*datastore.Query)

	}

	var records []*Record
	keys, err := query.GetAll(m.AppEngineContext(), &records)

	if err == nil {

		// update the key for each loaded record
		for index, record := range records {
			record.configureRecord(m, keys[index])
			m.AfterFind.Trigger(record)
		}

		return records, nil

	}

	return nil, err

}

/*
	datastore.Keys
	----------------------------------------------------------------------
*/

// Creates a new datastore Key for this kind of record.
func (m *Model) NewKey() *datastore.Key {
	return datastore.NewIncompleteKey(m.AppEngineContext(), m.recordType, nil)
}

// Creates a new datastore Key for this kind of record with the specified ID.
func (m *Model) NewKeyWithID(id int64) *datastore.Key {
	return datastore.NewKey(m.AppEngineContext(), m.recordType, "", int64(id), nil)
}
<|endoftext|>


<commit_before>// Copyright 2016 Stratumn SAS. All rights reserved.
// Use of this source code is governed by an Apache License 2.0
// that can be found in the LICENSE file.

// Package bcbatchfossilizer implements a fossilizer that fossilize batches of hashes on a blockchain.
package bcbatchfossilizer

import (
	"errors"
	"log"

	"github.com/stratumn/go/fossilizer"
	"github.com/stratumn/goprivate/batchfossilizer"
	"github.com/stratumn/goprivate/blockchain"
)

const (
	// Name is the name set in the fossilizer's information.
	Name = "bcbatch"

	// Description is the description set in the fossilizer's information.
	Description = "Stratumn Blockchain Batch Fossilizer"
)

// Config contains configuration options for the fossilizer.
type Config struct {
	HashTimestamper blockchain.HashTimestamper
}

// Evidence is the evidence sent to the result channel.
type Evidence struct {
	*batchfossilizer.Evidence
	TransactionID blockchain.TransactionID `json:"txid"`
}

// Fossilizer is the type that implements github.com/stratumn/go/fossilizer.Adapter.
type Fossilizer struct {
	*batchfossilizer.Fossilizer
	config      *Config
	resultChans []chan *fossilizer.Result
	resultChan  chan *fossilizer.Result
}

// New creates an instance of a Fossilizer.
func New(config *Config, batchConfig *batchfossilizer.Config) *Fossilizer {
	return &Fossilizer{
		Fossilizer: batchfossilizer.New(batchConfig),
		config:     config,
	}
}

// Start starts the fossilizer.
func (a *Fossilizer) Start() {
	a.resultChan = make(chan *fossilizer.Result)
	a.Fossilizer.AddResultChan(a.resultChan)

	go func() {
		for r := range a.resultChan {
			batchEvidenceWrapper, ok := r.Evidence.(*batchfossilizer.EvidenceWrapper)
			if !ok {
				log.Printf("unexpected batch evidence: %v\n", batchEvidenceWrapper)
				continue
			}

			root := batchEvidenceWrapper.Evidence.Root
			transactionID, err := a.config.HashTimestamper.TimestampHash(root)
			if err != nil {
				log.Println(err)
				continue
			}

			evidenceWrapper := map[string]*Evidence{}
			evidenceWrapper[a.config.HashTimestamper.Network().String()] = &Evidence{
				Evidence:      batchEvidenceWrapper.Evidence,
				TransactionID: transactionID,
			}
			r.Evidence = evidenceWrapper

			for _, c := range a.resultChans {
				c <- r
			}
		}
	}()

	a.Fossilizer.Start()
}

// Stop stops the fossilizer.
func (a *Fossilizer) Stop() {
	a.Fossilizer.Stop()
	close(a.resultChan)
}

// GetInfo implements github.com/stratumn/go/fossilizer.Adapter.GetInfo.
func (a *Fossilizer) GetInfo() (interface{}, error) {
	batchInfo, err := a.Fossilizer.GetInfo()
	if err != nil {
		return nil, err
	}

	info, ok := batchInfo.(map[string]interface{})
	if !ok {
		return nil, errors.New("unexpected batchfossilizer info")
	}

	info["name"] = Name
	info["description"] = Description
	info["blockchain"] = a.config.HashTimestamper.Network().String()

	return info, nil
}

// AddResultChan implements github.com/stratumn/go/fossilizer.Adapter.AddResultChan.
func (a *Fossilizer) AddResultChan(resultChan chan *fossilizer.Result) {
	a.resultChans = append(a.resultChans, resultChan)
}
<commit_msg>bcbatchfossilizer: Fix bcbatchfossilizer timestamping every result<commit_after>// Copyright 2016 Stratumn SAS. All rights reserved.
// Use of this source code is governed by an Apache License 2.0
// that can be found in the LICENSE file.

// Package bcbatchfossilizer implements a fossilizer that fossilize batches of hashes on a blockchain.
package bcbatchfossilizer

import (
	"errors"
	"log"

	"github.com/stratumn/go/fossilizer"
	"github.com/stratumn/goprivate/batchfossilizer"
	"github.com/stratumn/goprivate/blockchain"
	"github.com/stratumn/goprivate/types"
)

const (
	// Name is the name set in the fossilizer's information.
	Name = "bcbatch"

	// Description is the description set in the fossilizer's information.
	Description = "Stratumn Blockchain Batch Fossilizer"
)

// Config contains configuration options for the fossilizer.
type Config struct {
	HashTimestamper blockchain.HashTimestamper
}

// Evidence is the evidence sent to the result channel.
type Evidence struct {
	*batchfossilizer.Evidence
	TransactionID blockchain.TransactionID `json:"txid"`
}

// Fossilizer is the type that implements github.com/stratumn/go/fossilizer.Adapter.
type Fossilizer struct {
	*batchfossilizer.Fossilizer
	config      *Config
	resultChans []chan *fossilizer.Result
	resultChan  chan *fossilizer.Result
}

// New creates an instance of a Fossilizer.
func New(config *Config, batchConfig *batchfossilizer.Config) *Fossilizer {
	return &Fossilizer{
		Fossilizer: batchfossilizer.New(batchConfig),
		config:     config,
	}
}

// Start starts the fossilizer.
func (a *Fossilizer) Start() {
	a.resultChan = make(chan *fossilizer.Result)
	a.Fossilizer.AddResultChan(a.resultChan)

	go func() {
		var (
			err               error
			lastRoot          types.Bytes32
			lastTransactionID blockchain.TransactionID
		)

		for r := range a.resultChan {
			batchEvidenceWrapper, ok := r.Evidence.(*batchfossilizer.EvidenceWrapper)
			if !ok {
				log.Printf("unexpected batch evidence: %v\n", batchEvidenceWrapper)
				continue
			}

			root := batchEvidenceWrapper.Evidence.Root

			if root != lastRoot {
				lastTransactionID, err = a.config.HashTimestamper.TimestampHash(root)
				if err != nil {
					log.Println(err)
					continue
				}
			}

			evidenceWrapper := map[string]*Evidence{}
			evidenceWrapper[a.config.HashTimestamper.Network().String()] = &Evidence{
				Evidence:      batchEvidenceWrapper.Evidence,
				TransactionID: lastTransactionID,
			}
			r.Evidence = evidenceWrapper

			for _, c := range a.resultChans {
				c <- r
			}

			lastRoot = root
		}
	}()

	a.Fossilizer.Start()
}

// Stop stops the fossilizer.
func (a *Fossilizer) Stop() {
	a.Fossilizer.Stop()
	close(a.resultChan)
}

// GetInfo implements github.com/stratumn/go/fossilizer.Adapter.GetInfo.
func (a *Fossilizer) GetInfo() (interface{}, error) {
	batchInfo, err := a.Fossilizer.GetInfo()
	if err != nil {
		return nil, err
	}

	info, ok := batchInfo.(map[string]interface{})
	if !ok {
		return nil, errors.New("unexpected batchfossilizer info")
	}

	info["name"] = Name
	info["description"] = Description
	info["blockchain"] = a.config.HashTimestamper.Network().String()

	return info, nil
}

// AddResultChan implements github.com/stratumn/go/fossilizer.Adapter.AddResultChan.
func (a *Fossilizer) AddResultChan(resultChan chan *fossilizer.Result) {
	a.resultChans = append(a.resultChans, resultChan)
}
<|endoftext|>


<commit_before>package apps

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/vito/cmdtest/matchers"

	. "github.com/pivotal-cf-experimental/cf-acceptance-tests/helpers"
	"time"
)

var _ = Describe("loggregator", func() {
	BeforeEach(func() {
		AppName = RandomName()

		PushApp(AppName, doraPath)
	})

	AfterEach(func() {
		DeleteApp(AppName)
	})

	Context("gcf logs", func() {
		It("blocks and exercises basic loggregator behavior", func() {
			logs := Cf("logs", AppName)

			Expect(logs).To(SayWithTimeout("Connected, tailing logs for app", time.Second*15))

			Eventually(Curling("/")).Should(Say("Hi, I'm Dora!"))

			Expect(logs).To(SayWithTimeout("OUT "+AppName+"."+IntegrationConfig.AppsDomain, time.Second*15))
		})
	})

	Context("gcf logs --recent", func() {
		It("makes loggregator buffer and dump log messages", func() {
		   	logs := Cf("logs", AppName, "--recent")

			Expect(logs).To(Say("Connected, dumping recent logs for app"))

			Expect(logs).To(Say("OUT Created app"))
			Expect(logs).To(Say("OUT Starting app instance"))
		})
	})
})
<commit_msg>import Cf helper<commit_after>package apps

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/vito/cmdtest/matchers"

        . "github.com/pivotal-cf-experimental/cf-test-helpers/cf"
	. "github.com/pivotal-cf-experimental/cf-acceptance-tests/helpers"
	"time"
)

var _ = Describe("loggregator", func() {
	BeforeEach(func() {
		AppName = RandomName()

		PushApp(AppName, doraPath)
	})

	AfterEach(func() {
		DeleteApp(AppName)
	})

	Context("gcf logs", func() {
		It("blocks and exercises basic loggregator behavior", func() {
			logs := Cf("logs", AppName)

			Expect(logs).To(SayWithTimeout("Connected, tailing logs for app", time.Second*15))

			Eventually(Curling("/")).Should(Say("Hi, I'm Dora!"))

			Expect(logs).To(SayWithTimeout("OUT "+AppName+"."+IntegrationConfig.AppsDomain, time.Second*15))
		})
	})

	Context("gcf logs --recent", func() {
		It("makes loggregator buffer and dump log messages", func() {
		   	logs := Cf("logs", AppName, "--recent")

			Expect(logs).To(Say("Connected, dumping recent logs for app"))

			Expect(logs).To(Say("OUT Created app"))
			Expect(logs).To(Say("OUT Starting app instance"))
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/youzan/ZanRedisDB/common"
	"github.com/youzan/ZanRedisDB/pdserver"

	"github.com/BurntSushi/toml"
	"github.com/absolute8511/glog"
	"github.com/judwhite/go-svc/svc"
	"github.com/mreiferson/go-options"
)

var (
	flagSet = flag.NewFlagSet("placedriver", flag.ExitOnError)

	config      = flagSet.String("config", "", "path to config file")
	showVersion = flagSet.Bool("version", false, "print version string")

	httpAddress        = flagSet.String("http-address", "0.0.0.0:18001", "<addr>:<port> to listen on for HTTP clients")
	broadcastAddress   = flagSet.String("broadcast-address", "", "address of this lookupd node, (default to the OS hostname)")
	broadcastInterface = flagSet.String("broadcast-interface", "", "address of this lookupd node, (default to the OS hostname)")
	reverseProxyPort   = flagSet.String("reverse-proxy-port", "", "<port> for reverse proxy")
	profilePort        = flagSet.String("profile-port", "6667", "<port> for golang profile")

	clusterLeadershipAddresses = flagSet.String("cluster-leadership-addresses", "", " the cluster leadership server list")
	clusterID                  = flagSet.String("cluster-id", "test-cluster", "the cluster id used for separating different cluster.")
	autoBalance                = flagSet.Bool("auto-balance-and-migrate", false, "auto balance and migrate the data while unstable")

	logLevel        = flagSet.Int("log-level", 1, "log verbose level")
	logDir          = flagSet.String("log-dir", "", "directory for log file")
	dataDir         = flagSet.String("data-dir", "", "directory for data")
	learnerRole     = flagSet.String("learner-role", "", "learner role for pd")
	balanceInterval = common.StringArray{}
)

func init() {
	flagSet.Var(&balanceInterval, "balance-interval", "the balance time interval")
}

type program struct {
	placedriver *pdserver.Server
}

func main() {
	defer glog.Flush()
	prg := &program{}
	if err := svc.Run(prg, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGINT); err != nil {
		log.Fatal(err)
	}
}

func (p *program) Init(env svc.Environment) error {
	if env.IsWindowsService() {
		dir := filepath.Dir(os.Args[0])
		return os.Chdir(dir)
	}
	return nil
}

func (p *program) Start() error {
	glog.InitWithFlag(flagSet)

	flagSet.Parse(os.Args[1:])
	fmt.Println(common.VerString("placedriver"))
	if *showVersion {
		os.Exit(0)
	}

	var cfg map[string]interface{}
	if *config != "" {
		_, err := toml.DecodeFile(*config, &cfg)
		if err != nil {
			log.Fatalf("ERROR: failed to load config file %s - %s", *config, err.Error())
		}
	}

	opts := pdserver.NewServerConfig()
	options.Resolve(opts, flagSet, cfg)
	if opts.LogDir != "" {
		glog.SetGLogDir(opts.LogDir)
	}
	glog.StartWorker(time.Second * 2)
	daemon := pdserver.NewServer(opts)

	daemon.Start()
	p.placedriver = daemon
	return nil
}

func (p *program) Stop() error {
	if p.placedriver != nil {
		p.placedriver.Stop()
	}
	return nil
}
<commit_msg>add flag for filter namespaces<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/youzan/ZanRedisDB/common"
	"github.com/youzan/ZanRedisDB/pdserver"

	"github.com/BurntSushi/toml"
	"github.com/absolute8511/glog"
	"github.com/judwhite/go-svc/svc"
	"github.com/mreiferson/go-options"
)

var (
	flagSet = flag.NewFlagSet("placedriver", flag.ExitOnError)

	config      = flagSet.String("config", "", "path to config file")
	showVersion = flagSet.Bool("version", false, "print version string")

	httpAddress        = flagSet.String("http-address", "0.0.0.0:18001", "<addr>:<port> to listen on for HTTP clients")
	broadcastAddress   = flagSet.String("broadcast-address", "", "address of this lookupd node, (default to the OS hostname)")
	broadcastInterface = flagSet.String("broadcast-interface", "", "address of this lookupd node, (default to the OS hostname)")
	reverseProxyPort   = flagSet.String("reverse-proxy-port", "", "<port> for reverse proxy")
	profilePort        = flagSet.String("profile-port", "6667", "<port> for golang profile")

	clusterLeadershipAddresses = flagSet.String("cluster-leadership-addresses", "", " the cluster leadership server list")
	clusterID                  = flagSet.String("cluster-id", "test-cluster", "the cluster id used for separating different cluster.")
	autoBalance                = flagSet.Bool("auto-balance-and-migrate", false, "auto balance and migrate the data while unstable")

	logLevel         = flagSet.Int("log-level", 1, "log verbose level")
	logDir           = flagSet.String("log-dir", "", "directory for log file")
	dataDir          = flagSet.String("data-dir", "", "directory for data")
	learnerRole      = flagSet.String("learner-role", "", "learner role for pd")
	filterNamespaces = flagSet.String("filter-namespaces", "", "filter namespaces while in learner role for pd")
	balanceInterval  = common.StringArray{}
)

func init() {
	flagSet.Var(&balanceInterval, "balance-interval", "the balance time interval")
}

type program struct {
	placedriver *pdserver.Server
}

func main() {
	defer glog.Flush()
	prg := &program{}
	if err := svc.Run(prg, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGINT); err != nil {
		log.Fatal(err)
	}
}

func (p *program) Init(env svc.Environment) error {
	if env.IsWindowsService() {
		dir := filepath.Dir(os.Args[0])
		return os.Chdir(dir)
	}
	return nil
}

func (p *program) Start() error {
	glog.InitWithFlag(flagSet)

	flagSet.Parse(os.Args[1:])
	fmt.Println(common.VerString("placedriver"))
	if *showVersion {
		os.Exit(0)
	}

	var cfg map[string]interface{}
	if *config != "" {
		_, err := toml.DecodeFile(*config, &cfg)
		if err != nil {
			log.Fatalf("ERROR: failed to load config file %s - %s", *config, err.Error())
		}
	}

	opts := pdserver.NewServerConfig()
	options.Resolve(opts, flagSet, cfg)
	if opts.LogDir != "" {
		glog.SetGLogDir(opts.LogDir)
	}
	glog.StartWorker(time.Second * 2)
	daemon := pdserver.NewServer(opts)

	daemon.Start()
	p.placedriver = daemon
	return nil
}

func (p *program) Stop() error {
	if p.placedriver != nil {
		p.placedriver.Stop()
	}
	return nil
}
<|endoftext|>


<commit_before>package app

import (
	"strconv"
	"time"

	"zxq.co/ripple/rippleapi/limit"
)

const reqsPerSecond = 5000
const sleepTime = time.Second / reqsPerSecond

var limiter = make(chan struct{}, reqsPerSecond)

func setUpLimiter() {
	for i := 0; i < reqsPerSecond; i++ {
		limiter <- struct{}{}
	}
	go func() {
		for {
			limiter <- struct{}{}
			time.Sleep(sleepTime)
		}
	}()
}

func rateLimiter() {
	<-limiter
}
func perUserRequestLimiter(uid int, ip string) {
	if uid == 0 {
		limit.Request("ip:"+ip, 60)
	} else {
		limit.Request("user:"+strconv.Itoa(uid), 2000)
	}
}
<commit_msg>Up the API rate limits slightly<commit_after>package app

import (
	"strconv"
	"time"

	"zxq.co/ripple/rippleapi/limit"
)

const reqsPerSecond = 5000
const sleepTime = time.Second / reqsPerSecond

var limiter = make(chan struct{}, reqsPerSecond)

func setUpLimiter() {
	for i := 0; i < reqsPerSecond; i++ {
		limiter <- struct{}{}
	}
	go func() {
		for {
			limiter <- struct{}{}
			time.Sleep(sleepTime)
		}
	}()
}

func rateLimiter() {
	<-limiter
}
func perUserRequestLimiter(uid int, ip string) {
	if uid == 0 {
		limit.Request("ip:"+ip, 200)
	} else {
		limit.Request("user:"+strconv.Itoa(uid), 3000)
	}
}
<|endoftext|>


<commit_before>package apps

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/vito/cmdtest/matchers"

	. "github.com/pivotal-cf-experimental/cf-acceptance-tests/helpers"
)

var _ = Describe("An application being staged", func() {
	BeforeEach(func() {
		AppName = RandomName()
	})

	AfterEach(func() {
		Expect(Cf("delete", AppName, "-f")).To(Say("OK"))
	})

	It("has its staging log streamed during a push", func() {
		push := Cf("push", AppName, "-p", doraPath)

		Expect(push).To(Say("Staging..."))
		Expect(push).To(Say("Installing dependencies"))
		Expect(push).To(Say("Uploading droplet"))
		Expect(push).To(Say("Started"))
	})
})
<commit_msg>Test failure: 'Staging...' missing from output<commit_after>package apps

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/vito/cmdtest/matchers"

	. "github.com/pivotal-cf-experimental/cf-acceptance-tests/helpers"
)

var _ = Describe("An application being staged", func() {
	BeforeEach(func() {
		AppName = RandomName()
	})

	AfterEach(func() {
		Expect(Cf("delete", AppName, "-f")).To(Say("OK"))
	})

	It("has its staging log streamed during a push", func() {
		push := Cf("push", AppName, "-p", doraPath)

		Expect(push).To(Say("Installing dependencies"))
		Expect(push).To(Say("Uploading droplet"))
		Expect(push).To(Say("Started"))
	})
})
<|endoftext|>


<commit_before>// +build windows

package hcsoci

// Contains functions relating to a LCOW container, as opposed to a utility VM

import (
	"context"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"

	"github.com/Microsoft/hcsshim/internal/layers"
	"github.com/Microsoft/hcsshim/internal/log"
	"github.com/Microsoft/hcsshim/internal/oci"
	"github.com/Microsoft/hcsshim/internal/resources"
	"github.com/Microsoft/hcsshim/internal/uvm"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
)

// getGPUVHDPath gets the gpu vhd path from the shim options or uses the default if no
// shim option is set. Right now we only support Nvidia gpus, so this will default to
// a gpu vhd with nvidia files
func getGPUVHDPath(coi *createOptionsInternal) (string, error) {
	gpuVHDPath, ok := coi.Spec.Annotations[oci.AnnotationGPUVHDPath]
	if !ok || gpuVHDPath == "" {
		return "", fmt.Errorf("no gpu vhd specified %s", gpuVHDPath)
	}
	if _, err := os.Stat(gpuVHDPath); err != nil {
		return "", errors.Wrapf(err, "failed to find gpu support vhd %s", gpuVHDPath)
	}
	return gpuVHDPath, nil
}

func allocateLinuxResources(ctx context.Context, coi *createOptionsInternal, r *resources.Resources, isSandbox bool) error {
	if coi.Spec.Root == nil {
		coi.Spec.Root = &specs.Root{}
	}
	containerRootInUVM := r.ContainerRootInUVM()
	if coi.Spec.Windows != nil && len(coi.Spec.Windows.LayerFolders) > 0 {
		log.G(ctx).Debug("hcsshim::allocateLinuxResources mounting storage")
		rootPath, err := layers.MountContainerLayers(ctx, coi.actualID, coi.Spec.Windows.LayerFolders, containerRootInUVM, "", coi.HostingSystem)
		if err != nil {
			return errors.Wrap(err, "failed to mount container storage")
		}
		coi.Spec.Root.Path = rootPath
		layers := layers.NewImageLayers(coi.HostingSystem, containerRootInUVM, coi.Spec.Windows.LayerFolders, "", isSandbox)
		r.SetLayers(layers)
	} else if coi.Spec.Root.Path != "" {
		// This is the "Plan 9" root filesystem.
		// TODO: We need a test for this. Ask @jstarks how you can even lay this out on Windows.
		hostPath := coi.Spec.Root.Path
		uvmPathForContainersFileSystem := path.Join(r.ContainerRootInUVM(), uvm.RootfsPath)
		share, err := coi.HostingSystem.AddPlan9(ctx, hostPath, uvmPathForContainersFileSystem, coi.Spec.Root.Readonly, false, nil)
		if err != nil {
			return errors.Wrap(err, "adding plan9 root")
		}
		coi.Spec.Root.Path = uvmPathForContainersFileSystem
		r.Add(share)
	} else {
		return errors.New("must provide either Windows.LayerFolders or Root.Path")
	}

	for i, mount := range coi.Spec.Mounts {
		switch mount.Type {
		case "bind":
		case "physical-disk":
		case "virtual-disk":
		default:
			// Unknown mount type
			continue
		}
		if mount.Destination == "" || mount.Source == "" {
			return fmt.Errorf("invalid OCI spec - a mount must have both source and a destination: %+v", mount)
		}

		if coi.HostingSystem != nil {
			hostPath := mount.Source
			uvmPathForShare := path.Join(containerRootInUVM, fmt.Sprintf(uvm.LCOWMountPathPrefix, i))
			uvmPathForFile := uvmPathForShare

			readOnly := false
			for _, o := range mount.Options {
				if strings.ToLower(o) == "ro" {
					readOnly = true
					break
				}
			}

			l := log.G(ctx).WithField("mount", fmt.Sprintf("%+v", mount))
			if mount.Type == "physical-disk" {
				l.Debug("hcsshim::allocateLinuxResources Hot-adding SCSI physical disk for OCI mount")
				uvmPathForShare = fmt.Sprintf(uvm.LCOWGlobalMountPrefix, coi.HostingSystem.UVMMountCounter())
				scsiMount, err := coi.HostingSystem.AddSCSIPhysicalDisk(ctx, hostPath, uvmPathForShare, readOnly, mount.Options)
				if err != nil {
					return errors.Wrapf(err, "adding SCSI physical disk mount %+v", mount)
				}

				uvmPathForFile = scsiMount.UVMPath
				r.Add(scsiMount)
				coi.Spec.Mounts[i].Type = "none"
			} else if mount.Type == "virtual-disk" {
				l.Debug("hcsshim::allocateLinuxResources Hot-adding SCSI virtual disk for OCI mount")
				uvmPathForShare = fmt.Sprintf(uvm.LCOWGlobalMountPrefix, coi.HostingSystem.UVMMountCounter())

				// if the scsi device is already attached then we take the uvm path that the function below returns
				// that is where it was previously mounted in UVM
				scsiMount, err := coi.HostingSystem.AddSCSI(ctx, hostPath, uvmPathForShare, readOnly, mount.Options, uvm.VMAccessTypeIndividual)
				if err != nil {
					return errors.Wrapf(err, "adding SCSI virtual disk mount %+v", mount)
				}

				uvmPathForFile = scsiMount.UVMPath
				r.Add(scsiMount)
				coi.Spec.Mounts[i].Type = "none"
			} else if strings.HasPrefix(mount.Source, "sandbox://") || strings.HasPrefix(mount.Source, "hugepages://") {
				// Mounts that map to a path in UVM are specified with 'sandbox://' prefix.
				// example: sandbox:///a/dirInUvm destination:/b/dirInContainer
				// Hugepages inside a container are backed by a mount created inside a UVM.
				uvmPathForFile = mount.Source
			} else {
				st, err := os.Stat(hostPath)
				if err != nil {
					return errors.Wrap(err, "could not open bind mount target")
				}
				restrictAccess := false
				var allowedNames []string
				if !st.IsDir() {
					// Map the containing directory in, but restrict the share to a single
					// file.
					var fileName string
					hostPath, fileName = filepath.Split(hostPath)
					allowedNames = append(allowedNames, fileName)
					restrictAccess = true
					uvmPathForFile = path.Join(uvmPathForShare, fileName)
				}
				l.Debug("hcsshim::allocateLinuxResources Hot-adding Plan9 for OCI mount")

				share, err := coi.HostingSystem.AddPlan9(ctx, hostPath, uvmPathForShare, readOnly, restrictAccess, allowedNames)
				if err != nil {
					return errors.Wrapf(err, "adding plan9 mount %+v", mount)
				}
				r.Add(share)
			}
			coi.Spec.Mounts[i].Source = uvmPathForFile
		}
	}

	addGPUVHD := false
	for i, d := range coi.Spec.Windows.Devices {
		switch d.IDType {
		case uvm.GPUDeviceIDType:
			addGPUVHD = true
			vpci, err := coi.HostingSystem.AssignDevice(ctx, d.ID)
			if err != nil {
				return errors.Wrapf(err, "failed to assign gpu device %s to pod %s", d.ID, coi.HostingSystem.ID())
			}
			r.Add(vpci)
			// update device ID on the spec to the assigned device's resulting vmbus guid so gcs knows which devices to
			// map into the container
			coi.Spec.Windows.Devices[i].ID = vpci.VMBusGUID
		default:
			return fmt.Errorf("specified device %s has unsupported type %s", d.ID, d.IDType)
		}
	}

	if addGPUVHD {
		gpuSupportVhdPath, err := getGPUVHDPath(coi)
		if err != nil {
			return errors.Wrapf(err, "failed to add gpu vhd to %v", coi.HostingSystem.ID())
		}
		// use lcowNvidiaMountPath since we only support nvidia gpus right now
		// must use scsi here since DDA'ing a hyper-v pci device is not supported on VMs that have ANY virtual memory
		// gpuvhd must be granted VM Group access.
		options := []string{"ro"}
		scsiMount, err := coi.HostingSystem.AddSCSI(ctx, gpuSupportVhdPath, uvm.LCOWNvidiaMountPath, true, options, uvm.VMAccessTypeNoop)
		if err != nil {
			return errors.Wrapf(err, "failed to add scsi device %s in the UVM %s at %s", gpuSupportVhdPath, coi.HostingSystem.ID(), uvm.LCOWNvidiaMountPath)
		}
		r.Add(scsiMount)
	}
	return nil
}
<commit_msg>Update test modules with up to date hcsshim code<commit_after>// +build windows

package hcsoci

// Contains functions relating to a LCOW container, as opposed to a utility VM

import (
	"context"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"

	"github.com/Microsoft/hcsshim/internal/layers"
	"github.com/Microsoft/hcsshim/internal/log"
	"github.com/Microsoft/hcsshim/internal/oci"
	"github.com/Microsoft/hcsshim/internal/resources"
	"github.com/Microsoft/hcsshim/internal/uvm"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
)

// getGPUVHDPath gets the gpu vhd path from the shim options or uses the default if no
// shim option is set. Right now we only support Nvidia gpus, so this will default to
// a gpu vhd with nvidia files
func getGPUVHDPath(coi *createOptionsInternal) (string, error) {
	gpuVHDPath, ok := coi.Spec.Annotations[oci.AnnotationGPUVHDPath]
	if !ok || gpuVHDPath == "" {
		return "", fmt.Errorf("no gpu vhd specified %s", gpuVHDPath)
	}
	if _, err := os.Stat(gpuVHDPath); err != nil {
		return "", errors.Wrapf(err, "failed to find gpu support vhd %s", gpuVHDPath)
	}
	return gpuVHDPath, nil
}

func allocateLinuxResources(ctx context.Context, coi *createOptionsInternal, r *resources.Resources, isSandbox bool) error {
	if coi.Spec.Root == nil {
		coi.Spec.Root = &specs.Root{}
	}
	containerRootInUVM := r.ContainerRootInUVM()
	if coi.Spec.Windows != nil && len(coi.Spec.Windows.LayerFolders) > 0 {
		log.G(ctx).Debug("hcsshim::allocateLinuxResources mounting storage")
		rootPath, err := layers.MountContainerLayers(ctx, coi.actualID, coi.Spec.Windows.LayerFolders, containerRootInUVM, "", coi.HostingSystem)
		if err != nil {
			return errors.Wrap(err, "failed to mount container storage")
		}
		coi.Spec.Root.Path = rootPath
		layers := layers.NewImageLayers(coi.HostingSystem, containerRootInUVM, coi.Spec.Windows.LayerFolders, "", isSandbox)
		r.SetLayers(layers)
	} else if coi.Spec.Root.Path != "" {
		// This is the "Plan 9" root filesystem.
		// TODO: We need a test for this. Ask @jstarks how you can even lay this out on Windows.
		hostPath := coi.Spec.Root.Path
		uvmPathForContainersFileSystem := path.Join(r.ContainerRootInUVM(), uvm.RootfsPath)
		share, err := coi.HostingSystem.AddPlan9(ctx, hostPath, uvmPathForContainersFileSystem, coi.Spec.Root.Readonly, false, nil)
		if err != nil {
			return errors.Wrap(err, "adding plan9 root")
		}
		coi.Spec.Root.Path = uvmPathForContainersFileSystem
		r.Add(share)
	} else {
		return errors.New("must provide either Windows.LayerFolders or Root.Path")
	}

	for i, mount := range coi.Spec.Mounts {
		switch mount.Type {
		case "bind":
		case "physical-disk":
		case "virtual-disk":
		default:
			// Unknown mount type
			continue
		}
		if mount.Destination == "" || mount.Source == "" {
			return fmt.Errorf("invalid OCI spec - a mount must have both source and a destination: %+v", mount)
		}

		if coi.HostingSystem != nil {
			hostPath := mount.Source
			uvmPathForShare := path.Join(containerRootInUVM, fmt.Sprintf(uvm.LCOWMountPathPrefix, i))
			uvmPathForFile := uvmPathForShare

			readOnly := false
			for _, o := range mount.Options {
				if strings.ToLower(o) == "ro" {
					readOnly = true
					break
				}
			}

			l := log.G(ctx).WithField("mount", fmt.Sprintf("%+v", mount))
			if mount.Type == "physical-disk" {
				l.Debug("hcsshim::allocateLinuxResources Hot-adding SCSI physical disk for OCI mount")
				uvmPathForShare = fmt.Sprintf(uvm.LCOWGlobalMountPrefix, coi.HostingSystem.UVMMountCounter())
				scsiMount, err := coi.HostingSystem.AddSCSIPhysicalDisk(ctx, hostPath, uvmPathForShare, readOnly, mount.Options)
				if err != nil {
					return errors.Wrapf(err, "adding SCSI physical disk mount %+v", mount)
				}

				uvmPathForFile = scsiMount.UVMPath
				r.Add(scsiMount)
				coi.Spec.Mounts[i].Type = "none"
			} else if mount.Type == "virtual-disk" {
				l.Debug("hcsshim::allocateLinuxResources Hot-adding SCSI virtual disk for OCI mount")
				uvmPathForShare = fmt.Sprintf(uvm.LCOWGlobalMountPrefix, coi.HostingSystem.UVMMountCounter())

				// if the scsi device is already attached then we take the uvm path that the function below returns
				// that is where it was previously mounted in UVM
				scsiMount, err := coi.HostingSystem.AddSCSI(ctx, hostPath, uvmPathForShare, readOnly, mount.Options, uvm.VMAccessTypeIndividual)
				if err != nil {
					return errors.Wrapf(err, "adding SCSI virtual disk mount %+v", mount)
				}

				uvmPathForFile = scsiMount.UVMPath
				r.Add(scsiMount)
				coi.Spec.Mounts[i].Type = "none"
			} else if strings.HasPrefix(mount.Source, "sandbox://") {
				// Mounts that map to a path in UVM are specified with 'sandbox://' prefix.
				// example: sandbox:///a/dirInUvm destination:/b/dirInContainer
				uvmPathForFile = mount.Source
			} else if strings.HasPrefix(mount.Source, "hugepages://") {
				// currently we only support 2M hugepage size
				hugePageSubDirs := strings.Split(strings.TrimPrefix(mount.Source, "hugepages://"), "/")
				if len(hugePageSubDirs) < 2 {
					return errors.Errorf(`%s mount path is invalid, expected format: hugepages://<hugepage-size>/<hugepage-src-location>`, mount.Source)
				}

				// hugepages:// should be followed by pagesize
				if hugePageSubDirs[0] != "2M" {
					return errors.Errorf(`only 2M (megabytes) pagesize is supported, got %s`, hugePageSubDirs[0])
				}
				// Hugepages inside a container are backed by a mount created inside a UVM.
				uvmPathForFile = mount.Source
			} else {
				st, err := os.Stat(hostPath)
				if err != nil {
					return errors.Wrap(err, "could not open bind mount target")
				}
				restrictAccess := false
				var allowedNames []string
				if !st.IsDir() {
					// Map the containing directory in, but restrict the share to a single
					// file.
					var fileName string
					hostPath, fileName = filepath.Split(hostPath)
					allowedNames = append(allowedNames, fileName)
					restrictAccess = true
					uvmPathForFile = path.Join(uvmPathForShare, fileName)
				}
				l.Debug("hcsshim::allocateLinuxResources Hot-adding Plan9 for OCI mount")

				share, err := coi.HostingSystem.AddPlan9(ctx, hostPath, uvmPathForShare, readOnly, restrictAccess, allowedNames)
				if err != nil {
					return errors.Wrapf(err, "adding plan9 mount %+v", mount)
				}
				r.Add(share)
			}
			coi.Spec.Mounts[i].Source = uvmPathForFile
		}
	}

	addGPUVHD := false
	for i, d := range coi.Spec.Windows.Devices {
		switch d.IDType {
		case uvm.GPUDeviceIDType:
			addGPUVHD = true
			vpci, err := coi.HostingSystem.AssignDevice(ctx, d.ID)
			if err != nil {
				return errors.Wrapf(err, "failed to assign gpu device %s to pod %s", d.ID, coi.HostingSystem.ID())
			}
			r.Add(vpci)
			// update device ID on the spec to the assigned device's resulting vmbus guid so gcs knows which devices to
			// map into the container
			coi.Spec.Windows.Devices[i].ID = vpci.VMBusGUID
		default:
			return fmt.Errorf("specified device %s has unsupported type %s", d.ID, d.IDType)
		}
	}

	if addGPUVHD {
		gpuSupportVhdPath, err := getGPUVHDPath(coi)
		if err != nil {
			return errors.Wrapf(err, "failed to add gpu vhd to %v", coi.HostingSystem.ID())
		}
		// use lcowNvidiaMountPath since we only support nvidia gpus right now
		// must use scsi here since DDA'ing a hyper-v pci device is not supported on VMs that have ANY virtual memory
		// gpuvhd must be granted VM Group access.
		options := []string{"ro"}
		scsiMount, err := coi.HostingSystem.AddSCSI(ctx, gpuSupportVhdPath, uvm.LCOWNvidiaMountPath, true, options, uvm.VMAccessTypeNoop)
		if err != nil {
			return errors.Wrapf(err, "failed to add scsi device %s in the UVM %s at %s", gpuSupportVhdPath, coi.HostingSystem.ID(), uvm.LCOWNvidiaMountPath)
		}
		r.Add(scsiMount)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The go-python 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 bind

import (
	"fmt"
	"go/token"
	"strings"

	"golang.org/x/tools/go/types"
)

const (
	goPreamble = `// Package py_%[1]s is an autogenerated binder stub for package %[1]s.
// gopy-gen -lang=go %[1]s
//
// File is generated by gopy-gen. Do not edit.
package py_%[1]s

// void init%[1]s(void);
import "C"

import (
	%[2]q
)

`
)

type goGen struct {
	*printer

	fset *token.FileSet
	pkg  *types.Package
	err  ErrorList
}

func (g *goGen) gen() error {

	g.genPreamble()

	var funcs []string

	scope := g.pkg.Scope()
	names := scope.Names()
	for _, name := range names {
		obj := scope.Lookup(name)
		if !obj.Exported() {
			debugf("ignore %q (not exported)\n", name)
			continue
		}
		debugf("processing %q...\n", name)

		switch obj := obj.(type) {
		case *types.Const:
			// TODO(sbinet)
			panic(fmt.Errorf("not yet supported: %v (%T)", obj, obj))
		case *types.Var:
			// TODO(sbinet)
			panic(fmt.Errorf("not yet supported: %v (%T)", obj, obj))

		case *types.Func:
			funcs = append(funcs, obj.Name())
			g.genFunc(obj)

		case *types.TypeName:
			named := obj.Type().(*types.Named)
			switch typ := named.Underlying().(type) {
			case *types.Struct:
				// TODO(sbinet)
				panic(fmt.Errorf("not yet supported: %v (%T)", typ, obj))
			case *types.Interface:
				// TODO(sbinet)
				panic(fmt.Errorf("not yet supported: %v (%T)", typ, obj))
			default:
				// TODO(sbinet)
				panic(fmt.Errorf("not yet supported: %v (%T)", typ, obj))
			}

		default:
			// TODO(sbinet)
			panic(fmt.Errorf("not yet supported: %v (%T)", obj, obj))

		}
	}

	g.Printf("// Register registers the generated CPython module with the CPython runtime\nfunc Register() {\n")
	g.Indent()
	g.Printf("C.init%[1]s()\n", g.pkg.Name())
	g.Outdent()
	g.Printf("}\n")

	if len(g.err) > 0 {
		return g.err
	}

	return nil
}

func (g *goGen) genFunc(o *types.Func) {
	sig := o.Type().(*types.Signature)
	args := sig.Params()
	res := sig.Results()

	g.Printf(`
//export GoPy_%[1]s
// GoPy_%[1]s wraps %[2]s.%[1]s
// %[3]s
// %[4]v
// %[5]v
// %[6]v
func GoPy_%[1]s%[7]v {
`,
		o.Name(), g.pkg.Name(), o.FullName(),
		sig, args, res,
		strings.TrimLeft(sig.String(), "func "),
	)

	g.Indent()
	g.genFuncBody(o)
	g.Outdent()
	g.Printf("}\n\n")
}

func (g *goGen) genFuncBody(o *types.Func) {

	sig := o.Type().(*types.Signature)
	ret := ""
	if sig.Results().Len() > 0 {
		ret = "return "
	}

	g.Printf(
		"%[3]s%[1]s.%[2]s(",
		g.pkg.Name(),
		o.Name(),
		ret,
	)

	args := sig.Params()
	for i := 0; i < args.Len(); i++ {
		arg := args.At(i)
		tail := ""
		if i+1 < args.Len() {
			tail = ", "
		}
		g.Printf("%s%s", arg.Name(), tail)
	}
	g.Printf(")\n")

}

func (g *goGen) genPreamble() {
	n := g.pkg.Name()
	g.Printf(goPreamble, n, g.pkg.Path())
}
<commit_msg>py/bind: cosmetics<commit_after>// Copyright 2015 The go-python 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 bind

import (
	"fmt"
	"go/token"
	"strings"

	"golang.org/x/tools/go/types"
)

const (
	goPreamble = `// Package py_%[1]s is an autogenerated binder stub for package %[1]s.
// gopy-gen -lang=go %[1]s
//
// File is generated by gopy-gen. Do not edit.
package py_%[1]s

// void init%[1]s(void);
import "C"

import (
	%[2]q
)

`
)

type goGen struct {
	*printer

	fset *token.FileSet
	pkg  *types.Package
	err  ErrorList
}

func (g *goGen) gen() error {

	g.genPreamble()

	var funcs []string

	scope := g.pkg.Scope()
	names := scope.Names()
	for _, name := range names {
		obj := scope.Lookup(name)
		if !obj.Exported() {
			debugf("ignore %q (not exported)\n", name)
			continue
		}
		debugf("processing %q...\n", name)

		switch obj := obj.(type) {
		case *types.Const:
			// TODO(sbinet)
			panic(fmt.Errorf("not yet supported: %v (%T)", obj, obj))
		case *types.Var:
			// TODO(sbinet)
			panic(fmt.Errorf("not yet supported: %v (%T)", obj, obj))

		case *types.Func:
			funcs = append(funcs, obj.Name())
			g.genFunc(obj)

		case *types.TypeName:
			named := obj.Type().(*types.Named)
			switch typ := named.Underlying().(type) {
			case *types.Struct:
				// TODO(sbinet)
				panic(fmt.Errorf("not yet supported: %v (%T)", typ, obj))
			case *types.Interface:
				// TODO(sbinet)
				panic(fmt.Errorf("not yet supported: %v (%T)", typ, obj))
			default:
				// TODO(sbinet)
				panic(fmt.Errorf("not yet supported: %v (%T)", typ, obj))
			}

		default:
			// TODO(sbinet)
			panic(fmt.Errorf("not yet supported: %v (%T)", obj, obj))

		}
	}

	g.Printf("// Register registers the generated CPython module with the CPython runtime\nfunc Register() {\n")
	g.Indent()
	g.Printf("C.init%[1]s()\n", g.pkg.Name())
	g.Outdent()
	g.Printf("}\n")

	if len(g.err) > 0 {
		return g.err
	}

	return nil
}

func (g *goGen) genFunc(o *types.Func) {
	sig := o.Type().(*types.Signature)

	g.Printf(`
//export GoPy_%[1]s
// GoPy_%[1]s wraps %[2]s
func GoPy_%[1]s%[3]v {
`,
		o.Name(), o.FullName(),
		strings.TrimLeft(sig.String(), "func "),
	)

	g.Indent()
	g.genFuncBody(o)
	g.Outdent()
	g.Printf("}\n\n")
}

func (g *goGen) genFuncBody(o *types.Func) {

	sig := o.Type().(*types.Signature)
	ret := ""
	if sig.Results().Len() > 0 {
		ret = "return "
	}

	g.Printf(
		"%[3]s%[1]s.%[2]s(",
		g.pkg.Name(),
		o.Name(),
		ret,
	)

	args := sig.Params()
	for i := 0; i < args.Len(); i++ {
		arg := args.At(i)
		tail := ""
		if i+1 < args.Len() {
			tail = ", "
		}
		g.Printf("%s%s", arg.Name(), tail)
	}
	g.Printf(")\n")

}

func (g *goGen) genPreamble() {
	n := g.pkg.Name()
	g.Printf(goPreamble, n, g.pkg.Path())
}
<|endoftext|>


<commit_before>package just

import (
	"sync"
)

type ISerializer interface {
	DefaultContentType() string
	Serialize(interface{}) ([]byte, error)
	Deserialize([]byte, interface{}) error
}

type ISerializerManager interface {
	NameDefaultSerializer() (string, bool)
	SetNameDefaultSerializer(string) ISerializerManager
	SetSerializer(string, []string, ISerializer) ISerializerManager
	SerializerNames() []string
	SerializerByName(string) ISerializer
	SerializerByContentType(string) ISerializer
}

// serializerManager менеджер сериализаторов
type serializerManager struct {
	sync.RWMutex
	nameDefaultSerializer    string
	serializersByName        map[string]ISerializer
	serializersByContentType map[string]ISerializer
}

func (m *serializerManager) SerializerNames() []string {
	names := make([]string, 0)
	for name, _ := range m.serializersByName {
		names = append(names, name)
	}
	return names
}

func (m *serializerManager) NameDefaultSerializer() (string, bool) {
	if len(m.nameDefaultSerializer) < 1 && len(m.serializersByName) > 0 {
		for name, _ := range m.serializersByName {
			return name, false
		}
	}
	return m.nameDefaultSerializer, true
}

func (m *serializerManager) SetNameDefaultSerializer(name string) ISerializerManager {
	m.RLock()
	defer m.RUnlock()
	if _, ok := m.serializersByName[name]; ok || len(name) < 1 {
		m.nameDefaultSerializer = name
	}
	return m
}

func (m *serializerManager) SetSerializer(name string, contentTypes []string, serializer ISerializer) ISerializerManager {
	m.RLock()
	defer m.RUnlock()
	if m.serializersByName == nil {
		m.serializersByName = make(map[string]ISerializer)
	}
	m.serializersByName[name] = serializer
	if m.serializersByContentType == nil {
		m.serializersByContentType = make(map[string]ISerializer)
	}
	if contentTypes != nil && len(contentTypes) > 0 {
		for _, contentType := range contentTypes {
			m.serializersByContentType[contentType] = serializer
		}
	}
	return m
}

func (m *serializerManager) SerializerByName(name string) ISerializer {
	if m.serializersByName != nil {
		if s, ok := m.serializersByName[name]; ok {
			return s
		}
	}
	return nil
}

func (m *serializerManager) SerializerByContentType(contentType string) ISerializer {
	if m.serializersByContentType != nil {
		if s, ok := m.serializersByContentType[contentType]; ok {
			return s
		}
	}
	return nil
}
<commit_msg>- Fixes<commit_after>package just

import (
	"sync"
)

type ISerializer interface {
	DefaultContentType() string
	Serialize(interface{}) ([]byte, error)
	Deserialize([]byte, interface{}) error
}

type ISerializerManager interface {
	NameDefaultSerializer() (string, bool)
	SetNameDefaultSerializer(string) ISerializerManager
	SetSerializer(string, []string, ISerializer) ISerializerManager
	SerializerNames() []string
	SerializerByName(string) ISerializer
	SerializerByContentType(string) ISerializer
}

// serializerManager менеджер сериализаторов
type serializerManager struct {
	sync.RWMutex
	nameDefaultSerializer    string
	serializersByName        map[string]ISerializer
	serializersByContentType map[string]ISerializer
}

func (m *serializerManager) SerializerNames() []string {
	names := make([]string, 0)
	for name := range m.serializersByName {
		names = append(names, name)
	}
	return names
}

func (m *serializerManager) NameDefaultSerializer() (string, bool) {
	if len(m.nameDefaultSerializer) < 1 && len(m.serializersByName) > 0 {
		for name := range m.serializersByName {
			return name, false
		}
	}
	return m.nameDefaultSerializer, true
}

func (m *serializerManager) SetNameDefaultSerializer(name string) ISerializerManager {
	m.RLock()
	defer m.RUnlock()
	if _, ok := m.serializersByName[name]; ok || len(name) < 1 {
		m.nameDefaultSerializer = name
	}
	return m
}

func (m *serializerManager) SetSerializer(name string, contentTypes []string, serializer ISerializer) ISerializerManager {
	m.RLock()
	defer m.RUnlock()
	if m.serializersByName == nil {
		m.serializersByName = make(map[string]ISerializer)
	}
	m.serializersByName[name] = serializer
	if m.serializersByContentType == nil {
		m.serializersByContentType = make(map[string]ISerializer)
	}
	if contentTypes != nil && len(contentTypes) > 0 {
		for _, contentType := range contentTypes {
			m.serializersByContentType[contentType] = serializer
		}
	}
	return m
}

func (m *serializerManager) SerializerByName(name string) ISerializer {
	if m.serializersByName != nil {
		if s, ok := m.serializersByName[name]; ok {
			return s
		}
	}
	return nil
}

func (m *serializerManager) SerializerByContentType(contentType string) ISerializer {
	if m.serializersByContentType != nil {
		if s, ok := m.serializersByContentType[contentType]; ok {
			return s
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 realglobe, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"github.com/realglobe-Inc/go-lib/erro"
	"github.com/realglobe-Inc/go-lib/rglog"
	"github.com/realglobe-Inc/go-lib/rglog/level"
	"net/http"
	"net/http/httputil"
)

const logRoot = "github.com/realglobe-Inc"

var log = rglog.Logger(logRoot + "/edo-lib/server")

func LogRequest(lv level.Level, r *http.Request, useBody bool, prefs ...interface{}) {
	if log.IsLoggable(lv) {
		buff, err := httputil.DumpRequest(r, useBody)
		if err != nil {
			log.Warn(append(prefs, erro.Unwrap(err)))
			log.Debug(append(prefs, erro.Wrap(err)))
			return
		}
		log.Log(lv, append(prefs, "Request: ", string(buff))...)
	}
}

func LogResponse(lv level.Level, r *http.Response, useBody bool, prefs ...interface{}) {
	if log.IsLoggable(lv) {
		buff, err := httputil.DumpResponse(r, useBody)
		if err != nil {
			log.Warn(append(prefs, erro.Unwrap(err)))
			log.Debug(append(prefs, erro.Wrap(err)))
			return
		}
		log.Log(lv, append(prefs, "Response: ", string(buff))...)
	}
}
<commit_msg>... の付け忘れを修正<commit_after>// Copyright 2015 realglobe, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"github.com/realglobe-Inc/go-lib/erro"
	"github.com/realglobe-Inc/go-lib/rglog"
	"github.com/realglobe-Inc/go-lib/rglog/level"
	"net/http"
	"net/http/httputil"
)

const logRoot = "github.com/realglobe-Inc"

var log = rglog.Logger(logRoot + "/edo-lib/server")

func LogRequest(lv level.Level, r *http.Request, useBody bool, prefs ...interface{}) {
	if log.IsLoggable(lv) {
		buff, err := httputil.DumpRequest(r, useBody)
		if err != nil {
			log.Warn(append(prefs, erro.Unwrap(err))...)
			log.Debug(append(prefs, erro.Wrap(err))...)
			return
		}
		log.Log(lv, append(prefs, "Request: ", string(buff))...)
	}
}

func LogResponse(lv level.Level, r *http.Response, useBody bool, prefs ...interface{}) {
	if log.IsLoggable(lv) {
		buff, err := httputil.DumpResponse(r, useBody)
		if err != nil {
			log.Warn(append(prefs, erro.Unwrap(err))...)
			log.Debug(append(prefs, erro.Wrap(err))...)
			return
		}
		log.Log(lv, append(prefs, "Response: ", string(buff))...)
	}
}
<|endoftext|>


<commit_before>package HologramGo

import (
	"testing"
	"fmt"
	"../Hologram-Go"
	"encoding/json"
	"io/ioutil"
)

func TestGetDeviceDataPlan(t *testing.T) {

	file, e := ioutil.ReadFile("json/plan.json")
	if e != nil {
		fmt.Printf("Error opening file: %v\n", e)
	}

	var payload = HologramGo.Placeholder{}
	err := json.Unmarshal(file, &payload)
	if err != nil {
		fmt.Println("Unable to parse file")
	}
	var plan = (HologramGo.Plan)(payload["data"].(map[string]interface{}))

	// Test for data plan id
	expectedFloat := (float64)(51)
	returnedFloat := plan.GetDataPlanId()
	if expectedFloat != returnedFloat {
		t.Fatalf("Expected %s, got %s", expectedFloat, returnedFloat)
	}
}
<commit_msg>added more test cases<commit_after>package HologramGo

import (
	"testing"
	"fmt"
	"../Hologram-Go"
	"encoding/json"
	"io/ioutil"
)

func TestGetDeviceDataPlan(t *testing.T) {

	file, e := ioutil.ReadFile("json/plan.json")
	if e != nil {
		fmt.Printf("Error opening file: %v\n", e)
	}

	var payload = HologramGo.Placeholder{}
	err := json.Unmarshal(file, &payload)
	if err != nil {
		fmt.Println("Unable to parse file")
	}
	var plans = (payload["data"].([]interface{}))
	var plan = (HologramGo.Plan)(plans[0].(map[string]interface{}))

	// Test for data plan id
	expectedFloat := (float64)(51)
	returnedFloat := plan.GetDataPlanId()
	if expectedFloat != returnedFloat {
		t.Fatalf("Expected %s, got %s", expectedFloat, returnedFloat)
	}

	// Test for data plan partner id.
	expectedFloat = (float64)(1)
	returnedFloat = plan.GetDataPlanPartnerId()
	if expectedFloat != returnedFloat {
		t.Fatalf("Expected %s, got %s", expectedFloat, returnedFloat)
	}

	// Test for data plan name.
	expectedString := "1 MB"
	returnedString := plan.GetDataPlanName()
	if expectedString != returnedString {
		t.Fatalf("Expected %s, got %s", expectedString, returnedString)
	}

	// Test for data plan subscription
	expectedString = ""
	returnedString = plan.GetDataPlanDescription()
	if expectedString != returnedString {
		t.Fatalf("Expected %s, got %s", expectedString, returnedString)
	}

	// Test for data plan size
	expectedFloat = (float64)(1000000)
	returnedFloat = plan.GetDataPlanSize()
	if expectedFloat != returnedFloat {
		t.Fatalf("Expected %s, got %s", expectedFloat, returnedFloat)
	}

	// Test for data plan billing period
	expectedFloat = (float64)(24)
	returnedFloat = plan.GetDataPlanBillingPeriod()
	if expectedFloat != returnedFloat {
		t.Fatalf("Expected %s, got %s", expectedFloat, returnedFloat)
	}

	// Test for data plan carrier id.
	expectedFloat = (float64)(1)
	returnedFloat = plan.GetDataPlanCarrierId()
	if expectedFloat != returnedFloat {
		t.Fatalf("Expected %s, got %s", expectedFloat, returnedFloat)
	}
}
<|endoftext|>


<commit_before>package jsonmap

import (
	"bytes"
	"encoding/json"
	"fmt"
	"reflect"
)

type ValidationError struct {
	reason string
	rpath  []string
}

func NewValidationError(reason string, a ...interface{}) *ValidationError {
	return &ValidationError{
		reason: fmt.Sprintf(reason, a...),
		rpath:  make([]string, 0, 2),
	}
}

func (e *ValidationError) Error() string {
	msg := e.reason
	for _, seg := range e.rpath {
		msg = seg + ": " + msg
	}
	return "validation error: " + msg
}

func (e *ValidationError) PushIndex(idx int) {
	e.rpath = append(e.rpath, fmt.Sprintf("index %d", idx))
}

func (e *ValidationError) PushKey(key string) {
	e.rpath = append(e.rpath, fmt.Sprintf("'%s'", key))
}

type Validator interface {
	Validate(interface{}) (interface{}, error)
}

type TypeMap interface {
	Unmarshal(parent *reflect.Value, partial interface{}, dstValue reflect.Value) error
	Marshal(parent *reflect.Value, field reflect.Value) (json.Marshaler, error)
}

type MappedField struct {
	StructFieldName string
	JSONFieldName   string
	Contains        TypeMap
	Validator       Validator
	Optional        bool
	ReadOnly        bool
}

type StructMap struct {
	UnderlyingType interface{}
	Fields         []MappedField
}

type russellRawMessage struct {
	Data []byte
}

func (rm russellRawMessage) MarshalJSON() ([]byte, error) {
	return rm.Data, nil
}

func (sm StructMap) Unmarshal(parent *reflect.Value, partial interface{}, dstValue reflect.Value) error {
	data, ok := partial.(map[string]interface{})
	if !ok {
		return NewValidationError("expected an object")
	}

	// In order to unmarshal into an interface{} we need to allocate an actual
	// instance of this type of struct, and set the interface{} to point to the
	// value.
	if dstValue.Kind() == reflect.Interface {
		dstValue.Set(reflect.New(reflect.TypeOf(sm.UnderlyingType)))
		dstValue = dstValue.Elem().Elem()
	}

	for _, field := range sm.Fields {
		if field.ReadOnly {
			continue
		}

		dstField := dstValue.FieldByName(field.StructFieldName)
		if !dstField.IsValid() {
			panic("no such underlying field: " + field.StructFieldName)
		}

		val, ok := data[field.JSONFieldName]
		if !ok {
			if field.Optional {
				continue
			} else {
				return NewValidationError("missing required field: %s", field.JSONFieldName)
			}
		}

		var err error

		if field.Contains != nil {
			err = field.Contains.Unmarshal(&dstValue, val, dstField)
		} else {
			val, err = field.Validator.Validate(val)
			if err == nil {
				dstField.Set(reflect.ValueOf(val))
			}
		}

		if err != nil {
			if ve, ok := err.(*ValidationError); ok {
				ve.PushKey(field.JSONFieldName)
			}
			return err
		}
	}

	return nil
}

func (sm StructMap) marshalField(parent reflect.Value, field MappedField, srcField reflect.Value) ([]byte, error) {
	var val interface{}
	if field.Contains != nil {
		var err error
		val, err = field.Contains.Marshal(&parent, srcField)
		if err != nil {
			return nil, err
		}
	} else {
		val = srcField.Interface()
	}

	return json.Marshal(val)
}

func (sm StructMap) Marshal(parent *reflect.Value, src reflect.Value) (json.Marshaler, error) {
	// An Interface's Elem() returns a Ptr whose Elem() returns the actual value
	if src.Kind() == reflect.Interface {
		src = src.Elem()
	}
	if src.Kind() == reflect.Ptr {
		src = src.Elem()
	}

	expectedType := reflect.TypeOf(sm.UnderlyingType)
	if src.Type() != expectedType {
		panic("wrong type: " + src.Type().String() + ", expected: " + expectedType.String())
	}

	buf := bytes.Buffer{}
	buf.WriteByte('{')

	for i, field := range sm.Fields {
		srcField := src.FieldByName(field.StructFieldName)
		if !srcField.IsValid() {
			panic("no such underlying field: " + field.StructFieldName)
		}

		keybuf, err := json.Marshal(field.JSONFieldName)
		if err != nil {
			return nil, err
		}

		valbuf, err := sm.marshalField(src, field, srcField)
		if err != nil {
			return nil, err
		}

		buf.Write(keybuf)
		buf.WriteByte(':')
		buf.Write(valbuf)

		if i != len(sm.Fields)-1 {
			buf.WriteByte(',')
		}
	}

	buf.WriteByte('}')

	return russellRawMessage{buf.Bytes()}, nil
}

type SliceMap struct {
	Contains TypeMap
}

func (sm SliceMap) Unmarshal(parent *reflect.Value, partial interface{}, dstValue reflect.Value) error {
	data, ok := partial.([]interface{})
	if !ok {
		return NewValidationError("expected a list")
	}

	// Appending to a reflect.Value returns a new reflect.Value despite the
	// indirection. So we'll keep a reference to the original one, and Set()
	// it when we're done constructing the desired Value.
	result := dstValue

	elementType := dstValue.Type().Elem()

	for i, val := range data {
		// Note: reflect.New() returns a pointer Value, so we have to take its
		// Elem() before putting it to use
		dstElem := reflect.New(elementType).Elem()

		err := sm.Contains.Unmarshal(&dstValue, val, dstElem)

		if err != nil {
			if ve, ok := err.(*ValidationError); ok {
				ve.PushIndex(i)
			}
			return err
		}

		result = reflect.Append(result, dstElem)
	}

	// Note: this actually works with a reflect.Value of a slice, even though it
	// wouldn't work with an actual slice because of the second level of
	// indirection.
	dstValue.Set(result)

	return nil
}

func (sm SliceMap) Marshal(parent *reflect.Value, src reflect.Value) (json.Marshaler, error) {
	if src.Kind() == reflect.Ptr {
		src = src.Elem()
	}

	result := make([]interface{}, src.Len())

	for i := 0; i < src.Len(); i++ {
		data, err := sm.Contains.Marshal(&src, src.Index(i))
		if err != nil {
			return nil, err
		}

		result[i] = data
	}

	data, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}

	return russellRawMessage{data}, nil
}

func SliceOf(elem TypeMap) TypeMap {
	return SliceMap{
		Contains: elem,
	}
}

// This is a horrible hack of the go type system
type variableType struct {
	switchOnFieldName string
	types             map[string]TypeMap
}

func (vt *variableType) pickTypeMap(parent *reflect.Value) (TypeMap, error) {
	typeKeyField := parent.FieldByName(vt.switchOnFieldName)
	if !typeKeyField.IsValid() {
		panic("no such underlying field: " + vt.switchOnFieldName)
	}

	typeKey := typeKeyField.String()
	typeMap, ok := vt.types[typeKey]

	if !ok {
		// NOTE: This error message isn't great because we don't have a way to know
		// the JSON field name uponw which we're switching.
		return nil, NewValidationError("invalid type identifier: '%s'", typeKey)
	}

	return typeMap, nil
}

func (vt *variableType) Unmarshal(parent *reflect.Value, partial interface{}, dstValue reflect.Value) error {
	tm, err := vt.pickTypeMap(parent)
	if err != nil {
		return err
	}

	return tm.Unmarshal(parent, partial, dstValue)
}

func (vt *variableType) Marshal(parent *reflect.Value, src reflect.Value) (json.Marshaler, error) {
	tm, err := vt.pickTypeMap(parent)
	if err != nil {
		panic("variable type serialization error: " + err.Error())
	}

	return tm.Marshal(parent, src)
}

func VariableType(switchOnFieldName string, types map[string]TypeMap) TypeMap {
	return &variableType{
		switchOnFieldName: switchOnFieldName,
		types:             types,
	}
}

type TypeMapper struct {
	typeMaps map[reflect.Type]TypeMap
}

func NewTypeMapper(maps ...StructMap) *TypeMapper {
	t := &TypeMapper{
		typeMaps: make(map[reflect.Type]TypeMap),
	}
	for _, m := range maps {
		t.typeMaps[reflect.TypeOf(m.UnderlyingType)] = m
	}
	return t
}

func (tm *TypeMapper) getTypeMap(obj interface{}) TypeMap {
	t := reflect.TypeOf(obj)
	isSlice := false

	if t.Kind() == reflect.Slice {
		isSlice = true
		t = t.Elem()
	}

	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	m, ok := tm.typeMaps[t]

	if !ok {
		panic("no TypeMap registered for type: " + t.String())
	}

	if isSlice {
		m = SliceOf(m)
	}

	return m
}

func (tm *TypeMapper) Unmarshal(data []byte, dest interface{}) error {
	if reflect.TypeOf(dest).Kind() != reflect.Ptr {
		panic("cannot unmarshal to non-pointer")
	}
	m := tm.getTypeMap(dest)
	partial := map[string]interface{}{}

	err := json.Unmarshal(data, &partial)
	if err != nil {
		if _, ok := err.(*json.SyntaxError); ok {
			err = NewValidationError(err.Error())
		}
		return err
	}

	return m.Unmarshal(nil, partial, reflect.ValueOf(dest).Elem())
}

func (tm *TypeMapper) Marshal(src interface{}) ([]byte, error) {
	m := tm.getTypeMap(src)
	data, err := m.Marshal(nil, reflect.ValueOf(src))
	if err != nil {
		return nil, err
	}
	return data.MarshalJSON()
}

func (tm *TypeMapper) MarshalIndent(src interface{}, prefix, indent string) ([]byte, error) {
	// This is nuts, but equivalent to how json.MarshalIndent() works
	data, err := tm.Marshal(src)
	if err != nil {
		return nil, err
	}

	buf := &bytes.Buffer{}

	err = json.Indent(buf, data, prefix, indent)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}
<commit_msg>Add support for using a getter method instead of a field name<commit_after>package jsonmap

import (
	"bytes"
	"encoding/json"
	"fmt"
	"reflect"
)

type ValidationError struct {
	reason string
	rpath  []string
}

func NewValidationError(reason string, a ...interface{}) *ValidationError {
	return &ValidationError{
		reason: fmt.Sprintf(reason, a...),
		rpath:  make([]string, 0, 2),
	}
}

func (e *ValidationError) Error() string {
	msg := e.reason
	for _, seg := range e.rpath {
		msg = seg + ": " + msg
	}
	return "validation error: " + msg
}

func (e *ValidationError) PushIndex(idx int) {
	e.rpath = append(e.rpath, fmt.Sprintf("index %d", idx))
}

func (e *ValidationError) PushKey(key string) {
	e.rpath = append(e.rpath, fmt.Sprintf("'%s'", key))
}

type Validator interface {
	Validate(interface{}) (interface{}, error)
}

type TypeMap interface {
	Unmarshal(parent *reflect.Value, partial interface{}, dstValue reflect.Value) error
	Marshal(parent *reflect.Value, field reflect.Value) (json.Marshaler, error)
}

type MappedField struct {
	StructFieldName  string
	StructGetterName string
	JSONFieldName    string
	Contains         TypeMap
	Validator        Validator
	Optional         bool
	ReadOnly         bool
}

type StructMap struct {
	UnderlyingType interface{}
	Fields         []MappedField
}

type russellRawMessage struct {
	Data []byte
}

func (rm russellRawMessage) MarshalJSON() ([]byte, error) {
	return rm.Data, nil
}

func (sm StructMap) Unmarshal(parent *reflect.Value, partial interface{}, dstValue reflect.Value) error {
	data, ok := partial.(map[string]interface{})
	if !ok {
		return NewValidationError("expected an object")
	}

	// In order to unmarshal into an interface{} we need to allocate an actual
	// instance of this type of struct, and set the interface{} to point to the
	// value.
	if dstValue.Kind() == reflect.Interface {
		dstValue.Set(reflect.New(reflect.TypeOf(sm.UnderlyingType)))
		dstValue = dstValue.Elem().Elem()
	}

	for _, field := range sm.Fields {
		if field.ReadOnly {
			continue
		}

		// TODO: Setters
		dstField := dstValue.FieldByName(field.StructFieldName)
		if !dstField.IsValid() {
			panic("no such underlying field: " + field.StructFieldName)
		}

		val, ok := data[field.JSONFieldName]
		if !ok {
			if field.Optional {
				continue
			} else {
				return NewValidationError("missing required field: %s", field.JSONFieldName)
			}
		}

		var err error

		if field.Contains != nil {
			err = field.Contains.Unmarshal(&dstValue, val, dstField)
		} else {
			val, err = field.Validator.Validate(val)
			if err == nil {
				dstField.Set(reflect.ValueOf(val))
			}
		}

		if err != nil {
			if ve, ok := err.(*ValidationError); ok {
				ve.PushKey(field.JSONFieldName)
			}
			return err
		}
	}

	return nil
}

func (sm StructMap) marshalField(parent reflect.Value, field MappedField, srcField reflect.Value) ([]byte, error) {
	var val interface{}
	if field.Contains != nil {
		var err error
		val, err = field.Contains.Marshal(&parent, srcField)
		if err != nil {
			return nil, err
		}
	} else {
		val = srcField.Interface()
	}

	return json.Marshal(val)
}

func (sm StructMap) Marshal(parent *reflect.Value, src reflect.Value) (json.Marshaler, error) {
	// An Interface's Elem() returns a Ptr whose Elem() returns the actual value
	if src.Kind() == reflect.Interface {
		src = src.Elem()
	}
	if src.Kind() == reflect.Ptr {
		src = src.Elem()
	}

	expectedType := reflect.TypeOf(sm.UnderlyingType)
	if src.Type() != expectedType {
		panic("wrong type: " + src.Type().String() + ", expected: " + expectedType.String())
	}

	buf := bytes.Buffer{}
	buf.WriteByte('{')

	for i, field := range sm.Fields {
		var srcField reflect.Value

		// TODO: Do validation ahead of time
		if field.StructFieldName != "" {
			srcField = src.FieldByName(field.StructFieldName)
			if !srcField.IsValid() {
				panic("no such underlying field: " + field.StructFieldName)
			}
		} else if field.StructGetterName != "" {
			srcGetter := src.MethodByName(field.StructGetterName)
			if !srcGetter.IsValid() {
				panic("no such underlying getter method: " + field.StructGetterName)
			}
			rets := srcGetter.Call([]reflect.Value{})
			if len(rets) != 2 {
				panic("invalid getter, should return (interface{}, error): " + field.StructGetterName)
			}
			if !rets[1].IsNil() {
				return nil, rets[1].Interface().(error)
			}
			srcField = rets[0]
		} else {
			panic("either StructFieldName or StructGetterName must be specified")
		}

		keybuf, err := json.Marshal(field.JSONFieldName)
		if err != nil {
			return nil, err
		}

		valbuf, err := sm.marshalField(src, field, srcField)
		if err != nil {
			return nil, err
		}

		buf.Write(keybuf)
		buf.WriteByte(':')
		buf.Write(valbuf)

		if i != len(sm.Fields)-1 {
			buf.WriteByte(',')
		}
	}

	buf.WriteByte('}')

	return russellRawMessage{buf.Bytes()}, nil
}

type SliceMap struct {
	Contains TypeMap
}

func (sm SliceMap) Unmarshal(parent *reflect.Value, partial interface{}, dstValue reflect.Value) error {
	data, ok := partial.([]interface{})
	if !ok {
		return NewValidationError("expected a list")
	}

	// Appending to a reflect.Value returns a new reflect.Value despite the
	// indirection. So we'll keep a reference to the original one, and Set()
	// it when we're done constructing the desired Value.
	result := dstValue

	elementType := dstValue.Type().Elem()

	for i, val := range data {
		// Note: reflect.New() returns a pointer Value, so we have to take its
		// Elem() before putting it to use
		dstElem := reflect.New(elementType).Elem()

		err := sm.Contains.Unmarshal(&dstValue, val, dstElem)

		if err != nil {
			if ve, ok := err.(*ValidationError); ok {
				ve.PushIndex(i)
			}
			return err
		}

		result = reflect.Append(result, dstElem)
	}

	// Note: this actually works with a reflect.Value of a slice, even though it
	// wouldn't work with an actual slice because of the second level of
	// indirection.
	dstValue.Set(result)

	return nil
}

func (sm SliceMap) Marshal(parent *reflect.Value, src reflect.Value) (json.Marshaler, error) {
	if src.Kind() == reflect.Ptr {
		src = src.Elem()
	}

	result := make([]interface{}, src.Len())

	for i := 0; i < src.Len(); i++ {
		data, err := sm.Contains.Marshal(&src, src.Index(i))
		if err != nil {
			return nil, err
		}

		result[i] = data
	}

	data, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}

	return russellRawMessage{data}, nil
}

func SliceOf(elem TypeMap) TypeMap {
	return SliceMap{
		Contains: elem,
	}
}

// This is a horrible hack of the go type system
type variableType struct {
	switchOnFieldName string
	types             map[string]TypeMap
}

func (vt *variableType) pickTypeMap(parent *reflect.Value) (TypeMap, error) {
	typeKeyField := parent.FieldByName(vt.switchOnFieldName)
	if !typeKeyField.IsValid() {
		panic("no such underlying field: " + vt.switchOnFieldName)
	}

	typeKey := typeKeyField.String()
	typeMap, ok := vt.types[typeKey]

	if !ok {
		// NOTE: This error message isn't great because we don't have a way to know
		// the JSON field name uponw which we're switching.
		return nil, NewValidationError("invalid type identifier: '%s'", typeKey)
	}

	return typeMap, nil
}

func (vt *variableType) Unmarshal(parent *reflect.Value, partial interface{}, dstValue reflect.Value) error {
	tm, err := vt.pickTypeMap(parent)
	if err != nil {
		return err
	}

	return tm.Unmarshal(parent, partial, dstValue)
}

func (vt *variableType) Marshal(parent *reflect.Value, src reflect.Value) (json.Marshaler, error) {
	tm, err := vt.pickTypeMap(parent)
	if err != nil {
		panic("variable type serialization error: " + err.Error())
	}

	return tm.Marshal(parent, src)
}

func VariableType(switchOnFieldName string, types map[string]TypeMap) TypeMap {
	return &variableType{
		switchOnFieldName: switchOnFieldName,
		types:             types,
	}
}

type TypeMapper struct {
	typeMaps map[reflect.Type]TypeMap
}

func NewTypeMapper(maps ...StructMap) *TypeMapper {
	t := &TypeMapper{
		typeMaps: make(map[reflect.Type]TypeMap),
	}
	for _, m := range maps {
		t.typeMaps[reflect.TypeOf(m.UnderlyingType)] = m
	}
	return t
}

func (tm *TypeMapper) getTypeMap(obj interface{}) TypeMap {
	t := reflect.TypeOf(obj)
	isSlice := false

	if t.Kind() == reflect.Slice {
		isSlice = true
		t = t.Elem()
	}

	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	m, ok := tm.typeMaps[t]

	if !ok {
		panic("no TypeMap registered for type: " + t.String())
	}

	if isSlice {
		m = SliceOf(m)
	}

	return m
}

func (tm *TypeMapper) Unmarshal(data []byte, dest interface{}) error {
	if reflect.TypeOf(dest).Kind() != reflect.Ptr {
		panic("cannot unmarshal to non-pointer")
	}
	m := tm.getTypeMap(dest)
	partial := map[string]interface{}{}

	err := json.Unmarshal(data, &partial)
	if err != nil {
		if _, ok := err.(*json.SyntaxError); ok {
			err = NewValidationError(err.Error())
		}
		return err
	}

	return m.Unmarshal(nil, partial, reflect.ValueOf(dest).Elem())
}

func (tm *TypeMapper) Marshal(src interface{}) ([]byte, error) {
	m := tm.getTypeMap(src)
	data, err := m.Marshal(nil, reflect.ValueOf(src))
	if err != nil {
		return nil, err
	}
	return data.MarshalJSON()
}

func (tm *TypeMapper) MarshalIndent(src interface{}, prefix, indent string) ([]byte, error) {
	// This is nuts, but equivalent to how json.MarshalIndent() works
	data, err := tm.Marshal(src)
	if err != nil {
		return nil, err
	}

	buf := &bytes.Buffer{}

	err = json.Indent(buf, data, prefix, indent)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}
<|endoftext|>


<commit_before>// © 2016-2017 Helix OpCo LLC. All rights reserved.
// Initial Author: Chris Williams

package reported_at

import (
	"bytes"
	"context"
	"testing"

	"github.com/myhelix/contextlogger/providers"
	cl_logrus "github.com/myhelix/contextlogger/providers/logrus"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var output *bytes.Buffer
var testProvider providers.LogProvider

func setup(t *testing.T, config Config) {
	RegisterTestingT(t)

	output = new(bytes.Buffer)
	outputProvider, err := cl_logrus.LogProvider(nil, cl_logrus.Config{
		output,
		"debug",
		&logrus.TextFormatter{
			DisableColors:   true,
			TimestampFormat: "sometime", // Omit timestamp to make output predictable
		},
	})
	Expect(err).To(BeNil())
	testProvider = LogProvider(outputProvider, config)
}

func TestReportedAt(t *testing.T) {
	setup(t, Config{})

	testProvider.Info(context.Background(), false, "foo")
	Expect(output.String()).To(MatchRegexp(`time=sometime level=info msg=foo reportedAt=".*/reported_at/provider_test.go:\d+`))
}

func TestReportedAtFiltering(t *testing.T) {
	setup(t, RecommendedConfig)

	testProvider.Info(context.Background(), false, "foo")
	Expect(output.String()).To(MatchRegexp(`time=sometime level=info msg=foo reportedAt=".*go/.*src/testing/testing.go:\d+`))
}
<commit_msg>Update providers/reported_at/provider_test.go<commit_after>// © 2016-2017 Helix OpCo LLC. All rights reserved.
// Initial Author: Chris Williams

package reported_at

import (
	"bytes"
	"context"
	"testing"

	"github.com/myhelix/contextlogger/providers"
	cl_logrus "github.com/myhelix/contextlogger/providers/logrus"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var output *bytes.Buffer
var testProvider providers.LogProvider

func setup(t *testing.T, config Config) {
	RegisterTestingT(t)

	output = new(bytes.Buffer)
	outputProvider, err := cl_logrus.LogProvider(nil, cl_logrus.Config{
		output,
		"debug",
		&logrus.TextFormatter{
			DisableColors:   true,
			TimestampFormat: "sometime", // Omit timestamp to make output predictable
		},
	})
	Expect(err).To(BeNil())
	testProvider = LogProvider(outputProvider, config)
}

func TestReportedAt(t *testing.T) {
	setup(t, Config{})

	testProvider.Info(context.Background(), false, "foo")
	Expect(output.String()).To(MatchRegexp(`time=sometime level=info msg=foo reportedAt=".*/reported_at/provider_test.go:\d+`))
}

func TestReportedAtFiltering(t *testing.T) {
	setup(t, RecommendedConfig)

	testProvider.Info(context.Background(), false, "foo")
	Expect(output.String()).To(MatchRegexp(`time=sometime level=info msg=foo reportedAt=".*src/testing/testing.go:\d+`))
}
<|endoftext|>