<commit_before>package openstack

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/helper/pathorcontents"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
)

var (
	OS_DB_ENVIRONMENT         = os.Getenv("OS_DB_ENVIRONMENT")
	OS_DB_DATASTORE_VERSION   = os.Getenv("OS_DB_DATASTORE_VERSION")
	OS_DB_DATASTORE_TYPE      = os.Getenv("OS_DB_DATASTORE_TYPE")
	OS_DEPRECATED_ENVIRONMENT = os.Getenv("OS_DEPRECATED_ENVIRONMENT")
	OS_DNS_ENVIRONMENT        = os.Getenv("OS_DNS_ENVIRONMENT")
	OS_EXTGW_ID               = os.Getenv("OS_EXTGW_ID")
	OS_FLAVOR_ID              = os.Getenv("OS_FLAVOR_ID")
	OS_FLAVOR_NAME            = os.Getenv("OS_FLAVOR_NAME")
	OS_IMAGE_ID               = os.Getenv("OS_IMAGE_ID")
	OS_IMAGE_NAME             = os.Getenv("OS_IMAGE_NAME")
	OS_NETWORK_ID             = os.Getenv("OS_NETWORK_ID")
	OS_POOL_NAME              = os.Getenv("OS_POOL_NAME")
	OS_REGION_NAME            = os.Getenv("OS_REGION_NAME")
	OS_SWIFT_ENVIRONMENT      = os.Getenv("OS_SWIFT_ENVIRONMENT")
)

var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider

func init() {
	testAccProvider = Provider().(*schema.Provider)
	testAccProviders = map[string]terraform.ResourceProvider{
		"openstack": testAccProvider,
	}
}

func testAccPreCheckRequiredEnvVars(t *testing.T) {
	v := os.Getenv("OS_AUTH_URL")
	if v == "" {
		t.Fatal("OS_AUTH_URL must be set for acceptance tests")
	}

	if OS_IMAGE_ID == "" && OS_IMAGE_NAME == "" {
		t.Fatal("OS_IMAGE_ID or OS_IMAGE_NAME must be set for acceptance tests")
	}

	if OS_POOL_NAME == "" {
		t.Fatal("OS_POOL_NAME must be set for acceptance tests")
	}

	if OS_FLAVOR_ID == "" && OS_FLAVOR_NAME == "" {
		t.Fatal("OS_FLAVOR_ID or OS_FLAVOR_NAME must be set for acceptance tests")
	}

	if OS_NETWORK_ID == "" {
		t.Fatal("OS_NETWORK_ID must be set for acceptance tests")
	}

	if OS_EXTGW_ID == "" {
		t.Fatal("OS_EXTGW_ID must be set for acceptance tests")
	}
}

func testAccPreCheck(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	// Do not run the test if this is a deprecated testing environment.
	if OS_DEPRECATED_ENVIRONMENT != "" {
		t.Skip("This environment only runs deprecated tests")
	}

	// Do not run the test if this is a standalone DNS environment.
	if OS_DNS_ENVIRONMENT != "" {
		t.Skip("This environment only runs DNS tests")
	}
}

func testAccPreCheckDeprecated(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	if OS_DEPRECATED_ENVIRONMENT == "" {
		t.Skip("This environment does not support deprecated tests")
	}
}

func testAccPreCheckDNS(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	if OS_DNS_ENVIRONMENT == "" {
		t.Skip("This environment does not support DNS tests")
	}
}

func testAccPreCheckSwift(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	if OS_SWIFT_ENVIRONMENT == "" {
		t.Skip("This environment does not support Swift tests")
	}
}

func testAccPreCheckDatabase(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	if OS_DB_ENVIRONMENT == "" {
		t.Skip("This environment does not support Database tests")
	}
}

func testAccPreCheckAdminOnly(t *testing.T) {
	v := os.Getenv("OS_USERNAME")
	if v != "admin" {
		t.Skip("Skipping test because it requires the admin user")
	}
}

func TestProvider(t *testing.T) {
	if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
		t.Fatalf("err: %s", err)
	}
}

func TestProvider_impl(t *testing.T) {
	var _ terraform.ResourceProvider = Provider()
}

// Steps for configuring OpenStack with SSL validation are here:
// https://github.com/hashicorp/terraform/pull/6279#issuecomment-219020144
func TestAccProvider_caCertFile(t *testing.T) {
	if os.Getenv("TF_ACC") == "" || os.Getenv("OS_SSL_TESTS") == "" {
		t.Skip("TF_ACC or OS_SSL_TESTS not set, skipping OpenStack SSL test.")
	}
	if os.Getenv("OS_CACERT") == "" {
		t.Skip("OS_CACERT is not set; skipping OpenStack CA test.")
	}

	p := Provider()

	caFile, err := envVarFile("OS_CACERT")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(caFile)

	raw := map[string]interface{}{
		"cacert_file": caFile,
	}
	rawConfig, err := config.NewRawConfig(raw)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = p.Configure(terraform.NewResourceConfig(rawConfig))
	if err != nil {
		t.Fatalf("Unexpected err when specifying OpenStack CA by file: %s", err)
	}
}

func TestAccProvider_caCertString(t *testing.T) {
	if os.Getenv("TF_ACC") == "" || os.Getenv("OS_SSL_TESTS") == "" {
		t.Skip("TF_ACC or OS_SSL_TESTS not set, skipping OpenStack SSL test.")
	}
	if os.Getenv("OS_CACERT") == "" {
		t.Skip("OS_CACERT is not set; skipping OpenStack CA test.")
	}

	p := Provider()

	caContents, err := envVarContents("OS_CACERT")
	if err != nil {
		t.Fatal(err)
	}
	raw := map[string]interface{}{
		"cacert_file": caContents,
	}
	rawConfig, err := config.NewRawConfig(raw)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = p.Configure(terraform.NewResourceConfig(rawConfig))
	if err != nil {
		t.Fatalf("Unexpected err when specifying OpenStack CA by string: %s", err)
	}
}

func TestAccProvider_clientCertFile(t *testing.T) {
	if os.Getenv("TF_ACC") == "" || os.Getenv("OS_SSL_TESTS") == "" {
		t.Skip("TF_ACC or OS_SSL_TESTS not set, skipping OpenStack SSL test.")
	}
	if os.Getenv("OS_CERT") == "" || os.Getenv("OS_KEY") == "" {
		t.Skip("OS_CERT or OS_KEY is not set; skipping OpenStack client SSL auth test.")
	}

	p := Provider()

	certFile, err := envVarFile("OS_CERT")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(certFile)
	keyFile, err := envVarFile("OS_KEY")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(keyFile)

	raw := map[string]interface{}{
		"cert": certFile,
		"key":  keyFile,
	}
	rawConfig, err := config.NewRawConfig(raw)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = p.Configure(terraform.NewResourceConfig(rawConfig))
	if err != nil {
		t.Fatalf("Unexpected err when specifying OpenStack Client keypair by file: %s", err)
	}
}

func TestAccProvider_clientCertString(t *testing.T) {
	if os.Getenv("TF_ACC") == "" || os.Getenv("OS_SSL_TESTS") == "" {
		t.Skip("TF_ACC or OS_SSL_TESTS not set, skipping OpenStack SSL test.")
	}
	if os.Getenv("OS_CERT") == "" || os.Getenv("OS_KEY") == "" {
		t.Skip("OS_CERT or OS_KEY is not set; skipping OpenStack client SSL auth test.")
	}

	p := Provider()

	certContents, err := envVarContents("OS_CERT")
	if err != nil {
		t.Fatal(err)
	}
	keyContents, err := envVarContents("OS_KEY")
	if err != nil {
		t.Fatal(err)
	}

	raw := map[string]interface{}{
		"cert": certContents,
		"key":  keyContents,
	}
	rawConfig, err := config.NewRawConfig(raw)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = p.Configure(terraform.NewResourceConfig(rawConfig))
	if err != nil {
		t.Fatalf("Unexpected err when specifying OpenStack Client keypair by contents: %s", err)
	}
}

func envVarContents(varName string) (string, error) {
	contents, _, err := pathorcontents.Read(os.Getenv(varName))
	if err != nil {
		return "", fmt.Errorf("Error reading %s: %s", varName, err)
	}
	return contents, nil
}

func envVarFile(varName string) (string, error) {
	contents, err := envVarContents(varName)
	if err != nil {
		return "", err
	}

	tmpFile, err := ioutil.TempFile("", varName)
	if err != nil {
		return "", fmt.Errorf("Error creating temp file: %s", err)
	}
	if _, err := tmpFile.Write([]byte(contents)); err != nil {
		_ = os.Remove(tmpFile.Name())
		return "", fmt.Errorf("Error writing temp file: %s", err)
	}
	if err := tmpFile.Close(); err != nil {
		_ = os.Remove(tmpFile.Name())
		return "", fmt.Errorf("Error closing temp file: %s", err)
	}
	return tmpFile.Name(), nil
}
<commit_msg>Acc Tests: Enable DNS test to run with other tests<commit_after>package openstack

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/helper/pathorcontents"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
)

var (
	OS_DB_ENVIRONMENT         = os.Getenv("OS_DB_ENVIRONMENT")
	OS_DB_DATASTORE_VERSION   = os.Getenv("OS_DB_DATASTORE_VERSION")
	OS_DB_DATASTORE_TYPE      = os.Getenv("OS_DB_DATASTORE_TYPE")
	OS_DEPRECATED_ENVIRONMENT = os.Getenv("OS_DEPRECATED_ENVIRONMENT")
	OS_DNS_ENVIRONMENT        = os.Getenv("OS_DNS_ENVIRONMENT")
	OS_EXTGW_ID               = os.Getenv("OS_EXTGW_ID")
	OS_FLAVOR_ID              = os.Getenv("OS_FLAVOR_ID")
	OS_FLAVOR_NAME            = os.Getenv("OS_FLAVOR_NAME")
	OS_IMAGE_ID               = os.Getenv("OS_IMAGE_ID")
	OS_IMAGE_NAME             = os.Getenv("OS_IMAGE_NAME")
	OS_NETWORK_ID             = os.Getenv("OS_NETWORK_ID")
	OS_POOL_NAME              = os.Getenv("OS_POOL_NAME")
	OS_REGION_NAME            = os.Getenv("OS_REGION_NAME")
	OS_SWIFT_ENVIRONMENT      = os.Getenv("OS_SWIFT_ENVIRONMENT")
)

var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider

func init() {
	testAccProvider = Provider().(*schema.Provider)
	testAccProviders = map[string]terraform.ResourceProvider{
		"openstack": testAccProvider,
	}
}

func testAccPreCheckRequiredEnvVars(t *testing.T) {
	v := os.Getenv("OS_AUTH_URL")
	if v == "" {
		t.Fatal("OS_AUTH_URL must be set for acceptance tests")
	}

	if OS_IMAGE_ID == "" && OS_IMAGE_NAME == "" {
		t.Fatal("OS_IMAGE_ID or OS_IMAGE_NAME must be set for acceptance tests")
	}

	if OS_POOL_NAME == "" {
		t.Fatal("OS_POOL_NAME must be set for acceptance tests")
	}

	if OS_FLAVOR_ID == "" && OS_FLAVOR_NAME == "" {
		t.Fatal("OS_FLAVOR_ID or OS_FLAVOR_NAME must be set for acceptance tests")
	}

	if OS_NETWORK_ID == "" {
		t.Fatal("OS_NETWORK_ID must be set for acceptance tests")
	}

	if OS_EXTGW_ID == "" {
		t.Fatal("OS_EXTGW_ID must be set for acceptance tests")
	}
}

func testAccPreCheck(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	// Do not run the test if this is a deprecated testing environment.
	if OS_DEPRECATED_ENVIRONMENT != "" {
		t.Skip("This environment only runs deprecated tests")
	}
}

func testAccPreCheckDeprecated(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	if OS_DEPRECATED_ENVIRONMENT == "" {
		t.Skip("This environment does not support deprecated tests")
	}
}

func testAccPreCheckDNS(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	if OS_DNS_ENVIRONMENT == "" {
		t.Skip("This environment does not support DNS tests")
	}
}

func testAccPreCheckSwift(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	if OS_SWIFT_ENVIRONMENT == "" {
		t.Skip("This environment does not support Swift tests")
	}
}

func testAccPreCheckDatabase(t *testing.T) {
	testAccPreCheckRequiredEnvVars(t)

	if OS_DB_ENVIRONMENT == "" {
		t.Skip("This environment does not support Database tests")
	}
}

func testAccPreCheckAdminOnly(t *testing.T) {
	v := os.Getenv("OS_USERNAME")
	if v != "admin" {
		t.Skip("Skipping test because it requires the admin user")
	}
}

func TestProvider(t *testing.T) {
	if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
		t.Fatalf("err: %s", err)
	}
}

func TestProvider_impl(t *testing.T) {
	var _ terraform.ResourceProvider = Provider()
}

