<commit_before>package dap

import (
	"fmt"
	"testing"
	"time"

	"airdispat.ch/message"
	"airdispat.ch/server"
	adTest "airdispat.ch/testing"
	adWire "airdispat.ch/wire"
)

func testingSetup(t *testing.T) (quit chan bool, results chan *TestingResult, scene adTest.Scenario, client *Client) {
	scene, err := adTest.CreateScenario()
	if err != nil {
		t.Error(err.Error())
		return
	}

	results = make(chan *TestingResult, 1)
	delegate := &TestingDelegate{
		Results: results,
	}

	started := make(chan bool)
	quit = make(chan bool)

	theServer := server.Server{
		LocationName: "localhost:9091",
		Key:          scene.Server,
		Delegate:     &server.BasicServer{},
		Router:       scene.Router,
		Handlers: []server.Handler{
			&Handler{
				Key:      scene.Server,
				Delegate: delegate,
			},
		},
		Start: started,
		Quit:  quit,
	}

	go func() {
		theServer.StartServer("9091")
	}()

	delegate.Scenario = scene

	client = &Client{
		Key:    scene.Sender,
		Server: scene.Server.Address,
	}

	// Wait for Started, begin Tests
	<-started

	return
}

// Test Delegate Registration Method
func TestRegister(t *testing.T) {
	quit, results, _, client := testingSetup(t)
	defer func() { quit <- true }()

	err := client.Register(map[string][]byte{
		"full_name": []byte("John Smith"),
	})
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

// Test Delegate Unregister Method
func TestUnregister(t *testing.T) {
	quit, results, _, client := testingSetup(t)
	defer func() { quit <- true }()

	err := client.Unregister(map[string][]byte{
		"reason": []byte("Too expensive!"),
	})
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

// Test GetMessages Method
func TestGetMessages(t *testing.T) {
	quit, results, scene, client := testingSetup(t)
	defer func() { quit <- true }()

	response, err := client.DownloadMessages(1, true)
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
		return
	}

	if len(response) != 1 {
		t.Error("Incorrect number of messages returned.")
		return
	}
	res := response[0]

	readStatus, ok := res.Context["read"]
	if !ok {
		t.Error("Cannot find read status of message.")
		return
	}
	if string(readStatus) != "yes" {
		t.Error("Incorrect read status of message.")
		return
	}

	receivedSign, err := res.Message.Decrypt(scene.Sender)
	if err != nil {
		t.Error("Decrypting Message: " + err.Error())
		return
	}

	if !receivedSign.Verify() {
		t.Error("Verifying Signature: " + err.Error())
		return
	}

	data, typ, h, err := receivedSign.ReconstructMessageWithTimestamp()
	if err != nil {
		t.Error("Reconstructing Message: " + err.Error())
		return
	}

	if typ != adWire.MailCode {
		t.Error("Type of Message is unexpected, " + typ)
		return
	}

	mail, err := message.CreateMailFromBytes(data, h)
	if err != nil {
		t.Error("Creating Mail Message: " + err.Error())
		return
	}

	if !mail.Components.HasComponent("test_verification") {
		t.Error("Message doesn't have right components.")
		return
	}

	if mail.Components.GetStringComponent("test_verification") != "Pass" {
		t.Error("Message test_verification doesn't match.")
		return
	}
}

// Test Delegate Publish Method
func TestPublish(t *testing.T) {
	quit, results, scene, client := testingSetup(t)
	defer func() { quit <- true }()

	mail := message.CreateMail(scene.Receiver.Address, scene.Sender.Address, time.Now())
	mail.Components.AddComponent(
		message.Component{
			Name: "test_verification",
			Data: []byte("Pass"),
		},
	)

	signed, err := message.SignMessage(mail, scene.Receiver)
	if err != nil {
		t.Error(err.Error())
		return
	}

	encrypted, err := signed.EncryptWithKey(scene.Sender.Address)
	if err != nil {
		t.Error(err.Error())
		return
	}

	_, err = client.PublishMessage(encrypted, []string{"not_real"}, "test_message", true)
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

// Test Delegate Update Message
func TestUpdate(t *testing.T) {
	quit, results, scene, client := testingSetup(t)
	defer func() { quit <- true }()

	mail := message.CreateMail(scene.Receiver.Address, scene.Sender.Address, time.Now())
	mail.Components.AddComponent(
		message.Component{
			Name: "test_verification",
			Data: []byte("Pass"),
		},
	)

	signed, err := message.SignMessage(mail, scene.Receiver)
	if err != nil {
		t.Error(err.Error())
		return
	}

	encrypted, err := signed.EncryptWithKey(scene.Sender.Address)
	if err != nil {
		t.Error(err.Error())
		return
	}

	err = client.UpdateMessage(encrypted, "test_message")
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

func TestGetData(t *testing.T) {
	quit, results, _, client := testingSetup(t)
	defer func() { quit <- true }()

	data, err := client.GetData("test_data")
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}

	if string(data) != "Pass" {
		t.Error("Returned data is incorrect.")
	}
}

func TestSetData(t *testing.T) {
	quit, results, _, client := testingSetup(t)
	defer func() { quit <- true }()

	err := client.SetData("test_data", []byte("Pass"))
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

type TestingResult struct {
	Location string
	Err      string
}

func (t *TestingResult) IsError() bool {
	return t.Err != ""
}

func (t *TestingResult) Error() string {
	return fmt.Sprintf("%s: %s", t.Location, t.Err)
}

type TestingDelegate struct {
	Scenario adTest.Scenario
	Results  chan *TestingResult
}

// Mock Registration Method
func (t *TestingDelegate) Register(addr string, keys map[string][]byte) error {
	if addr != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Register", "Checking address is correct."}
		return nil
	}

	name, ok := keys["full_name"]
	if !ok || string(name) != "John Smith" {
		t.Results <- &TestingResult{"Register", "Checking dictionary is correct."}
		return nil
	}

	t.Results <- nil
	return nil
}

// Mock Unregistration Method
func (t *TestingDelegate) Unregister(addr string, keys map[string][]byte) error {
	if addr != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Unregister", "Checking address is correct."}
		return nil
	}

	name, ok := keys["reason"]
	if !ok || string(name) != "Too expensive!" {
		t.Results <- &TestingResult{"Unregister", "Checking dictionary is correct."}
		return nil
	}

	t.Results <- nil
	return nil
}

// Mock GetMessages
func (t *TestingDelegate) GetMessages(since uint64, owner string, context bool) ([]*ResponseMessage, error) {
	if owner != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"GetMessages", "Checking address is correct."}
		return nil, nil
	}

	if since != 1 {
		t.Results <- &TestingResult{"GetMessages", "Checking that since value is correct."}
		return nil, nil
	}

	if !context {
		t.Results <- &TestingResult{"GetMessages", "Checking that context value is correct."}
		return nil, nil
	}

	mail := message.CreateMail(t.Scenario.Receiver.Address, t.Scenario.Sender.Address, time.Now())
	mail.Components.AddComponent(
		message.Component{
			Name: "test_verification",
			Data: []byte("Pass"),
		},
	)

	signed, err := message.SignMessage(mail, t.Scenario.Receiver)
	if err != nil {
		t.Results <- &TestingResult{"GetMessages, Signing Message", err.Error()}
		return nil, nil
	}

	encrypted, err := signed.EncryptWithKey(t.Scenario.Sender.Address)
	if err != nil {
		t.Results <- &TestingResult{"GetMessages, Encrypting Message", err.Error()}
		return nil, nil
	}

	resMsg := CreateResponseMessage(encrypted, t.Scenario.Server.Address, t.Scenario.Sender.Address)
	resMsg.Context["read"] = []byte("yes")

	t.Results <- nil
	return []*ResponseMessage{resMsg}, nil
}

// Mock PublishMessge
func (t *TestingDelegate) PublishMessage(name string, to []string, author string, msg *message.EncryptedMessage, alerted bool) error {
	// Verifiy Arguments
	if author != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Publish Message", "Checking address is correct."}
		return nil
	}

	if name != "test_message" {
		t.Results <- &TestingResult{"Publish Message", "Checking that name is correct."}
		return nil
	}

	if len(to) != 1 || to[0] != "not_real" {
		t.Results <- &TestingResult{"Publish Message", "Checking that to is correct."}
		return nil
	}

	if !alerted {
		t.Results <- &TestingResult{"Publish Message", "Checking that alerted is correct."}
		return nil
	}

	// Verify Message
	receivedSign, err := msg.Decrypt(t.Scenario.Sender)
	if err != nil {
		t.Results <- &TestingResult{"Publish Message, Decryption", err.Error()}
		return nil
	}

	if !receivedSign.Verify() {
		t.Results <- &TestingResult{"Publish Message, Verification", err.Error()}
		return nil
	}

	data, typ, h, err := receivedSign.ReconstructMessageWithTimestamp()
	if err != nil {
		t.Results <- &TestingResult{"Publish Message, Reconstruction", err.Error()}
		return nil
	}

	if typ != adWire.MailCode {
		t.Results <- &TestingResult{"Publish Message", "Type of Message is unexpected, " + typ}
		return nil
	}

	mail, err := message.CreateMailFromBytes(data, h)
	if err != nil {
		t.Results <- &TestingResult{"Publish Message, Creation", err.Error()}
		return nil
	}

	if !mail.Components.HasComponent("test_verification") {
		t.Results <- &TestingResult{"Publish Message", "Message doesn't have right components."}
		return nil
	}

	if mail.Components.GetStringComponent("test_verification") != "Pass" {
		t.Results <- &TestingResult{"Publish Message", "Message test_verification doesn't match."}
		return nil
	}

	t.Results <- nil
	return nil
}

// Mock UpdateMessage
func (t *TestingDelegate) UpdateMessage(name string, author string, msg *message.EncryptedMessage) error {
	// Verifiy Arguments
	if author != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Update Message", "Checking address is correct."}
		return nil
	}

	if name != "test_message" {
		t.Results <- &TestingResult{"Update Message", "Checking that name is correct."}
		return nil
	}

	// Verify Message
	receivedSign, err := msg.Decrypt(t.Scenario.Sender)
	if err != nil {
		t.Results <- &TestingResult{"Update Message, Decryption", err.Error()}
		return nil
	}

	if !receivedSign.Verify() {
		t.Results <- &TestingResult{"Update Message, Verification", err.Error()}
		return nil
	}

	data, typ, h, err := receivedSign.ReconstructMessageWithTimestamp()
	if err != nil {
		t.Results <- &TestingResult{"Update Message, Reconstruction", err.Error()}
		return nil
	}

	if typ != adWire.MailCode {
		t.Results <- &TestingResult{"Update Message", "Type of Message is unexpected, " + typ}
		return nil
	}

	mail, err := message.CreateMailFromBytes(data, h)
	if err != nil {
		t.Results <- &TestingResult{"Update Message, Creation", err.Error()}
		return nil
	}

	if !mail.Components.HasComponent("test_verification") {
		t.Results <- &TestingResult{"Update Message", "Message doesn't have right components."}
		return nil
	}

	if mail.Components.GetStringComponent("test_verification") != "Pass" {
		t.Results <- &TestingResult{"Update Message", "Message test_verification doesn't match."}
		return nil
	}

	t.Results <- nil
	return nil
}

// Mock GetData
func (t *TestingDelegate) GetData(owner string, key string) ([]byte, error) {
	// Verifiy Arguments
	if owner != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Get Data", "Checking address is correct."}
		return nil, nil
	}

	if key != "test_data" {
		t.Results <- &TestingResult{"Get Data", "Checking that name is correct."}
		return nil, nil
	}

	t.Results <- nil
	return []byte("Pass"), nil
}

// Mock SetData
func (t *TestingDelegate) SetData(owner string, key string, data []byte) error {
	// Verifiy Arguments
	if owner != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Get Data", "Checking address is correct."}
		return nil
	}

	if key != "test_data" {
		t.Results <- &TestingResult{"Get Data", "Checking that name is correct."}
		return nil
	}

	if string(data) != "Pass" {
		t.Results <- &TestingResult{"Get Data", "Check that data is correct."}
		return nil
	}

	t.Results <- nil
	return nil
}
<commit_msg>Updated DAP Tests<commit_after>package dap

import (
	"fmt"
	"testing"
	"time"

	"airdispat.ch/identity"
	"airdispat.ch/message"
	"airdispat.ch/server"
	adTest "airdispat.ch/testing"
	adWire "airdispat.ch/wire"
)