// Steps for configuring OpenStack with SSL validation are here:
// https://github.com/hashicorp/terraform/pull/6279#issuecomment-219020144
func TestAccProvider_caCertFile(t *testing.T) {
	if os.Getenv("TF_ACC") == "" || os.Getenv("OS_SSL_TESTS") == "" {
		t.Skip("TF_ACC or OS_SSL_TESTS not set, skipping OpenStack SSL test.")
	}
	if os.Getenv("OS_CACERT") == "" {
		t.Skip("OS_CACERT is not set; skipping OpenStack CA test.")
	}

	p := Provider()

	caFile, err := envVarFile("OS_CACERT")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(caFile)

	raw := map[string]interface{}{
		"cacert_file": caFile,
	}
	rawConfig, err := config.NewRawConfig(raw)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = p.Configure(terraform.NewResourceConfig(rawConfig))
	if err != nil {
		t.Fatalf("Unexpected err when specifying OpenStack CA by file: %s", err)
	}
}

func TestAccProvider_caCertString(t *testing.T) {
	if os.Getenv("TF_ACC") == "" || os.Getenv("OS_SSL_TESTS") == "" {
		t.Skip("TF_ACC or OS_SSL_TESTS not set, skipping OpenStack SSL test.")
	}
	if os.Getenv("OS_CACERT") == "" {
		t.Skip("OS_CACERT is not set; skipping OpenStack CA test.")
	}

	p := Provider()

	caContents, err := envVarContents("OS_CACERT")
	if err != nil {
		t.Fatal(err)
	}
	raw := map[string]interface{}{
		"cacert_file": caContents,
	}
	rawConfig, err := config.NewRawConfig(raw)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = p.Configure(terraform.NewResourceConfig(rawConfig))
	if err != nil {
		t.Fatalf("Unexpected err when specifying OpenStack CA by string: %s", err)
	}
}

func TestAccProvider_clientCertFile(t *testing.T) {
	if os.Getenv("TF_ACC") == "" || os.Getenv("OS_SSL_TESTS") == "" {
		t.Skip("TF_ACC or OS_SSL_TESTS not set, skipping OpenStack SSL test.")
	}
	if os.Getenv("OS_CERT") == "" || os.Getenv("OS_KEY") == "" {
		t.Skip("OS_CERT or OS_KEY is not set; skipping OpenStack client SSL auth test.")
	}

	p := Provider()

	certFile, err := envVarFile("OS_CERT")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(certFile)
	keyFile, err := envVarFile("OS_KEY")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(keyFile)

	raw := map[string]interface{}{
		"cert": certFile,
		"key":  keyFile,
	}
	rawConfig, err := config.NewRawConfig(raw)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = p.Configure(terraform.NewResourceConfig(rawConfig))
	if err != nil {
		t.Fatalf("Unexpected err when specifying OpenStack Client keypair by file: %s", err)
	}
}

func TestAccProvider_clientCertString(t *testing.T) {
	if os.Getenv("TF_ACC") == "" || os.Getenv("OS_SSL_TESTS") == "" {
		t.Skip("TF_ACC or OS_SSL_TESTS not set, skipping OpenStack SSL test.")
	}
	if os.Getenv("OS_CERT") == "" || os.Getenv("OS_KEY") == "" {
		t.Skip("OS_CERT or OS_KEY is not set; skipping OpenStack client SSL auth test.")
	}

	p := Provider()

	certContents, err := envVarContents("OS_CERT")
	if err != nil {
		t.Fatal(err)
	}
	keyContents, err := envVarContents("OS_KEY")
	if err != nil {
		t.Fatal(err)
	}

	raw := map[string]interface{}{
		"cert": certContents,
		"key":  keyContents,
	}
	rawConfig, err := config.NewRawConfig(raw)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = p.Configure(terraform.NewResourceConfig(rawConfig))
	if err != nil {
		t.Fatalf("Unexpected err when specifying OpenStack Client keypair by contents: %s", err)
	}
}

func envVarContents(varName string) (string, error) {
	contents, _, err := pathorcontents.Read(os.Getenv(varName))
	if err != nil {
		return "", fmt.Errorf("Error reading %s: %s", varName, err)
	}
	return contents, nil
}

func envVarFile(varName string) (string, error) {
	contents, err := envVarContents(varName)
	if err != nil {
		return "", err
	}

	tmpFile, err := ioutil.TempFile("", varName)
	if err != nil {
		return "", fmt.Errorf("Error creating temp file: %s", err)
	}
	if _, err := tmpFile.Write([]byte(contents)); err != nil {
		_ = os.Remove(tmpFile.Name())
		return "", fmt.Errorf("Error writing temp file: %s", err)
	}
	if err := tmpFile.Close(); err != nil {
		_ = os.Remove(tmpFile.Name())
		return "", fmt.Errorf("Error closing temp file: %s", err)
	}
	return tmpFile.Name(), nil
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"github.com/smancke/guble/client"
	"github.com/smancke/guble/server/service"
	"github.com/stretchr/testify/assert"
	"strconv"
	"sync"
	"testing"
	"time"
)

const (
	testTopic = "/topic"
)

type sender func(c client.Client) error

func sendMessageSample(c client.Client) error {
	return c.Send(testTopic, "test-body", "{id:id}")
}

type benchParams struct {
	*testing.B
	workers       int           // number of fcm workers
	subscriptions int           // number of subscriptions listening on the topic
	timeout       time.Duration // fcm timeout response
	clients       int           // number of clients
	sender        sender        // the function that will send the messages
	sent          int           // sent messages
	received      int           // received messages

	service  *service.Service
	receiveC chan bool
	doneC    chan struct{}

	wg    sync.WaitGroup
	start time.Time
	end   time.Time
}

func (params *benchParams) createClients() (clients []client.Client) {
	wsURL := "ws://" + params.service.WebServer().GetAddr() + "/stream/user/"
	for clientID := 0; clientID < params.clients; clientID++ {
		location := wsURL + strconv.Itoa(clientID)
		c, err := client.Open(location, "http://localhost/", 1000, true)
		if err != nil {
			assert.FailNow(params, "guble client could not connect to server")
		}
		clients = append(clients, c)
	}
	return
}

func (params *benchParams) receiveLoop() {
	for i := 0; i <= params.workers; i++ {
		go func() {
			for {
				select {
				case <-params.receiveC:
					params.received++
					logger.WithField("received", params.received).Debug("Received a call")
					params.wg.Done()
				case <-params.doneC:
					return
				}
			}
		}()
	}
}

func (params *benchParams) String() string {
	return fmt.Sprintf(`
		Throughput %.2f messages/second using:
			%d workers
			%d subscriptions
			%s response timeout
			%d clients
	`, params.messagesPerSecond(), params.workers, params.subscriptions, params.timeout, params.clients)
}

func (params *benchParams) ResetTimer() {
	params.start = time.Now()
	params.B.ResetTimer()
}

func (params *benchParams) StopTimer() {
	params.end = time.Now()
	params.B.StopTimer()
}

func (params *benchParams) duration() time.Duration {
	return params.end.Sub(params.start)
}

func (params *benchParams) messagesPerSecond() float64 {
	return float64(params.received) / params.duration().Seconds()
}
<commit_msg> minor - updating doc<commit_after>package server

import (
	"fmt"
	"github.com/smancke/guble/client"
	"github.com/smancke/guble/server/service"
	"github.com/stretchr/testify/assert"
	"strconv"
	"sync"
	"testing"
	"time"
)

const (
	testTopic = "/topic"
)

type sender func(c client.Client) error

func sendMessageSample(c client.Client) error {
	return c.Send(testTopic, "test-body", "{id:id}")
}

type benchParams struct {
	*testing.B
	workers       int           // number of workers
	subscriptions int           // number of subscriptions listening on the topic
	timeout       time.Duration // timeout response
	clients       int           // number of clients
	sender        sender        // the function that will send the messages
	sent          int           // sent messages
	received      int           // received messages

	service  *service.Service
	receiveC chan bool
	doneC    chan struct{}

	wg    sync.WaitGroup
	start time.Time
	end   time.Time
}

func (params *benchParams) createClients() (clients []client.Client) {
	wsURL := "ws://" + params.service.WebServer().GetAddr() + "/stream/user/"
	for clientID := 0; clientID < params.clients; clientID++ {
		location := wsURL + strconv.Itoa(clientID)
		c, err := client.Open(location, "http://localhost/", 1000, true)
		if err != nil {
			assert.FailNow(params, "guble client could not connect to server")
		}
		clients = append(clients, c)
	}
	return
}

func (params *benchParams) receiveLoop() {
	for i := 0; i <= params.workers; i++ {
		go func() {
			for {
				select {
				case <-params.receiveC:
					params.received++
					logger.WithField("received", params.received).Debug("Received a call")
					params.wg.Done()
				case <-params.doneC:
					return
				}
			}
		}()
	}
}

func (params *benchParams) String() string {
	return fmt.Sprintf(`
		Throughput %.2f messages/second using:
			%d workers
			%d subscriptions
			%s response timeout
			%d clients
	`, params.messagesPerSecond(), params.workers, params.subscriptions, params.timeout, params.clients)
}

func (params *benchParams) ResetTimer() {
	params.start = time.Now()
	params.B.ResetTimer()
}

func (params *benchParams) StopTimer() {
	params.end = time.Now()
	params.B.StopTimer()
}

func (params *benchParams) duration() time.Duration {
	return params.end.Sub(params.start)
}

func (params *benchParams) messagesPerSecond() float64 {
	return float64(params.received) / params.duration().Seconds()
}
<|endoftext|>


<commit_before>package plugins

import (
	seabird ".."
	"../util"

	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/thoj/go-ircevent"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

type LastAddress struct {
	Nick     string
	Location util.Location
}

// Basic structures from https://github.com/mlbright/forecast/blob/master/v2/forecast.go
// TODO: cleanup
type DataPoint struct {
	Time                   int64
	Summary                string
	Icon                   string
	SunriseTime            float64
	SunsetTime             float64
	PrecipIntensity        float64
	PrecipIntensityMax     float64
	PrecipIntensityMaxTime float64
	PrecipProbability      float64
	PrecipType             string
	PrecipAccumulation     float64
	Temperature            float64
	TemperatureMin         float64
	TemperatureMinTime     float64
	TemperatureMax         float64
	TemperatureMaxTime     float64
	DewPoint               float64
	WindSpeed              float64
	WindBearing            float64
	CloudCover             float64
	Humidity               float64
	Pressure               float64
	Visibility             float64
	Ozone                  float64
}

type DataBlock struct {
	Summary string
	Icon    string
	Data    []DataPoint
}

type alert struct {
	Title   string
	Expires float64
	URI     string
}

type Flags struct {
	DarkSkyUnavailable string
	DarkSkyStations    []string
	DataPointStations  []string
	ISDStations        []string
	LAMPStations       []string
	METARStations      []string
	METNOLicense       string
	Sources            []string
	Units              string
}

type ForecastResponse struct {
	Latitude  float64
	Longitude float64
	Timezone  string
	Offset    float64
	Currently DataPoint
	Minutely  DataBlock
	Hourly    DataBlock
	Daily     DataBlock
	Alerts    []alert
	Flags     Flags
	APICalls  int
}

func (p *ForecastPlugin) forecastQuery(loc util.Coordinates) (*ForecastResponse, error) {

	link := fmt.Sprintf("https://api.forecast.io/forecast/%s/%.4f,%.4f",
		p.Key,
		loc.Lat,
		loc.Lon)

	r, err := http.Get(link)
	if err != nil {
		return nil, err
	}

	f := ForecastResponse{}
	dec := json.NewDecoder(r.Body)
	defer r.Body.Close()
	dec.Decode(&f)

	return &f, nil
}

type ForecastPlugin struct {
	Bot *seabird.Bot
	Key string
	C   *mgo.Collection
}

func init() {
	seabird.RegisterPlugin("forecast", NewForecastPlugin)
}

func NewForecastPlugin(b *seabird.Bot, c json.RawMessage) {
	p := &ForecastPlugin{Bot: b, C: b.DB.C("weather")}

	err := json.Unmarshal(c, &p.Key)
	if err != nil {
		fmt.Println(err)
	}

	b.RegisterFunction("forecast", p.ForecastDaily)
	b.RegisterFunction("weather", p.ForecastCurrent)
}

func (p *ForecastPlugin) getLocation(e *irc.Event) (*util.Location, error) {
	l := e.Message()

	loc, err := util.FetchLocation(l)
	if err == nil {
		return loc, nil
	} else if l != "" {
		return nil, err
	}

	la := &LastAddress{}
	cerr := p.C.Find(bson.M{"nick": e.Nick}).One(la)
	if cerr != nil {
		// intentionally use the err from other call.
		// not finding the entry in the DB is ok.
		return nil, err
	}

	return &la.Location, nil
}

func (p *ForecastPlugin) saveLocation(e *irc.Event, loc *util.Location) {
	la := LastAddress{e.Nick, *loc}
	p.C.Upsert(bson.M{"nick": e.Nick}, la)
}

func (p *ForecastPlugin) ForecastDaily(e *irc.Event) {
	loc, err := p.getLocation(e)
	if err != nil {
		p.Bot.MentionReply(e, "%s", err.Error())
		return
	}

	fc, err := p.forecastQuery(loc.Coords)
	if err != nil {
		p.Bot.MentionReply(e, "%s", err.Error())
		return
	}

	p.Bot.MentionReply(e, "3 day forecast for %s.", loc.Address)
	for _, block := range fc.Daily.Data[1:4] {
		day := time.Unix(block.Time, 0).Weekday()

		p.Bot.MentionReply(e,
			"%s: High %.2f, Low %.2f, %s %.f%% Humidity.",
			day,
			block.TemperatureMax,
			block.TemperatureMin,
			block.Summary,
			block.Humidity*100)
	}

	p.saveLocation(e, loc)
}

func (p *ForecastPlugin) ForecastCurrent(e *irc.Event) {
	loc, err := p.getLocation(e)
	if err != nil {
		p.Bot.MentionReply(e, "%s", err.Error())
		return
	}

	fc, err := p.forecastQuery(loc.Coords)
	if err != nil {
		p.Bot.MentionReply(e, "%s", err.Error())
		return
	}

	today := fc.Daily.Data[0]
	p.Bot.MentionReply(e,
		"%s. Currently %.1f. High %.2f, Low %.2f. %s. %.f%% Humidity.",
		loc.Address,
		fc.Currently.Temperature,
		today.TemperatureMax,
		today.TemperatureMin,
		fc.Currently.Summary,
		fc.Currently.Humidity*100)

	p.saveLocation(e, loc)
}
<commit_msg>Update formatting with forecast plugin<commit_after>package plugins

import (
	seabird ".."
	"../util"

	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/thoj/go-ircevent"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

type LastAddress struct {
	Nick     string
	Location util.Location
}

// Basic structures from https://github.com/mlbright/forecast/blob/master/v2/forecast.go
// TODO: cleanup
type DataPoint struct {
	Time                   int64
	Summary                string
	Icon                   string
	SunriseTime            float64
	SunsetTime             float64
	PrecipIntensity        float64
	PrecipIntensityMax     float64
	PrecipIntensityMaxTime float64
	PrecipProbability      float64
	PrecipType             string
	PrecipAccumulation     float64
	Temperature            float64
	TemperatureMin         float64
	TemperatureMinTime     float64
	TemperatureMax         float64
	TemperatureMaxTime     float64
	DewPoint               float64
	WindSpeed              float64
	WindBearing            float64
	CloudCover             float64
	Humidity               float64
	Pressure               float64
	Visibility             float64
	Ozone                  float64
}

type DataBlock struct {
	Summary string
	Icon    string
	Data    []DataPoint
}

type alert struct {
	Title   string
	Expires float64
	URI     string
}

type Flags struct {
	DarkSkyUnavailable string
	DarkSkyStations    []string
	DataPointStations  []string
	ISDStations        []string
	LAMPStations       []string
	METARStations      []string
	METNOLicense       string
	Sources            []string
	Units              string
}

type ForecastResponse struct {
	Latitude  float64
	Longitude float64
	Timezone  string
	Offset    float64
	Currently DataPoint
	Minutely  DataBlock
	Hourly    DataBlock
	Daily     DataBlock
	Alerts    []alert
	Flags     Flags
	APICalls  int
}

func (p *ForecastPlugin) forecastQuery(loc util.Coordinates) (*ForecastResponse, error) {

	link := fmt.Sprintf("https://api.forecast.io/forecast/%s/%.4f,%.4f",
		p.Key,
		loc.Lat,
		loc.Lon)

	r, err := http.Get(link)
	if err != nil {
		return nil, err
	}

	f := ForecastResponse{}
	dec := json.NewDecoder(r.Body)
	defer r.Body.Close()
	dec.Decode(&f)

	return &f, nil
}

type ForecastPlugin struct {
	Bot *seabird.Bot
	Key string
	C   *mgo.Collection
}

func init() {
	seabird.RegisterPlugin("forecast", NewForecastPlugin)
}

func NewForecastPlugin(b *seabird.Bot, c json.RawMessage) {
	p := &ForecastPlugin{Bot: b, C: b.DB.C("weather")}

	err := json.Unmarshal(c, &p.Key)
	if err != nil {
		fmt.Println(err)
	}

	b.RegisterFunction("forecast", p.ForecastDaily)
	b.RegisterFunction("weather", p.ForecastCurrent)
}

func (p *ForecastPlugin) getLocation(e *irc.Event) (*util.Location, error) {
	l := e.Message()

	loc, err := util.FetchLocation(l)
	if err == nil {
		return loc, nil
	} else if l != "" {
		return nil, err
	}

	la := &LastAddress{}
	cerr := p.C.Find(bson.M{"nick": e.Nick}).One(la)
	if cerr != nil {
		// intentionally use the err from other call.
		// not finding the entry in the DB is ok.
		return nil, err
	}

	return &la.Location, nil
}

func (p *ForecastPlugin) saveLocation(e *irc.Event, loc *util.Location) {
	la := LastAddress{e.Nick, *loc}
	p.C.Upsert(bson.M{"nick": e.Nick}, la)
}

func (p *ForecastPlugin) ForecastDaily(e *irc.Event) {
	loc, err := p.getLocation(e)
	if err != nil {
		p.Bot.MentionReply(e, "%s", err.Error())
		return
	}

	fc, err := p.forecastQuery(loc.Coords)
	if err != nil {
		p.Bot.MentionReply(e, "%s", err.Error())
		return
	}

	p.Bot.MentionReply(e, "3 day forecast for %s.", loc.Address)
	for _, block := range fc.Daily.Data[1:4] {
		day := time.Unix(block.Time, 0).Weekday()

		p.Bot.MentionReply(e,
			"%s: High %.2f, Low %.2f, Humidity %.f%%. %s.",
			day,
			block.TemperatureMax,
			block.TemperatureMin,
			block.Humidity*100,
			block.Summary)
	}

	p.saveLocation(e, loc)
}

func (p *ForecastPlugin) ForecastCurrent(e *irc.Event) {
	loc, err := p.getLocation(e)
	if err != nil {
		p.Bot.MentionReply(e, "%s", err.Error())
		return
	}

	fc, err := p.forecastQuery(loc.Coords)
	if err != nil {
		p.Bot.MentionReply(e, "%s", err.Error())
		return
	}

	today := fc.Daily.Data[0]
	p.Bot.MentionReply(e,
		"%s. Currently %.1f. High %.2f, Low %.2f, Humidity %.f%%. %s",
		loc.Address,
		fc.Currently.Temperature,
		today.TemperatureMax,
		today.TemperatureMin,
		fc.Currently.Humidity*100,
		fc.Currently.Summary)

	p.saveLocation(e, loc)
}
<|endoftext|>


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

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

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

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

// Package sysinit provides an abstraction over init systems like systemctl
package sysinit

import (
	"bytes"
	"context"
	"fmt"
	"html/template"
	"os/exec"
	"path"
	"time"

	"github.com/pkg/errors"
	"k8s.io/klog/v2"
	"k8s.io/minikube/pkg/minikube/assets"
	"k8s.io/minikube/pkg/minikube/vmpath"
)

var restartWrapper = `#!/bin/bash
# Wrapper script to emulate systemd restart on non-systemd systems
readonly UNIT_PATH=$1

while true; do
  if [[ -f "${UNIT_PATH}" ]]; then
	eval $(egrep "^ExecStart=" "${UNIT_PATH}" | cut -d"=" -f2-)
  fi
  sleep 1
done
`

var initScriptTmpl = template.Must(template.New("initScript").Parse(`#!/bin/bash
# OpenRC init script shim for systemd units
readonly NAME="{{.Name}}"
readonly RESTART_WRAPPER="{{.Wrapper}}"
readonly UNIT_PATH="{{.Unit}}"
readonly PID_PATH="/var/run/${NAME}.pid"

function start() {
    start-stop-daemon --oknodo --pidfile "${PID_PATH}" --background --start --make-pid --exec "${RESTART_WRAPPER}" "${UNIT_PATH}"
}

function stop() {
	if [[ -f "${PID_PATH}" ]]; then
		pkill -P "$(cat ${PID_PATH})"
	fi
	start-stop-daemon --oknodo --pidfile "${PID_PATH}" --stop
}

case "$1" in
    start)
        start
		;;
    stop)
        stop
		;;
    restart)
        stop
        start
		;;
    status)
        start-stop-daemon --pidfile "${PID_PATH}" --status
		;;
	*)
	    echo "Usage: {{.Name}} {start|stop|restart|status}"
		exit 1
		;;
esac
`))

// OpenRC is a service manager for OpenRC-like init systems
type OpenRC struct {
	r Runner
}

// Name returns the name of the init system
func (s *OpenRC) Name() string {
	return "OpenRC"
}

// Active checks if a service is running
func (s *OpenRC) Active(svc string) bool {
	_, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "status"))
	return err == nil
}

// Start starts a service idempotently
func (s *OpenRC) Start(svc string) error {
	if s.Active(svc) {
		return nil
	}
	ctx, cb := context.WithTimeout(context.Background(), 5*time.Second)
	defer cb()

	rr, err := s.r.RunCmd(exec.CommandContext(ctx, "sudo", "service", svc, "start"))
	klog.Infof("start output: %s", rr.Output())
	return err
}

// Disable does nothing
func (s *OpenRC) Disable(svc string) error {
	return nil
}

// DisableNow not implemented for openRC
func (s *OpenRC) DisableNow(svc string) error {
	// supposed to do disable + stop
	// disable does nothing for OpenRC, so just Stop here
	return s.Stop(svc)
}

// Mask does nothing
func (s *OpenRC) Mask(svc string) error {
	return nil
}

// Enable does nothing
func (s *OpenRC) Enable(svc string) error {
	return nil
}

// EnableNow  not implemented for openRC
func (s *OpenRC) EnableNow(svc string) error {
	// supposed to do enable + start
	// enable does nothing for OpenRC, so just Start here
	return s.Start(svc)
}

// Unmask does nothing
func (s *OpenRC) Unmask(svc string) error {
	return nil
}

// Restart restarts a service
func (s *OpenRC) Restart(svc string) error {
	rr, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "restart"))
	klog.Infof("restart output: %s", rr.Output())
	return err
}

// Reload reloads a service
// currently only used by our docker-env that doesn't need openrc implementation
func (s *OpenRC) Reload(svc string) error {
	return fmt.Errorf("reload is not implemented for OpenRC yet ! Please implement if needed")
}

// Stop stops a service
func (s *OpenRC) Stop(svc string) error {
	rr, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "stop"))
	klog.Infof("stop output: %s", rr.Output())
	return err
}

// ForceStop stops a service with prejuidice
func (s *OpenRC) ForceStop(svc string) error {
	return s.Stop(svc)
}

// GenerateInitShim generates any additional init files required for this service
func (s *OpenRC) GenerateInitShim(svc string, binary string, unit string) ([]assets.CopyableFile, error) {
	restartWrapperPath := path.Join(vmpath.GuestPersistentDir, "openrc-restart-wrapper.sh")

	opts := struct {
		Binary  string
		Wrapper string
		Name    string
		Unit    string
	}{
		Name:    svc,
		Binary:  binary,
		Wrapper: restartWrapperPath,
		Unit:    unit,
	}

	var b bytes.Buffer
	if err := initScriptTmpl.Execute(&b, opts); err != nil {
		return nil, errors.Wrap(err, "template execute")
	}

	files := []assets.CopyableFile{
		assets.NewMemoryAssetTarget([]byte(restartWrapper), restartWrapperPath, "0755"),
		assets.NewMemoryAssetTarget(b.Bytes(), path.Join("/etc/init.d/", svc), "0755"),
	}

	return files, nil
}
<commit_msg>fix comments<commit_after>/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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

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

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

// Package sysinit provides an abstraction over init systems like systemctl
package sysinit

import (
	"bytes"
	"context"
	"fmt"
	"html/template"
	"os/exec"
	"path"
	"time"

	"github.com/pkg/errors"
	"k8s.io/klog/v2"
	"k8s.io/minikube/pkg/minikube/assets"
	"k8s.io/minikube/pkg/minikube/vmpath"
)

var restartWrapper = `#!/bin/bash
# Wrapper script to emulate systemd restart on non-systemd systems
readonly UNIT_PATH=$1

while true; do
  if [[ -f "${UNIT_PATH}" ]]; then
	eval $(egrep "^ExecStart=" "${UNIT_PATH}" | cut -d"=" -f2-)
  fi
  sleep 1
done
`

var initScriptTmpl = template.Must(template.New("initScript").Parse(`#!/bin/bash
# OpenRC init script shim for systemd units
readonly NAME="{{.Name}}"
readonly RESTART_WRAPPER="{{.Wrapper}}"
readonly UNIT_PATH="{{.Unit}}"
readonly PID_PATH="/var/run/${NAME}.pid"

function start() {
    start-stop-daemon --oknodo --pidfile "${PID_PATH}" --background --start --make-pid --exec "${RESTART_WRAPPER}" "${UNIT_PATH}"
}

function stop() {
	if [[ -f "${PID_PATH}" ]]; then
		pkill -P "$(cat ${PID_PATH})"
	fi
	start-stop-daemon --oknodo --pidfile "${PID_PATH}" --stop
}

case "$1" in
    start)
        start
		;;
    stop)
        stop
		;;
    restart)
        stop
        start
		;;
    status)
        start-stop-daemon --pidfile "${PID_PATH}" --status
		;;
	*)
	    echo "Usage: {{.Name}} {start|stop|restart|status}"
		exit 1
		;;
esac
`))