func testingSetup(t *testing.T) (quit chan bool, results chan *TestingResult, scene adTest.Scenario, client *Client) {
	scene, err := adTest.CreateScenario()
	if err != nil {
		t.Error(err.Error())
		return
	}

	results = make(chan *TestingResult, 1)
	delegate := &TestingDelegate{
		Results: results,
	}

	started := make(chan bool)
	quit = make(chan bool)

	theServer := server.Server{
		LocationName: "localhost:9091",
		Key:          scene.Server,
		Delegate:     &server.BasicServer{},
		Router:       scene.Router,
		Handlers: []server.Handler{
			&Handler{
				Key:      scene.Server,
				Delegate: delegate,
			},
		},
		Start: started,
		Quit:  quit,
	}

	go func() {
		theServer.StartServer("9091")
	}()

	delegate.Scenario = scene

	client = &Client{
		Key:    scene.Sender,
		Server: scene.Server.Address,
	}

	// Wait for Started, begin Tests
	<-started

	return
}

// Test Delegate Registration Method
func TestRegister(t *testing.T) {
	quit, results, _, client := testingSetup(t)
	defer func() { quit <- true }()

	err := client.Register(map[string][]byte{
		"full_name": []byte("John Smith"),
	})
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

// Test Delegate Unregister Method
func TestUnregister(t *testing.T) {
	quit, results, _, client := testingSetup(t)
	defer func() { quit <- true }()

	err := client.Unregister(map[string][]byte{
		"reason": []byte("Too expensive!"),
	})
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

// Test GetMessages Method
func TestGetMessages(t *testing.T) {
	quit, results, scene, client := testingSetup(t)
	defer func() { quit <- true }()

	response, err := client.DownloadMessages(1, true)
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
		return
	}

	if len(response) != 1 {
		t.Error("Incorrect number of messages returned.")
		return
	}
	res := response[0]

	readStatus, ok := res.Context["read"]
	if !ok {
		t.Error("Cannot find read status of message.")
		return
	}
	if string(readStatus) != "yes" {
		t.Error("Incorrect read status of message.")
		return
	}

	receivedSign, err := res.Message.Decrypt(scene.Receiver)
	if err != nil {
		t.Error("Decrypting Message: " + err.Error())
		return
	}

	if !receivedSign.Verify() {
		t.Error("Verifying Signature: " + err.Error())
		return
	}

	data, typ, h, err := receivedSign.ReconstructMessageWithTimestamp()
	if err != nil {
		t.Error("Reconstructing Message: " + err.Error())
		return
	}

	if typ != adWire.MailCode {
		t.Error("Type of Message is unexpected, " + typ)
		return
	}

	mail, err := message.CreateMailFromBytes(data, h)
	if err != nil {
		t.Error("Creating Mail Message: " + err.Error())
		return
	}

	if !mail.Components.HasComponent("test_verification") {
		t.Error("Message doesn't have right components.")
		return
	}

	if mail.Components.GetStringComponent("test_verification") != "Pass" {
		t.Error("Message test_verification doesn't match.")
		return
	}
}

// Test Delegate Publish Method
func TestPublish(t *testing.T) {
	quit, results, scene, client := testingSetup(t)
	defer func() { quit <- true }()

	mail := message.CreateMail(scene.Sender.Address, time.Now(), "test_message", scene.Receiver.Address)
	mail.Components.AddComponent(
		message.Component{
			Name: "test_verification",
			Data: []byte("Pass"),
		},
	)

	_, err := client.PublishMessage(mail, []*identity.Address{
		scene.Receiver.Address,
	}, "test_message", true)
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

// Test Delegate Update Message
func TestUpdate(t *testing.T) {
	quit, results, scene, client := testingSetup(t)
	defer func() { quit <- true }()

	mail := message.CreateMail(scene.Sender.Address, time.Now(), "test_message", scene.Receiver.Address)
	mail.Components.AddComponent(
		message.Component{
			Name: "test_verification",
			Data: []byte("Pass"),
		},
	)

	err := client.UpdateMessage(mail, []*identity.Address{scene.Receiver.Address}, "test_message")
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

func TestGetData(t *testing.T) {
	quit, results, _, client := testingSetup(t)
	defer func() { quit <- true }()

	data, err := client.GetData("test_data")
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}

	if string(data) != "Pass" {
		t.Error("Returned data is incorrect.")
	}
}

func TestSetData(t *testing.T) {
	quit, results, _, client := testingSetup(t)
	defer func() { quit <- true }()

	err := client.SetData("test_data", []byte("Pass"))
	if err != nil {
		t.Error(err.Error())
		return
	}

	result := <-results
	if result != nil {
		t.Error(result.Error())
	}
}

type TestingResult struct {
	Location string
	Err      string
}

func (t *TestingResult) IsError() bool {
	return t.Err != ""
}

func (t *TestingResult) Error() string {
	return fmt.Sprintf("%s: %s", t.Location, t.Err)
}

type TestingDelegate struct {
	Scenario adTest.Scenario
	Results  chan *TestingResult
}

// Mock Registration Method
func (t *TestingDelegate) Register(addr string, keys map[string][]byte) error {
	if addr != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Register", "Checking address is correct."}
		return nil
	}

	name, ok := keys["full_name"]
	if !ok || string(name) != "John Smith" {
		t.Results <- &TestingResult{"Register", "Checking dictionary is correct."}
		return nil
	}

	t.Results <- nil
	return nil
}

// Mock Unregistration Method
func (t *TestingDelegate) Unregister(addr string, keys map[string][]byte) error {
	if addr != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Unregister", "Checking address is correct."}
		return nil
	}

	name, ok := keys["reason"]
	if !ok || string(name) != "Too expensive!" {
		t.Results <- &TestingResult{"Unregister", "Checking dictionary is correct."}
		return nil
	}

	t.Results <- nil
	return nil
}

// Mock GetMessages
func (t *TestingDelegate) GetMessages(since uint64, owner string, context bool) ([]*ResponseMessage, error) {
	if owner != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"GetMessages", "Checking address is correct."}
		return nil, nil
	}

	if since != 1 {
		t.Results <- &TestingResult{"GetMessages", "Checking that since value is correct."}
		return nil, nil
	}

	if !context {
		t.Results <- &TestingResult{"GetMessages", "Checking that context value is correct."}
		return nil, nil
	}

	mail := message.CreateMail(t.Scenario.Sender.Address, time.Now(), "test_message", t.Scenario.Receiver.Address)
	mail.Components.AddComponent(
		message.Component{
			Name: "test_verification",
			Data: []byte("Pass"),
		},
	)

	signed, err := message.SignMessage(mail, t.Scenario.Sender)
	if err != nil {
		t.Results <- &TestingResult{"GetMessages, Signing Message", err.Error()}
		return nil, nil
	}

	encrypted, err := signed.EncryptWithKey(t.Scenario.Receiver.Address)
	if err != nil {
		t.Results <- &TestingResult{"GetMessages, Encrypting Message", err.Error()}
		return nil, nil
	}

	resMsg := CreateResponseMessage(encrypted, t.Scenario.Server.Address, t.Scenario.Sender.Address)
	resMsg.Context["read"] = []byte("yes")

	t.Results <- nil
	return []*ResponseMessage{resMsg}, nil
}

// Mock PublishMessge
func (t *TestingDelegate) PublishMessage(name string, to []string, author string, msg *message.EncryptedMessage, alerted bool) error {
	// Verifiy Arguments
	if author != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Publish Message", "Checking address is correct."}
		return nil
	}

	if name != "test_message" {
		t.Results <- &TestingResult{"Publish Message", "Checking that name is correct."}
		return nil
	}

	if len(to) != 1 || to[0] != t.Scenario.Receiver.Address.String() {
		t.Results <- &TestingResult{"Publish Message", "Checking that to is correct."}
		return nil
	}

	if !alerted {
		t.Results <- &TestingResult{"Publish Message", "Checking that alerted is correct."}
		return nil
	}

	// Verify Message
	receivedSign, err := msg.Decrypt(t.Scenario.Receiver)
	if err != nil {
		t.Results <- &TestingResult{"Publish Message, Decryption", err.Error()}
		return nil
	}

	if !receivedSign.Verify() {
		t.Results <- &TestingResult{"Publish Message, Verification", err.Error()}
		return nil
	}

	data, typ, h, err := receivedSign.ReconstructMessageWithTimestamp()
	if err != nil {
		t.Results <- &TestingResult{"Publish Message, Reconstruction", err.Error()}
		return nil
	}

	if typ != adWire.MailCode {
		t.Results <- &TestingResult{"Publish Message", "Type of Message is unexpected, " + typ}
		return nil
	}

	mail, err := message.CreateMailFromBytes(data, h)
	if err != nil {
		t.Results <- &TestingResult{"Publish Message, Creation", err.Error()}
		return nil
	}

	if !mail.Components.HasComponent("test_verification") {
		t.Results <- &TestingResult{"Publish Message", "Message doesn't have right components."}
		return nil
	}

	if mail.Components.GetStringComponent("test_verification") != "Pass" {
		t.Results <- &TestingResult{"Publish Message", "Message test_verification doesn't match."}
		return nil
	}

	t.Results <- nil
	return nil
}

// func (t *TestingDelegate) PublishDataMessage(name string, to []string, author string, message *message.EncryptedMessage, length uint64, r ReadVerifier) error {
// 	return nil
// }

// Mock UpdateMessage
func (t *TestingDelegate) UpdateMessage(name string, author string, msg *message.EncryptedMessage) error {
	// Verifiy Arguments
	if author != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Update Message", "Checking address is correct."}
		return nil
	}

	if name != "test_message" {
		t.Results <- &TestingResult{"Update Message", "Checking that name is correct."}
		return nil
	}

	// Verify Message
	receivedSign, err := msg.Decrypt(t.Scenario.Receiver)
	if err != nil {
		t.Results <- &TestingResult{"Update Message, Decryption", err.Error()}
		return nil
	}

	if !receivedSign.Verify() {
		t.Results <- &TestingResult{"Update Message, Verification", err.Error()}
		return nil
	}

	data, typ, h, err := receivedSign.ReconstructMessageWithTimestamp()
	if err != nil {
		t.Results <- &TestingResult{"Update Message, Reconstruction", err.Error()}
		return nil
	}

	if typ != adWire.MailCode {
		t.Results <- &TestingResult{"Update Message", "Type of Message is unexpected, " + typ}
		return nil
	}

	mail, err := message.CreateMailFromBytes(data, h)
	if err != nil {
		t.Results <- &TestingResult{"Update Message, Creation", err.Error()}
		return nil
	}

	if !mail.Components.HasComponent("test_verification") {
		t.Results <- &TestingResult{"Update Message", "Message doesn't have right components."}
		return nil
	}

	if mail.Components.GetStringComponent("test_verification") != "Pass" {
		t.Results <- &TestingResult{"Update Message", "Message test_verification doesn't match."}
		return nil
	}

	t.Results <- nil
	return nil
}

// Mock GetData
func (t *TestingDelegate) GetData(owner string, key string) ([]byte, error) {
	// Verifiy Arguments
	if owner != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Get Data", "Checking address is correct."}
		return nil, nil
	}

	if key != "test_data" {
		t.Results <- &TestingResult{"Get Data", "Checking that name is correct."}
		return nil, nil
	}

	t.Results <- nil
	return []byte("Pass"), nil
}

// Mock SetData
func (t *TestingDelegate) SetData(owner string, key string, data []byte) error {
	// Verifiy Arguments
	if owner != t.Scenario.Sender.Address.String() {
		t.Results <- &TestingResult{"Get Data", "Checking address is correct."}
		return nil
	}

	if key != "test_data" {
		t.Results <- &TestingResult{"Get Data", "Checking that name is correct."}
		return nil
	}

	if string(data) != "Pass" {
		t.Results <- &TestingResult{"Get Data", "Check that data is correct."}
		return nil
	}

	t.Results <- nil
	return nil
}
<|endoftext|>


<commit_before>package lib

import (
	// "errors"
	"fmt"
	"github.com/namsral/flag"
	"os"
	"strings"
)

// ReservedSpace -
const ReservedSpace = 450000000 // 450Mb