// OpenRC is a service manager for OpenRC-like init systems
type OpenRC struct {
	r Runner
}

// Name returns the name of the init system
func (s *OpenRC) Name() string {
	return "OpenRC"
}

// Active checks if a service is running
func (s *OpenRC) Active(svc string) bool {
	_, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "status"))
	return err == nil
}

// Start starts a service idempotently
func (s *OpenRC) Start(svc string) error {
	if s.Active(svc) {
		return nil
	}
	ctx, cb := context.WithTimeout(context.Background(), 5*time.Second)
	defer cb()

	rr, err := s.r.RunCmd(exec.CommandContext(ctx, "sudo", "service", svc, "start"))
	klog.Infof("start output: %s", rr.Output())
	return err
}

// Disable does nothing
func (s *OpenRC) Disable(svc string) error {
	return nil
}

// DisableNow does Disable + Stop
func (s *OpenRC) DisableNow(svc string) error {
	// supposed to do disable + stop
	// disable does nothing for OpenRC, so just Stop here
	return s.Stop(svc)
}

// Mask does nothing
func (s *OpenRC) Mask(svc string) error {
	return nil
}

// Enable does nothing
func (s *OpenRC) Enable(svc string) error {
	return nil
}

// EnableNow does Enable + Start
func (s *OpenRC) EnableNow(svc string) error {
	// supposed to do enable + start
	// enable does nothing for OpenRC, so just Start here
	return s.Start(svc)
}

// Unmask does nothing
func (s *OpenRC) Unmask(svc string) error {
	return nil
}

// Restart restarts a service
func (s *OpenRC) Restart(svc string) error {
	rr, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "restart"))
	klog.Infof("restart output: %s", rr.Output())
	return err
}

// Reload reloads a service
// currently only used by our docker-env that doesn't need openrc implementation
func (s *OpenRC) Reload(svc string) error {
	return fmt.Errorf("reload is not implemented for OpenRC yet ! Please implement if needed")
}

// Stop stops a service
func (s *OpenRC) Stop(svc string) error {
	rr, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "stop"))
	klog.Infof("stop output: %s", rr.Output())
	return err
}

// ForceStop stops a service with prejuidice
func (s *OpenRC) ForceStop(svc string) error {
	return s.Stop(svc)
}

// GenerateInitShim generates any additional init files required for this service
func (s *OpenRC) GenerateInitShim(svc string, binary string, unit string) ([]assets.CopyableFile, error) {
	restartWrapperPath := path.Join(vmpath.GuestPersistentDir, "openrc-restart-wrapper.sh")

	opts := struct {
		Binary  string
		Wrapper string
		Name    string
		Unit    string
	}{
		Name:    svc,
		Binary:  binary,
		Wrapper: restartWrapperPath,
		Unit:    unit,
	}

	var b bytes.Buffer
	if err := initScriptTmpl.Execute(&b, opts); err != nil {
		return nil, errors.Wrap(err, "template execute")
	}

	files := []assets.CopyableFile{
		assets.NewMemoryAssetTarget([]byte(restartWrapper), restartWrapperPath, "0755"),
		assets.NewMemoryAssetTarget(b.Bytes(), path.Join("/etc/init.d/", svc), "0755"),
	}

	return files, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 Google LLC
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
    https://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 main

import (
	"bytes"
	"context"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"os"

	secretmanager "cloud.google.com/go/secretmanager/apiv1"
	"github.com/google/uuid"
	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
)

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		log.Fatal("PORT environment variable not specified")
	}

	projectID := os.Getenv("PROJECT_ID")
	if projectID == "" {
		log.Fatal("PROJECT_ID environment variable not specified")
	}

	cfg := botConfig{
		project: projectID,
	}

	mux := http.NewServeMux()
	// TODO: remove the legacy v0 endpoint once we've confirmed everything
	// is working as expected:
	mux.Handle("/v0", botCronProxy(cfg))
	mux.Handle("/v0/cron", botCronProxy(cfg))
	mux.Handle("/v0/pubsub", botPubSubProxy(cfg))
	mux.Handle("/v0/container", botContainerProxy(cfg))

	addr := ":" + port
	log.Printf("starting to listen on %s", addr)
	var err error
	if cert, key := os.Getenv("TLS_CERT"), os.Getenv("TLS_KEY"); cert != "" && key != "" {
		err = http.ListenAndServeTLS(addr, cert, key, mux)
	} else {
		err = http.ListenAndServe(addr, mux)
	}

	if err != http.ErrServerClosed {
		log.Fatalf("listen error: %+v", err)
	}

	log.Printf("server shutdown successfully")
}

func rewriteBotCronURL(c botConfig) func(*http.Request) {
	return func(req *http.Request) {
		req.Header.Add("x-github-event", "schedule.repository")
		parser := func(bodyBytes []byte) (string, string) {
			var pay reqPayload
			json.Unmarshal(bodyBytes, &pay)
			return pay.Name, pay.Location
		}
		rewriteBotURL(c, parser, req)
	}
}

func rewriteBotPubSubURL(c botConfig) func(*http.Request) {
	return func(req *http.Request) {
		req.Header.Add("x-github-event", "pubsub.message")
		parser := func(bodyBytes []byte) (string, string) {
			var pay PubSubMessage
			json.Unmarshal(bodyBytes, &pay)
			log.Printf("handling pubsub message for subscription: %v\n", pay.Subscription)

			var msg RepoAutomationPubSubMessage
			json.Unmarshal(pay.Message.Data, &msg)
			log.Printf("pubsub message for bot: %v in %v\n", msg.Name, msg.Location)
			return msg.Name, msg.Location
		}
		rewriteBotURL(c, parser, req)
	}
}

func rewriteBotContainerURL(c botConfig) func(*http.Request) {
	return func(req *http.Request) {
		req.Header.Add("x-github-event", "pubsub.message")
		parser := func(bodyBytes []byte) (string, string) {
			var pay PubSubMessage
			if err := json.Unmarshal(bodyBytes, &pay); err != nil {
				log.Printf("error occurred parsing container pubsub message: %v\n", err)
			}
			log.Printf("handling container pubsub message for subscription: %v\n", pay.Subscription)
			// TODO: pull bot name and location into configuration, once
			// we validate this approach:
			return "owl_bot", "us-central1"
		}
		rewriteBotURL(c, parser, req)
	}
}

func rewriteBotURL(c botConfig, parser func([]byte) (string, string), req *http.Request) {

	var bodyBytes []byte
	if req.Body != nil {
		bodyBytes, _ = ioutil.ReadAll(req.Body)
		req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
	} else {
		log.Println("request had no body")
	}

	botName, botLocation := parser(bodyBytes)

	u := req.URL.String()
	req.URL.Scheme = "https"

	// Explicitly remove UserAgent header
	req.Header.Del("user-agent")

	newHost := fmt.Sprintf("%v-%v.cloudfunctions.net", botLocation, c.project)

	req.Host = newHost
	req.URL.Host = newHost
	req.URL.Path = fmt.Sprintf("/%v", botName)

	key, err := getBotSecret(req.Context(), c, botName)
	if err != nil {
		log.Printf("error getting bot secret: %v", err)
	}

	// Make a hmac sig
	signer := hmac.New(sha1.New, key)
	signer.Write(bodyBytes)

	req.Header.Add("x-hub-signature", base64.StdEncoding.EncodeToString(signer.Sum(nil)))
	req.Header.Add("x-github-delivery", uuid.New().String())

	log.Printf("rewrote url: %s into %s", u, req.URL)
}

// botCronProxy returns a reverse proxy to the specified bot.
func botCronProxy(cfg botConfig) http.HandlerFunc {
	return (&httputil.ReverseProxy{
		Director: rewriteBotCronURL(cfg),
	}).ServeHTTP
}

func botPubSubProxy(cfg botConfig) http.HandlerFunc {
	return (&httputil.ReverseProxy{
		Director: rewriteBotPubSubURL(cfg),
	}).ServeHTTP
}

func botContainerProxy(cfg botConfig) http.HandlerFunc {
	return (&httputil.ReverseProxy{
		Director: rewriteBotContainerURL(cfg),
	}).ServeHTTP
}

type reqPayload struct {
	Name     string
	Type     string
	Location string
}

type botConfig struct {
	project string
}

func getBotSecret(ctx context.Context, b botConfig, botName string) ([]byte, error) {
	name := fmt.Sprintf("projects/%v/secrets/%v/versions/latest", b.project, botName)

	client, err := secretmanager.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to create secretmanager client: %v", err)
	}
	defer client.Close()

	// Build the request.
	req := &secretmanagerpb.AccessSecretVersionRequest{
		Name: name,
	}

	// Call the API.
	result, err := client.AccessSecretVersion(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to access secret version: %v", err)
	}

	return result.Payload.Data, nil
}

// RepoAutomationPubSubMessage represents
// THe data recieved from a PubSubMessage
type RepoAutomationPubSubMessage struct {
	Name     string `json:"Name"`     // Name of Bot
	Location string `json:"Location"` // Region where bot lives
}

// PubSubMessage is the payload of a Pub/Sub event.
type PubSubMessage struct {
	Message struct {
		Data []byte `json:"data,omitempty"`
		ID   string `json:"id"`
	} `json:"message"`
	Subscription string `json:"subscription"`
}
<commit_msg>fix: fix serverless proxy signing (#2101)<commit_after>/*
Copyright 2019 Google LLC
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
    https://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 main

import (
	"bytes"
	"context"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"os"

	secretmanager "cloud.google.com/go/secretmanager/apiv1"
	"github.com/google/uuid"
	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
)

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		log.Fatal("PORT environment variable not specified")
	}

	projectID := os.Getenv("PROJECT_ID")
	if projectID == "" {
		log.Fatal("PROJECT_ID environment variable not specified")
	}

	cfg := botConfig{
		project: projectID,
	}

	mux := http.NewServeMux()
	// TODO: remove the legacy v0 endpoint once we've confirmed everything
	// is working as expected:
	mux.Handle("/v0", botCronProxy(cfg))
	mux.Handle("/v0/cron", botCronProxy(cfg))
	mux.Handle("/v0/pubsub", botPubSubProxy(cfg))
	mux.Handle("/v0/container", botContainerProxy(cfg))

	addr := ":" + port
	log.Printf("starting to listen on %s", addr)
	var err error
	if cert, key := os.Getenv("TLS_CERT"), os.Getenv("TLS_KEY"); cert != "" && key != "" {
		err = http.ListenAndServeTLS(addr, cert, key, mux)
	} else {
		err = http.ListenAndServe(addr, mux)
	}

	if err != http.ErrServerClosed {
		log.Fatalf("listen error: %+v", err)
	}

	log.Printf("server shutdown successfully")
}

func rewriteBotCronURL(c botConfig) func(*http.Request) {
	return func(req *http.Request) {
		req.Header.Add("x-github-event", "schedule.repository")
		parser := func(bodyBytes []byte) (string, string) {
			var pay reqPayload
			json.Unmarshal(bodyBytes, &pay)
			return pay.Name, pay.Location
		}
		rewriteBotURL(c, parser, req)
	}
}

func rewriteBotPubSubURL(c botConfig) func(*http.Request) {
	return func(req *http.Request) {
		req.Header.Add("x-github-event", "pubsub.message")
		parser := func(bodyBytes []byte) (string, string) {
			var pay PubSubMessage
			json.Unmarshal(bodyBytes, &pay)
			log.Printf("handling pubsub message for subscription: %v\n", pay.Subscription)

			var msg RepoAutomationPubSubMessage
			json.Unmarshal(pay.Message.Data, &msg)
			log.Printf("pubsub message for bot: %v in %v\n", msg.Name, msg.Location)
			return msg.Name, msg.Location
		}
		rewriteBotURL(c, parser, req)
	}
}

func rewriteBotContainerURL(c botConfig) func(*http.Request) {
	return func(req *http.Request) {
		req.Header.Add("x-github-event", "pubsub.message")
		parser := func(bodyBytes []byte) (string, string) {
			var pay PubSubMessage
			if err := json.Unmarshal(bodyBytes, &pay); err != nil {
				log.Printf("error occurred parsing container pubsub message: %v\n", err)
			}
			log.Printf("handling container pubsub message for subscription: %v\n", pay.Subscription)
			// TODO: pull bot name and location into configuration, once
			// we validate this approach:
			return "owl_bot", "us-central1"
		}
		rewriteBotURL(c, parser, req)
	}
}