// Config -
type Config struct {
	Folders        []string `json:"folders"`
	DryRun         bool     `json:"dryRun"`
	NotifyCalc     int      `json:"notifyCalc"`
	NotifyMove     int      `json:"notifyMove"`
	ReservedAmount int64    `json:"reservedAmount"`
	ReservedUnit   string   `json:"reservedUnit"`
	RsyncFlags     []string `json:"rsyncFlags"`
	Version        string   `json:"version"`
}

// NotifyCalc/NotifyMove possible values
// 0 - no notification
// 1 - simple notification
// 2 - detailed notification

// Settings -
type Settings struct {
	Config

	Conf       string
	Port       string
	Log        string
	APIFolders []string
	// ReservedSpace int64
}

// NewSettings -
func NewSettings(version string) (*Settings, error) {
	var config, port, log, folders, rsyncFlags, apiFolders string
	var dryRun bool
	var notifyCalc, notifyMove int

	// location := SearchFile(name, locations)
	// if location != "" {
	// 	flag.Set("config", filepath.Join(location, name))
	// }

	// /boot/config/plugins/unbalance/
	flag.StringVar(&config, "config", "", "config location")
	flag.StringVar(&port, "port", "6237", "port to run the server")
	flag.StringVar(&log, "log", "/boot/logs/unbalance.log", "pathname where log file will be written to")
	flag.StringVar(&folders, "folders", "", "folders that will be scanned for media")
	flag.BoolVar(&dryRun, "dryRun", true, "perform a dry-run rather than actual work")
	flag.IntVar(&notifyCalc, "notifyCalc", 0, "notify via email after calculation operation has completed (unraid notifications must be set up first): 0 - No notifications; 1 - Simple notifications; 2 - Detailed notifications")
	flag.IntVar(&notifyMove, "notifyMove", 0, "notify via email after move operation has completed (unraid notifications must be set up first): 0 - No notifications; 1 - Simple notifications; 2 - Detailed notifications")
	flag.StringVar(&rsyncFlags, "rsyncFlags", "", "custom rsync flags")
	flag.StringVar(&apiFolders, "apiFolders", "/var/local/emhttp", "folders to look for api endpoints")

	flag.Set("config", "/boot/config/plugins/unbalance/unbalance.conf")
	flag.Parse()

	// fmt.Printf("folders: %s\nconfig: %s\n", folders, config)

	s := &Settings{}

	if folders == "" {
		s.Folders = make([]string, 0)
	} else {
		s.Folders = strings.Split(folders, "|")
	}

	if rsyncFlags == "" {
		s.RsyncFlags = []string{"-avRX", "--partial"}
	} else {
		s.RsyncFlags = strings.Split(rsyncFlags, "|")
	}

	s.DryRun = dryRun
	s.NotifyCalc = notifyCalc
	s.NotifyMove = notifyMove
	s.ReservedAmount = ReservedSpace / 1000 / 1000
	s.ReservedUnit = "Mb"
	s.Version = version

	s.Conf = config
	s.Port = port
	s.Log = log
	s.APIFolders = strings.Split(apiFolders, "|")

	return s, nil
}

// AddFolder -
func (s *Settings) AddFolder(folder string) {
	s.Folders = append(s.Folders, folder)
}

// DeleteFolder -
func (s *Settings) DeleteFolder(folder string) {

	index := -1
	for p, v := range s.Folders {
		if v == folder {
			index = p
			break
		}
	}

	if index == -1 {
		return
	}

	s.Folders = append(s.Folders[:index], s.Folders[index+1:]...)
}

// ToggleDryRun -
func (s *Settings) ToggleDryRun() {
	s.DryRun = !s.DryRun
}

// Save -
func (s *Settings) Save() (err error) {
	tmpFile := s.Conf + ".tmp"

	folders := strings.Join(s.Folders, "|")
	if err = WriteLine(tmpFile, fmt.Sprintf("folders=%s", folders)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("dryRun=%t", s.DryRun)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("notifyCalc=%d", s.NotifyCalc)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("notifyMove=%d", s.NotifyCalc)); err != nil {
		return err
	}

	rsyncFlags := strings.Join(s.RsyncFlags, "|")
	if err = WriteLine(tmpFile, fmt.Sprintf("rsyncFlags=%s", rsyncFlags)); err != nil {
		return err
	}

	os.Rename(tmpFile, s.Conf)

	return
}
<commit_msg>Check for config file presence<commit_after>package lib

import (
	"fmt"
	"github.com/namsral/flag"
	"os"
	"strings"
)

// ReservedSpace -
const ReservedSpace = 450000000 // 450Mb

// Config -
type Config struct {
	Folders        []string `json:"folders"`
	DryRun         bool     `json:"dryRun"`
	NotifyCalc     int      `json:"notifyCalc"`
	NotifyMove     int      `json:"notifyMove"`
	ReservedAmount int64    `json:"reservedAmount"`
	ReservedUnit   string   `json:"reservedUnit"`
	RsyncFlags     []string `json:"rsyncFlags"`
	Version        string   `json:"version"`
}

// NotifyCalc/NotifyMove possible values
// 0 - no notification
// 1 - simple notification
// 2 - detailed notification

// Settings -
type Settings struct {
	Config

	Conf       string
	Port       string
	Log        string
	APIFolders []string
	// ReservedSpace int64
}

// NewSettings -
func NewSettings(version string) (*Settings, error) {
	var config, port, log, folders, rsyncFlags, apiFolders string
	var dryRun bool
	var notifyCalc, notifyMove int

	found, err := Exists("/boot/config/plugins/unbalance/unbalance.conf")
	if !found || err != nil {
		msg := "Unable to find /boot/config/plugins/unbalance/unbalance.conf. Either create this file or re-install the plugin."
		if err != nil {
			msg += fmt.Sprintf(" (%s)", err)
		}
		fmt.Printf("%s\n", msg)
		os.Exit(3)
	}

	// /boot/config/plugins/unbalance/
	flag.StringVar(&config, "config", "", "config location")
	flag.StringVar(&port, "port", "6237", "port to run the server")
	flag.StringVar(&log, "log", "/boot/logs/unbalance.log", "pathname where log file will be written to")
	flag.StringVar(&folders, "folders", "", "folders that will be scanned for media")
	flag.BoolVar(&dryRun, "dryRun", true, "perform a dry-run rather than actual work")
	flag.IntVar(&notifyCalc, "notifyCalc", 0, "notify via email after calculation operation has completed (unraid notifications must be set up first): 0 - No notifications; 1 - Simple notifications; 2 - Detailed notifications")
	flag.IntVar(&notifyMove, "notifyMove", 0, "notify via email after move operation has completed (unraid notifications must be set up first): 0 - No notifications; 1 - Simple notifications; 2 - Detailed notifications")
	flag.StringVar(&rsyncFlags, "rsyncFlags", "", "custom rsync flags")
	flag.StringVar(&apiFolders, "apiFolders", "/var/local/emhttp", "folders to look for api endpoints")

	flag.Set("config", "/boot/config/plugins/unbalance/unbalance.conf")
	flag.Parse()

	// fmt.Printf("folders: %s\nconfig: %s\n", folders, config)

	s := &Settings{}

	if folders == "" {
		s.Folders = make([]string, 0)
	} else {
		s.Folders = strings.Split(folders, "|")
	}

	if rsyncFlags == "" {
		s.RsyncFlags = []string{"-avRX", "--partial"}
	} else {
		s.RsyncFlags = strings.Split(rsyncFlags, "|")
	}

	s.DryRun = dryRun
	s.NotifyCalc = notifyCalc
	s.NotifyMove = notifyMove
	s.ReservedAmount = ReservedSpace / 1000 / 1000
	s.ReservedUnit = "Mb"
	s.Version = version

	s.Conf = config
	s.Port = port
	s.Log = log
	s.APIFolders = strings.Split(apiFolders, "|")

	return s, nil
}

// AddFolder -
func (s *Settings) AddFolder(folder string) {
	s.Folders = append(s.Folders, folder)
}

// DeleteFolder -
func (s *Settings) DeleteFolder(folder string) {

	index := -1
	for p, v := range s.Folders {
		if v == folder {
			index = p
			break
		}
	}

	if index == -1 {
		return
	}

	s.Folders = append(s.Folders[:index], s.Folders[index+1:]...)
}

// ToggleDryRun -
func (s *Settings) ToggleDryRun() {
	s.DryRun = !s.DryRun
}

// Save -
func (s *Settings) Save() (err error) {
	tmpFile := s.Conf + ".tmp"

	folders := strings.Join(s.Folders, "|")
	if err = WriteLine(tmpFile, fmt.Sprintf("folders=%s", folders)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("dryRun=%t", s.DryRun)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("notifyCalc=%d", s.NotifyCalc)); err != nil {
		return err
	}

	if err = WriteLine(tmpFile, fmt.Sprintf("notifyMove=%d", s.NotifyCalc)); err != nil {
		return err
	}

	rsyncFlags := strings.Join(s.RsyncFlags, "|")
	if err = WriteLine(tmpFile, fmt.Sprintf("rsyncFlags=%s", rsyncFlags)); err != nil {
		return err
	}

	os.Rename(tmpFile, s.Conf)

	return
}
<|endoftext|>


<commit_before>package server

import (
	"log"
	"testing"
)

// keeps track of a messages sent to players
var sentMessages map[*Player][]interface{}

// create a new test world
func NewTestWorld() *World {
	return &World{
		knownPlayersByName: make(map[string]*Player),
	}
}

// create a new test player that can track sent messages through 'sentmessages'
func NewTestPlayer(name string) *Player {
	p := Player{
		Name: name,
	}
	p.Send = func(message interface{}) {
		log.Printf("sending fake! %s p is %s", message, p.Name)
		sentMessages[&p] = append(sentMessages[&p], message)
	}
	return &p
}

// tell receiver about it
func TestHandleTell_success(t *testing.T) {
	// arrange
	w := NewTestWorld()
	sentMessages = make(map[*Player][]interface{})
	senderPlayer := NewTestPlayer("sender")
	receiverPlayer := NewTestPlayer("receiver")
	w.knownPlayersByName[receiverPlayer.Name] = receiverPlayer
	w.knownPlayersByName[senderPlayer.Name] = senderPlayer

	msg := IncomingMessage{
		Player: senderPlayer,
		Body:   make(map[string]string),
	}
	msg.Body["to"] = "receiver"
	msg.Body["value"] = "hi"

	// act
	w.handleTell(&msg)

	// assert
	if len(sentMessages) != 2 {
		t.Error("Unexpected messages found: %d", len(sentMessages))
	}

	// assert tell to receiver
	if len(sentMessages[receiverPlayer]) != 1 {
		t.Errorf("expected receiver to get a message %s", sentMessages)
	}
	recdMessage := sentMessages[receiverPlayer][0].(TellNotification)
	if recdMessage.From != senderPlayer.Name {
		t.Errorf("Didn't get expected senderPlayer.Name: %s", recdMessage.From)
	}
	if recdMessage.MessageType != "tell" {
		t.Errorf("MsgType wasn't tell: %s", recdMessage.MessageType)
	}
	if recdMessage.Value != "hi" {
		t.Errorf("value wasn't hi: %s", recdMessage.Value)
	}

	// assert tell-response to sender
	if len(sentMessages[senderPlayer]) != 1 {
		t.Errorf("expected sender to get a response %s", sentMessages)
	}
	senderResponse := sentMessages[senderPlayer][0].(Response)
	if senderResponse.MessageType != "tell" {
		t.Errorf("expected sender response tell: %s", senderResponse.MessageType)
	}
	if senderResponse.ResultCode != "OK" {
		t.Errorf("expected sender response ok: %s", senderResponse.ResultCode)
	}
	if !senderResponse.Successful {
		t.Error("expected sender response to be successful")
	}
}

func TestHandleTell_receiverNotFound(t *testing.T) {
	// arrange
	w := NewTestWorld()
	sentMessages = make(map[*Player][]interface{})
	senderPlayer := NewTestPlayer("sender")
	// note: receiver doesn't exist
	w.knownPlayersByName[senderPlayer.Name] = senderPlayer

	msg := IncomingMessage{
		Player: senderPlayer,
		Body:   make(map[string]string),
	}
	msg.Body["to"] = "receiver"
	msg.Body["value"] = "hi"

	// act
	w.handleTell(&msg)

	// assert tell-response to sender
	if len(sentMessages[senderPlayer]) != 1 {
		t.Errorf("expected sender to get a response %s", sentMessages)
	}

	// no other messages
	if len(sentMessages) != 1 {
		t.Errorf("Unexpected messages found: %d", len(sentMessages))
	}

	senderResponse := sentMessages[senderPlayer][0].(Response)
	if senderResponse.MessageType != "tell" {
		t.Errorf("sender response message type: %s", senderResponse.MessageType)
	}
	if senderResponse.ResultCode != "TO_PLAYER_NOT_FOUND" {
		t.Errorf("sender response: %s", senderResponse.ResultCode)
	}
	if senderResponse.Successful {
		t.Error("expected sender response to be a failure")
	}
}
<commit_msg>error -> errorf<commit_after>package server

import (
	"log"
	"testing"
)

// keeps track of a messages sent to players
var sentMessages map[*Player][]interface{}

// create a new test world
func NewTestWorld() *World {
	return &World{
		knownPlayersByName: make(map[string]*Player),
	}
}

// create a new test player that can track sent messages through 'sentmessages'
func NewTestPlayer(name string) *Player {
	p := Player{
		Name: name,
	}
	p.Send = func(message interface{}) {
		log.Printf("sending fake! %s p is %s", message, p.Name)
		sentMessages[&p] = append(sentMessages[&p], message)
	}
	return &p
}

// tell receiver about it
func TestHandleTell_success(t *testing.T) {
	// arrange
	w := NewTestWorld()
	sentMessages = make(map[*Player][]interface{})
	senderPlayer := NewTestPlayer("sender")
	receiverPlayer := NewTestPlayer("receiver")
	w.knownPlayersByName[receiverPlayer.Name] = receiverPlayer
	w.knownPlayersByName[senderPlayer.Name] = senderPlayer

	msg := IncomingMessage{
		Player: senderPlayer,
		Body:   make(map[string]string),
	}
	msg.Body["to"] = "receiver"
	msg.Body["value"] = "hi"

	// act
	w.handleTell(&msg)

	// assert
	if len(sentMessages) != 2 {
		t.Errorf("Unexpected messages found: %d", len(sentMessages))
	}

	// assert tell to receiver
	if len(sentMessages[receiverPlayer]) != 1 {
		t.Errorf("expected receiver to get a message %s", sentMessages)
	}
	recdMessage := sentMessages[receiverPlayer][0].(TellNotification)
	if recdMessage.From != senderPlayer.Name {
		t.Errorf("Didn't get expected senderPlayer.Name: %s", recdMessage.From)
	}
	if recdMessage.MessageType != "tell" {
		t.Errorf("MsgType wasn't tell: %s", recdMessage.MessageType)
	}
	if recdMessage.Value != "hi" {
		t.Errorf("value wasn't hi: %s", recdMessage.Value)
	}

	// assert tell-response to sender
	if len(sentMessages[senderPlayer]) != 1 {
		t.Errorf("expected sender to get a response %s", sentMessages)
	}
	senderResponse := sentMessages[senderPlayer][0].(Response)
	if senderResponse.MessageType != "tell" {
		t.Errorf("expected sender response tell: %s", senderResponse.MessageType)
	}
	if senderResponse.ResultCode != "OK" {
		t.Errorf("expected sender response ok: %s", senderResponse.ResultCode)
	}
	if !senderResponse.Successful {
		t.Error("expected sender response to be successful")
	}
}

func TestHandleTell_receiverNotFound(t *testing.T) {
	// arrange
	w := NewTestWorld()
	sentMessages = make(map[*Player][]interface{})
	senderPlayer := NewTestPlayer("sender")
	// note: receiver doesn't exist
	w.knownPlayersByName[senderPlayer.Name] = senderPlayer

	msg := IncomingMessage{
		Player: senderPlayer,
		Body:   make(map[string]string),
	}
	msg.Body["to"] = "receiver"
	msg.Body["value"] = "hi"

	// act
	w.handleTell(&msg)

	// assert tell-response to sender
	if len(sentMessages[senderPlayer]) != 1 {
		t.Errorf("expected sender to get a response %s", sentMessages)
	}

	// no other messages
	if len(sentMessages) != 1 {
		t.Errorf("Unexpected messages found: %d", len(sentMessages))
	}

	senderResponse := sentMessages[senderPlayer][0].(Response)
	if senderResponse.MessageType != "tell" {
		t.Errorf("sender response message type: %s", senderResponse.MessageType)
	}
	if senderResponse.ResultCode != "TO_PLAYER_NOT_FOUND" {
		t.Errorf("sender response: %s", senderResponse.ResultCode)
	}
	if senderResponse.Successful {
		t.Error("expected sender response to be a failure")
	}
}
<|endoftext|>


<commit_before>package model

import (
	"time"

	"github.com/jinzhu/gorm"
	"github.com/oinume/lekcije/server/errors"
)

const DefaultMPlanID = uint8(1)

type MPlan struct {
	ID                   uint8 `gorm:"primary_key"`
	Name                 string
	InternalName         string
	Price                int16
	NotificationInterval uint8
	ShowAd               bool
	CreatedAt            time.Time
	UpdatedAt            time.Time
}

func (*MPlan) TableName() string {
	return "m_plan"
}

type MPlanService struct {
	db *gorm.DB
}

func NewMPlanService(db *gorm.DB) *MPlanService {
	return &MPlanService{db: db}
}

func (s *MPlanService) TableName() string {
	return (&MPlan{}).TableName()
}

func (s *MPlanService) FindByPK(id uint8) (*MPlan, error) {
	plan := &MPlan{}
	if err := s.db.First(plan, &MPlan{ID: id}).Error; err != nil {
		return nil, errors.NewAnnotatedError(
			errors.CodeNotFound,
			errors.WithError(err),
			errors.WithResource(errors.NewResource("m_plan", "id", id)),
		)
	}
	return plan, nil
}
<commit_msg>Add a field<commit_after>package model

import (
	"time"

	"github.com/jinzhu/gorm"
	"github.com/oinume/lekcije/server/errors"
)

const DefaultMPlanID = uint8(1)

type MPlan struct {
	ID                   uint8 `gorm:"primary_key"`
	Name                 string
	InternalName         string
	StripeTestProductID  string
	Price                int16
	NotificationInterval uint8
	ShowAd               bool
	CreatedAt            time.Time
	UpdatedAt            time.Time
}

func (*MPlan) TableName() string {
	return "m_plan"
}

type MPlanService struct {
	db *gorm.DB
}

func NewMPlanService(db *gorm.DB) *MPlanService {
	return &MPlanService{db: db}
}

func (s *MPlanService) TableName() string {
	return (&MPlan{}).TableName()
}

func (s *MPlanService) FindByPK(id uint8) (*MPlan, error) {
	plan := &MPlan{}
	if err := s.db.First(plan, &MPlan{ID: id}).Error; err != nil {
		return nil, errors.NewAnnotatedError(
			errors.CodeNotFound,
			errors.WithError(err),
			errors.WithResource(errors.NewResource("m_plan", "id", id)),
		)
	}
	return plan, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/smtp"
	"net/url"
	"os"
	"os/user"
)

const (
	name   = "trafficjam"
	apiURL = "https://maps.googleapis.com/maps/api/distancematrix/json"
)

type config struct {
	Origins      string `json:"origins"`
	Destinations string `json:"destinations"`
	APIKey       string `json:"api_key"`
	Mode         string `json:"mode"`
	Avoid        string `json:"avoid"`
	TrafficModel string `json:"traffic_model"`
	MaxDuration  int    `json:"max_duration"`
	SMTP         struct {
		Host string `json:"host"`
		Port int    `json:"port"`
		User string `json:"user"`
		Pass string `json:"pass"`
	} `json:"smtp"`
	Recipient string `json:"recipient"`
}

type apiResponse struct {
	Rows []struct {
		Elements []struct {
			DurationInTraffic struct {
				Value int `json:"value"`
			} `json:"duration_in_traffic"`
			Status string `json:"status"`
		} `json:"elements"`
	} `json:"rows"`
	Status string `json:"status"`
}

func main() {
	conf, err := readConfig(os.Args[1])
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s: %v\n", name, err)
		os.Exit(1)
	}

	params := map[string]string{
		"origins":        conf.Origins,
		"destinations":   conf.Destinations,
		"key":            conf.APIKey,
		"mode":           conf.Mode,
		"avoid":          conf.Avoid,
		"departure_time": "now",
		"traffic_model":  conf.TrafficModel,
	}

	apiResp, err := queryMapsAPI(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s: %v\n", name, err)
		os.Exit(1)
	}

	duration := apiResp.Rows[0].Elements[0].DurationInTraffic.Value
	durationMins := int(float64(duration)/60.0 + 0.5) // round

	if durationMins > conf.MaxDuration {
		sendMail(conf, fmt.Sprintf("%d minutes", durationMins))
	}
}

func readConfig(filename string) (*config, error) {
	var conf config

	confData, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(confData, &conf); err != nil {
		return nil, err
	}

	return &conf, nil
}

func queryMapsAPI(params map[string]string) (*apiResponse, error) {
	urlBuf := bytes.NewBufferString(apiURL)
	urlBuf.WriteByte('?')

	for key, val := range params {
		urlBuf.WriteString(url.QueryEscape(key))
		urlBuf.WriteByte('=')
		urlBuf.WriteString(url.QueryEscape(val))
		urlBuf.WriteByte('&')
	}

	resp, err := http.Get(urlBuf.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var apiResp apiResponse
	if err := json.Unmarshal(body, &apiResp); err != nil {
		return nil, err
	}

	if apiResp.Status != "OK" {
		return nil, fmt.Errorf("%s: bad response status: %s\n", name, apiResp.Status)
	}
	if len(apiResp.Rows) != 1 {
		return nil, fmt.Errorf("%s: response row count is not 1\n", name)
	}
	if len(apiResp.Rows[0].Elements) != 1 {
		return nil, fmt.Errorf("%s: response first row element count is not 1\n", name)
	}
	if apiResp.Rows[0].Elements[0].Status != "OK" {
		return nil, fmt.Errorf("%s: bad response first row first element status: %s\n", name, apiResp.Rows[0].Elements[0].Status)
	}

	return &apiResp, nil
}

func sendMail(conf *config, body string) error {
	user, err := user.Current()
	if err != nil {
		return err
	}

	hostname, err := os.Hostname()
	if err != nil {
		return err
	}

	auth := smtp.PlainAuth("", conf.SMTP.User, conf.SMTP.Pass, conf.SMTP.Host)
	sender := user.Username + "@" + hostname
	to := []string{conf.Recipient}
	msg := []byte("To: " + conf.Recipient + "\r\n" +
		"Subject: " + name + " alert\r\n" +
		"\r\n" +
		body + "\r\n")

	return smtp.SendMail(fmt.Sprintf("%s:%d", conf.SMTP.Host, conf.SMTP.Port), auth, sender, to, msg)
}
<commit_msg>Use log.Fatal/f to print errors and exit program<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/smtp"
	"net/url"
	"os"
	"os/user"
)

const (
	name   = "trafficjam"
	apiURL = "https://maps.googleapis.com/maps/api/distancematrix/json"
)

type config struct {
	Origins      string `json:"origins"`
	Destinations string `json:"destinations"`
	APIKey       string `json:"api_key"`
	Mode         string `json:"mode"`
	Avoid        string `json:"avoid"`
	TrafficModel string `json:"traffic_model"`
	MaxDuration  int    `json:"max_duration"`
	SMTP         struct {
		Host string `json:"host"`
		Port int    `json:"port"`
		User string `json:"user"`
		Pass string `json:"pass"`
	} `json:"smtp"`
	Recipient string `json:"recipient"`
}

type apiResponse struct {
	Rows []struct {
		Elements []struct {
			DurationInTraffic struct {
				Value int `json:"value"`
			} `json:"duration_in_traffic"`
			Status string `json:"status"`
		} `json:"elements"`
	} `json:"rows"`
	Status string `json:"status"`
}

func main() {
	log.SetPrefix(name + ": ")
	log.SetFlags(0)

	conf, err := readConfig(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}

	params := map[string]string{
		"origins":        conf.Origins,
		"destinations":   conf.Destinations,
		"key":            conf.APIKey,
		"mode":           conf.Mode,
		"avoid":          conf.Avoid,
		"departure_time": "now",
		"traffic_model":  conf.TrafficModel,
	}

	apiResp, err := queryMapsAPI(params)
	if err != nil {
		log.Fatal(err)
	}

	duration := apiResp.Rows[0].Elements[0].DurationInTraffic.Value
	durationMins := int(float64(duration)/60.0 + 0.5) // round

	if durationMins > conf.MaxDuration {
		sendMail(conf, fmt.Sprintf("%d minutes", durationMins))
	}
}