func rewriteBotURL(c botConfig, parser func([]byte) (string, string), req *http.Request) {

	var bodyBytes []byte
	if req.Body != nil {
		bodyBytes, _ = ioutil.ReadAll(req.Body)
		req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
	} else {
		log.Println("request had no body")
	}

	botName, botLocation := parser(bodyBytes)

	u := req.URL.String()
	req.URL.Scheme = "https"

	// Explicitly remove UserAgent header
	req.Header.Del("user-agent")

	newHost := fmt.Sprintf("%v-%v.cloudfunctions.net", botLocation, c.project)

	req.Host = newHost
	req.URL.Host = newHost
	req.URL.Path = fmt.Sprintf("/%v", botName)

	key, err := getBotSecret(req.Context(), c, botName)
	if err != nil {
		log.Printf("error getting bot secret: %v", err)
	}

	var secrets SecretConfig
	if err := json.Unmarshal(key, &secrets); err != nil {
		log.Printf("error occurred parsing container secret contents: %v\n", err)
	}

	// Make a hmac sig, convert to hex
	signer := hmac.New(sha1.New, []byte(secrets.Secret))
	signer.Write(bodyBytes)
	signature := hex.EncodeToString(signer.Sum(nil))

	req.Header.Add("x-hub-signature", "sha1="+signature)
	req.Header.Add("x-github-delivery", uuid.New().String())

	log.Printf("rewrote url: %s into %s", u, req.URL)
}

// botCronProxy returns a reverse proxy to the specified bot.
func botCronProxy(cfg botConfig) http.HandlerFunc {
	return (&httputil.ReverseProxy{
		Director: rewriteBotCronURL(cfg),
	}).ServeHTTP
}

func botPubSubProxy(cfg botConfig) http.HandlerFunc {
	return (&httputil.ReverseProxy{
		Director: rewriteBotPubSubURL(cfg),
	}).ServeHTTP
}

func botContainerProxy(cfg botConfig) http.HandlerFunc {
	return (&httputil.ReverseProxy{
		Director: rewriteBotContainerURL(cfg),
	}).ServeHTTP
}

type SecretConfig struct {
	PrivateKey string `json:"privateKey"`
	AppId      int    `json:"appId"`
	Secret     string `json:"secret"`
}

type reqPayload struct {
	Name     string
	Type     string
	Location string
}

type botConfig struct {
	project string
}

func getBotSecret(ctx context.Context, b botConfig, botName string) ([]byte, error) {
	name := fmt.Sprintf("projects/%v/secrets/%v/versions/latest", b.project, botName)

	client, err := secretmanager.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to create secretmanager client: %v", err)
	}
	defer client.Close()

	// Build the request.
	req := &secretmanagerpb.AccessSecretVersionRequest{
		Name: name,
	}

	// Call the API.
	result, err := client.AccessSecretVersion(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to access secret version: %v", err)
	}

	return result.Payload.Data, nil
}

// RepoAutomationPubSubMessage represents
// THe data recieved from a PubSubMessage
type RepoAutomationPubSubMessage struct {
	Name     string `json:"Name"`     // Name of Bot
	Location string `json:"Location"` // Region where bot lives
}

// PubSubMessage is the payload of a Pub/Sub event.
type PubSubMessage struct {
	Message struct {
		Data []byte `json:"data,omitempty"`
		ID   string `json:"id"`
	} `json:"message"`
	Subscription string `json:"subscription"`
}
<|endoftext|>


<commit_before>package optshttp

import (
  "net/http"
  "time"
  "github.com/gorilla/mux"
  "fmt"
  "strconv"
  "reflect"
  "strings"
)

const(
  flagForm = "form"
  flagPath = "path"
  flagInline = "inline"
)

func UnmarshalForm(req *http.Request, v interface{}) error {
  return unmarshalStruct(reflect.ValueOf(v).Elem(), flagForm, func(s string) string {return req.FormValue(s)})
}

func UnmarshalPath(req *http.Request, v interface{}) error {
  vars := mux.Vars(req)
  return unmarshalStruct(reflect.ValueOf(v).Elem(), flagPath, func(s string) string {return vars[s]})
}

type optsError struct{
  optType string
  optKey string
  optVal string
}

func (e *optsError) Error() string {
  return fmt.Sprintf("Invalid %s %s: %s", e.optType, e.optKey, e.optVal)
}

func unmarshalStruct(v reflect.Value, tagKey string, varLookup func(string) string) error {
  vt := v.Type()
  numField := vt.NumField()
  for i := 0; i < numField; i++ {
    field := vt.Field(i)
    if tagStr, ok := field.Tag.Lookup(tagKey); ok {
      if (len(tagStr) == 0) {
        continue
      }
      tagFields := strings.Split(tagStr, ",")
      if len(tagFields) > 1 {
        for _, flag := range tagFields[1:] {
          switch flag {
            case flagInline:
              if err := unmarshalStruct(v.Field(i), tagKey, varLookup); err != nil {
                return err
              }
          }
        }
      }
      if len(tagFields) > 0 && len(tagFields[0]) > 0 {
        if formStr := varLookup(tagFields[0]); len(formStr) > 0 {
          if err := setValue(v.Field(i), tagFields[0], formStr); err != nil {
            return err
          }
        }
      }
    }
  }
  return nil
}

var timeType = reflect.TypeOf(time.Time{})

func setValue(v reflect.Value, formKey string, formStr string) error {
  switch v.Kind() {
    case reflect.String:
      v.SetString(formStr)
    case reflect.Int:
      if val, err := strconv.ParseInt(formStr, 10, 0); err != nil{
        return &optsError{"integer", formKey, formStr}
      } else {
        v.SetInt(val)
      }
    case reflect.Uint:
      if val, err := strconv.ParseUint(formStr, 10, 0); err != nil{
        return &optsError{"unsigned integer", formKey, formStr}
      } else {
        v.SetUint(val)
      }
    case reflect.Struct:
      if v.Type() == timeType {
        t := &time.Time{}
        if err := t.UnmarshalText([]byte(formStr)); err != nil {
          return &optsError{"time in RFC3339 format", formKey, formStr}
        }
        v.Set(reflect.ValueOf(*t))
      }
    case reflect.Ptr:
      if v.IsNil() {
          v.Set(reflect.New(v.Type().Elem()))
      }
      return setValue(v.Elem(), formKey, formStr)
  }
  return nil
}
<commit_msg>For backwards compatibility with go 1.6<commit_after>package optshttp

import (
  "net/http"
  "time"
  "github.com/gorilla/mux"
  "fmt"
  "strconv"
  "reflect"
  "strings"
)

const(
  flagForm = "form"
  flagPath = "path"
  flagInline = "inline"
)

func UnmarshalForm(req *http.Request, v interface{}) error {
  return unmarshalStruct(reflect.ValueOf(v).Elem(), flagForm, func(s string) string {return req.FormValue(s)})
}

func UnmarshalPath(req *http.Request, v interface{}) error {
  vars := mux.Vars(req)
  return unmarshalStruct(reflect.ValueOf(v).Elem(), flagPath, func(s string) string {return vars[s]})
}

type optsError struct{
  optType string
  optKey string
  optVal string
}

func (e *optsError) Error() string {
  return fmt.Sprintf("Invalid %s %s: %s", e.optType, e.optKey, e.optVal)
}

func unmarshalStruct(v reflect.Value, tagKey string, varLookup func(string) string) error {
  vt := v.Type()
  numField := vt.NumField()
  for i := 0; i < numField; i++ {
    field := vt.Field(i)
    if tagStr := field.Tag.Get(tagKey); len(tagStr) != 0 {
      tagFields := strings.Split(tagStr, ",")
      if len(tagFields) > 1 {
        for _, flag := range tagFields[1:] {
          switch flag {
            case flagInline:
              if err := unmarshalStruct(v.Field(i), tagKey, varLookup); err != nil {
                return err
              }
          }
        }
      }
      if len(tagFields) > 0 && len(tagFields[0]) > 0 {
        if formStr := varLookup(tagFields[0]); len(formStr) > 0 {
          if err := setValue(v.Field(i), tagFields[0], formStr); err != nil {
            return err
          }
        }
      }
    }
  }
  return nil
}

var timeType = reflect.TypeOf(time.Time{})

func setValue(v reflect.Value, formKey string, formStr string) error {
  switch v.Kind() {
    case reflect.String:
      v.SetString(formStr)
    case reflect.Int:
      if val, err := strconv.ParseInt(formStr, 10, 0); err != nil{
        return &optsError{"integer", formKey, formStr}
      } else {
        v.SetInt(val)
      }
    case reflect.Uint:
      if val, err := strconv.ParseUint(formStr, 10, 0); err != nil{
        return &optsError{"unsigned integer", formKey, formStr}
      } else {
        v.SetUint(val)
      }
    case reflect.Struct:
      if v.Type() == timeType {
        t := &time.Time{}
        if err := t.UnmarshalText([]byte(formStr)); err != nil {
          return &optsError{"time in RFC3339 format", formKey, formStr}
        }
        v.Set(reflect.ValueOf(*t))
      }
    case reflect.Ptr:
      if v.IsNil() {
          v.Set(reflect.New(v.Type().Elem()))
      }
      return setValue(v.Elem(), formKey, formStr)
  }
  return nil
}
<|endoftext|>


<commit_before>package application

import (
	"fmt"
	"net/http"
	"net/url"

	"github.com/kumoru/kumoru-sdk-go/kumoru"
)

func Create(poolUuid, name, image, providerCredentials string, envVars, rules, ports []string) (*http.Response, string, []error) {

	k := kumoru.New()

	k = k.Post(fmt.Sprintf("%s/v1/applications/", k.EndPoint.Application))

	k = k.Send(genParameters(name, image, providerCredentials, envVars, rules, ports))

	k = k.Send(fmt.Sprintf("pool_uuid=%s&", url.QueryEscape(poolUuid)))

	return k.SignRequest(true).
		End()
}

func List() (*http.Response, string, []error) {
	k := kumoru.New()

	return k.Get(fmt.Sprintf("%s/v1/applications/", k.EndPoint.Application)).
		SignRequest(true).
		End()
}

func Show(applicationUuid string) (*http.Response, string, []error) {
	k := kumoru.New()

	return k.Get(fmt.Sprintf("%s/v1/applications/%s", k.EndPoint.Application, applicationUuid)).
		SignRequest(true).
		End()
}

func Deploy(applicationUuid string) (*http.Response, string, []error) {
	k := kumoru.New()

	return k.Post(fmt.Sprintf("%s/v1/applications/%s/deployments/", k.EndPoint.Application, applicationUuid)).
		SignRequest(true).
		End()
}

func Delete(applicationUuid string) (*http.Response, string, []error) {
	k := kumoru.New()

	resp, body, errs := k.Delete(fmt.Sprintf("%s/v1/applications/%s", k.EndPoint.Application, applicationUuid)).
		SignRequest(true).
		End()

	return resp, body, errs
}

func Patch(applicationUuid, name, image, providerCredentials string, envVars, rules, ports []string) (*http.Response, string, []error) {

	k := kumoru.New()

	k = k.Patch(fmt.Sprintf("%s/v1/applications/%s", k.EndPoint.Application, applicationUuid))

	k = k.Send(genParameters(name, image, providerCredentials, envVars, rules, ports))

	return k.SignRequest(true).
		End()
}

func genParameters(name, image, providerCredentials string, envVars, rules, ports []string) string {
	var params string

	if name != "" {
		params += fmt.Sprintf("name=%s&", url.QueryEscape(name))
	}

	if image != "" {
		params += fmt.Sprintf("image_url=%s&", url.QueryEscape(image))
	}

	if providerCredentials != "" {
		params += fmt.Sprintf("provider_credentials=%s&", url.QueryEscape(providerCredentials))
	}

	for _, envVar := range envVars {
		params += fmt.Sprintf("environment=%s&", url.QueryEscape(envVar))
	}

	for _, port := range ports {
		params += fmt.Sprintf("ports=%s&", url.QueryEscape(port))
	}

	for _, rule := range rules {
		params += fmt.Sprintf("rule=%s&", url.QueryEscape(rule))
	}

	return params
}
<commit_msg>add metadata to application<commit_after>package application

import (
	"fmt"
	"net/http"
	"net/url"

	"github.com/kumoru/kumoru-sdk-go/kumoru"
)

func Create(poolUuid, name, image, providerCredentials, metaData string, envVars, rules, ports []string) (*http.Response, string, []error) {
	k := kumoru.New()

	k = k.Post(fmt.Sprintf("%s/v1/applications/", k.EndPoint.Application))

	k = k.Send(genParameters(name, image, providerCredentials, metaData, envVars, rules, ports))

	k = k.Send(fmt.Sprintf("pool_uuid=%s&", url.QueryEscape(poolUuid)))

	return k.SignRequest(true).
		End()
}

func List() (*http.Response, string, []error) {
	k := kumoru.New()

	return k.Get(fmt.Sprintf("%s/v1/applications/", k.EndPoint.Application)).
		SignRequest(true).
		End()
}

func Show(applicationUuid string) (*http.Response, string, []error) {
	k := kumoru.New()

	return k.Get(fmt.Sprintf("%s/v1/applications/%s", k.EndPoint.Application, applicationUuid)).
		SignRequest(true).
		End()
}

func Deploy(applicationUuid string) (*http.Response, string, []error) {
	k := kumoru.New()

	return k.Post(fmt.Sprintf("%s/v1/applications/%s/deployments/", k.EndPoint.Application, applicationUuid)).
		SignRequest(true).
		End()
}