func readConfig(filename string) (*config, error) {
	var conf config

	confData, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(confData, &conf); err != nil {
		return nil, err
	}

	return &conf, nil
}

func queryMapsAPI(params map[string]string) (*apiResponse, error) {
	urlBuf := bytes.NewBufferString(apiURL)
	urlBuf.WriteByte('?')

	for key, val := range params {
		urlBuf.WriteString(url.QueryEscape(key))
		urlBuf.WriteByte('=')
		urlBuf.WriteString(url.QueryEscape(val))
		urlBuf.WriteByte('&')
	}

	resp, err := http.Get(urlBuf.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var apiResp apiResponse
	if err := json.Unmarshal(body, &apiResp); err != nil {
		return nil, err
	}

	if apiResp.Status != "OK" {
		return nil, fmt.Errorf("%s: bad response status: %s\n", name, apiResp.Status)
	}
	if len(apiResp.Rows) != 1 {
		return nil, fmt.Errorf("%s: response row count is not 1\n", name)
	}
	if len(apiResp.Rows[0].Elements) != 1 {
		return nil, fmt.Errorf("%s: response first row element count is not 1\n", name)
	}
	if apiResp.Rows[0].Elements[0].Status != "OK" {
		return nil, fmt.Errorf("%s: bad response first row first element status: %s\n", name, apiResp.Rows[0].Elements[0].Status)
	}

	return &apiResp, nil
}

func sendMail(conf *config, body string) error {
	user, err := user.Current()
	if err != nil {
		return err
	}

	hostname, err := os.Hostname()
	if err != nil {
		return err
	}

	auth := smtp.PlainAuth("", conf.SMTP.User, conf.SMTP.Pass, conf.SMTP.Host)
	sender := user.Username + "@" + hostname
	to := []string{conf.Recipient}
	msg := []byte("To: " + conf.Recipient + "\r\n" +
		"Subject: " + name + " alert\r\n" +
		"\r\n" +
		body + "\r\n")

	return smtp.SendMail(fmt.Sprintf("%s:%d", conf.SMTP.Host, conf.SMTP.Port), auth, sender, to, msg)
}
<|endoftext|>


<commit_before>package endly

import (
	"fmt"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/data"
	"strings"
)

//DsUnitTableData represents table data
type DsUnitTableData struct {
	Table         string
	Value         interface{}
	AutoGenerate  map[string]string `json:",omitempty"`
	PostIncrement []string          `json:",omitempty"`
	Key           string
}

//AuotGenerateIfNeeded retrieves auto generated values
func (d *DsUnitTableData) AuotGenerateIfNeeded(state data.Map) error {
	for k, v := range d.AutoGenerate {
		value, has := state.GetValue(v)
		if !has {
			return fmt.Errorf("failed to autogenerate value for %v - unable to eval: %v", k, v)
		}
		state.SetValue(k, value)
	}
	return nil
}

//PostIncrementIfNeeded increments all specified counters by one.
func (d *DsUnitTableData) PostIncrementIfNeeded(state data.Map) {
	for _, key := range d.PostIncrement {
		keyText := toolbox.AsString(key)
		value, has := state.GetValue(keyText)
		if !has {
			value = 0
		}
		state.SetValue(keyText, toolbox.AsInt(value)+1)
	}
}

//GetValues a table records.
func (d *DsUnitTableData) GetValues(state data.Map) []map[string]interface{} {
	if toolbox.IsMap(d.Value) {
		var value =d.GetValue(state, d.Value)
		if len(value) == 0 {
			return []map[string]interface{}{}
		}
		return []map[string]interface{}{
			d.GetValue(state, d.Value),
		}
	}
	var result = make([]map[string]interface{}, 0)
	if toolbox.IsSlice(d.Value) {
		var aSlice = toolbox.AsSlice(d.Value)
		for _, item := range aSlice {
			value := d.GetValue(state, item)
			if len(value) > 0 {
				result = append(result, value)
			}
		}
	}
	return result
}

func (d *DsUnitTableData) expandThis(textValue string, value map[string]interface{}) interface{} {
	if strings.Contains(textValue, "this.") {
		var thisState = data.NewMap()
		for subKey, subValue := range value {
			if toolbox.IsString(subValue) {
				subKeyTextValue := toolbox.AsString(subValue)
				if !strings.Contains(subKeyTextValue, "this") {
					thisState.SetValue(fmt.Sprintf("this.%v", subKey), subKeyTextValue)
				}
			}
		}
		return thisState.Expand(textValue)
	}
	return textValue
}

//GetValue returns record.
func (d *DsUnitTableData) GetValue(state data.Map, source interface{}) map[string]interface{} {
	value := toolbox.AsMap(state.Expand(source))
	for k, v := range value {
		var textValue = toolbox.AsString(v)
		if strings.Contains(textValue, "this") {
			value[k] = d.expandThis(textValue, value)
		} else if strings.HasPrefix(textValue, "$") {
			delete(value, k)
		} else if strings.HasPrefix(textValue, "\\$") {
			value[k] = string(textValue[1:])
		}
	}

	dataStoreState := state.GetMap(DataStoreUnitServiceID)

	var key = d.Key
	if key == "" {
		key = d.Table
	}
	if !dataStoreState.Has(key) {
		dataStoreState.Put(key, data.NewCollection())
	}
	records := dataStoreState.GetCollection(key)
	records.Push(value)
	return value
}

//AsTableRecords converts source into slice of *DsUnitTableData to create dsunit data as map[string][]map[string]interface{} (table with records)
func AsTableRecords(source interface{}, state data.Map) (interface{}, error) {
	var result = make(map[string][]map[string]interface{})
	if source == nil {
		return nil, reportError(fmt.Errorf("Source was nil"))
	}
	if !state.Has(DataStoreUnitServiceID) {
		state.Put(DataStoreUnitServiceID, data.NewMap())
	}

	var prepareTableData, ok = source.([]*DsUnitTableData)

	if ! ok {
		prepareTableData = make([]*DsUnitTableData, 0)
		err := converter.AssignConverted(&prepareTableData, source)
		if err != nil {
			return nil, err
		}
	}
	for _, tableData := range prepareTableData {
		var table = tableData.Table
		err := tableData.AuotGenerateIfNeeded(state)
		if err != nil {
			return nil, err
		}
		var values = tableData.GetValues(state)
		if len(values) > 0 {
			result[table] = append(result[table], values...)
			tableData.PostIncrementIfNeeded(state)
		}
	}
	dataStoreState := state.GetMap(DataStoreUnitServiceID)
	var variable = &Variable{
		Name:    DataStoreUnitServiceID,
		Persist: true,
		Value:   dataStoreState,
	}
	err := variable.PersistValue()
	if err != nil {
		return nil, err
	}
	return result, nil
}
<commit_msg>patched dsunit udf<commit_after>package endly

import (
	"fmt"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/data"
	"strings"
)

//DsUnitTableData represents table data
type DsUnitTableData struct {
	Table         string
	Value         interface{}
	AutoGenerate  map[string]string `json:",omitempty"`
	PostIncrement []string          `json:",omitempty"`
	Key           string
}

//AuotGenerateIfNeeded retrieves auto generated values
func (d *DsUnitTableData) AuotGenerateIfNeeded(state data.Map) error {
	for k, v := range d.AutoGenerate {
		value, has := state.GetValue(v)
		if !has {
			return fmt.Errorf("failed to autogenerate value for %v - unable to eval: %v", k, v)
		}
		state.SetValue(k, value)
	}
	return nil
}

//PostIncrementIfNeeded increments all specified counters by one.
func (d *DsUnitTableData) PostIncrementIfNeeded(state data.Map) {
	for _, key := range d.PostIncrement {
		keyText := toolbox.AsString(key)
		value, has := state.GetValue(keyText)
		if !has {
			value = 0
		}
		state.SetValue(keyText, toolbox.AsInt(value)+1)
	}
}

//GetValues a table records.
func (d *DsUnitTableData) GetValues(state data.Map) []map[string]interface{} {
	if toolbox.IsMap(d.Value) {
		var value =d.GetValue(state, d.Value)
		if len(value) == 0 {
			return []map[string]interface{}{}
		}
		return []map[string]interface{}{
			value,
		}
	}
	var result = make([]map[string]interface{}, 0)
	if toolbox.IsSlice(d.Value) {
		var aSlice = toolbox.AsSlice(d.Value)
		for _, item := range aSlice {
			value := d.GetValue(state, item)
			if len(value) > 0 {
				result = append(result, value)
			}
		}
	}
	return result
}

func (d *DsUnitTableData) expandThis(textValue string, value map[string]interface{}) interface{} {
	if strings.Contains(textValue, "this.") {
		var thisState = data.NewMap()
		for subKey, subValue := range value {
			if toolbox.IsString(subValue) {
				subKeyTextValue := toolbox.AsString(subValue)
				if !strings.Contains(subKeyTextValue, "this") {
					thisState.SetValue(fmt.Sprintf("this.%v", subKey), subKeyTextValue)
				}
			}
		}
		return thisState.Expand(textValue)
	}
	return textValue
}

//GetValue returns record.
func (d *DsUnitTableData) GetValue(state data.Map, source interface{}) map[string]interface{} {
	value := toolbox.AsMap(state.Expand(source))
	for k, v := range value {
		var textValue = toolbox.AsString(v)
		if strings.Contains(textValue, "this") {
			value[k] = d.expandThis(textValue, value)
		} else if strings.HasPrefix(textValue, "$") {
			delete(value, k)
		} else if strings.HasPrefix(textValue, "\\$") {
			value[k] = string(textValue[1:])
		}
	}

	dataStoreState := state.GetMap(DataStoreUnitServiceID)
	var key = d.Key
	if key == "" {
		key = d.Table
	}
	if !dataStoreState.Has(key) {
		dataStoreState.Put(key, data.NewCollection())
	}

	records := dataStoreState.GetCollection(key)
	records.Push(value)
	return value
}

//AsTableRecords converts source into slice of *DsUnitTableData to create dsunit data as map[string][]map[string]interface{} (table with records)
func AsTableRecords(source interface{}, state data.Map) (interface{}, error) {
	var result = make(map[string][]map[string]interface{})
	if source == nil {
		return nil, reportError(fmt.Errorf("Source was nil"))
	}
	if !state.Has(DataStoreUnitServiceID) {
		state.Put(DataStoreUnitServiceID, data.NewMap())
	}

	var prepareTableData, ok = source.([]*DsUnitTableData)

	if ! ok {
		prepareTableData = make([]*DsUnitTableData, 0)
		err := converter.AssignConverted(&prepareTableData, source)
		if err != nil {
			return nil, err
		}
	}
	for _, tableData := range prepareTableData {
		var table = tableData.Table
		err := tableData.AuotGenerateIfNeeded(state)
		if err != nil {
			return nil, err
		}
		var values = tableData.GetValues(state)
		if len(values) > 0 {
			result[table] = append(result[table], values...)
			tableData.PostIncrementIfNeeded(state)
		}
	}

	dataStoreState := state.GetMap(DataStoreUnitServiceID)
	var variable = &Variable{
		Name:    DataStoreUnitServiceID,
		Persist: true,
		Value:   dataStoreState,
	}
	err := variable.PersistValue()
	if err != nil {
		return nil, err
	}
	return result, nil
}
<|endoftext|>


<commit_before>package helpers

import (
	"encoding/json"
	"fmt"
	"time"

	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers"
)

const (
	BROKER_START_TIMEOUT = 5 * time.Minute
	DEFAULT_TIMEOUT      = 30 * time.Second
)

type ServiceBroker struct {
	Name    string
	Path    string
	context helpers.SuiteContext
	Service struct {
		Name            string `json:"name"`
		ID              string `json:"id"`
		DashboardClient struct {
			ID          string `json:"id"`
			Secret      string `json:"secret"`
			RedirectUri string `json:"redirect_uri"`
		}
	}
	Plan struct {
		Name string `json:"name"`
		ID   string `json:"id"`
	}
}

type ServicesResponse struct {
	Resources []ServiceResponse
}

type ServiceResponse struct {
	Entity struct {
		Label        string
		ServicePlans []ServicePlanResponse `json:"service_plans"`
	}
}

type ServicePlanResponse struct {
	Entity struct {
		Name   string
		Public bool
	}
	Metadata struct {
		Url  string
		Guid string
	}
}

type ServiceInstance struct {
	Metadata struct {
		Guid string `json:"guid"`
	}
}

type ServiceInstanceResponse struct {
	Resources []ServiceInstance
}

type SpaceJson struct {
	Resources []struct {
		Metadata struct {
			Guid string
		}
	}
}

func NewServiceBroker(name string, path string, context helpers.SuiteContext) ServiceBroker {
	b := ServiceBroker{}
	b.Path = path
	b.Name = name
	b.Service.Name = generator.RandomName()
	b.Service.ID = generator.RandomName()
	b.Plan.Name = generator.RandomName()
	b.Plan.ID = generator.RandomName()
	b.Service.DashboardClient.ID = generator.RandomName()
	b.Service.DashboardClient.Secret = generator.RandomName()
	b.Service.DashboardClient.RedirectUri = generator.RandomName()
	b.context = context
	return b
}

func (b ServiceBroker) Push() {
	Expect(cf.Cf("push", b.Name, "-p", b.Path).Wait(BROKER_START_TIMEOUT)).To(Exit(0))
}

func (b ServiceBroker) Configure() {
	Expect(cf.Cf("set-env", b.Name, "CONFIG", b.ToJSON()).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	b.Restart()
}

func (b ServiceBroker) Restart() {
	Expect(cf.Cf("restart", b.Name).Wait(BROKER_START_TIMEOUT)).To(Exit(0))
}

func (b ServiceBroker) Create() {
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("create-service-broker", b.Name, "username", "password", helpers.AppUri(b.Name, "")).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		Expect(cf.Cf("service-brokers").Wait(DEFAULT_TIMEOUT)).To(Say(b.Name))
	})
}

func (b ServiceBroker) Update() {
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("update-service-broker", b.Name).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})
}

func (b ServiceBroker) Delete() {
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("delete-service-broker", b.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

		brokers := cf.Cf("service-brokers").Wait(DEFAULT_TIMEOUT)
		Expect(brokers).To(Exit(0))
		Expect(brokers.Out.Contents()).ToNot(ContainSubstring(b.Name))
	})
}

func (b ServiceBroker) Destroy() {
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("purge-service-offering", b.Service.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})
	b.Delete()
	Expect(cf.Cf("delete", b.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
}

func (b ServiceBroker) ToJSON() string {
	attributes := make(map[string]interface{})
	attributes["service"] = b.Service
	attributes["plan"] = b.Plan
	attributes["dashboard_client"] = b.Service.DashboardClient
	jsonBytes, _ := json.Marshal(attributes)
	return string(jsonBytes)
}

func (b ServiceBroker) PublicizePlans() {
	url := fmt.Sprintf("/v2/services?inline-relations-depth=1&q=label:%s", b.Service.Name)
	var session *Session
	cf.AsUser(b.context.AdminUserContext(), func() {
		session = cf.Cf("curl", url).Wait(DEFAULT_TIMEOUT)
		Expect(session).To(Exit(0))
	})
	structure := ServicesResponse{}
	json.Unmarshal(session.Out.Contents(), &structure)

	for _, service := range structure.Resources {
		if service.Entity.Label == b.Service.Name {
			for _, plan := range service.Entity.ServicePlans {
				if plan.Entity.Name == b.Plan.Name {
					b.PublicizePlan(plan.Metadata.Url)
					break
				}
			}
		}
	}
}

func (b ServiceBroker) PublicizePlan(url string) {
	jsonMap := make(map[string]bool)
	jsonMap["public"] = true
	planJson, _ := json.Marshal(jsonMap)
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("curl", url, "-X", "PUT", "-d", string(planJson)).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})
}

func (b ServiceBroker) CreateServiceInstance(instanceName string) string {
	Expect(cf.Cf("create-service", b.Service.Name, b.Plan.Name, instanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	url := fmt.Sprintf("/v2/service_instances?q=name:%s", instanceName)
	serviceInstance := ServiceInstanceResponse{}
	curl := cf.Cf("curl", url).Wait(DEFAULT_TIMEOUT)
	Expect(curl).To(Exit(0))
	json.Unmarshal(curl.Out.Contents(), &serviceInstance)
	return serviceInstance.Resources[0].Metadata.Guid
}

func (b ServiceBroker) GetSpaceGuid() string {
	url := fmt.Sprintf("/v2/spaces?q=name%%3A%s", b.context.RegularUserContext().Space)
	jsonResults := SpaceJson{}
	curl := cf.Cf("curl", url).Wait(DEFAULT_TIMEOUT)
	Expect(curl).To(Exit(0))
	json.Unmarshal(curl.Out.Contents(), &jsonResults)
	return jsonResults.Resources[0].Metadata.Guid
}
<commit_msg>Revert "Change update-service-broker usage to reflect recent CLI change."<commit_after>package helpers

import (
	"encoding/json"
	"fmt"
	"time"

	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers"
)

const (
	BROKER_START_TIMEOUT = 5 * time.Minute
	DEFAULT_TIMEOUT      = 30 * time.Second
)

type ServiceBroker struct {
	Name    string
	Path    string
	context helpers.SuiteContext
	Service struct {
		Name            string `json:"name"`
		ID              string `json:"id"`
		DashboardClient struct {
			ID          string `json:"id"`
			Secret      string `json:"secret"`
			RedirectUri string `json:"redirect_uri"`
		}
	}
	Plan struct {
		Name string `json:"name"`
		ID   string `json:"id"`
	}
}

type ServicesResponse struct {
	Resources []ServiceResponse
}

type ServiceResponse struct {
	Entity struct {
		Label        string
		ServicePlans []ServicePlanResponse `json:"service_plans"`
	}
}

type ServicePlanResponse struct {
	Entity struct {
		Name   string
		Public bool
	}
	Metadata struct {
		Url  string
		Guid string
	}
}

type ServiceInstance struct {
	Metadata struct {
		Guid string `json:"guid"`
	}
}

type ServiceInstanceResponse struct {
	Resources []ServiceInstance
}

type SpaceJson struct {
	Resources []struct {
		Metadata struct {
			Guid string
		}
	}
}

func NewServiceBroker(name string, path string, context helpers.SuiteContext) ServiceBroker {
	b := ServiceBroker{}
	b.Path = path
	b.Name = name
	b.Service.Name = generator.RandomName()
	b.Service.ID = generator.RandomName()
	b.Plan.Name = generator.RandomName()
	b.Plan.ID = generator.RandomName()
	b.Service.DashboardClient.ID = generator.RandomName()
	b.Service.DashboardClient.Secret = generator.RandomName()
	b.Service.DashboardClient.RedirectUri = generator.RandomName()
	b.context = context
	return b
}

func (b ServiceBroker) Push() {
	Expect(cf.Cf("push", b.Name, "-p", b.Path).Wait(BROKER_START_TIMEOUT)).To(Exit(0))
}

func (b ServiceBroker) Configure() {
	Expect(cf.Cf("set-env", b.Name, "CONFIG", b.ToJSON()).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	b.Restart()
}

func (b ServiceBroker) Restart() {
	Expect(cf.Cf("restart", b.Name).Wait(BROKER_START_TIMEOUT)).To(Exit(0))
}

func (b ServiceBroker) Create() {
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("create-service-broker", b.Name, "username", "password", helpers.AppUri(b.Name, "")).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		Expect(cf.Cf("service-brokers").Wait(DEFAULT_TIMEOUT)).To(Say(b.Name))
	})
}

func (b ServiceBroker) Update() {
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("update-service-broker", b.Name, "username", "password", helpers.AppUri(b.Name, "")).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})
}

func (b ServiceBroker) Delete() {
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("delete-service-broker", b.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

		brokers := cf.Cf("service-brokers").Wait(DEFAULT_TIMEOUT)
		Expect(brokers).To(Exit(0))
		Expect(brokers.Out.Contents()).ToNot(ContainSubstring(b.Name))
	})
}

func (b ServiceBroker) Destroy() {
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("purge-service-offering", b.Service.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})
	b.Delete()
	Expect(cf.Cf("delete", b.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
}

func (b ServiceBroker) ToJSON() string {
	attributes := make(map[string]interface{})
	attributes["service"] = b.Service
	attributes["plan"] = b.Plan
	attributes["dashboard_client"] = b.Service.DashboardClient
	jsonBytes, _ := json.Marshal(attributes)
	return string(jsonBytes)
}

func (b ServiceBroker) PublicizePlans() {
	url := fmt.Sprintf("/v2/services?inline-relations-depth=1&q=label:%s", b.Service.Name)
	var session *Session
	cf.AsUser(b.context.AdminUserContext(), func() {
		session = cf.Cf("curl", url).Wait(DEFAULT_TIMEOUT)
		Expect(session).To(Exit(0))
	})
	structure := ServicesResponse{}
	json.Unmarshal(session.Out.Contents(), &structure)

	for _, service := range structure.Resources {
		if service.Entity.Label == b.Service.Name {
			for _, plan := range service.Entity.ServicePlans {
				if plan.Entity.Name == b.Plan.Name {
					b.PublicizePlan(plan.Metadata.Url)
					break
				}
			}
		}
	}
}

func (b ServiceBroker) PublicizePlan(url string) {
	jsonMap := make(map[string]bool)
	jsonMap["public"] = true
	planJson, _ := json.Marshal(jsonMap)
	cf.AsUser(b.context.AdminUserContext(), func() {
		Expect(cf.Cf("curl", url, "-X", "PUT", "-d", string(planJson)).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})
}

func (b ServiceBroker) CreateServiceInstance(instanceName string) string {
	Expect(cf.Cf("create-service", b.Service.Name, b.Plan.Name, instanceName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	url := fmt.Sprintf("/v2/service_instances?q=name:%s", instanceName)
	serviceInstance := ServiceInstanceResponse{}
	curl := cf.Cf("curl", url).Wait(DEFAULT_TIMEOUT)
	Expect(curl).To(Exit(0))
	json.Unmarshal(curl.Out.Contents(), &serviceInstance)
	return serviceInstance.Resources[0].Metadata.Guid
}

func (b ServiceBroker) GetSpaceGuid() string {
	url := fmt.Sprintf("/v2/spaces?q=name%%3A%s", b.context.RegularUserContext().Space)
	jsonResults := SpaceJson{}
	curl := cf.Cf("curl", url).Wait(DEFAULT_TIMEOUT)
	Expect(curl).To(Exit(0))
	json.Unmarshal(curl.Out.Contents(), &jsonResults)
	return jsonResults.Resources[0].Metadata.Guid
}
<|endoftext|>


<commit_before>package sessions

import "time"

// CookieOptions for the session cookies themselves.
type CookieOptions struct {
	// Name for the session cookie
	Name string
	// ClientExpiry is set as well as max-age, max-age is determined from
	// ClientExpiry
	ClientExpiry time.Duration
	// Secure ensures the cookie is only given on https connections
	Secure bool
	// HTTPOnly means the browser will never allow JS to touch this cookie
	HTTPOnly bool
}

// NewCookieOptions gives healthy defaults for session cookies
func NewCookieOptions() CookieOptions {
	return CookieOptions{
		Name:         "id",
		ClientExpiry: 0,
		Secure:       true,
		HTTPOnly:     true,
	}
}
<commit_msg>Create makeCookie function<commit_after>package sessions

import (
	"net/http"
	"time"
)

// CookieOptions for the session cookies themselves.
type CookieOptions struct {
	// Name for the session cookie
	Name string
	// MaxAge sets the max-age and the expires fields of a cookie.
	MaxAge time.Duration
	// Secure ensures the cookie is only given on https connections
	Secure bool
	// HTTPOnly means the browser will never allow JS to touch this cookie
	HTTPOnly bool
}

// NewCookieOptions gives healthy defaults for session cookies
func NewCookieOptions() CookieOptions {
	return CookieOptions{
		Name:     "id",
		MaxAge:   0,
		Secure:   true,
		HTTPOnly: true,
	}
}

func (c CookieOptions) makeCookie(value string) *http.Cookie {
	return &http.Cookie{
		Name:     c.Name,
		Value:    value,
		MaxAge:   int(c.MaxAge.Seconds()),
		Expires:  time.Now().UTC().Add(c.MaxAge),
		HttpOnly: c.HTTPOnly,
		Secure:   c.Secure,
	}
}
<|endoftext|>


<commit_before>package logged

import (
	"bytes"
	"encoding/json"
	"io"
	"testing"
	"time"

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

func TestJSONSerializer(t *testing.T) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{Timestamp: "rightnow", Level: "somelevel", Message: "test123", Data: map[string]string{"test": "123", "test2": "345"}}
		out Entry
	)

	assert.NoError(t, s.Write(e))
	assert.NoError(t, json.NewDecoder(&buf).Decode(&out))
	assert.Equal(t, e, &out)
}

func TestJSONSerializerNoData(t *testing.T) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{Timestamp: "sometimelater", Level: "otherlevel", Message: "345test"}
		out Entry
	)

	assert.NoError(t, s.Write(e))
	assert.NoError(t, json.NewDecoder(&buf).Decode(&out))
	assert.Equal(t, e, &out)
}

func TestJSONSerializerBadChars(t *testing.T) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{Timestamp: "sometimelater", Level: "otherlevel", Message: "\" \\ \b \f \n \r \t"}
		out Entry
	)

	assert.NoError(t, s.Write(e))
	assert.NoError(t, json.NewDecoder(&buf).Decode(&out))
	assert.Equal(t, e, &out)
}