func Delete(applicationUuid string) (*http.Response, string, []error) {
	k := kumoru.New()

	resp, body, errs := k.Delete(fmt.Sprintf("%s/v1/applications/%s", k.EndPoint.Application, applicationUuid)).
		SignRequest(true).
		End()

	return resp, body, errs
}

func Patch(applicationUuid, name, image, providerCredentials, metaData string, envVars, rules, ports []string) (*http.Response, string, []error) {
	k := kumoru.New()

	k = k.Patch(fmt.Sprintf("%s/v1/applications/%s", k.EndPoint.Application, applicationUuid))

	k = k.Send(genParameters(name, image, providerCredentials, metaData, envVars, rules, ports))

	return k.SignRequest(true).
		End()
}

func genParameters(name, image, providerCredentials, metaData string, envVars, rules, ports []string) string {
	var params string

	if name != "" {
		params += fmt.Sprintf("name=%s&", url.QueryEscape(name))
	}

	if image != "" {
		params += fmt.Sprintf("image_url=%s&", url.QueryEscape(image))
	}

	if providerCredentials != "" {
		params += fmt.Sprintf("provider_credentials=%s&", url.QueryEscape(providerCredentials))
	}

	if metaData != "" {
		params += fmt.Sprintf("metadata=%s&", url.QueryEscape(metaData))
	}

	for _, envVar := range envVars {
		params += fmt.Sprintf("environment=%s&", url.QueryEscape(envVar))
	}

	for _, port := range ports {
		params += fmt.Sprintf("ports=%s&", url.QueryEscape(port))
	}

	for _, rule := range rules {
		params += fmt.Sprintf("rule=%s&", url.QueryEscape(rule))
	}

	return params
}
<|endoftext|>


<commit_before>package schedule

import (
	"testing"
	"time"
)

func TestBuildCommitSchedule(t *testing.T) {
	var tests = []struct {
		startDay            time.Time
		numNotAFieldEntries int
	}{
		{time.Date(2009, time.November, 9, 0, 0, 0, 0, time.UTC), 5},
		{time.Date(2016, time.February, 28, 0, 0, 0, 0, time.UTC), 12},
		{time.Date(2016, time.February, 29, 0, 0, 0, 0, time.UTC), 11},
		{time.Date(2013, time.February, 28, 0, 0, 0, 0, time.UTC), 4},
	}
	for _, test := range tests {
		days := getTestDays(test.startDay)
		schedule := BuildCommitSchedule(days)
		numNotAFieldEntries := 0
		for _, row := range schedule {
			for _, entry := range row {
				if entry != EMPTY && entry != NOT_A_FIELD {
					t.Errorf("Entry should be EMPTY or NOT_A_FIELD, but was %v", entry)
				}
				if entry == NOT_A_FIELD {
					numNotAFieldEntries++
				}
			}

		}
		if numNotAFieldEntries != test.numNotAFieldEntries {
			t.Errorf("Expected %d NOT_A_FIELD entries, but got %d",
				test.numNotAFieldEntries, numNotAFieldEntries)
		}

	}
}

func getTestDays(startDay time.Time) []time.Time {
	var resultingDays []time.Time
	days := GetDaysSinceDateMinusOneYear(startDay)
	for day := range days {
		resultingDays = append(resultingDays, day)
	}
	return resultingDays
}

func TestBuildFirstWeek(t *testing.T) {
	var tests = []struct {
		day              time.Weekday
		expectedSchedule []int
	}{
		{time.Sunday, []int{0, 0, 0, 0, 0, 0, 0}},
		{time.Monday, []int{-1, 0, 0, 0, 0, 0, 0}},
		{time.Tuesday, []int{-1, -1, 0, 0, 0, 0, 0}},
		{time.Wednesday, []int{-1, -1, -1, 0, 0, 0, 0}},
		{time.Thursday, []int{-1, -1, -1, -1, 0, 0, 0}},
		{time.Friday, []int{-1, -1, -1, -1, -1, 0, 0}},
		{time.Saturday, []int{-1, -1, -1, -1, -1, -1, 0}},
	}
	for _, test := range tests {
		actualSchedule := buildFirstWeek(test.day)
		if !sliceEqual(actualSchedule, test.expectedSchedule) {
			fmt := "Expected %v as schedule, but got %v"
			t.Errorf(fmt, test.expectedSchedule, actualSchedule)
		}
	}
}

func TestBuildLastWeek(t *testing.T) {
	var tests = []struct {
		day              time.Weekday
		expectedSchedule []int
	}{
		{time.Sunday, []int{0, -1, -1, -1, -1, -1, -1}},
		{time.Monday, []int{0, 0, -1, -1, -1, -1, -1}},
		{time.Tuesday, []int{0, 0, 0, -1, -1, -1, -1}},
		{time.Wednesday, []int{0, 0, 0, 0, -1, -1, -1}},
		{time.Thursday, []int{0, 0, 0, 0, 0, -1, -1}},
		{time.Friday, []int{0, 0, 0, 0, 0, 0, -1}},
		{time.Saturday, []int{0, 0, 0, 0, 0, 0, 0}},
	}
	for _, test := range tests {
		actualSchedule := buildLastWeek(test.day)
		if !sliceEqual(actualSchedule, test.expectedSchedule) {
			fmt := "Expected %v as schedule, but got %v"
			t.Errorf(fmt, test.expectedSchedule, actualSchedule)
		}
	}
}

func sliceEqual(sliceA, sliceB []int) bool {
	if len(sliceA) != len(sliceB) {
		return false
	}
	for i := 0; i < len(sliceA); i++ {
		if sliceA[i] != sliceB[i] {
			return false
		}
	}
	return true
}

func TestConnectWeeksToSchedule(t *testing.T) {
	var tests = []struct {
		firstDay            time.Weekday
		lastDay             time.Weekday
		numEntries          int
		numNotAFieldEntries int
	}{
		{time.Sunday, time.Saturday, 371, 0},
		{time.Monday, time.Saturday, 371, 1},
		{time.Wednesday, time.Wednesday, 371, 6},
		{time.Saturday, time.Sunday, 371, 12},
	}
	for _, test := range tests {
		firstWeek := buildFirstWeek(test.firstDay)
		lastWeek := buildLastWeek(test.lastDay)
		schedule := connectWeeksToSchedule(firstWeek, lastWeek)
		length := 0
		numNotAFieldEntries := 0
		for _, row := range schedule {
			for _, entry := range row {
				if entry != EMPTY && entry != NOT_A_FIELD {
					t.Errorf("Entry should be EMPTY or NOT_A_FIELD, but was %v", entry)
				}
				if entry == NOT_A_FIELD {
					numNotAFieldEntries++
				}
				length++
			}
		}

		if length != test.numEntries {
			t.Errorf("Expected length was %d, but got %d", test.numEntries, length)
		}

		if numNotAFieldEntries != test.numNotAFieldEntries {
			t.Errorf("Expected %d NOT_A_FIELD entries, but got %d",
				test.numNotAFieldEntries, numNotAFieldEntries)
		}
	}
}
<commit_msg>Start refactoring test for schedule entries.<commit_after>package schedule

import (
	"testing"
	"time"
)

func TestBuildCommitSchedule(t *testing.T) {
	var tests = []struct {
		startDay            time.Time
		numNotAFieldEntries int
	}{
		{time.Date(2009, time.November, 9, 0, 0, 0, 0, time.UTC), 5},
		{time.Date(2016, time.February, 28, 0, 0, 0, 0, time.UTC), 12},
		{time.Date(2016, time.February, 29, 0, 0, 0, 0, time.UTC), 11},
		{time.Date(2013, time.February, 28, 0, 0, 0, 0, time.UTC), 4},
	}
	for _, test := range tests {
		days := getTestDays(test.startDay)
		schedule := BuildCommitSchedule(days)
		numNotAFieldEntries := 0
		for _, row := range schedule {
			for _, entry := range row {
				if entry.NumCommits != EMPTY { // } && entry != NOT_A_FIELD {
					t.Errorf("Entry should be EMPTY or NOT_A_FIELD, but was %v", entry)
				}
				if entry == NOT_A_FIELD {
					numNotAFieldEntries++
				}
			}

		}
		if numNotAFieldEntries != test.numNotAFieldEntries {
			t.Errorf("Expected %d NOT_A_FIELD entries, but got %d",
				test.numNotAFieldEntries, numNotAFieldEntries)
		}

	}
}

func getTestDays(startDay time.Time) []time.Time {
	var resultingDays []time.Time
	days := GetDaysSinceDateMinusOneYear(startDay)
	for day := range days {
		resultingDays = append(resultingDays, day)
	}
	return resultingDays
}

func TestBuildFirstWeek(t *testing.T) {
	var tests = []struct {
		day              time.Weekday
		expectedSchedule []int
	}{
		{time.Sunday, []int{0, 0, 0, 0, 0, 0, 0}},
		{time.Monday, []int{-1, 0, 0, 0, 0, 0, 0}},
		{time.Tuesday, []int{-1, -1, 0, 0, 0, 0, 0}},
		{time.Wednesday, []int{-1, -1, -1, 0, 0, 0, 0}},
		{time.Thursday, []int{-1, -1, -1, -1, 0, 0, 0}},
		{time.Friday, []int{-1, -1, -1, -1, -1, 0, 0}},
		{time.Saturday, []int{-1, -1, -1, -1, -1, -1, 0}},
	}
	for _, test := range tests {
		actualSchedule := buildFirstWeek(test.day)
		if !sliceEqual(actualSchedule, test.expectedSchedule) {
			fmt := "Expected %v as schedule, but got %v"
			t.Errorf(fmt, test.expectedSchedule, actualSchedule)
		}
	}
}

func TestBuildLastWeek(t *testing.T) {
	var tests = []struct {
		day              time.Weekday
		expectedSchedule []int
	}{
		{time.Sunday, []int{0, -1, -1, -1, -1, -1, -1}},
		{time.Monday, []int{0, 0, -1, -1, -1, -1, -1}},
		{time.Tuesday, []int{0, 0, 0, -1, -1, -1, -1}},
		{time.Wednesday, []int{0, 0, 0, 0, -1, -1, -1}},
		{time.Thursday, []int{0, 0, 0, 0, 0, -1, -1}},
		{time.Friday, []int{0, 0, 0, 0, 0, 0, -1}},
		{time.Saturday, []int{0, 0, 0, 0, 0, 0, 0}},
	}
	for _, test := range tests {
		actualSchedule := buildLastWeek(test.day)
		if !sliceEqual(actualSchedule, test.expectedSchedule) {
			fmt := "Expected %v as schedule, but got %v"
			t.Errorf(fmt, test.expectedSchedule, actualSchedule)
		}
	}
}

func sliceEqual(sliceA, sliceB []int) bool {
	if len(sliceA) != len(sliceB) {
		return false
	}
	for i := 0; i < len(sliceA); i++ {
		if sliceA[i] != sliceB[i] {
			return false
		}
	}
	return true
}

func TestGetFirstDayOfWeek(t *testing.T) {
	var tests = []struct {
		day                  time.Time
		expectedFirstWeekDay time.Time
	}{
		{time.Date(2009, time.November, 10, 0, 0, 0, 0, time.UTC), time.Date(2009, time.November, 8, 0, 0, 0, 0, time.UTC)},
		{time.Date(2016, time.February, 28, 0, 0, 0, 0, time.UTC), time.Date(2016, time.February, 28, 0, 0, 0, 0, time.UTC)},
		{time.Date(2013, time.February, 28, 0, 0, 0, 0, time.UTC), time.Date(2013, time.February, 24, 0, 0, 0, 0, time.UTC)},
	}
	for _, test := range tests {
		actual := getFirstDayOfWeek(test.day)
		if !actual.Equal(test.expectedFirstWeekDay) {
			t.Errorf("Expected first weekday to be %v, but got %v", actual, test.expectedFirstWeekDay)
		}
	}
}

func TestConnectWeeksToSchedule(t *testing.T) {
	var tests = []struct {
		firstDay            time.Weekday
		lastDay             time.Weekday
		numEntries          int
		numNotAFieldEntries int
	}{
		{time.Sunday, time.Saturday, 371, 0},
		{time.Monday, time.Saturday, 371, 1},
		{time.Wednesday, time.Wednesday, 371, 6},
		{time.Saturday, time.Sunday, 371, 12},
	}
	for _, test := range tests {
		firstWeek := buildFirstWeek(test.firstDay)
		lastWeek := buildLastWeek(test.lastDay)
		schedule := connectWeeksToSchedule(firstWeek, lastWeek)
		length := 0
		numNotAFieldEntries := 0
		for _, row := range schedule {
			for _, entry := range row {
				if entry != EMPTY && entry != NOT_A_FIELD {
					t.Errorf("Entry should be EMPTY or NOT_A_FIELD, but was %v", entry)
				}
				if entry == NOT_A_FIELD {
					numNotAFieldEntries++
				}
				length++
			}
		}

		if length != test.numEntries {
			t.Errorf("Expected length was %d, but got %d", test.numEntries, length)
		}

		if numNotAFieldEntries != test.numNotAFieldEntries {
			t.Errorf("Expected %d NOT_A_FIELD entries, but got %d",
				test.numNotAFieldEntries, numNotAFieldEntries)
		}
	}
}
<|endoftext|>