func TestJSONSerializerExtended(t *testing.T) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{Timestamp: "sometimelater", Level: "otherlevel", Message: "Hello, 世界 √ 😂 \ufffd"}
		out Entry
	)

	assert.NoError(t, s.Write(e))
	assert.NoError(t, json.NewDecoder(&buf).Decode(&out))
	assert.Equal(t, e, &out)
}

func BenchmarkJSONSerializer(b *testing.B) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{
			Level:     "debug",
			Timestamp: time.Now().UTC().Format(time.RFC3339Nano),
			Message:   "this is a test of the serializer for a message",
		}
	)

	for n := 0; n < b.N; n++ {
		s.Write(e)
	}
}

func newStdlibJSONSerializer(w io.Writer) Serializer {
	return &stdlibJSONSerializer{
		e: json.NewEncoder(w),
	}
}

type stdlibJSONSerializer struct {
	e *json.Encoder
}

func (s *stdlibJSONSerializer) Write(e *Entry) error {
	return s.e.Encode(e)
}

func BenchmarkStdlibJSONSerializer(b *testing.B) {
	var (
		buf bytes.Buffer
		s   = newStdlibJSONSerializer(&buf)
		e   = &Entry{
			Level:     "debug",
			Timestamp: time.Now().UTC().Format(time.RFC3339Nano),
			Message:   "this is a test of the serializer for a message",
		}
	)

	for n := 0; n < b.N; n++ {
		s.Write(e)
	}
}
<commit_msg>Cleaner<commit_after>package logged

import (
	"bytes"
	"encoding/json"
	"testing"
	"time"

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

func TestJSONSerializer(t *testing.T) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{Timestamp: "rightnow", Level: "somelevel", Message: "test123", Data: map[string]string{"test": "123", "test2": "345"}}
		out Entry
	)

	assert.NoError(t, s.Write(e))
	assert.NoError(t, json.NewDecoder(&buf).Decode(&out))
	assert.Equal(t, e, &out)
}

func TestJSONSerializerNoData(t *testing.T) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{Timestamp: "sometimelater", Level: "otherlevel", Message: "345test"}
		out Entry
	)

	assert.NoError(t, s.Write(e))
	assert.NoError(t, json.NewDecoder(&buf).Decode(&out))
	assert.Equal(t, e, &out)
}

func TestJSONSerializerBadChars(t *testing.T) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{Timestamp: "sometimelater", Level: "otherlevel", Message: "\" \\ \b \f \n \r \t"}
		out Entry
	)

	assert.NoError(t, s.Write(e))
	assert.NoError(t, json.NewDecoder(&buf).Decode(&out))
	assert.Equal(t, e, &out)
}

func TestJSONSerializerExtended(t *testing.T) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{Timestamp: "sometimelater", Level: "otherlevel", Message: "Hello, 世界 √ 😂 \ufffd"}
		out Entry
	)

	assert.NoError(t, s.Write(e))
	assert.NoError(t, json.NewDecoder(&buf).Decode(&out))
	assert.Equal(t, e, &out)
}

func BenchmarkJSONSerializer(b *testing.B) {
	var (
		buf bytes.Buffer
		s   = NewJSONSerializer(&buf)
		e   = &Entry{
			Level:     "debug",
			Timestamp: time.Now().UTC().Format(time.RFC3339Nano),
			Message:   "this is a test of the serializer for a message",
		}
	)

	for n := 0; n < b.N; n++ {
		s.Write(e)
	}
}

type stdlibJSONSerializer struct{ e *json.Encoder }

func (s *stdlibJSONSerializer) Write(e *Entry) error { return s.e.Encode(e) }

func BenchmarkStdlibJSONSerializer(b *testing.B) {
	var (
		buf bytes.Buffer
		s   = &stdlibJSONSerializer{json.NewEncoder(&buf)}
		e   = &Entry{
			Level:     "debug",
			Timestamp: time.Now().UTC().Format(time.RFC3339Nano),
			Message:   "this is a test of the serializer for a message",
		}
	)

	for n := 0; n < b.N; n++ {
		s.Write(e)
	}
}
<|endoftext|>


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

package fuseops

import (
	"bytes"
	"log"
	"time"
	"unsafe"

	"github.com/jacobsa/fuse/internal/fusekernel"
	"github.com/jacobsa/fuse/internal/fuseshim"
	"golang.org/x/net/context"
)