<commit_before>package assertions

import (
	"fmt"
	"strconv"

	"ci.guzzler.io/guzzler/corcel/core"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type AssertionTestCase struct {
	Actual               interface{}
	Instance             interface{}
	ActualStringNumber   bool
	InstanceStringNumber bool
}

func NewAsssertionTestCase(actual interface{}, instance interface{}) (newInstance AssertionTestCase) {
	newInstance.Actual = actual
	newInstance.Instance = instance
	switch actualType := actual.(type) {
	case string:
		_, err := strconv.ParseFloat(actualType, 64)
		if err == nil {
			newInstance.ActualStringNumber = true
		}
	}
	switch instanceType := instance.(type) {
	case string:
		_, err := strconv.ParseFloat(instanceType, 64)
		if err == nil {
			newInstance.InstanceStringNumber = true
		}
	}
	return
}

var _ = FDescribe("Assertions", func() {

	key := "some:key"

	assert := func(testCases []AssertionTestCase, test func(actual interface{}, instance interface{})) {

		for _, testCase := range testCases {
			actualValue := testCase.Actual
			instanceValue := testCase.Instance
			testName := fmt.Sprintf("When Actual is of type %T and Instance is of type %T", actualValue, instanceValue)
			if testCase.ActualStringNumber {
				testName = fmt.Sprintf("%s. Actual value is a STRING NUMBER in this case", testName)
			}
			if testCase.InstanceStringNumber {
				testName = fmt.Sprintf("%s. Instance value is a STRING NUMBER in this case", testName)
			}
			It(testName, func() {
				test(actualValue, instanceValue)
			})
		}
	}

	/*
	   Using this test function and the test cases we get a nice readable output.  If you run ginkgo -v here is an example of the output

	   Assertions Greater Than Succeeds
	     When Actual is of type int and Instance is of type string. Instance value is a STRING NUMBER
	*/

	var nilValue interface{}

	FContext("Greater Than", func() {

		Context("Succeeds", func() {
			var testCases = []AssertionTestCase{
				NewAsssertionTestCase(float64(1.1), nilValue),
				NewAsssertionTestCase(int(1), nilValue),
				NewAsssertionTestCase("1", nilValue),
				NewAsssertionTestCase("a", nilValue),
				NewAsssertionTestCase(float64(5), float64(1)),
				NewAsssertionTestCase(int(5), float64(1)),
				NewAsssertionTestCase("2.2", float64(1)),
				NewAsssertionTestCase(int(5), int(1)),
				NewAsssertionTestCase("5", int(1)),
				NewAsssertionTestCase("abc", "a"),
				NewAsssertionTestCase(float64(1.3), "1.2"),
				NewAsssertionTestCase(int(3), "1"),
				NewAsssertionTestCase("3.1", "2"),
			}

			assert(testCases, func(actualValue interface{}, instanceValue interface{}) {
				key := "some:key"
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			})
		})

		FContext("Fails", func() {
			var testCases = []AssertionTestCase{
				NewAsssertionTestCase(nilValue, nilValue),
				NewAsssertionTestCase(nilValue, int(5)),
				NewAsssertionTestCase(nilValue, "5.1"),
				NewAsssertionTestCase(nilValue, "fubar"),
				NewAsssertionTestCase(nilValue, float64(6.1)),
				NewAsssertionTestCase(float64(5.1), float64(6.1)),
				NewAsssertionTestCase(int(5), float64(6.1)),
				NewAsssertionTestCase("5", float64(6.1)),
				NewAsssertionTestCase(float64(3.1), int(6)),
				NewAsssertionTestCase(int(3), int(6)),
				NewAsssertionTestCase("5.1", int(6)),
			}

			assert(testCases, func(actualValue interface{}, instanceValue interface{}) {
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(false))
				Expect(result["message"]).To(Equal(fmt.Sprintf("FAIL: %v is not greater %v", actualValue, instanceValue)))
			})
			/*
				PIt("When Actual is string-number and Instance is int", func() {

				})

				PIt("When Actual is string and Instance is int", func() {

				})

				PIt("When Actual is string and Instance is float64", func() {

				})

				PIt("When Actual is string and Instance is string-number", func() {

				})

				PIt("When Actual is string and Instance is string", func() {

				})

				PIt("When Actual is float64 and Instance is string", func() {

				})

				PIt("When Actual is int and Instance is string", func() {

				})

				PIt("When Actual string-number int and Instance is string", func() {

				})
			*/
		})

	})

	Context("Not Equal Assertion", func() {

		It("Succeeds", func() {
			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Fails", func() {
			executionResult := core.ExecutionResult{
				key: 7,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 7 does match 7"))
		})
	})

	Context("Exact Assertion", func() {
		It("Exact Assertion Succeeds", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: expectedValue,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Exact Assertion Fails", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 8 does not match 7"))
		})

		//NOTHING is currently using the message when an assertion fails but we will need
		//it for when we put the errors into the report.  One of the edge cases with the message
		//is that say the actual value was a string "7" and the expected is an int 7.  The message
		//will not include the quotes so the message would read 7 does not equal 7 as opposed
		//to "7" does not equal 7.  Notice this is a type mismatch
		PIt("Exact Assertion Fails when actual and expected are different types", func() {
			key := "some:key"
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: "7",
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: \"7\" does not match 7"))
		})
	})

})
<commit_msg>Fails When Actual is of type string and Instance is of type int<commit_after>package assertions

import (
	"fmt"
	"strconv"

	"ci.guzzler.io/guzzler/corcel/core"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type AssertionTestCase struct {
	Actual               interface{}
	Instance             interface{}
	ActualStringNumber   bool
	InstanceStringNumber bool
}

func NewAsssertionTestCase(actual interface{}, instance interface{}) (newInstance AssertionTestCase) {
	newInstance.Actual = actual
	newInstance.Instance = instance
	switch actualType := actual.(type) {
	case string:
		_, err := strconv.ParseFloat(actualType, 64)
		if err == nil {
			newInstance.ActualStringNumber = true
		}
	}
	switch instanceType := instance.(type) {
	case string:
		_, err := strconv.ParseFloat(instanceType, 64)
		if err == nil {
			newInstance.InstanceStringNumber = true
		}
	}
	return
}

var _ = FDescribe("Assertions", func() {

	key := "some:key"

	assert := func(testCases []AssertionTestCase, test func(actual interface{}, instance interface{})) {

		for _, testCase := range testCases {
			actualValue := testCase.Actual
			instanceValue := testCase.Instance
			testName := fmt.Sprintf("When Actual is of type %T and Instance is of type %T", actualValue, instanceValue)
			if testCase.ActualStringNumber {
				testName = fmt.Sprintf("%s. Actual value is a STRING NUMBER in this case", testName)
			}
			if testCase.InstanceStringNumber {
				testName = fmt.Sprintf("%s. Instance value is a STRING NUMBER in this case", testName)
			}
			It(testName, func() {
				test(actualValue, instanceValue)
			})
		}
	}

	/*
	   Using this test function and the test cases we get a nice readable output.  If you run ginkgo -v here is an example of the output

	   Assertions Greater Than Succeeds
	     When Actual is of type int and Instance is of type string. Instance value is a STRING NUMBER
	*/

	var nilValue interface{}

	FContext("Greater Than", func() {

		Context("Succeeds", func() {
			var testCases = []AssertionTestCase{
				NewAsssertionTestCase(float64(1.1), nilValue),
				NewAsssertionTestCase(int(1), nilValue),
				NewAsssertionTestCase("1", nilValue),
				NewAsssertionTestCase("a", nilValue),
				NewAsssertionTestCase(float64(5), float64(1)),
				NewAsssertionTestCase(int(5), float64(1)),
				NewAsssertionTestCase("2.2", float64(1)),
				NewAsssertionTestCase(int(5), int(1)),
				NewAsssertionTestCase("5", int(1)),
				NewAsssertionTestCase("abc", "a"),
				NewAsssertionTestCase(float64(1.3), "1.2"),
				NewAsssertionTestCase(int(3), "1"),
				NewAsssertionTestCase("3.1", "2"),
			}

			assert(testCases, func(actualValue interface{}, instanceValue interface{}) {
				key := "some:key"
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			})
		})

		FContext("Fails", func() {
			var testCases = []AssertionTestCase{
				NewAsssertionTestCase(nilValue, nilValue),
				NewAsssertionTestCase(nilValue, int(5)),
				NewAsssertionTestCase(nilValue, "5.1"),
				NewAsssertionTestCase(nilValue, "fubar"),
				NewAsssertionTestCase(nilValue, float64(6.1)),
				NewAsssertionTestCase(float64(5.1), float64(6.1)),
				NewAsssertionTestCase(int(5), float64(6.1)),
				NewAsssertionTestCase("5", float64(6.1)),
				NewAsssertionTestCase(float64(3.1), int(6)),
				NewAsssertionTestCase(int(3), int(6)),
				NewAsssertionTestCase("5.1", int(6)),
				NewAsssertionTestCase("fubar", int(6)),
			}

			assert(testCases, func(actualValue interface{}, instanceValue interface{}) {
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(false))
				Expect(result["message"]).To(Equal(fmt.Sprintf("FAIL: %v is not greater %v", actualValue, instanceValue)))
			})
			/*
				PIt("When Actual is string and Instance is int", func() {

				})

				PIt("When Actual is string and Instance is float64", func() {

				})

				PIt("When Actual is string and Instance is string-number", func() {

				})

				PIt("When Actual is string and Instance is string", func() {

				})

				PIt("When Actual is float64 and Instance is string", func() {

				})

				PIt("When Actual is int and Instance is string", func() {

				})

				PIt("When Actual string-number int and Instance is string", func() {

				})
			*/
		})

	})

	Context("Not Equal Assertion", func() {

		It("Succeeds", func() {
			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Fails", func() {
			executionResult := core.ExecutionResult{
				key: 7,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 7 does match 7"))
		})
	})

	Context("Exact Assertion", func() {
		It("Exact Assertion Succeeds", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: expectedValue,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Exact Assertion Fails", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 8 does not match 7"))
		})

		//NOTHING is currently using the message when an assertion fails but we will need
		//it for when we put the errors into the report.  One of the edge cases with the message
		//is that say the actual value was a string "7" and the expected is an int 7.  The message
		//will not include the quotes so the message would read 7 does not equal 7 as opposed
		//to "7" does not equal 7.  Notice this is a type mismatch
		PIt("Exact Assertion Fails when actual and expected are different types", func() {
			key := "some:key"
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: "7",
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: \"7\" does not match 7"))
		})
	})

})
<|endoftext|>


<commit_before>package main

import (
	path "path/filepath"
	"os"
	"github.com/qlova/ilang/src"
	_ "github.com/qlova/ilang/src/modules/all"
	_ "github.com/qlova/ilang/src/types/all"
)

func ic(input, directory string) {

	file, err := os.Open(input)
	if err != nil {
		return
	}

	ic := ilang.NewCompiler(file)

	if directory == "" {
		directory = path.Dir(input)
	}

	//Open the output file with the file type replaced to .u
	var filename = path.Base(input)[:len(path.Base(input))-2]+".u"

	if output, err := os.Create(directory+"/"+filename); err != nil {
		ic.RaiseError("Could not create output file!", err.Error())
	} else {
		ic.Output = output
	}

	if lib, err := os.Create(directory+"/ilang.u"); err != nil {
		ic.RaiseError("Could not create output library file!", err.Error())
	} else {
		ic.Lib = lib
	}

	ic.Compile()
}
<commit_msg>Fix .it directory not being deleted on windows.<commit_after>package main

import (
	path "path/filepath"
	"os"
	"github.com/qlova/ilang/src"
	_ "github.com/qlova/ilang/src/modules/all"
	_ "github.com/qlova/ilang/src/types/all"
)

func ic(input, directory string) {

	file, err := os.Open(input)
	if err != nil {
		return
	}

	ic := ilang.NewCompiler(file)

	if directory == "" {
		directory = path.Dir(input)
	}

	//Open the output file with the file type replaced to .u
	var filename = path.Base(input)[:len(path.Base(input))-2]+".u"

	if output, err := os.Create(directory+"/"+filename); err != nil {
		ic.RaiseError("Could not create output file!", err.Error())
	} else {
		ic.Output = output
		defer output.Close()
	}

	if lib, err := os.Create(directory+"/ilang.u"); err != nil {
		ic.RaiseError("Could not create output library file!", err.Error())
	} else {
		ic.Lib = lib
		defer lib.Close()
	}

	ic.Compile()
}
<|endoftext|>


<commit_before>// Copyright 2012 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"io/ioutil"
	"log"
	"net"
	"os"
	"strings"
)