// This function is an implementation detail of the fuse package, and must not
// be called by anyone else.
//
// Convert the supplied fuse kernel message to an Op. finished will be called
// with the error supplied to o.Respond when the user invokes that method,
// before a response is sent to the kernel. o.Respond will destroy the message.
//
// It is guaranteed that o != nil. If the op is unknown, a special unexported
// type will be used.
//
// The debug logging function and error logger may be nil.
func Convert(
	opCtx context.Context,
	m *fuseshim.Message,
	protocol fusekernel.Protocol,
	debugLogForOp func(int, string, ...interface{}),
	errorLogger *log.Logger,
	finished func(error)) (o Op) {
	var co *commonOp

	var io internalOp
	switch m.Hdr.Opcode {
	case fusekernel.OpLookup:
		buf := m.Bytes()
		n := len(buf)
		if n == 0 || buf[n-1] != '\x00' {
			goto corrupt
		}

		to := &LookUpInodeOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(buf[:n-1]),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpGetattr:
		to := &GetInodeAttributesOp{
			Inode: InodeID(m.Header().Node),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpSetattr:
		in := (*fusekernel.SetattrIn)(m.Data())
		if m.Len() < unsafe.Sizeof(*in) {
			goto corrupt
		}

		to := &SetInodeAttributesOp{
			Inode: InodeID(m.Header().Node),
		}

		valid := fusekernel.SetattrValid(in.Valid)
		if valid&fusekernel.SetattrSize != 0 {
			to.Size = &in.Size
		}

		if valid&fusekernel.SetattrMode != 0 {
			mode := fuseshim.FileMode(in.Mode)
			to.Mode = &mode
		}

		if valid&fusekernel.SetattrAtime != 0 {
			t := time.Unix(int64(in.Atime), int64(in.AtimeNsec))
			to.Atime = &t
		}

		if valid&fusekernel.SetattrMtime != 0 {
			t := time.Unix(int64(in.Mtime), int64(in.MtimeNsec))
			to.Mtime = &t
		}

		io = to
		co = &to.commonOp

	case fusekernel.OpForget:
		in := (*fusekernel.ForgetIn)(m.Data())
		if m.Len() < unsafe.Sizeof(*in) {
			goto corrupt
		}

		to := &ForgetInodeOp{
			Inode: InodeID(m.Header().Node),
			N:     in.Nlookup,
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpMkdir:
		size := fusekernel.MkdirInSize(protocol)
		if m.Len() < size {
			goto corrupt
		}
		in := (*fusekernel.MkdirIn)(m.Data())
		name := m.Bytes()[size:]
		i := bytes.IndexByte(name, '\x00')
		if i < 0 {
			goto corrupt
		}
		name = name[:i]

		to := &MkDirOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(name),
			Mode:   fuseshim.FileMode(in.Mode),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpCreate:
		size := fusekernel.CreateInSize(protocol)
		if m.Len() < size {
			goto corrupt
		}
		in := (*fusekernel.CreateIn)(m.Data())
		name := m.Bytes()[size:]
		i := bytes.IndexByte(name, '\x00')
		if i < 0 {
			goto corrupt
		}
		name = name[:i]

		to := &CreateFileOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(name),
			Mode:   fuseshim.FileMode(in.Mode),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpSymlink:
		// m.Bytes() is "newName\0target\0"
		names := m.Bytes()
		if len(names) == 0 || names[len(names)-1] != 0 {
			goto corrupt
		}
		i := bytes.IndexByte(names, '\x00')
		if i < 0 {
			goto corrupt
		}
		newName, target := names[0:i], names[i+1:len(names)-1]

		to := &CreateSymlinkOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(newName),
			Target: string(target),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpRename:
		in := (*fusekernel.RenameIn)(m.Data())
		if m.Len() < unsafe.Sizeof(*in) {
			goto corrupt
		}
		names := m.Bytes()[unsafe.Sizeof(*in):]
		// names should be "old\x00new\x00"
		if len(names) < 4 {
			goto corrupt
		}
		if names[len(names)-1] != '\x00' {
			goto corrupt
		}
		i := bytes.IndexByte(names, '\x00')
		if i < 0 {
			goto corrupt
		}
		oldName, newName := names[:i], names[i+1:len(names)-1]

		to := &RenameOp{
			OldParent: InodeID(m.Header().Node),
			OldName:   string(oldName),
			NewParent: InodeID(in.Newdir),
			NewName:   string(newName),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpUnlink:
		buf := m.Bytes()
		n := len(buf)
		if n == 0 || buf[n-1] != '\x00' {
			goto corrupt
		}

		to := &UnlinkOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(buf[:n-1]),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpRmdir:
		buf := m.Bytes()
		n := len(buf)
		if n == 0 || buf[n-1] != '\x00' {
			goto corrupt
		}

		to := &RmDirOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(buf[:n-1]),
		}
		io = to
		co = &to.commonOp

	case *fuseshim.OpenRequest:
		if typed.Dir {
			to := &OpenDirOp{
				bfReq: typed,
				Inode: InodeID(typed.Header.Node),
			}
			io = to
			co = &to.commonOp
		} else {
			to := &OpenFileOp{
				bfReq: typed,
				Inode: InodeID(typed.Header.Node),
			}
			io = to
			co = &to.commonOp
		}

	case fusekernel.OpRead:
		in := (*fusekernel.ReadIn)(m.Data())
		if m.Len() < fusekernel.ReadInSize(protocol) {
			goto corrupt
		}

		to := &ReadFileOp{
			Inode:  InodeID(m.Header().Node),
			Handle: HandleID(in.Fh),
			Offset: int64(in.Offset),
			Size:   int(in.Size),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpReaddir:
		in := (*fusekernel.ReadIn)(m.Data())
		if m.Len() < fusekernel.ReadInSize(protocol) {
			goto corrupt
		}

		to := &ReadDirOp{
			Inode:  InodeID(m.Header().Node),
			Handle: HandleID(in.Fh),
			Offset: int64(in.Offset),
			Size:   int(in.Size),
		}
		io = to
		co = &to.commonOp

	case *fuseshim.ReleaseRequest:
		if typed.Dir {
			to := &ReleaseDirHandleOp{
				bfReq:  typed,
				Handle: HandleID(typed.Handle),
			}
			io = to
			co = &to.commonOp
		} else {
			to := &ReleaseFileHandleOp{
				bfReq:  typed,
				Handle: HandleID(typed.Handle),
			}
			io = to
			co = &to.commonOp
		}

	case *fuseshim.WriteRequest:
		to := &WriteFileOp{
			bfReq:  typed,
			Inode:  InodeID(typed.Header.Node),
			Handle: HandleID(typed.Handle),
			Data:   typed.Data,
			Offset: typed.Offset,
		}
		io = to
		co = &to.commonOp

	case *fuseshim.FsyncRequest:
		// We don't currently support this for directories.
		if typed.Dir {
			to := &unknownOp{}
			io = to
			co = &to.commonOp
		} else {
			to := &SyncFileOp{
				bfReq:  typed,
				Inode:  InodeID(typed.Header.Node),
				Handle: HandleID(typed.Handle),
			}
			io = to
			co = &to.commonOp
		}

	case *fuseshim.FlushRequest:
		to := &FlushFileOp{
			bfReq:  typed,
			Inode:  InodeID(typed.Header.Node),
			Handle: HandleID(typed.Handle),
		}
		io = to
		co = &to.commonOp

	case *fuseshim.ReadlinkRequest:
		to := &ReadSymlinkOp{
			bfReq: typed,
			Inode: InodeID(typed.Header.Node),
		}
		io = to
		co = &to.commonOp

	default:
		to := &unknownOp{}
		io = to
		co = &to.commonOp
	}

	co.init(
		opCtx,
		io,
		r,
		debugLogForOp,
		errorLogger,
		finished)

	o = io
	return
}

func convertAttributes(
	inode InodeID,
	attr InodeAttributes,
	expiration time.Time) fuseshim.Attr {
	return fuseshim.Attr{
		Inode:  uint64(inode),
		Size:   attr.Size,
		Mode:   attr.Mode,
		Nlink:  uint32(attr.Nlink),
		Atime:  attr.Atime,
		Mtime:  attr.Mtime,
		Ctime:  attr.Ctime,
		Crtime: attr.Crtime,
		Uid:    attr.Uid,
		Gid:    attr.Gid,
		Valid:  convertExpirationTime(expiration),
	}
}

// Convert an absolute cache expiration time to a relative time from now for
// consumption by fuse.
func convertExpirationTime(t time.Time) (d time.Duration) {
	// Fuse represents durations as unsigned 64-bit counts of seconds and 32-bit
	// counts of nanoseconds (cf. http://goo.gl/EJupJV). The bazil.org/fuse
	// package converts time.Duration values to this form in a straightforward
	// way (cf. http://goo.gl/FJhV8j).
	//
	// So negative durations are right out. There is no need to cap the positive
	// magnitude, because 2^64 seconds is well longer than the 2^63 ns range of
	// time.Duration.
	d = t.Sub(time.Now())
	if d < 0 {
		d = 0
	}

	return
}

func convertChildInodeEntry(
	in *ChildInodeEntry,
	out *fuseshim.LookupResponse) {
	out.Node = fuseshim.NodeID(in.Child)
	out.Generation = uint64(in.Generation)
	out.Attr = convertAttributes(in.Child, in.Attributes, in.AttributesExpiration)
	out.EntryValid = convertExpirationTime(in.EntryExpiration)
}
<commit_msg>OpenFileOp<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package fuseops

import (
	"bytes"
	"log"
	"time"
	"unsafe"

	"github.com/jacobsa/fuse/internal/fusekernel"
	"github.com/jacobsa/fuse/internal/fuseshim"
	"golang.org/x/net/context"
)

// This function is an implementation detail of the fuse package, and must not
// be called by anyone else.
//
// Convert the supplied fuse kernel message to an Op. finished will be called
// with the error supplied to o.Respond when the user invokes that method,
// before a response is sent to the kernel. o.Respond will destroy the message.
//
// It is guaranteed that o != nil. If the op is unknown, a special unexported
// type will be used.
//
// The debug logging function and error logger may be nil.
func Convert(
	opCtx context.Context,
	m *fuseshim.Message,
	protocol fusekernel.Protocol,
	debugLogForOp func(int, string, ...interface{}),
	errorLogger *log.Logger,
	finished func(error)) (o Op) {
	var co *commonOp

	var io internalOp
	switch m.Hdr.Opcode {
	case fusekernel.OpLookup:
		buf := m.Bytes()
		n := len(buf)
		if n == 0 || buf[n-1] != '\x00' {
			goto corrupt
		}

		to := &LookUpInodeOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(buf[:n-1]),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpGetattr:
		to := &GetInodeAttributesOp{
			Inode: InodeID(m.Header().Node),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpSetattr:
		in := (*fusekernel.SetattrIn)(m.Data())
		if m.Len() < unsafe.Sizeof(*in) {
			goto corrupt
		}

		to := &SetInodeAttributesOp{
			Inode: InodeID(m.Header().Node),
		}

		valid := fusekernel.SetattrValid(in.Valid)
		if valid&fusekernel.SetattrSize != 0 {
			to.Size = &in.Size
		}

		if valid&fusekernel.SetattrMode != 0 {
			mode := fuseshim.FileMode(in.Mode)
			to.Mode = &mode
		}

		if valid&fusekernel.SetattrAtime != 0 {
			t := time.Unix(int64(in.Atime), int64(in.AtimeNsec))
			to.Atime = &t
		}

		if valid&fusekernel.SetattrMtime != 0 {
			t := time.Unix(int64(in.Mtime), int64(in.MtimeNsec))
			to.Mtime = &t
		}

		io = to
		co = &to.commonOp

	case fusekernel.OpForget:
		in := (*fusekernel.ForgetIn)(m.Data())
		if m.Len() < unsafe.Sizeof(*in) {
			goto corrupt
		}

		to := &ForgetInodeOp{
			Inode: InodeID(m.Header().Node),
			N:     in.Nlookup,
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpMkdir:
		size := fusekernel.MkdirInSize(protocol)
		if m.Len() < size {
			goto corrupt
		}
		in := (*fusekernel.MkdirIn)(m.Data())
		name := m.Bytes()[size:]
		i := bytes.IndexByte(name, '\x00')
		if i < 0 {
			goto corrupt
		}
		name = name[:i]

		to := &MkDirOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(name),
			Mode:   fuseshim.FileMode(in.Mode),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpCreate:
		size := fusekernel.CreateInSize(protocol)
		if m.Len() < size {
			goto corrupt
		}
		in := (*fusekernel.CreateIn)(m.Data())
		name := m.Bytes()[size:]
		i := bytes.IndexByte(name, '\x00')
		if i < 0 {
			goto corrupt
		}
		name = name[:i]

		to := &CreateFileOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(name),
			Mode:   fuseshim.FileMode(in.Mode),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpSymlink:
		// m.Bytes() is "newName\0target\0"
		names := m.Bytes()
		if len(names) == 0 || names[len(names)-1] != 0 {
			goto corrupt
		}
		i := bytes.IndexByte(names, '\x00')
		if i < 0 {
			goto corrupt
		}
		newName, target := names[0:i], names[i+1:len(names)-1]

		to := &CreateSymlinkOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(newName),
			Target: string(target),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpRename:
		in := (*fusekernel.RenameIn)(m.Data())
		if m.Len() < unsafe.Sizeof(*in) {
			goto corrupt
		}
		names := m.Bytes()[unsafe.Sizeof(*in):]
		// names should be "old\x00new\x00"
		if len(names) < 4 {
			goto corrupt
		}
		if names[len(names)-1] != '\x00' {
			goto corrupt
		}
		i := bytes.IndexByte(names, '\x00')
		if i < 0 {
			goto corrupt
		}
		oldName, newName := names[:i], names[i+1:len(names)-1]

		to := &RenameOp{
			OldParent: InodeID(m.Header().Node),
			OldName:   string(oldName),
			NewParent: InodeID(in.Newdir),
			NewName:   string(newName),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpUnlink:
		buf := m.Bytes()
		n := len(buf)
		if n == 0 || buf[n-1] != '\x00' {
			goto corrupt
		}

		to := &UnlinkOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(buf[:n-1]),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpRmdir:
		buf := m.Bytes()
		n := len(buf)
		if n == 0 || buf[n-1] != '\x00' {
			goto corrupt
		}

		to := &RmDirOp{
			Parent: InodeID(m.Header().Node),
			Name:   string(buf[:n-1]),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpOpen:
		to := &OpenFileOp{
			Inode: InodeID(m.Header().Node),
		}
		io = to
		co = &to.commonOp

	case *fuseshim.OpenRequest:
		if typed.Dir {
			to := &OpenDirOp{
				bfReq: typed,
				Inode: InodeID(typed.Header.Node),
			}
			io = to
			co = &to.commonOp
		} else {
			to := &OpenFileOp{
				bfReq: typed,
				Inode: InodeID(typed.Header.Node),
			}
			io = to
			co = &to.commonOp
		}

	case fusekernel.OpRead:
		in := (*fusekernel.ReadIn)(m.Data())
		if m.Len() < fusekernel.ReadInSize(protocol) {
			goto corrupt
		}

		to := &ReadFileOp{
			Inode:  InodeID(m.Header().Node),
			Handle: HandleID(in.Fh),
			Offset: int64(in.Offset),
			Size:   int(in.Size),
		}
		io = to
		co = &to.commonOp

	case fusekernel.OpReaddir:
		in := (*fusekernel.ReadIn)(m.Data())
		if m.Len() < fusekernel.ReadInSize(protocol) {
			goto corrupt
		}

		to := &ReadDirOp{
			Inode:  InodeID(m.Header().Node),
			Handle: HandleID(in.Fh),
			Offset: int64(in.Offset),
			Size:   int(in.Size),
		}
		io = to
		co = &to.commonOp

	case *fuseshim.ReleaseRequest:
		if typed.Dir {
			to := &ReleaseDirHandleOp{
				bfReq:  typed,
				Handle: HandleID(typed.Handle),
			}
			io = to
			co = &to.commonOp
		} else {
			to := &ReleaseFileHandleOp{
				bfReq:  typed,
				Handle: HandleID(typed.Handle),
			}
			io = to
			co = &to.commonOp
		}

	case *fuseshim.WriteRequest:
		to := &WriteFileOp{
			bfReq:  typed,
			Inode:  InodeID(typed.Header.Node),
			Handle: HandleID(typed.Handle),
			Data:   typed.Data,
			Offset: typed.Offset,
		}
		io = to
		co = &to.commonOp

	case *fuseshim.FsyncRequest:
		// We don't currently support this for directories.
		if typed.Dir {
			to := &unknownOp{}
			io = to
			co = &to.commonOp
		} else {
			to := &SyncFileOp{
				bfReq:  typed,
				Inode:  InodeID(typed.Header.Node),
				Handle: HandleID(typed.Handle),
			}
			io = to
			co = &to.commonOp
		}

	case *fuseshim.FlushRequest:
		to := &FlushFileOp{
			bfReq:  typed,
			Inode:  InodeID(typed.Header.Node),
			Handle: HandleID(typed.Handle),
		}
		io = to
		co = &to.commonOp

	case *fuseshim.ReadlinkRequest:
		to := &ReadSymlinkOp{
			bfReq: typed,
			Inode: InodeID(typed.Header.Node),
		}
		io = to
		co = &to.commonOp

	default:
		to := &unknownOp{}
		io = to
		co = &to.commonOp
	}

	co.init(
		opCtx,
		io,
		r,
		debugLogForOp,
		errorLogger,
		finished)

	o = io
	return
}

func convertAttributes(
	inode InodeID,
	attr InodeAttributes,
	expiration time.Time) fuseshim.Attr {
	return fuseshim.Attr{
		Inode:  uint64(inode),
		Size:   attr.Size,
		Mode:   attr.Mode,
		Nlink:  uint32(attr.Nlink),
		Atime:  attr.Atime,
		Mtime:  attr.Mtime,
		Ctime:  attr.Ctime,
		Crtime: attr.Crtime,
		Uid:    attr.Uid,
		Gid:    attr.Gid,
		Valid:  convertExpirationTime(expiration),
	}
}

// Convert an absolute cache expiration time to a relative time from now for
// consumption by fuse.
func convertExpirationTime(t time.Time) (d time.Duration) {
	// Fuse represents durations as unsigned 64-bit counts of seconds and 32-bit
	// counts of nanoseconds (cf. http://goo.gl/EJupJV). The bazil.org/fuse
	// package converts time.Duration values to this form in a straightforward
	// way (cf. http://goo.gl/FJhV8j).
	//
	// So negative durations are right out. There is no need to cap the positive
	// magnitude, because 2^64 seconds is well longer than the 2^63 ns range of
	// time.Duration.
	d = t.Sub(time.Now())
	if d < 0 {
		d = 0
	}

	return
}

func convertChildInodeEntry(
	in *ChildInodeEntry,
	out *fuseshim.LookupResponse) {
	out.Node = fuseshim.NodeID(in.Child)
	out.Generation = uint64(in.Generation)
	out.Attr = convertAttributes(in.Child, in.Attributes, in.AttributesExpiration)
	out.EntryValid = convertExpirationTime(in.EntryExpiration)
}
<|endoftext|>