// you will notice that I suck at parsers. That said, here is the method to my madness.
// The language of ip is not super consistent and has lots of convenience shortcuts.
// The BNF it shows you doesn't show them.
// The inputs is just the set of args.
// It's very short.
// Each token is just a string and we need not produce terminals with them -- they can
// just be the terminals and we can switch on them.
// The cursor is always our current token pointer. We do a dumb recursive descent parser
// and accumulate information into a global set of variables. At any point we can see into the
// whole set of args and see where we are. We can indicate at each point what we're expecting so
// that in usage() or recover() we can tell the user exactly what we wanted, unlike IP,
// which just barfs a whole (incorrect) BNF at you when you do anything wrong.
// To handle errors in too few arguments, we just do a recover block. That lets us blindly
// reference the arg[] array without having to check the length everywhere.

// Note the plethora of globals. The reason is simple: we parse one command, do it, and quit.
// It doesn't make sense to write this otherwise.
var (
	// Cursor is out next token pointer.
	// The language of this command doesn't require much more.
	cursor    int
	arg       []string
	whatIWant = "addr|route|link"
	l         = log.New(os.Stdout, "ip: ", 0)
)

// the pattern:
// at each level parse off arg[0]. If it matches, continue. If it does not, all error with how far you got, what arg you saw,
// and why it did not work out.

func usage() {
	log.Fatalf("This was fine: '%v', and this was left, '%v', and this was not understood, '%v'; only options are '%v'",
		arg[0:cursor], arg[cursor:], arg[cursor], whatIWant)
}

func adddelip(op, ip, dev string) error {
	addr, network, err := net.ParseCIDR(ip)
	if err != nil {
		l.Fatalf("%v is not in CIDR format: %v", ip, err)
	}
	iface, err := net.InterfaceByName(dev)
	if err != nil {
		l.Fatalf("%v not found: %v", dev, err)
		return err
	}

	switch op {
	case "add":
		if err := NetworkLinkAddIp(iface, addr, network); err != nil {
			l.Fatalf("Adding %v to %v failed: %v", ip, dev, err)
		}
	default:
		l.Fatalf("%v is not supported yet", op)
	}
	return nil

}

// in the ip command, turns out 'dev' is a noise word.
// The BNF is not right there either.
// Always make it optional.
func dev() *net.Interface {
	cursor++
	whatIWant = "dev|device name"
	if arg[cursor] == "dev" {
		cursor++
	}
	whatIWant = "device name"
	iface, err := net.InterfaceByName(arg[cursor])
	if err != nil {
		usage()
	}
	return iface
}

func showips() {
	ifaces, err := net.Interfaces()
	if err != nil {
		l.Fatalf("Can't enumerate interfaces? %v", err)
	}
	for _, v := range ifaces {
		addrs, err := v.Addrs()
		if err != nil {
			l.Printf("Can't enumerate addresses")
		}
		l.Printf("%v: %v", v, addrs)
	}
}
func addrip() {
	var err error
	var addr net.IP
	var network *net.IPNet
	if len(arg) == 1 {
		showips()
		return
	}
	cursor++
	whatIWant = "add|del"
	cmd := arg[cursor]

	switch cmd {
	case "add", "del":
		cursor++
		whatIWant = "CIDR format address"
		addr, network, err = net.ParseCIDR(arg[cursor])
		if err != nil {
			usage()
		}
	default:
		usage()
	}
	iface := dev()
	switch cmd {
	case "add":
		if err := NetworkLinkAddIp(iface, addr, network); err != nil {
			l.Fatalf("Adding %v to %v failed: %v", arg[1], arg[2], err)
		}
	case "del":
		if err := NetworkLinkDelIp(iface, addr, network); err != nil {
			l.Fatalf("Deleting %v from %v failed: %v", arg[1], arg[2], err)
		}
	default:
		l.Fatalf("devip: arg[0] changed: can't happen")
	}
	return

}

func linkshow() {
	cursor++
	whatIWant = "<nothing>|<device name>"
	if len(arg[cursor:]) == 0 {
		showips()
	}
}

func linkset() {
	iface := dev()
	cursor++
	whatIWant = "up|down"
	switch arg[cursor] {
	case "up":
		if err := NetworkLinkUp(iface); err != nil {
			l.Fatalf("%v can't make it up: %v", dev, err)
		}
	case "down":
		if err := NetworkLinkDown(iface); err != nil {
			l.Fatalf("%v can't make it down: %v", dev, err)
		}
	default:
		usage()
	}
}

func link() {
	cursor++
	whatIWant = "show|set"
	cmd := arg[cursor]

	switch cmd {
	case "show":
		linkshow()
	case "set":
		linkset()
	default:
		usage()
	}
	return
}

func routeshow() {
	if b, err := ioutil.ReadFile("/proc/net/route"); err == nil {
		l.Printf("%s", string(b))
	} else {
		l.Fatalf("Route show failed: %v", err)
	}
}
func nodespec() string {
	cursor++
	whatIWant = "default|CIDR"
	return arg[cursor]
}

func nexthop() (string, string) {
	cursor++
	whatIWant = "via"
	if arg[cursor] != "via" {
		usage()
	}
	nh := arg[cursor]
	cursor++
	whatIWant = "Gateway CIDR"
	return nh, arg[cursor]
}

func routeadddefault() {
	nh, nhval := nexthop()
	// TODO: NHFLAGS.
	d := dev()
	switch nh {
	case "via":
		l.Printf("Add default route %v via %v", nhval, d)
		AddDefaultGw(nhval, d.Name)
	default:
		usage()
	}
}

func routeadd() {
	ns := nodespec()
	switch ns {
	case "default":
		routeadddefault()
	default:
		usage()
	}
}

func route() {
	cursor++
	if len(arg[cursor:]) == 0 {
		routeshow()
		return
	}

	whatIWant = "show|add"
	switch arg[cursor] {
	case "show":
		routeshow()
	case "add":
		routeadd()
	default:
		usage()
	}

}
func main() {
	flag.Parse()
	arg = flag.Args()
	defer func() {
		switch err := recover().(type) {
		case nil:
		case error:
			if strings.Contains(err.Error(), "index out of range") {
				l.Fatalf("Args: %v, I got to arg %v, I wanted %v after that", arg, cursor, whatIWant)
			} else if strings.Contains(err.Error(), "slice bounds out of range") {
				l.Fatalf("Args: %v, I got to arg %v, I wanted %v after that", arg, cursor, whatIWant)
			} else {
				l.Fatalf("FUCK: %v", err.Error())
			}
			l.Fatalf("Bummer: %v", err)
		default:
			l.Fatalf("unexpected panic value: %T(%v)", err, err)
		}
	}()
	// The ip command doesn't actually follow the BNF it prints on error.
	// There are lots of handy shortcuts that people will expect.
	switch arg[cursor] {
	case "addr":
		addrip()
	case "link":
		link()
	case "route":
		route()
	default:
		usage()
	}
}
<commit_msg>Trim out crap we don't need.<commit_after>// Copyright 2012 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"io/ioutil"
	"log"
	"net"
	"os"
	"strings"
)

// you will notice that I suck at parsers. That said, here is the method to my madness.
// The language of ip is not super consistent and has lots of convenience shortcuts.
// The BNF it shows you doesn't show them.
// The inputs is just the set of args.
// It's very short.
// Each token is just a string and we need not produce terminals with them -- they can
// just be the terminals and we can switch on them.
// The cursor is always our current token pointer. We do a dumb recursive descent parser
// and accumulate information into a global set of variables. At any point we can see into the
// whole set of args and see where we are. We can indicate at each point what we're expecting so
// that in usage() or recover() we can tell the user exactly what we wanted, unlike IP,
// which just barfs a whole (incorrect) BNF at you when you do anything wrong.
// To handle errors in too few arguments, we just do a recover block. That lets us blindly
// reference the arg[] array without having to check the length everywhere.

// Note the plethora of globals. The reason is simple: we parse one command, do it, and quit.
// It doesn't make sense to write this otherwise.
var (
	// Cursor is out next token pointer.
	// The language of this command doesn't require much more.
	cursor    int
	arg       []string
	whatIWant = "addr|route|link"
	l         = log.New(os.Stdout, "ip: ", 0)
)

// the pattern:
// at each level parse off arg[0]. If it matches, continue. If it does not, all error with how far you got, what arg you saw,
// and why it did not work out.

func usage() {
	log.Fatalf("This was fine: '%v', and this was left, '%v', and this was not understood, '%v'; only options are '%v'",
		arg[0:cursor], arg[cursor:], arg[cursor], whatIWant)
}

// in the ip command, turns out 'dev' is a noise word.
// The BNF is not right there either.
// Always make it optional.
func dev() *net.Interface {
	cursor++
	whatIWant = "dev|device name"
	if arg[cursor] == "dev" {
		cursor++
	}
	whatIWant = "device name"
	iface, err := net.InterfaceByName(arg[cursor])
	if err != nil {
		usage()
	}
	return iface
}

func showips() {
	ifaces, err := net.Interfaces()
	if err != nil {
		l.Fatalf("Can't enumerate interfaces? %v", err)
	}
	for _, v := range ifaces {
		addrs, err := v.Addrs()
		if err != nil {
			l.Printf("Can't enumerate addresses")
		}
		l.Printf("%v: %v", v, addrs)
	}
}

func addrip() {
	var err error
	var addr net.IP
	var network *net.IPNet
	if len(arg) == 1 {
		showips()
		return
	}
	cursor++
	whatIWant = "add|del"
	cmd := arg[cursor]

	switch cmd {
	case "add", "del":
		cursor++
		whatIWant = "CIDR format address"
		addr, network, err = net.ParseCIDR(arg[cursor])
		if err != nil {
			usage()
		}
	default:
		usage()
	}
	iface := dev()
	switch cmd {
	case "add":
		if err := NetworkLinkAddIp(iface, addr, network); err != nil {
			l.Fatalf("Adding %v to %v failed: %v", arg[1], arg[2], err)
		}
	case "del":
		if err := NetworkLinkDelIp(iface, addr, network); err != nil {
			l.Fatalf("Deleting %v from %v failed: %v", arg[1], arg[2], err)
		}
	default:
		l.Fatalf("devip: arg[0] changed: can't happen")
	}
	return

}

func linkshow() {
	cursor++
	whatIWant = "<nothing>|<device name>"
	if len(arg[cursor:]) == 0 {
		showips()
	}
}

func linkset() {
	iface := dev()
	cursor++
	whatIWant = "up|down"
	switch arg[cursor] {
	case "up":
		if err := NetworkLinkUp(iface); err != nil {
			l.Fatalf("%v can't make it up: %v", dev, err)
		}
	case "down":
		if err := NetworkLinkDown(iface); err != nil {
			l.Fatalf("%v can't make it down: %v", dev, err)
		}
	default:
		usage()
	}
}

func link() {
	cursor++
	whatIWant = "show|set"
	cmd := arg[cursor]

	switch cmd {
	case "show":
		linkshow()
	case "set":
		linkset()
	default:
		usage()
	}
	return
}

func routeshow() {
	if b, err := ioutil.ReadFile("/proc/net/route"); err == nil {
		l.Printf("%s", string(b))
	} else {
		l.Fatalf("Route show failed: %v", err)
	}
}
func nodespec() string {
	cursor++
	whatIWant = "default|CIDR"
	return arg[cursor]
}

func nexthop() (string, string) {
	cursor++
	whatIWant = "via"
	if arg[cursor] != "via" {
		usage()
	}
	nh := arg[cursor]
	cursor++
	whatIWant = "Gateway CIDR"
	return nh, arg[cursor]
}

func routeadddefault() {
	nh, nhval := nexthop()
	// TODO: NHFLAGS.
	d := dev()
	switch nh {
	case "via":
		l.Printf("Add default route %v via %v", nhval, d)
		AddDefaultGw(nhval, d.Name)
	default:
		usage()
	}
}

func routeadd() {
	ns := nodespec()
	switch ns {
	case "default":
		routeadddefault()
	default:
		usage()
	}
}

func route() {
	cursor++
	if len(arg[cursor:]) == 0 {
		routeshow()
		return
	}

	whatIWant = "show|add"
	switch arg[cursor] {
	case "show":
		routeshow()
	case "add":
		routeadd()
	default:
		usage()
	}

}
func main() {
	flag.Parse()
	arg = flag.Args()
	defer func() {
		switch err := recover().(type) {
		case nil:
		case error:
			if strings.Contains(err.Error(), "index out of range") {
				l.Fatalf("Args: %v, I got to arg %v, I wanted %v after that", arg, cursor, whatIWant)
			} else if strings.Contains(err.Error(), "slice bounds out of range") {
				l.Fatalf("Args: %v, I got to arg %v, I wanted %v after that", arg, cursor, whatIWant)
			} else {
				l.Fatalf("FUCK: %v", err.Error())
			}
			l.Fatalf("Bummer: %v", err)
		default:
			l.Fatalf("unexpected panic value: %T(%v)", err, err)
		}
	}()
	// The ip command doesn't actually follow the BNF it prints on error.
	// There are lots of handy shortcuts that people will expect.
	switch arg[cursor] {
	case "addr":
		addrip()
	case "link":
		link()
	case "route":
		route()
	default:
		usage()
	}
}
<|endoftext|>