<commit_before>package main

import (
	"fmt"

	"github.com/whitepages/terraform-provider-stingray/Godeps/_workspace/src/github.com/hashicorp/terraform/helper/hashcode"
	"github.com/whitepages/terraform-provider-stingray/Godeps/_workspace/src/github.com/hashicorp/terraform/helper/schema"
	"github.com/whitepages/terraform-provider-stingray/Godeps/_workspace/src/github.com/whitepages/go-stingray"
)

func resourceVirtualServer() *schema.Resource {
	return &schema.Resource{
		Create: resourceVirtualServerCreate,
		Read:   resourceVirtualServerRead,
		Update: resourceVirtualServerUpdate,
		Delete: resourceVirtualServerDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"connection_errors_error_file": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"connection_keepalive_timeout": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},

			"connection_timeout": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Default:  10,
			},

			"connect_timeout": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},

			// Default value of enabled in v3.2 of the
			// REST API is false
			"enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},

			"gzip_enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"gzip_include_mime": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},

			"http_location_rewrite": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"listen_on_any": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"listen_on_traffic_ips": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},

			"log_enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"log_filename": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"log_format": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"log_server_connection_failures": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"note": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"pool": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"port": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},

			"protocol": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"recent_connections_save_all": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"request_rules": &schema.Schema{
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},

			"response_rules": &schema.Schema{
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},

			"ssl_add_http_headers": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"ssl_decrypt": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"ssl_server_cert_default": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"ssl_server_cert_host_mapping": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"certificate": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},
						"host": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},
					},
				},
				Set: func(v interface{}) int {
					m := v.(map[string]interface{})
					return hashcode.String(m["host"].(string))
				},
			},

			"syslog_format": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"web_cache_enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"web_cache_max_time": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
		},
	}
}

func resourceVirtualServerCreate(d *schema.ResourceData, meta interface{}) error {
	err := resourceVirtualServerSet(d, meta)
	if err != nil {
		return err
	}

	return resourceVirtualServerRead(d, meta)
}

func resourceVirtualServerRead(d *schema.ResourceData, meta interface{}) error {
	c := meta.(*providerConfig).client

	r, resp, err := c.GetVirtualServer(d.Get("name").(string))
	if err != nil {
		if resp != nil && resp.StatusCode == 404 {
			// The resource doesn't exist anymore
			d.SetId("")

			return nil
		}

		return fmt.Errorf("Error reading resource: %s", err)
	}

	d.Set("connection_errors_error_file", string(*r.ConnectionErrors.ErrorFile))
	d.Set("connection_keepalive_timeout", int(*r.Connection.KeepaliveTimeout))
	d.Set("connection_timeout", int(*r.Connection.Timeout))
	d.Set("connect_timeout", int(*r.Basic.ConnectTimeout))
	d.Set("enabled", bool(*r.Basic.Enabled))
	d.Set("gzip_enabled", bool(*r.Gzip.Enabled))
	d.Set("gzip_include_mime", []string(*r.Gzip.IncludeMIME))
	d.Set("http_location_rewrite", string(*r.HTTP.LocationRewrite))
	d.Set("listen_on_any", bool(*r.Basic.ListenOnAny))
	d.Set("listen_on_traffic_ips", []string(*r.Basic.ListenOnTrafficIPs))
	d.Set("log_enabled", bool(*r.Log.Enabled))
	d.Set("log_filename", string(*r.Log.Filename))
	d.Set("log_format", string(*r.Log.Format))
	d.Set("log_server_connection_failures", bool(*r.Log.ServerConnectionFailures))
	d.Set("note", string(*r.Basic.Note))
	d.Set("pool", string(*r.Basic.Pool))
	d.Set("port", int(*r.Basic.Port))
	d.Set("protocol", string(*r.Basic.Protocol))
	d.Set("recent_connections_save_all", bool(*r.RecentConnections.SaveAll))
	d.Set("request_rules", []string(*r.Basic.RequestRules))
	d.Set("response_rules", []string(*r.Basic.ResponseRules))
	d.Set("ssl_add_http_headers", bool(*r.SSL.AddHTTPHeaders))
	d.Set("ssl_decrypt", bool(*r.Basic.SSLDecrypt))
	d.Set("ssl_server_cert_default", string(*r.SSL.ServerCertDefault))
	d.Set("ssl_server_cert_host_mapping", flattenServerCertHostMappingTable(*r.SSL.ServerCertHostMapping))
	d.Set("syslog_format", string(*r.Syslog.Format))
	d.Set("web_cache_enabled", bool(*r.WebCache.Enabled))
	d.Set("web_cache_max_time", int(*r.WebCache.MaxTime))

	return nil
}

func resourceVirtualServerUpdate(d *schema.ResourceData, meta interface{}) error {
	err := resourceVirtualServerSet(d, meta)
	if err != nil {
		return err
	}

	return resourceVirtualServerRead(d, meta)
}

func resourceVirtualServerDelete(d *schema.ResourceData, meta interface{}) error {
	c := meta.(*providerConfig).client
	r := stingray.NewVirtualServer(d.Id())

	_, err := c.Delete(r)
	if err != nil {
		return err
	}

	return nil
}

func resourceVirtualServerSet(d *schema.ResourceData, meta interface{}) error {
	c := meta.(*providerConfig).client
	r := stingray.NewVirtualServer(d.Get("name").(string))

	setString(&r.ConnectionErrors.ErrorFile, d, "connection_errors_error_file")
	setInt(&r.Connection.KeepaliveTimeout, d, "connection_keepalive_timeout")
	setInt(&r.Connection.Timeout, d, "connection_timeout")
	setInt(&r.Basic.ConnectTimeout, d, "connect_timeout")
	r.Basic.Enabled = stingray.Bool(d.Get("enabled").(bool))
	setStringSet(&r.Gzip.IncludeMIME, d, "gzip_include_mime")
	setBool(&r.Gzip.Enabled, d, "gzip_enabled")
	setString(&r.HTTP.LocationRewrite, d, "http_location_rewrite")
	r.Basic.ListenOnAny = stingray.Bool(d.Get("listen_on_any").(bool))
	setStringSet(&r.Basic.ListenOnTrafficIPs, d, "listen_on_traffic_ips")
	setBool(&r.Log.Enabled, d, "log_enabled")
	setString(&r.Log.Filename, d, "log_filename")
	setString(&r.Log.Format, d, "log_format")
	setBool(&r.Log.ServerConnectionFailures, d, "log_server_connection_failures")
	setString(&r.Basic.Note, d, "note")
	setString(&r.Basic.Pool, d, "pool")
	setInt(&r.Basic.Port, d, "port")
	setString(&r.Basic.Protocol, d, "protocol")
	setBool(&r.RecentConnections.SaveAll, d, "recent_connections_save_all")
	setStringList(&r.Basic.RequestRules, d, "request_rules")
	setStringList(&r.Basic.ResponseRules, d, "response_rules")
	setBool(&r.SSL.AddHTTPHeaders, d, "ssl_add_http_headers")
	setBool(&r.Basic.SSLDecrypt, d, "ssl_decrypt")
	setString(&r.SSL.ServerCertDefault, d, "ssl_server_cert_default")
	setServerCertHostMappingTable(&r.SSL.ServerCertHostMapping, d, "ssl_server_cert_host_mapping")
	setString(&r.Syslog.Format, d, "syslog_format")
	setBool(&r.WebCache.Enabled, d, "web_cache_enabled")
	setInt(&r.WebCache.MaxTime, d, "web_cache_max_time")

	_, err := c.Set(r)
	if err != nil {
		return err
	}

	d.SetId(d.Get("name").(string))

	return nil
}

func setServerCertHostMappingTable(target **stingray.ServerCertHostMappingTable, d *schema.ResourceData, key string) {
	if _, ok := d.GetOk(key); ok {
		table := d.Get(key).(*schema.Set).List()
		*target, _ = expandServerCertHostMappingTable(table)
	}
}

func expandServerCertHostMappingTable(configured []interface{}) (*stingray.ServerCertHostMappingTable, error) {
	table := make(stingray.ServerCertHostMappingTable, 0, len(configured))

	for _, raw := range configured {
		data := raw.(map[string]interface{})

		s := stingray.ServerCertHostMapping{
			Certificate: stingray.String(data["certificate"].(string)),
			Host:        stingray.String(data["host"].(string)),
		}

		table = append(table, s)
	}

	return &table, nil
}

func flattenServerCertHostMappingTable(list stingray.ServerCertHostMappingTable) []map[string]interface{} {
	result := make([]map[string]interface{}, 0, len(list))
	for _, i := range list {
		s := map[string]interface{}{
			"certificate": *i.Certificate,
			"host":        *i.Host,
		}
		result = append(result, s)
	}
	return result
}
<commit_msg>Add newline before return<commit_after>package main

import (
	"fmt"

	"github.com/whitepages/terraform-provider-stingray/Godeps/_workspace/src/github.com/hashicorp/terraform/helper/hashcode"
	"github.com/whitepages/terraform-provider-stingray/Godeps/_workspace/src/github.com/hashicorp/terraform/helper/schema"
	"github.com/whitepages/terraform-provider-stingray/Godeps/_workspace/src/github.com/whitepages/go-stingray"
)

func resourceVirtualServer() *schema.Resource {
	return &schema.Resource{
		Create: resourceVirtualServerCreate,
		Read:   resourceVirtualServerRead,
		Update: resourceVirtualServerUpdate,
		Delete: resourceVirtualServerDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"connection_errors_error_file": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"connection_keepalive_timeout": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},

			"connection_timeout": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Default:  10,
			},

			"connect_timeout": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},

			// Default value of enabled in v3.2 of the
			// REST API is false
			"enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},

			"gzip_enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"gzip_include_mime": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},

			"http_location_rewrite": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"listen_on_any": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"listen_on_traffic_ips": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set: func(v interface{}) int {
					return hashcode.String(v.(string))
				},
			},

			"log_enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"log_filename": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"log_format": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"log_server_connection_failures": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"note": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"pool": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"port": &schema.Schema{
				Type:     schema.TypeInt,
				Required: true,
			},

			"protocol": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"recent_connections_save_all": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"request_rules": &schema.Schema{
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},

			"response_rules": &schema.Schema{
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},

			"ssl_add_http_headers": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"ssl_decrypt": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"ssl_server_cert_default": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"ssl_server_cert_host_mapping": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				Computed: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"certificate": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},
						"host": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},
					},
				},
				Set: func(v interface{}) int {
					m := v.(map[string]interface{})
					return hashcode.String(m["host"].(string))
				},
			},

			"syslog_format": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"web_cache_enabled": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"web_cache_max_time": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
		},
	}
}

func resourceVirtualServerCreate(d *schema.ResourceData, meta interface{}) error {
	err := resourceVirtualServerSet(d, meta)
	if err != nil {
		return err
	}

	return resourceVirtualServerRead(d, meta)
}

func resourceVirtualServerRead(d *schema.ResourceData, meta interface{}) error {
	c := meta.(*providerConfig).client

	r, resp, err := c.GetVirtualServer(d.Get("name").(string))
	if err != nil {
		if resp != nil && resp.StatusCode == 404 {
			// The resource doesn't exist anymore
			d.SetId("")

			return nil
		}

		return fmt.Errorf("Error reading resource: %s", err)
	}

	d.Set("connection_errors_error_file", string(*r.ConnectionErrors.ErrorFile))
	d.Set("connection_keepalive_timeout", int(*r.Connection.KeepaliveTimeout))
	d.Set("connection_timeout", int(*r.Connection.Timeout))
	d.Set("connect_timeout", int(*r.Basic.ConnectTimeout))
	d.Set("enabled", bool(*r.Basic.Enabled))
	d.Set("gzip_enabled", bool(*r.Gzip.Enabled))
	d.Set("gzip_include_mime", []string(*r.Gzip.IncludeMIME))
	d.Set("http_location_rewrite", string(*r.HTTP.LocationRewrite))
	d.Set("listen_on_any", bool(*r.Basic.ListenOnAny))
	d.Set("listen_on_traffic_ips", []string(*r.Basic.ListenOnTrafficIPs))
	d.Set("log_enabled", bool(*r.Log.Enabled))
	d.Set("log_filename", string(*r.Log.Filename))
	d.Set("log_format", string(*r.Log.Format))
	d.Set("log_server_connection_failures", bool(*r.Log.ServerConnectionFailures))
	d.Set("note", string(*r.Basic.Note))
	d.Set("pool", string(*r.Basic.Pool))
	d.Set("port", int(*r.Basic.Port))
	d.Set("protocol", string(*r.Basic.Protocol))
	d.Set("recent_connections_save_all", bool(*r.RecentConnections.SaveAll))
	d.Set("request_rules", []string(*r.Basic.RequestRules))
	d.Set("response_rules", []string(*r.Basic.ResponseRules))
	d.Set("ssl_add_http_headers", bool(*r.SSL.AddHTTPHeaders))
	d.Set("ssl_decrypt", bool(*r.Basic.SSLDecrypt))
	d.Set("ssl_server_cert_default", string(*r.SSL.ServerCertDefault))
	d.Set("ssl_server_cert_host_mapping", flattenServerCertHostMappingTable(*r.SSL.ServerCertHostMapping))
	d.Set("syslog_format", string(*r.Syslog.Format))
	d.Set("web_cache_enabled", bool(*r.WebCache.Enabled))
	d.Set("web_cache_max_time", int(*r.WebCache.MaxTime))

	return nil
}

func resourceVirtualServerUpdate(d *schema.ResourceData, meta interface{}) error {
	err := resourceVirtualServerSet(d, meta)
	if err != nil {
		return err
	}

	return resourceVirtualServerRead(d, meta)
}

func resourceVirtualServerDelete(d *schema.ResourceData, meta interface{}) error {
	c := meta.(*providerConfig).client
	r := stingray.NewVirtualServer(d.Id())

	_, err := c.Delete(r)
	if err != nil {
		return err
	}

	return nil
}

func resourceVirtualServerSet(d *schema.ResourceData, meta interface{}) error {
	c := meta.(*providerConfig).client
	r := stingray.NewVirtualServer(d.Get("name").(string))

	setString(&r.ConnectionErrors.ErrorFile, d, "connection_errors_error_file")
	setInt(&r.Connection.KeepaliveTimeout, d, "connection_keepalive_timeout")
	setInt(&r.Connection.Timeout, d, "connection_timeout")
	setInt(&r.Basic.ConnectTimeout, d, "connect_timeout")
	r.Basic.Enabled = stingray.Bool(d.Get("enabled").(bool))
	setStringSet(&r.Gzip.IncludeMIME, d, "gzip_include_mime")
	setBool(&r.Gzip.Enabled, d, "gzip_enabled")
	setString(&r.HTTP.LocationRewrite, d, "http_location_rewrite")
	r.Basic.ListenOnAny = stingray.Bool(d.Get("listen_on_any").(bool))
	setStringSet(&r.Basic.ListenOnTrafficIPs, d, "listen_on_traffic_ips")
	setBool(&r.Log.Enabled, d, "log_enabled")
	setString(&r.Log.Filename, d, "log_filename")
	setString(&r.Log.Format, d, "log_format")
	setBool(&r.Log.ServerConnectionFailures, d, "log_server_connection_failures")
	setString(&r.Basic.Note, d, "note")
	setString(&r.Basic.Pool, d, "pool")
	setInt(&r.Basic.Port, d, "port")
	setString(&r.Basic.Protocol, d, "protocol")
	setBool(&r.RecentConnections.SaveAll, d, "recent_connections_save_all")
	setStringList(&r.Basic.RequestRules, d, "request_rules")
	setStringList(&r.Basic.ResponseRules, d, "response_rules")
	setBool(&r.SSL.AddHTTPHeaders, d, "ssl_add_http_headers")
	setBool(&r.Basic.SSLDecrypt, d, "ssl_decrypt")
	setString(&r.SSL.ServerCertDefault, d, "ssl_server_cert_default")
	setServerCertHostMappingTable(&r.SSL.ServerCertHostMapping, d, "ssl_server_cert_host_mapping")
	setString(&r.Syslog.Format, d, "syslog_format")
	setBool(&r.WebCache.Enabled, d, "web_cache_enabled")
	setInt(&r.WebCache.MaxTime, d, "web_cache_max_time")

	_, err := c.Set(r)
	if err != nil {
		return err
	}

	d.SetId(d.Get("name").(string))

	return nil
}

func setServerCertHostMappingTable(target **stingray.ServerCertHostMappingTable, d *schema.ResourceData, key string) {
	if _, ok := d.GetOk(key); ok {
		table := d.Get(key).(*schema.Set).List()
		*target, _ = expandServerCertHostMappingTable(table)
	}
}

func expandServerCertHostMappingTable(configured []interface{}) (*stingray.ServerCertHostMappingTable, error) {
	table := make(stingray.ServerCertHostMappingTable, 0, len(configured))

	for _, raw := range configured {
		data := raw.(map[string]interface{})

		s := stingray.ServerCertHostMapping{
			Certificate: stingray.String(data["certificate"].(string)),
			Host:        stingray.String(data["host"].(string)),
		}

		table = append(table, s)
	}

	return &table, nil
}

func flattenServerCertHostMappingTable(list stingray.ServerCertHostMappingTable) []map[string]interface{} {
	result := make([]map[string]interface{}, 0, len(list))
	for _, i := range list {
		s := map[string]interface{}{
			"certificate": *i.Certificate,
			"host":        *i.Host,
		}
		result = append(result, s)
	}

	return result
}
<|endoftext|>


<commit_before>package openzwave

// #cgo LDFLAGS: -lopenzwave -Lgo/src/github.com/ninjasphere/go-openzwave/openzwave
// #cgo CPPFLAGS: -Iopenzwave/cpp/src/platform -Iopenzwave/cpp/src -Iopenzwave/cpp/src/value_classes
//
// #include "api.h"
import "C"

import (
	"fmt"

	"github.com/ninjasphere/go-openzwave/NT"
)

type state int

const (
	STATE_INIT  state = iota
	STATE_READY       = iota
)

type Node interface {
	GetHomeId() uint32
	GetId() uint8

	GetDevice() Device

	GetProductId() *ProductId
	GetProductDescription() *ProductDescription
	GetNodeName() string

	GetValue(commandClassId uint8, instanceId uint8, index uint8) Value
}

type ProductId struct {
	ManufacturerId string
	ProductId      string
}

type ProductDescription struct {
	ManufacturerName string
	ProductName      string
	ProductType      string
}

type node struct {
	cRef    *C.Node
	classes map[uint8]*valueClass
	state   state
	device  Device
}

type valueClass struct {
	commandClass uint8
	instances    map[uint8]*valueInstance
}

type valueInstance struct {
	instance uint8
	values   map[uint8]*value
}

func newGoNode(cRef *C.Node) *node {
	return &node{cRef, make(map[uint8]*valueClass), STATE_INIT, nil}
}

func (self *node) String() string {
	cRef := self.cRef

	return fmt.Sprintf(
		"Node["+
			"homeId=0x%08x, "+
			"nodeId=%03d, "+
			"basicType=%02x, "+
			"genericType=%02x, "+
			"specificType=%02x, "+
			"nodeType='%s', "+
			"manufacturerName='%s', "+
			"productName='%s', "+
			"location='%s', "+
			"manufacturerId=%s, "+
			"productType=%s, "+
			"productId=%s]",
		uint32(cRef.nodeId.homeId),
		uint8(cRef.nodeId.nodeId),
		uint8(cRef.basicType),
		uint8(cRef.genericType),
		uint8(cRef.specificType),
		C.GoString(cRef.nodeType),
		C.GoString(cRef.manufacturerName),
		C.GoString(cRef.productName),
		C.GoString(cRef.location),
		C.GoString(cRef.manufacturerId),
		C.GoString(cRef.productType),
		C.GoString(cRef.productId))
}

func (self *node) GetHomeId() uint32 {
	return uint32(self.cRef.nodeId.homeId)
}

func (self *node) GetId() uint8 {
	return uint8(self.cRef.nodeId.nodeId)
}

func (self *node) notify(api *api, nt *notification) {

	var event Event

	notificationType := nt.cRef.notificationType
	switch notificationType {
	case NT.NODE_REMOVED:
		event = &NodeUnavailable{nodeEvent{self}}
		if self.device != nil {
			self.device.NodeRemoved()
		}
		api.notifyEvent(event)
		// TODO: free the C structure.
		break

	case NT.VALUE_REMOVED:
		self.removeValue(nt)
		break

	case NT.ESSENTIAL_NODE_QUERIES_COMPLETE,
		NT.NODE_QUERIES_COMPLETE:
		// move the node into the initialized state
		// begin admission processing for the node

		switch self.state {
		case STATE_INIT:
			self.state = STATE_READY

			event = &NodeAvailable{nodeEvent{self}}
			//
			// Use a callback to construct the device for this node, then
			// pass the event to the device.
			//

			self.device = api.deviceFactory(api, self)
			self.device.NodeAdded()

			break
		default:
			event = &NodeChanged{nodeEvent{self}}
			self.device.NodeChanged()
			//
			// Pass the event to the node.
			//
		}
		api.notifyEvent(event)
		break

	case NT.VALUE_ADDED,
		NT.VALUE_CHANGED,
		NT.VALUE_REFRESHED:
		v := self.takeValue(nt)
		if self.device != nil {
			self.device.ValueChanged(v)
		}
		break

	case NT.NODE_NAMING,
		NT.NODE_PROTOCOL_INFO:
		// log the related information for diagnostics purposes

	}
}

// take the value structure from the notification
func (self *node) takeValue(nt *notification) *value {
	commandClassId := (uint8)(nt.value.cRef.valueId.commandClassId)
	instanceId := (uint8)(nt.value.cRef.valueId.instance)
	index := (uint8)(nt.value.cRef.valueId.index)

	instance := self.createOrGetInstance(commandClassId, instanceId)
	v, ok := instance.values[index]
	if !ok {
		v = nt.swapValueImpl(nil)
		instance.values[index] = v

	} else {
		nt.swapValueImpl(v)
	}
	return v
}

func (self *node) createOrGetInstance(commandClassId uint8, instanceId uint8) *valueInstance {
	class, ok := self.classes[commandClassId]
	if !ok {
		class = &valueClass{commandClassId, make(map[uint8]*valueInstance)}
		self.classes[commandClassId] = class
	}
	instance, ok := class.instances[instanceId]
	if !ok {
		instance = &valueInstance{instanceId, make(map[uint8]*value)}
		class.instances[instanceId] = instance
	}
	return instance
}

func (self *node) GetValue(commandClassId uint8, instanceId uint8, index uint8) Value {
	var v *value
	class, ok := self.classes[commandClassId]
	if ok {
		instance, ok := class.instances[instanceId]
		if ok {
			v, ok = instance.values[index]
		}
	}
	if ok {
		return v
	} else {
		return &missingValue{} // accessor that does nothing
	}
	return v
}

func (self *node) removeValue(nt *notification) {
	commandClassId := (uint8)(nt.value.cRef.valueId.commandClassId)
	instanceId := (uint8)(nt.value.cRef.valueId.instance)
	index := (uint8)(nt.value.cRef.valueId.index)

	class, ok := self.classes[commandClassId]
	if !ok {
		return
	}

	instance, ok := class.instances[instanceId]
	if !ok {
		return
	}

	value, ok := instance.values[index]
	_ = value

	if !ok {
		return
	} else {
		// TODO: free the C structure
		delete(instance.values, index)
		if len(instance.values) == 0 {
			delete(class.instances, instanceId)
			if len(class.instances) == 0 {
				delete(self.classes, commandClassId)
			}
		}
	}

}

func (self *node) GetDevice() Device {
	return self.device
}

func (self *node) GetProductId() *ProductId {
	return &ProductId{C.GoString(self.cRef.manufacturerId), C.GoString(self.cRef.productId)}
}

func (self *node) GetProductDescription() *ProductDescription {
	return &ProductDescription{
		C.GoString(self.cRef.manufacturerName),
		C.GoString(self.cRef.productName),
		C.GoString(self.cRef.productType)}
}

func (self *node) GetNodeName() string {
	return C.GoString(self.cRef.nodeName)
}

func (self *node) free() {
	C.freeNode(self.cRef)
}
<commit_msg>Support getting value by Id.<commit_after>package openzwave

// #cgo LDFLAGS: -lopenzwave -Lgo/src/github.com/ninjasphere/go-openzwave/openzwave
// #cgo CPPFLAGS: -Iopenzwave/cpp/src/platform -Iopenzwave/cpp/src -Iopenzwave/cpp/src/value_classes
//
// #include "api.h"
import "C"

import (
	"fmt"

	"github.com/ninjasphere/go-openzwave/NT"
)

type state int

const (
	STATE_INIT  state = iota
	STATE_READY       = iota
)

type Node interface {
	GetHomeId() uint32
	GetId() uint8

	GetDevice() Device

	GetProductId() *ProductId
	GetProductDescription() *ProductDescription
	GetNodeName() string

	GetValue(commandClassId uint8, instanceId uint8, index uint8) Value
	GetValueWithId(valueId ValueID) Value
}

type ProductId struct {
	ManufacturerId string
	ProductId      string
}

type ProductDescription struct {
	ManufacturerName string
	ProductName      string
	ProductType      string
}

type node struct {
	cRef    *C.Node
	classes map[uint8]*valueClass
	state   state
	device  Device
}

type valueClass struct {
	commandClass uint8
	instances    map[uint8]*valueInstance
}

type valueInstance struct {
	instance uint8
	values   map[uint8]*value
}

func newGoNode(cRef *C.Node) *node {
	return &node{cRef, make(map[uint8]*valueClass), STATE_INIT, nil}
}

func (self *node) String() string {
	cRef := self.cRef

	return fmt.Sprintf(
		"Node["+
			"homeId=0x%08x, "+
			"nodeId=%03d, "+
			"basicType=%02x, "+
			"genericType=%02x, "+
			"specificType=%02x, "+
			"nodeType='%s', "+
			"manufacturerName='%s', "+
			"productName='%s', "+
			"location='%s', "+
			"manufacturerId=%s, "+
			"productType=%s, "+
			"productId=%s]",
		uint32(cRef.nodeId.homeId),
		uint8(cRef.nodeId.nodeId),
		uint8(cRef.basicType),
		uint8(cRef.genericType),
		uint8(cRef.specificType),
		C.GoString(cRef.nodeType),
		C.GoString(cRef.manufacturerName),
		C.GoString(cRef.productName),
		C.GoString(cRef.location),
		C.GoString(cRef.manufacturerId),
		C.GoString(cRef.productType),
		C.GoString(cRef.productId))
}

func (self *node) GetHomeId() uint32 {
	return uint32(self.cRef.nodeId.homeId)
}

func (self *node) GetId() uint8 {
	return uint8(self.cRef.nodeId.nodeId)
}

func (self *node) notify(api *api, nt *notification) {

	var event Event

	notificationType := nt.cRef.notificationType
	switch notificationType {
	case NT.NODE_REMOVED:
		event = &NodeUnavailable{nodeEvent{self}}
		if self.device != nil {
			self.device.NodeRemoved()
		}
		api.notifyEvent(event)
		// TODO: free the C structure.
		break

	case NT.VALUE_REMOVED:
		self.removeValue(nt)
		break

	case NT.ESSENTIAL_NODE_QUERIES_COMPLETE,
		NT.NODE_QUERIES_COMPLETE:
		// move the node into the initialized state
		// begin admission processing for the node

		switch self.state {
		case STATE_INIT:
			self.state = STATE_READY

			event = &NodeAvailable{nodeEvent{self}}
			//
			// Use a callback to construct the device for this node, then
			// pass the event to the device.
			//

			self.device = api.deviceFactory(api, self)
			self.device.NodeAdded()

			break
		default:
			event = &NodeChanged{nodeEvent{self}}
			self.device.NodeChanged()
			//
			// Pass the event to the node.
			//
		}
		api.notifyEvent(event)
		break

	case NT.VALUE_ADDED,
		NT.VALUE_CHANGED,
		NT.VALUE_REFRESHED:
		v := self.takeValue(nt)
		if self.device != nil {
			self.device.ValueChanged(v)
		}
		break

	case NT.NODE_NAMING,
		NT.NODE_PROTOCOL_INFO:
		// log the related information for diagnostics purposes

	}
}

// take the value structure from the notification
func (self *node) takeValue(nt *notification) *value {
	commandClassId := (uint8)(nt.value.cRef.valueId.commandClassId)
	instanceId := (uint8)(nt.value.cRef.valueId.instance)
	index := (uint8)(nt.value.cRef.valueId.index)

	instance := self.createOrGetInstance(commandClassId, instanceId)
	v, ok := instance.values[index]
	if !ok {
		v = nt.swapValueImpl(nil)
		instance.values[index] = v

	} else {
		nt.swapValueImpl(v)
	}
	return v
}

func (self *node) createOrGetInstance(commandClassId uint8, instanceId uint8) *valueInstance {
	class, ok := self.classes[commandClassId]
	if !ok {
		class = &valueClass{commandClassId, make(map[uint8]*valueInstance)}
		self.classes[commandClassId] = class
	}
	instance, ok := class.instances[instanceId]
	if !ok {
		instance = &valueInstance{instanceId, make(map[uint8]*value)}
		class.instances[instanceId] = instance
	}
	return instance
}

func (self *node) GetValue(commandClassId uint8, instanceId uint8, index uint8) Value {
	var v *value
	class, ok := self.classes[commandClassId]
	if ok {
		instance, ok := class.instances[instanceId]
		if ok {
			v, ok = instance.values[index]
		}
	}
	if ok {
		return v
	} else {
		return &missingValue{} // accessor that does nothing
	}
	return v
}

func (self *node) GetValueWithId(valueId ValueID) Value {
	return self.GetValue(valueId.CommandClassId, valueId.Instance, valueId.Index)
}

func (self *node) removeValue(nt *notification) {
	commandClassId := (uint8)(nt.value.cRef.valueId.commandClassId)
	instanceId := (uint8)(nt.value.cRef.valueId.instance)
	index := (uint8)(nt.value.cRef.valueId.index)

	class, ok := self.classes[commandClassId]
	if !ok {
		return
	}

	instance, ok := class.instances[instanceId]
	if !ok {
		return
	}

	value, ok := instance.values[index]
	_ = value

	if !ok {
		return
	} else {
		// TODO: free the C structure
		delete(instance.values, index)
		if len(instance.values) == 0 {
			delete(class.instances, instanceId)
			if len(class.instances) == 0 {
				delete(self.classes, commandClassId)
			}
		}
	}

}

func (self *node) GetDevice() Device {
	return self.device
}

func (self *node) GetProductId() *ProductId {
	return &ProductId{C.GoString(self.cRef.manufacturerId), C.GoString(self.cRef.productId)}
}

func (self *node) GetProductDescription() *ProductDescription {
	return &ProductDescription{
		C.GoString(self.cRef.manufacturerName),
		C.GoString(self.cRef.productName),
		C.GoString(self.cRef.productType)}
}

func (self *node) GetNodeName() string {
	return C.GoString(self.cRef.nodeName)
}

func (self *node) free() {
	C.freeNode(self.cRef)
}
<|endoftext|>


<commit_before>package docker

import (
	"github.com/dotcloud/docker/utils"
	"strings"
	"testing"
	"time"
)

func TestContainerTagImageDelete(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)

	srv := &Server{runtime: runtime}

	initialImages, err := srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if err := srv.runtime.repositories.Set("utest", "tag1", unitTestImageName, false); err != nil {
		t.Fatal(err)
	}

	if err := srv.runtime.repositories.Set("utest/docker", "tag2", unitTestImageName, false); err != nil {
		t.Fatal(err)
	}
	if err := srv.runtime.repositories.Set("utest:5000/docker", "tag3", unitTestImageName, false); err != nil {
		t.Fatal(err)
	}

	images, err := srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images) != len(initialImages)+3 {
		t.Errorf("Expected %d images, %d found", len(initialImages)+2, len(images))
	}

	if _, err := srv.ImageDelete("utest/docker:tag2", true); err != nil {
		t.Fatal(err)
	}

	images, err = srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images) != len(initialImages)+2 {
		t.Errorf("Expected %d images, %d found", len(initialImages)+2, len(images))
	}

	if _, err := srv.ImageDelete("utest:5000/docker:tag3", true); err != nil {
		t.Fatal(err)
	}

	images, err = srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images) != len(initialImages)+1 {
		t.Errorf("Expected %d images, %d found", len(initialImages)+1, len(images))
	}

	if _, err := srv.ImageDelete("utest:tag1", true); err != nil {
		t.Fatal(err)
	}

	images, err = srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images) != len(initialImages) {
		t.Errorf("Expected %d image, %d found", len(initialImages), len(images))
	}
}

func TestCreateRm(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)

	srv := &Server{runtime: runtime}

	config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	id, err := srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	if len(runtime.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime.List()))
	}

	if err = srv.ContainerDestroy(id, true); err != nil {
		t.Fatal(err)
	}

	if len(runtime.List()) != 0 {
		t.Errorf("Expected 0 container, %v found", len(runtime.List()))
	}

}

func TestCommit(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)

	srv := &Server{runtime: runtime}

	config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "/bin/cat"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	id, err := srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	if _, err := srv.ContainerCommit(id, "testrepo", "testtag", "", "", config); err != nil {
		t.Fatal(err)
	}
}

func TestCreateStartRestartStopStartKillRm(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)

	srv := &Server{runtime: runtime}

	config, hostConfig, _, err := ParseRun([]string{GetTestImage(runtime).ID, "/bin/cat"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	id, err := srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	if len(runtime.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime.List()))
	}

	err = srv.ContainerStart(id, hostConfig)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerRestart(id, 1)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerStop(id, 1)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerStart(id, hostConfig)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerKill(id)
	if err != nil {
		t.Fatal(err)
	}

	// FIXME: this failed once with a race condition ("Unable to remove filesystem for xxx: directory not empty")
	if err = srv.ContainerDestroy(id, true); err != nil {
		t.Fatal(err)
	}

	if len(runtime.List()) != 0 {
		t.Errorf("Expected 0 container, %v found", len(runtime.List()))
	}

}

func TestRunWithTooLowMemoryLimit(t *testing.T) {
	var err error
	runtime := mkRuntime(t)
	srv := &Server{runtime: runtime}
	defer nuke(runtime)
	// Try to create a container with a memory limit of 1 byte less than the minimum allowed limit.
	_, err = srv.ContainerCreate(
		&Config{
			Image:     GetTestImage(runtime).ID,
			Memory:    524287,
			CpuShares: 1000,
			Cmd:       []string{"/bin/cat"},
		},
	)
	if err == nil {
		t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
	}

}

func TestContainerTop(t *testing.T) {
	runtime := mkRuntime(t)
	srv := &Server{runtime: runtime}
	defer nuke(runtime)

	c, hostConfig := mkContainer(runtime, []string{"_", "/bin/sh", "-c", "sleep 2"}, t)
	defer runtime.Destroy(c)
	if err := c.Start(hostConfig); err != nil {
		t.Fatal(err)
	}

	// Give some time to the process to start
	c.WaitTimeout(500 * time.Millisecond)

	if !c.State.Running {
		t.Errorf("Container should be running")
	}
	procs, err := srv.ContainerTop(c.ID)
	if err != nil {
		t.Fatal(err)
	}

	if len(procs) != 2 {
		t.Fatalf("Expected 2 processes, found %d.", len(procs))
	}

	if procs[0].Cmd != "sh" && procs[0].Cmd != "busybox" {
		t.Fatalf("Expected `busybox` or `sh`, found %s.", procs[0].Cmd)
	}

	if procs[1].Cmd != "sh" && procs[1].Cmd != "busybox" {
		t.Fatalf("Expected `busybox` or `sh`, found %s.", procs[1].Cmd)
	}
}

func TestPools(t *testing.T) {
	runtime := mkRuntime(t)
	srv := &Server{
		runtime:     runtime,
		pullingPool: make(map[string]struct{}),
		pushingPool: make(map[string]struct{}),
	}
	defer nuke(runtime)

	err := srv.poolAdd("pull", "test1")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolAdd("pull", "test2")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolAdd("push", "test1")
	if err == nil || err.Error() != "pull test1 is already in progress" {
		t.Fatalf("Expected `pull test1 is already in progress`")
	}
	err = srv.poolAdd("pull", "test1")
	if err == nil || err.Error() != "pull test1 is already in progress" {
		t.Fatalf("Expected `pull test1 is already in progress`")
	}
	err = srv.poolAdd("wait", "test3")
	if err == nil || err.Error() != "Unkown pool type" {
		t.Fatalf("Expected `Unkown pool type`")
	}

	err = srv.poolRemove("pull", "test2")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolRemove("pull", "test2")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolRemove("pull", "test1")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolRemove("push", "test1")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolRemove("wait", "test3")
	if err == nil || err.Error() != "Unkown pool type" {
		t.Fatalf("Expected `Unkown pool type`")
	}
}

func TestLogEvent(t *testing.T) {
	runtime := mkRuntime(t)
	srv := &Server{
		runtime:   runtime,
		events:    make([]utils.JSONMessage, 0, 64),
		listeners: make(map[string]chan utils.JSONMessage),
	}

	srv.LogEvent("fakeaction", "fakeid")

	listener := make(chan utils.JSONMessage)
	srv.Lock()
	srv.listeners["test"] = listener
	srv.Unlock()

	srv.LogEvent("fakeaction2", "fakeid")

	if len(srv.events) != 2 {
		t.Fatalf("Expected 2 events, found %d", len(srv.events))
	}
	go func() {
		time.Sleep(200 * time.Millisecond)
		srv.LogEvent("fakeaction3", "fakeid")
		time.Sleep(200 * time.Millisecond)
		srv.LogEvent("fakeaction4", "fakeid")
	}()

	setTimeout(t, "Listening for events timed out", 2*time.Second, func() {
		for i := 2; i < 4; i++ {
			event := <-listener
			if event != srv.events[i] {
				t.Fatalf("Event received it different than expected")
			}
		}
	})
}

func TestRmi(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)
	srv := &Server{runtime: runtime}

	initialImages, err := srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	config, hostConfig, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	containerID, err := srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	//To remove
	err = srv.ContainerStart(containerID, hostConfig)
	if err != nil {
		t.Fatal(err)
	}

	imageID, err := srv.ContainerCommit(containerID, "test", "", "", "", nil)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerTag(imageID, "test", "0.1", false)
	if err != nil {
		t.Fatal(err)
	}

	containerID, err = srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	//To remove
	err = srv.ContainerStart(containerID, hostConfig)
	if err != nil {
		t.Fatal(err)
	}

	_, err = srv.ContainerCommit(containerID, "test", "", "", "", nil)
	if err != nil {
		t.Fatal(err)
	}

	images, err := srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images)-len(initialImages) != 2 {
		t.Fatalf("Expected 2 new images, found %d.", len(images)-len(initialImages))
	}

	_, err = srv.ImageDelete(imageID, true)
	if err != nil {
		t.Fatal(err)
	}

	images, err = srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images)-len(initialImages) != 1 {
		t.Fatalf("Expected 1 new image, found %d.", len(images)-len(initialImages))
	}

	for _, image := range images {
		if strings.Contains(unitTestImageID, image.ID) {
			continue
		}
		if image.Repository == "" {
			t.Fatalf("Expected tagged image, got untagged one.")
		}
	}
}
<commit_msg>rebase master<commit_after>package docker

import (
	"github.com/dotcloud/docker/utils"
	"strings"
	"testing"
	"time"
)

func TestContainerTagImageDelete(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)

	srv := &Server{runtime: runtime}

	initialImages, err := srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if err := srv.runtime.repositories.Set("utest", "tag1", unitTestImageName, false); err != nil {
		t.Fatal(err)
	}

	if err := srv.runtime.repositories.Set("utest/docker", "tag2", unitTestImageName, false); err != nil {
		t.Fatal(err)
	}
	if err := srv.runtime.repositories.Set("utest:5000/docker", "tag3", unitTestImageName, false); err != nil {
		t.Fatal(err)
	}

	images, err := srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images) != len(initialImages)+3 {
		t.Errorf("Expected %d images, %d found", len(initialImages)+2, len(images))
	}

	if _, err := srv.ImageDelete("utest/docker:tag2", true); err != nil {
		t.Fatal(err)
	}

	images, err = srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images) != len(initialImages)+2 {
		t.Errorf("Expected %d images, %d found", len(initialImages)+2, len(images))
	}

	if _, err := srv.ImageDelete("utest:5000/docker:tag3", true); err != nil {
		t.Fatal(err)
	}

	images, err = srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images) != len(initialImages)+1 {
		t.Errorf("Expected %d images, %d found", len(initialImages)+1, len(images))
	}

	if _, err := srv.ImageDelete("utest:tag1", true); err != nil {
		t.Fatal(err)
	}

	images, err = srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images) != len(initialImages) {
		t.Errorf("Expected %d image, %d found", len(initialImages), len(images))
	}
}

func TestCreateRm(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)

	srv := &Server{runtime: runtime}

	config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	id, err := srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	if len(runtime.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime.List()))
	}

	if err = srv.ContainerDestroy(id, true); err != nil {
		t.Fatal(err)
	}

	if len(runtime.List()) != 0 {
		t.Errorf("Expected 0 container, %v found", len(runtime.List()))
	}

}

func TestCommit(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)

	srv := &Server{runtime: runtime}

	config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "/bin/cat"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	id, err := srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	if _, err := srv.ContainerCommit(id, "testrepo", "testtag", "", "", config); err != nil {
		t.Fatal(err)
	}
}

func TestCreateStartRestartStopStartKillRm(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)

	srv := &Server{runtime: runtime}

	config, hostConfig, _, err := ParseRun([]string{GetTestImage(runtime).ID, "/bin/cat"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	id, err := srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	if len(runtime.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime.List()))
	}

	err = srv.ContainerStart(id, hostConfig)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerRestart(id, 1)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerStop(id, 1)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerStart(id, hostConfig)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerKill(id)
	if err != nil {
		t.Fatal(err)
	}

	// FIXME: this failed once with a race condition ("Unable to remove filesystem for xxx: directory not empty")
	if err = srv.ContainerDestroy(id, true); err != nil {
		t.Fatal(err)
	}

	if len(runtime.List()) != 0 {
		t.Errorf("Expected 0 container, %v found", len(runtime.List()))
	}

}

func TestRunWithTooLowMemoryLimit(t *testing.T) {
	var err error
	runtime := mkRuntime(t)
	srv := &Server{runtime: runtime}
	defer nuke(runtime)
	// Try to create a container with a memory limit of 1 byte less than the minimum allowed limit.
	_, err = srv.ContainerCreate(
		&Config{
			Image:     GetTestImage(runtime).ID,
			Memory:    524287,
			CpuShares: 1000,
			Cmd:       []string{"/bin/cat"},
		},
	)
	if err == nil {
		t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
	}

}

func TestContainerTop(t *testing.T) {
	runtime := mkRuntime(t)
	srv := &Server{runtime: runtime}
	defer nuke(runtime)

	c, hostConfig, _ := mkContainer(runtime, []string{"_", "/bin/sh", "-c", "sleep 2"}, t)
	defer runtime.Destroy(c)
	if err := c.Start(hostConfig); err != nil {
		t.Fatal(err)
	}

	// Give some time to the process to start
	c.WaitTimeout(500 * time.Millisecond)

	if !c.State.Running {
		t.Errorf("Container should be running")
	}
	procs, err := srv.ContainerTop(c.ID, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(procs.Processes) != 2 {
		t.Fatalf("Expected 2 processes, found %d.", len(procs.Processes))
	}

	pos := -1
	for i := 0; i < len(procs.Titles); i++ {
		if procs.Titles[i] == "CMD" {
			pos = i
			break
		}
	}

	if pos == -1 {
		t.Fatalf("Expected CMD, not found.")
	}

	if procs.Processes[0][pos] != "sh" && procs.Processes[0][pos] != "busybox" {
		t.Fatalf("Expected `busybox` or `sh`, found %s.", procs.Processes[0][pos])
	}

	if procs.Processes[1][pos] != "sh" && procs.Processes[1][pos] != "busybox" {
		t.Fatalf("Expected `busybox` or `sh`, found %s.", procs.Processes[1][pos])
	}
}

func TestPools(t *testing.T) {
	runtime := mkRuntime(t)
	srv := &Server{
		runtime:     runtime,
		pullingPool: make(map[string]struct{}),
		pushingPool: make(map[string]struct{}),
	}
	defer nuke(runtime)

	err := srv.poolAdd("pull", "test1")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolAdd("pull", "test2")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolAdd("push", "test1")
	if err == nil || err.Error() != "pull test1 is already in progress" {
		t.Fatalf("Expected `pull test1 is already in progress`")
	}
	err = srv.poolAdd("pull", "test1")
	if err == nil || err.Error() != "pull test1 is already in progress" {
		t.Fatalf("Expected `pull test1 is already in progress`")
	}
	err = srv.poolAdd("wait", "test3")
	if err == nil || err.Error() != "Unkown pool type" {
		t.Fatalf("Expected `Unkown pool type`")
	}

	err = srv.poolRemove("pull", "test2")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolRemove("pull", "test2")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolRemove("pull", "test1")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolRemove("push", "test1")
	if err != nil {
		t.Fatal(err)
	}
	err = srv.poolRemove("wait", "test3")
	if err == nil || err.Error() != "Unkown pool type" {
		t.Fatalf("Expected `Unkown pool type`")
	}
}

func TestLogEvent(t *testing.T) {
	runtime := mkRuntime(t)
	srv := &Server{
		runtime:   runtime,
		events:    make([]utils.JSONMessage, 0, 64),
		listeners: make(map[string]chan utils.JSONMessage),
	}

	srv.LogEvent("fakeaction", "fakeid")

	listener := make(chan utils.JSONMessage)
	srv.Lock()
	srv.listeners["test"] = listener
	srv.Unlock()

	srv.LogEvent("fakeaction2", "fakeid")

	if len(srv.events) != 2 {
		t.Fatalf("Expected 2 events, found %d", len(srv.events))
	}
	go func() {
		time.Sleep(200 * time.Millisecond)
		srv.LogEvent("fakeaction3", "fakeid")
		time.Sleep(200 * time.Millisecond)
		srv.LogEvent("fakeaction4", "fakeid")
	}()

	setTimeout(t, "Listening for events timed out", 2*time.Second, func() {
		for i := 2; i < 4; i++ {
			event := <-listener
			if event != srv.events[i] {
				t.Fatalf("Event received it different than expected")
			}
		}
	})
}

func TestRmi(t *testing.T) {
	runtime := mkRuntime(t)
	defer nuke(runtime)
	srv := &Server{runtime: runtime}

	initialImages, err := srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	config, hostConfig, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	containerID, err := srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	//To remove
	err = srv.ContainerStart(containerID, hostConfig)
	if err != nil {
		t.Fatal(err)
	}

	imageID, err := srv.ContainerCommit(containerID, "test", "", "", "", nil)
	if err != nil {
		t.Fatal(err)
	}

	err = srv.ContainerTag(imageID, "test", "0.1", false)
	if err != nil {
		t.Fatal(err)
	}

	containerID, err = srv.ContainerCreate(config)
	if err != nil {
		t.Fatal(err)
	}

	//To remove
	err = srv.ContainerStart(containerID, hostConfig)
	if err != nil {
		t.Fatal(err)
	}

	_, err = srv.ContainerCommit(containerID, "test", "", "", "", nil)
	if err != nil {
		t.Fatal(err)
	}

	images, err := srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images)-len(initialImages) != 2 {
		t.Fatalf("Expected 2 new images, found %d.", len(images)-len(initialImages))
	}

	_, err = srv.ImageDelete(imageID, true)
	if err != nil {
		t.Fatal(err)
	}

	images, err = srv.Images(false, "")
	if err != nil {
		t.Fatal(err)
	}

	if len(images)-len(initialImages) != 1 {
		t.Fatalf("Expected 1 new image, found %d.", len(images)-len(initialImages))
	}

	for _, image := range images {
		if strings.Contains(unitTestImageID, image.ID) {
			continue
		}
		if image.Repository == "" {
			t.Fatalf("Expected tagged image, got untagged one.")
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

const gitUser = "git"
const gitHome = "/home/git"

const prereceiveScript = `
#!/bin/bash
cat | %s hook
`

func getExitCode(err error) (int, error) {
	exitCode := 0
	if exiterr, ok := err.(*exec.ExitError); ok {
		if procExit := exiterr.Sys().(syscall.WaitStatus); ok {
			return procExit.ExitStatus(), nil
		}
	}
	return exitCode, fmt.Errorf("failed to get exit code")
}

func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
	exitCode = 0
	out, err := cmd.CombinedOutput()
	if err != nil {
		var exiterr error
		if exitCode, exiterr = getExitCode(err); exiterr != nil {
			// TODO: Fix this so we check the error's text.
			// we've failed to retrieve exit code, so we set it to 127
			exitCode = 127
		}
	}
	output = string(out)
	return
}

func runCommand(cmd *exec.Cmd) (exitCode int, err error) {
	exitCode = 0
	err = cmd.Run()
	if err != nil {
		var exiterr error
		if exitCode, exiterr = getExitCode(err); exiterr != nil {
			// TODO: Fix this so we check the error's text.
			// we've failed to retrieve exit code, so we set it to 127
			exitCode = 127
		}
	}
	return
}

func addGitUser(homeDirectory, gitUsername string) {
	userAddCmd := exec.Command("useradd", "-d", homeDirectory, gitUsername)
	if out, _, err := runCommandWithOutput(userAddCmd); err != nil {
		fmt.Printf("failed to execute add user %s\n", out)
		os.Exit(1)
	}

	sshDir := fmt.Sprintf("%s/.ssh", homeDirectory)
	addSshDirCmd := exec.Command("mkdir", "-p", sshDir)
	if _, _, err := runCommandWithOutput(addSshDirCmd); err != nil {
		fmt.Printf("failed to create the .ssh directory\n")
		os.Exit(1)
	}

	sshKeysFile := fmt.Sprintf("%s/.ssh/authorized_keys", homeDirectory)
	addSshKeysFile := exec.Command("touch", sshKeysFile)
	if _, _, err := runCommandWithOutput(addSshKeysFile); err != nil {
		fmt.Printf("failed to touch file\n")
		os.Exit(1)
	}

	changeOWnership := exec.Command("chown", "-R", gitUsername, homeDirectory)
	if _, _, err := runCommandWithOutput(changeOWnership); err != nil {
		fmt.Printf("failed to change ownership\n")
		os.Exit(1)
	}
	fmt.Printf("Created receiver script in %s for user '%s'.\n", homeDirectory, gitUsername)
}

func uploadKey(homeDirectory, gitreceivePath, username string) {
	inputRawKey, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Printf("failed to read key from stdin\n")
		os.Exit(1)
	}
	key := string(inputRawKey)

	// ssh-keygen doesn't read from pipes and sometimes /dev/stdin doesn't work
	// create a temporary file to write the key to it
	createTmpFile := exec.Command("mktemp")
	tmpFilename, _, err := runCommandWithOutput(createTmpFile)
	if err != nil {
		fmt.Printf("failed to create a temporary file\n")
		os.Exit(1)
	}

	tmpFile, err := os.OpenFile(tmpFilename, os.O_RDWR|os.O_CREATE, 0770)
	if err != nil {
		fmt.Printf("failed to open temporary file %s\n", tmpFilename)
		os.Exit(1)
	}

	if _, err := tmpFile.WriteString(key); err != nil {
		fmt.Printf("failed to write key to temporary file %s\n", tmpFilename)
		tmpFile.Close()
		os.Exit(1)
	}
	tmpFile.Close()

	getFingerprint := exec.Command("ssh-keygen", "-lf", tmpFilename)
	rawFingerprint, _, err := runCommandWithOutput(getFingerprint)
	if err != nil {
		fmt.Printf("failed to read key %s %s\n", err, rawFingerprint)
		os.Exit(1)
	}

	splitFingerprint := strings.Split(rawFingerprint, " ")
	if len(splitFingerprint) < 2 {
		fmt.Printf("fingerprint seems invalid: %s\n", rawFingerprint)
		os.Exit(1)
	}

	if err := os.Remove(tmpFilename); err != nil {
		fmt.Printf("failed to remove the temporary file %s\n", tmpFilename)
		os.Exit(1)
	}

	authorizedKeysFilename := fmt.Sprintf("%s/.ssh/authorized_keys", homeDirectory)
	authorizedKeys, err := os.OpenFile(authorizedKeysFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600)
	if err != nil {
		fmt.Printf("failed to open authorized_keys %s\n", authorizedKeysFilename)
		os.Exit(1)
	}
	fingerprint := splitFingerprint[1]

	keyPrefixTemplate := `command=%s run %s %s,no-agent-forwarding,no-pty,no-user-rc,no-X11-forwarding,no-port-forwarding`
	keyPrefix := fmt.Sprintf(keyPrefixTemplate, gitreceivePath, username, fingerprint)
	authorizedKeyEntry := fmt.Sprintf("%s %s", keyPrefix, key)

	if _, err := authorizedKeys.WriteString(authorizedKeyEntry); err != nil {
		fmt.Printf("failed to add key to authorized_keys")
		authorizedKeys.Close()
		os.Exit(1)
	}
	authorizedKeys.Close()

	fmt.Printf("%s\n", fingerprint)
}

func run(gitHome, receiveUser, receiveFingerprint, gitreceivePath string) {
	originalSSHCommand := os.Getenv("SSH_ORIGINAL_COMMAND")
	if len(originalSSHCommand) == 0 {
		fmt.Printf("SSH_ORIGINAL_COMMAND is undefined\n")
		os.Exit(1)
	}

	splitOriginalSSHCommand := strings.Split(originalSSHCommand, " ")
	if len(splitOriginalSSHCommand) < 2 {
		fmt.Printf("SSH_ORIGINAL_COMMAND is too short %s\n", originalSSHCommand)
		os.Exit(1)
	}

	repoRaw := splitOriginalSSHCommand[1]
	for key, value := range splitOriginalSSHCommand {
		splitOriginalSSHCommand[key] = strings.Trim(value, "'")
	}

	repo := strings.Trim(repoRaw, "'")

	repoPath := fmt.Sprintf("%s/%s", gitHome, repo)

	if _, err := os.Stat(repoPath); os.IsNotExist(err) {
		if err := os.Mkdir(repoPath, 0770); err != nil {
			fmt.Printf("failed to create repo directory\n")
			os.Exit(1)
		}
		initRepo := exec.Command("git", "init", "--bare")
		initRepo.Dir = repoPath
		if _, _, err := runCommandWithOutput(initRepo); err != nil {
			fmt.Printf("failed to initialize repository\n")
			os.Exit(1)
		}
	}

	prereceiveHookPath := fmt.Sprintf("%s/hooks/pre-receive", repoPath)
	prereceiveHook, err := os.OpenFile(prereceiveHookPath, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0770)
	if err != nil {
		fmt.Printf("failed to open repo pre-receive hook script\n")
		os.Exit(1)
	}

	renderedPrereceiveScript := fmt.Sprintf(prereceiveScript, gitreceivePath)
	if _, err := prereceiveHook.WriteString(renderedPrereceiveScript); err != nil {
		prereceiveHook.Close()
		fmt.Printf("failed to write repo pre-receive hook script\n")
		os.Exit(1)
	}
	prereceiveHook.Close()
	env := os.Environ()

	receiveUserEnv := fmt.Sprintf("RECEIVE_USER=%s", receiveUser)
	receiveFingerprintEnv := fmt.Sprintf("RECEIVE_FINGERPRINT=%s", receiveFingerprint)
	receiveRepo := fmt.Sprintf("RECEIVE_REPO=%s", repo)
	githomeEnv := fmt.Sprintf("GITHOME=%s", gitHome)

	originalSSHCmd := exec.Command(splitOriginalSSHCommand[0], splitOriginalSSHCommand[1:]...)
	originalSSHCmd.Dir = gitHome
	originalSSHCmd.Env = append(env, receiveUserEnv, receiveFingerprintEnv, receiveRepo, githomeEnv)
	originalSSHCmd.Stdout = os.Stdout
	originalSSHCmd.Stdin = os.Stdin
	originalSSHCmd.Stderr = os.Stderr

	if exitCode, err := runCommand(originalSSHCmd); err != nil {
		fmt.Println(err)
		os.Exit(exitCode)
	}
}

func hook() {
	lineReader := bufio.NewScanner(os.Stdin)

	receiveUser := os.Getenv("RECEIVE_USER")
	receiveFingerprint := os.Getenv("RECEIVE_FINGERPRINT")
	receiveRepo := os.Getenv("RECEIVE_REPO")
	githomeEnv := os.Getenv("GITHOME")

	receiverPath := fmt.Sprintf("%s/receiver", githomeEnv)

	for lineReader.Scan() {
		line := lineReader.Text()
		args := strings.Split(line, " ")
		//oldRev := args[0]
		newRev := args[1]
		refName := args[2]

		if refName != "refs/heads/master" {
			continue
		}

		gitArchiver := exec.Command("git", "archive", newRev)
		receiver := exec.Command(receiverPath, receiveRepo, newRev, receiveUser, receiveFingerprint)
		receiver.Stdin, _ = gitArchiver.StdoutPipe()
		receiver.Stdout = os.Stdout
		err := receiver.Start()
		if err != nil {
			fmt.Printf("push denied - failed to start receiver for %s %s", newRev, err)
			os.Exit(1)
		}
		err = gitArchiver.Run()
		if err != nil {
			fmt.Printf("push denied - failed to run git archiver for %s %s", newRev, err)
			os.Exit(1)
		}
		err = receiver.Wait()
		if err != nil {
			fmt.Printf("push denied - receiver failed to exit cleanly for %s %s", newRev, err)
			os.Exit(1)
		}
	}
}

func main() {
	if len(os.Args) == 1 {
		return
	}

	gitreceivePath := os.Args[0]

	switch os.Args[1] {
	case "init":
		addGitUser(gitHome, gitUser)
	case "upload-key":
		uploadKey(gitHome, gitreceivePath, os.Args[2])
	case "run":
		run(gitHome, os.Args[2], os.Args[3], gitreceivePath)
	case "hook":
		hook()
	}

}
<commit_msg>open authorized_keys, instead of touching it<commit_after>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

const gitUser = "git"
const gitHome = "/home/git"

const prereceiveScript = `
#!/bin/bash
cat | %s hook
`

func getExitCode(err error) (int, error) {
	exitCode := 0
	if exiterr, ok := err.(*exec.ExitError); ok {
		if procExit := exiterr.Sys().(syscall.WaitStatus); ok {
			return procExit.ExitStatus(), nil
		}
	}
	return exitCode, fmt.Errorf("failed to get exit code")
}

func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
	exitCode = 0
	out, err := cmd.CombinedOutput()
	if err != nil {
		var exiterr error
		if exitCode, exiterr = getExitCode(err); exiterr != nil {
			// TODO: Fix this so we check the error's text.
			// we've failed to retrieve exit code, so we set it to 127
			exitCode = 127
		}
	}
	output = string(out)
	return
}

func runCommand(cmd *exec.Cmd) (exitCode int, err error) {
	exitCode = 0
	err = cmd.Run()
	if err != nil {
		var exiterr error
		if exitCode, exiterr = getExitCode(err); exiterr != nil {
			// TODO: Fix this so we check the error's text.
			// we've failed to retrieve exit code, so we set it to 127
			exitCode = 127
		}
	}
	return
}

func addGitUser(homeDirectory, gitUsername string) {
	userAddCmd := exec.Command("useradd", "-d", homeDirectory, gitUsername)
	if out, _, err := runCommandWithOutput(userAddCmd); err != nil {
		fmt.Printf("failed to execute add user %s\n", out)
		os.Exit(1)
	}

	sshDir := fmt.Sprintf("%s/.ssh", homeDirectory)
	addSshDirCmd := exec.Command("mkdir", "-p", sshDir)
	if _, _, err := runCommandWithOutput(addSshDirCmd); err != nil {
		fmt.Printf("failed to create the .ssh directory\n")
		os.Exit(1)
	}

	authorizedKeysFilename := fmt.Sprintf("%s/.ssh/authorized_keys", homeDirectory)
	authorizedKeys, err := os.OpenFile(authorizedKeysFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600)
	if err != nil {
		fmt.Printf("failed to open authorized_keys %s\n", authorizedKeysFilename)
		os.Exit(1)
	}
	authorizedKeys.Close()

	changeOWnership := exec.Command("chown", "-R", gitUsername, homeDirectory)
	if _, _, err := runCommandWithOutput(changeOWnership); err != nil {
		fmt.Printf("failed to change ownership\n")
		os.Exit(1)
	}
	fmt.Printf("Created receiver script in %s for user '%s'.\n", homeDirectory, gitUsername)
}

func uploadKey(homeDirectory, gitreceivePath, username string) {
	inputRawKey, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Printf("failed to read key from stdin\n")
		os.Exit(1)
	}
	key := string(inputRawKey)

	// ssh-keygen doesn't read from pipes and sometimes /dev/stdin doesn't work
	// create a temporary file to write the key to it
	createTmpFile := exec.Command("mktemp")
	tmpFilename, _, err := runCommandWithOutput(createTmpFile)
	if err != nil {
		fmt.Printf("failed to create a temporary file\n")
		os.Exit(1)
	}

	tmpFile, err := os.OpenFile(tmpFilename, os.O_RDWR|os.O_CREATE, 0770)
	if err != nil {
		fmt.Printf("failed to open temporary file %s\n", tmpFilename)
		os.Exit(1)
	}

	if _, err := tmpFile.WriteString(key); err != nil {
		fmt.Printf("failed to write key to temporary file %s\n", tmpFilename)
		tmpFile.Close()
		os.Exit(1)
	}
	tmpFile.Close()

	getFingerprint := exec.Command("ssh-keygen", "-lf", tmpFilename)
	rawFingerprint, _, err := runCommandWithOutput(getFingerprint)
	if err != nil {
		fmt.Printf("failed to read key %s %s\n", err, rawFingerprint)
		os.Exit(1)
	}

	splitFingerprint := strings.Split(rawFingerprint, " ")
	if len(splitFingerprint) < 2 {
		fmt.Printf("fingerprint seems invalid: %s\n", rawFingerprint)
		os.Exit(1)
	}

	if err := os.Remove(tmpFilename); err != nil {
		fmt.Printf("failed to remove the temporary file %s\n", tmpFilename)
		os.Exit(1)
	}

	authorizedKeysFilename := fmt.Sprintf("%s/.ssh/authorized_keys", homeDirectory)
	authorizedKeys, err := os.OpenFile(authorizedKeysFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600)
	if err != nil {
		fmt.Printf("failed to open authorized_keys %s\n", authorizedKeysFilename)
		os.Exit(1)
	}
	fingerprint := splitFingerprint[1]

	keyPrefixTemplate := `command=%s run %s %s,no-agent-forwarding,no-pty,no-user-rc,no-X11-forwarding,no-port-forwarding`
	keyPrefix := fmt.Sprintf(keyPrefixTemplate, gitreceivePath, username, fingerprint)
	authorizedKeyEntry := fmt.Sprintf("%s %s", keyPrefix, key)

	if _, err := authorizedKeys.WriteString(authorizedKeyEntry); err != nil {
		fmt.Printf("failed to add key to authorized_keys")
		authorizedKeys.Close()
		os.Exit(1)
	}
	authorizedKeys.Close()

	fmt.Printf("%s\n", fingerprint)
}

func run(gitHome, receiveUser, receiveFingerprint, gitreceivePath string) {
	originalSSHCommand := os.Getenv("SSH_ORIGINAL_COMMAND")
	if len(originalSSHCommand) == 0 {
		fmt.Printf("SSH_ORIGINAL_COMMAND is undefined\n")
		os.Exit(1)
	}

	splitOriginalSSHCommand := strings.Split(originalSSHCommand, " ")
	if len(splitOriginalSSHCommand) < 2 {
		fmt.Printf("SSH_ORIGINAL_COMMAND is too short %s\n", originalSSHCommand)
		os.Exit(1)
	}

	repoRaw := splitOriginalSSHCommand[1]
	for key, value := range splitOriginalSSHCommand {
		splitOriginalSSHCommand[key] = strings.Trim(value, "'")
	}

	repo := strings.Trim(repoRaw, "'")

	repoPath := fmt.Sprintf("%s/%s", gitHome, repo)

	if _, err := os.Stat(repoPath); os.IsNotExist(err) {
		if err := os.Mkdir(repoPath, 0770); err != nil {
			fmt.Printf("failed to create repo directory\n")
			os.Exit(1)
		}
		initRepo := exec.Command("git", "init", "--bare")
		initRepo.Dir = repoPath
		if _, _, err := runCommandWithOutput(initRepo); err != nil {
			fmt.Printf("failed to initialize repository\n")
			os.Exit(1)
		}
	}

	prereceiveHookPath := fmt.Sprintf("%s/hooks/pre-receive", repoPath)
	prereceiveHook, err := os.OpenFile(prereceiveHookPath, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0770)
	if err != nil {
		fmt.Printf("failed to open repo pre-receive hook script\n")
		os.Exit(1)
	}

	renderedPrereceiveScript := fmt.Sprintf(prereceiveScript, gitreceivePath)
	if _, err := prereceiveHook.WriteString(renderedPrereceiveScript); err != nil {
		prereceiveHook.Close()
		fmt.Printf("failed to write repo pre-receive hook script\n")
		os.Exit(1)
	}
	prereceiveHook.Close()
	env := os.Environ()

	receiveUserEnv := fmt.Sprintf("RECEIVE_USER=%s", receiveUser)
	receiveFingerprintEnv := fmt.Sprintf("RECEIVE_FINGERPRINT=%s", receiveFingerprint)
	receiveRepo := fmt.Sprintf("RECEIVE_REPO=%s", repo)
	githomeEnv := fmt.Sprintf("GITHOME=%s", gitHome)

	originalSSHCmd := exec.Command(splitOriginalSSHCommand[0], splitOriginalSSHCommand[1:]...)
	originalSSHCmd.Dir = gitHome
	originalSSHCmd.Env = append(env, receiveUserEnv, receiveFingerprintEnv, receiveRepo, githomeEnv)
	originalSSHCmd.Stdout = os.Stdout
	originalSSHCmd.Stdin = os.Stdin
	originalSSHCmd.Stderr = os.Stderr

	if exitCode, err := runCommand(originalSSHCmd); err != nil {
		fmt.Println(err)
		os.Exit(exitCode)
	}
}

func hook() {
	lineReader := bufio.NewScanner(os.Stdin)

	receiveUser := os.Getenv("RECEIVE_USER")
	receiveFingerprint := os.Getenv("RECEIVE_FINGERPRINT")
	receiveRepo := os.Getenv("RECEIVE_REPO")
	githomeEnv := os.Getenv("GITHOME")

	receiverPath := fmt.Sprintf("%s/receiver", githomeEnv)

	for lineReader.Scan() {
		line := lineReader.Text()
		args := strings.Split(line, " ")
		//oldRev := args[0]
		newRev := args[1]
		refName := args[2]

		if refName != "refs/heads/master" {
			continue
		}

		gitArchiver := exec.Command("git", "archive", newRev)
		receiver := exec.Command(receiverPath, receiveRepo, newRev, receiveUser, receiveFingerprint)
		receiver.Stdin, _ = gitArchiver.StdoutPipe()
		receiver.Stdout = os.Stdout
		err := receiver.Start()
		if err != nil {
			fmt.Printf("push denied - failed to start receiver for %s %s", newRev, err)
			os.Exit(1)
		}
		err = gitArchiver.Run()
		if err != nil {
			fmt.Printf("push denied - failed to run git archiver for %s %s", newRev, err)
			os.Exit(1)
		}
		err = receiver.Wait()
		if err != nil {
			fmt.Printf("push denied - receiver failed to exit cleanly for %s %s", newRev, err)
			os.Exit(1)
		}
	}
}

func main() {
	if len(os.Args) == 1 {
		return
	}

	gitreceivePath := os.Args[0]

	switch os.Args[1] {
	case "init":
		addGitUser(gitHome, gitUser)
	case "upload-key":
		uploadKey(gitHome, gitreceivePath, os.Args[2])
	case "run":
		run(gitHome, os.Args[2], os.Args[3], gitreceivePath)
	case "hook":
		hook()
	}

}
<|endoftext|>


<commit_before>package velocity

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

	git "gopkg.in/src-d/go-git.v4"
	"gopkg.in/src-d/go-git.v4/plumbing"
)

type Task struct {
	Name        string            `json:"name" yaml:"name"`
	Description string            `json:"description" yaml:"description"`
	Git         TaskGit           `json:"git" yaml:"git"`
	Parameters  []ConfigParameter `json:"parameters" yaml:"parameters"`
	Steps       []Step            `json:"steps" yaml:"steps"`
	runID       string
}

type TaskGit struct {
	Submodule bool `json:"submodule"`
}

// Maybe pass git repository to clone?
func (t *Task) Setup(
	emitter Emitter,
	backupResolver BackupResolver,
	repository *GitRepository,
	commitHash string,
) error {
	t.runID = fmt.Sprintf("vci-%s", time.Now().Format("060102150405"))

	writer := emitter.GetStreamWriter("setup")
	writer.SetStatus(StateRunning)

	// Resolve parameters
	parameters := map[string]Parameter{}
	for _, config := range t.Parameters {
		writer.Write([]byte(fmt.Sprintf("Resolving parameter %s", config.GetInfo())))
		params, err := config.GetParameters(writer, t.runID, backupResolver)
		if err != nil {
			writer.SetStatus(StateFailed)
			log.Printf("could not resolve parameter: %v", err)
		}
		for _, param := range params {
			parameters[param.Name] = param
			writer.Write([]byte(fmt.Sprintf("Added parameter %s", param.Name)))
		}
	}

	// Update params on steps
	for _, s := range t.Steps {
		s.SetParams(parameters)
	}

	// Clone repository if necessary
	if repository != nil {
		repo, dir, err := GitClone(repository, false, true, t.Git.Submodule, writer)
		if err != nil {
			log.Println(err)
			writer.SetStatus(StateFailed)
			writer.Write([]byte(fmt.Sprintf("%s\n### FAILED: %s \x1b[0m", errorANSI, err)))
			return err
		}
		w, err := repo.Worktree()
		if err != nil {
			log.Println(err)
			writer.SetStatus(StateFailed)
			writer.Write([]byte(fmt.Sprintf("%s\n### FAILED: %s \x1b[0m", errorANSI, err)))
			return err
		}
		log.Printf("Checking out %s", commitHash)
		err = w.Checkout(&git.CheckoutOptions{
			Hash: plumbing.NewHash(commitHash),
		})
		if err != nil {
			log.Println(err)
			writer.SetStatus(StateFailed)
			writer.Write([]byte(fmt.Sprintf("%s\n### FAILED: %s \x1b[0m", errorANSI, err)))
			return err
		}
		os.Chdir(dir)
	}

	writer.SetStatus(StateSuccess)
	writer.Write([]byte(""))
	writer.Write([]byte("Setup success.\n"))

	return nil
}

func (t *Task) String() string {
	j, _ := json.Marshal(t)
	return string(j)
}

func NewTask() Task {
	return Task{
		Name:        "",
		Description: "",
		Parameters:  []ConfigParameter{},
		Steps:       []Step{},
	}
}

func (t *Task) UnmarshalJSON(b []byte) error {
	var objMap map[string]*json.RawMessage
	// We'll store the error (if any) so we can return it if necessary
	err := json.Unmarshal(b, &objMap)
	if err != nil {
		return err
	}

	// Deserialize Name
	err = json.Unmarshal(*objMap["name"], &t.Name)
	if err != nil {
		return err
	}

	// Deserialize Description
	err = json.Unmarshal(*objMap["description"], &t.Description)
	if err != nil {
		return err
	}

	// Deserialize Parameters
	var rawParameters []*json.RawMessage
	err = json.Unmarshal(*objMap["parameters"], &rawParameters)
	if err != nil {
		log.Println("could not find parameters")
		return err
	}
	t.Parameters = []ConfigParameter{}
	for _, rawMessage := range rawParameters {
		var m map[string]interface{}
		err = json.Unmarshal(*rawMessage, &m)
		if err != nil {
			log.Println("could not unmarshal parameters")
			return err
		}
		if _, ok := m["use"]; ok { // derivedParam
			p := DerivedParameter{}
			err = json.Unmarshal(*rawMessage, &p)
			if err != nil {
				log.Println("could not unmarshal determined parameter")
				return err
			}
			t.Parameters = append(t.Parameters, p)
		} else if _, ok := m["name"]; ok { // basicParam
			p := BasicParameter{}
			err = json.Unmarshal(*rawMessage, &p)
			if err != nil {
				log.Println("could not unmarshal determined parameter")
				return err
			}
			t.Parameters = append(t.Parameters, p)
		}

	}

	// Deserialize Steps by type
	var rawSteps []*json.RawMessage
	err = json.Unmarshal(*objMap["steps"], &rawSteps)
	if err != nil {
		log.Println("could not find steps")
		return err
	}
	t.Steps = []Step{}
	var m map[string]interface{}
	for _, rawMessage := range rawSteps {
		err = json.Unmarshal(*rawMessage, &m)
		if err != nil {
			log.Println("could not unmarshal step")
			return err
		}

		var s Step
		switch m["type"] {
		case "run":
			s = NewDockerRun()
			break
		case "build":
			s = NewDockerBuild()
			break
		case "compose":
			s = NewDockerCompose()
			break
		// case "plugin":
		// s = NewPlugin()
		default:
			log.Println("could not determine step")
			// return fmt.Errorf("unsupported type in json.Unmarshal: %s", m["type"])
		}
		if s != nil {
			err := json.Unmarshal(*rawMessage, s)
			if err != nil {
				return err
			}
			t.Steps = append(t.Steps, s)
		}
	}

	return nil
}

func (t *Task) UnmarshalYAML(unmarshal func(interface{}) error) error {
	var taskMap map[string]interface{}
	err := unmarshal(&taskMap)
	if err != nil {
		log.Printf("unable to unmarshal task")
		return err
	}

	switch x := taskMap["name"].(type) {
	case string:
		t.Name = x
		break
	}

	switch x := taskMap["description"].(type) {
	case string:
		t.Description = x
		break
	}

	t.Git = TaskGit{
		Submodule: false,
	}
	switch x := taskMap["git"].(type) {
	case map[interface{}]interface{}:
		t.Git = TaskGit{
			Submodule: x["submodule"].(bool),
		}
		break
	}

	t.Parameters = []ConfigParameter{}
	switch x := taskMap["parameters"].(type) {
	case []interface{}:
		for _, p := range x {
			switch y := p.(type) {
			case map[interface{}]interface{}:
				if _, ok := y["use"]; ok { // derivedParam
					var dP DerivedParameter
					dP.UnmarshalYamlInterface(y)
					t.Parameters = append(t.Parameters, dP)
				} else if _, ok := y["name"]; ok { // basicParam
					var bP BasicParameter
					bP.UnmarshalYamlInterface(y)
					t.Parameters = append(t.Parameters, bP)
				}
				break
			}
		}
		break
	}

	t.Steps = []Step{}
	switch x := taskMap["steps"].(type) {
	case []interface{}:
		for _, s := range x {
			switch y := s.(type) {
			case map[interface{}]interface{}:
				switch y["type"] {
				case "run":
					var s DockerRun
					s.UnmarshalYamlInterface(y)
					t.Steps = append(t.Steps, &s)
					break
				case "build":
					var s DockerBuild
					s.UnmarshalYamlInterface(y)
					break
				case "compose":
					var s DockerCompose
					s.UnmarshalYamlInterface(y)
					t.Steps = append(t.Steps, &s)
					break
				// case "plugin":
				// 	var s Plugin
				// 	s.UnmarshalYamlInterface(y)
				// 	break
				default:
					log.Printf("could determine step %s", y["type"])
				}
				break
			}
		}
		break
	}

	// log.Printf("Unmarshalled Task: %+v", t)
	return nil
}
<commit_msg>Fixed YAML unmarshalling step metadata<commit_after>package velocity

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

	git "gopkg.in/src-d/go-git.v4"
	"gopkg.in/src-d/go-git.v4/plumbing"
)

type Task struct {
	Name        string            `json:"name" yaml:"name"`
	Description string            `json:"description" yaml:"description"`
	Git         TaskGit           `json:"git" yaml:"git"`
	Parameters  []ConfigParameter `json:"parameters" yaml:"parameters"`
	Steps       []Step            `json:"steps" yaml:"steps"`
	runID       string
}

type TaskGit struct {
	Submodule bool `json:"submodule"`
}

// Maybe pass git repository to clone?
func (t *Task) Setup(
	emitter Emitter,
	backupResolver BackupResolver,
	repository *GitRepository,
	commitHash string,
) error {
	t.runID = fmt.Sprintf("vci-%s", time.Now().Format("060102150405"))

	writer := emitter.GetStreamWriter("setup")
	writer.SetStatus(StateRunning)

	// Resolve parameters
	parameters := map[string]Parameter{}
	for _, config := range t.Parameters {
		writer.Write([]byte(fmt.Sprintf("Resolving parameter %s", config.GetInfo())))
		params, err := config.GetParameters(writer, t.runID, backupResolver)
		if err != nil {
			writer.SetStatus(StateFailed)
			log.Printf("could not resolve parameter: %v", err)
		}
		for _, param := range params {
			parameters[param.Name] = param
			writer.Write([]byte(fmt.Sprintf("Added parameter %s", param.Name)))
		}
	}

	// Update params on steps
	for _, s := range t.Steps {
		s.SetParams(parameters)
	}

	// Clone repository if necessary
	if repository != nil {
		repo, dir, err := GitClone(repository, false, true, t.Git.Submodule, writer)
		if err != nil {
			log.Println(err)
			writer.SetStatus(StateFailed)
			writer.Write([]byte(fmt.Sprintf("%s\n### FAILED: %s \x1b[0m", errorANSI, err)))
			return err
		}
		w, err := repo.Worktree()
		if err != nil {
			log.Println(err)
			writer.SetStatus(StateFailed)
			writer.Write([]byte(fmt.Sprintf("%s\n### FAILED: %s \x1b[0m", errorANSI, err)))
			return err
		}
		log.Printf("Checking out %s", commitHash)
		err = w.Checkout(&git.CheckoutOptions{
			Hash: plumbing.NewHash(commitHash),
		})
		if err != nil {
			log.Println(err)
			writer.SetStatus(StateFailed)
			writer.Write([]byte(fmt.Sprintf("%s\n### FAILED: %s \x1b[0m", errorANSI, err)))
			return err
		}
		os.Chdir(dir)
	}

	writer.SetStatus(StateSuccess)
	writer.Write([]byte(""))
	writer.Write([]byte("Setup success.\n"))

	return nil
}

func (t *Task) String() string {
	j, _ := json.Marshal(t)
	return string(j)
}

func NewTask() Task {
	return Task{
		Name:        "",
		Description: "",
		Parameters:  []ConfigParameter{},
		Steps:       []Step{},
	}
}

func (t *Task) UnmarshalJSON(b []byte) error {
	var objMap map[string]*json.RawMessage
	// We'll store the error (if any) so we can return it if necessary
	err := json.Unmarshal(b, &objMap)
	if err != nil {
		return err
	}

	// Deserialize Name
	err = json.Unmarshal(*objMap["name"], &t.Name)
	if err != nil {
		return err
	}

	// Deserialize Description
	err = json.Unmarshal(*objMap["description"], &t.Description)
	if err != nil {
		return err
	}

	// Deserialize Parameters
	var rawParameters []*json.RawMessage
	err = json.Unmarshal(*objMap["parameters"], &rawParameters)
	if err != nil {
		log.Println("could not find parameters")
		return err
	}
	t.Parameters = []ConfigParameter{}
	for _, rawMessage := range rawParameters {
		var m map[string]interface{}
		err = json.Unmarshal(*rawMessage, &m)
		if err != nil {
			log.Println("could not unmarshal parameters")
			return err
		}
		if _, ok := m["use"]; ok { // derivedParam
			p := DerivedParameter{}
			err = json.Unmarshal(*rawMessage, &p)
			if err != nil {
				log.Println("could not unmarshal determined parameter")
				return err
			}
			t.Parameters = append(t.Parameters, p)
		} else if _, ok := m["name"]; ok { // basicParam
			p := BasicParameter{}
			err = json.Unmarshal(*rawMessage, &p)
			if err != nil {
				log.Println("could not unmarshal determined parameter")
				return err
			}
			t.Parameters = append(t.Parameters, p)
		}

	}

	// Deserialize Steps by type
	var rawSteps []*json.RawMessage
	err = json.Unmarshal(*objMap["steps"], &rawSteps)
	if err != nil {
		log.Println("could not find steps")
		return err
	}
	t.Steps = []Step{}
	var m map[string]interface{}
	for _, rawMessage := range rawSteps {
		err = json.Unmarshal(*rawMessage, &m)
		if err != nil {
			log.Println("could not unmarshal step")
			return err
		}

		var s Step
		switch m["type"] {
		case "run":
			s = NewDockerRun()
			break
		case "build":
			s = NewDockerBuild()
			break
		case "compose":
			s = NewDockerCompose()
			break
		// case "plugin":
		// s = NewPlugin()
		default:
			log.Printf("could not determine step %s", m["type"])
			// return fmt.Errorf("unsupported type in json.Unmarshal: %s", m["type"])
		}
		if s != nil {
			err := json.Unmarshal(*rawMessage, s)
			if err != nil {
				return err
			}
			t.Steps = append(t.Steps, s)
		}
	}

	return nil
}

func (t *Task) UnmarshalYAML(unmarshal func(interface{}) error) error {
	var taskMap map[string]interface{}
	err := unmarshal(&taskMap)
	if err != nil {
		log.Printf("unable to unmarshal task")
		return err
	}

	switch x := taskMap["name"].(type) {
	case string:
		t.Name = x
		break
	}

	switch x := taskMap["description"].(type) {
	case string:
		t.Description = x
		break
	}

	t.Git = TaskGit{
		Submodule: false,
	}
	switch x := taskMap["git"].(type) {
	case map[interface{}]interface{}:
		t.Git = TaskGit{
			Submodule: x["submodule"].(bool),
		}
		break
	}

	t.Parameters = []ConfigParameter{}
	switch x := taskMap["parameters"].(type) {
	case []interface{}:
		for _, p := range x {
			switch y := p.(type) {
			case map[interface{}]interface{}:
				if _, ok := y["use"]; ok { // derivedParam
					var dP DerivedParameter
					dP.UnmarshalYamlInterface(y)
					t.Parameters = append(t.Parameters, dP)
				} else if _, ok := y["name"]; ok { // basicParam
					var bP BasicParameter
					bP.UnmarshalYamlInterface(y)
					t.Parameters = append(t.Parameters, bP)
				}
				break
			}
		}
		break
	}

	t.Steps = []Step{}
	switch x := taskMap["steps"].(type) {
	case []interface{}:
		for _, s := range x {
			switch y := s.(type) {
			case map[interface{}]interface{}:
				switch y["type"] {
				case "run":
					s := NewDockerRun()
					s.UnmarshalYamlInterface(y)
					t.Steps = append(t.Steps, s)
					break
				case "build":
					s := NewDockerBuild()
					s.UnmarshalYamlInterface(y)
					t.Steps = append(t.Steps, s)
					break
				case "compose":
					s := NewDockerCompose()
					s.UnmarshalYamlInterface(y)
					t.Steps = append(t.Steps, s)
					break
				// case "plugin":
				// 	var s Plugin
				// 	s.UnmarshalYamlInterface(y)
				// 	break
				default:
					log.Printf("could determine step %s", y["type"])
				}
				break
			}
		}
		break
	}

	// log.Printf("Unmarshalled Task: %+v", t)
	return nil
}
<|endoftext|>


<commit_before>// +build gofuzz

package uint256

const (
	opUdivrem = 0
	opMul     = 1
)

func Fuzz(data []byte) int {
	if len(data) != 65 {
		return 0
	}

	op := data[0]

	var x, y Int
	x.SetBytes(data[1:33])
	y.SetBytes(data[33:])

	bx := x.ToBig()
	by := y.ToBig()

	switch op {
	case opUdivrem:
		if y.IsZero() {
			return 0
		}

		var q, r Int
		q.Div(&x, &y)
		r.Mod(&x, &y)
		bx.QuoRem(bx, by, by)
		eq, _ := FromBig(bx)
		er, _ := FromBig(by)

		if !q.Eq(eq) {
			panic("invalid quotient")
		}

		if !r.Eq(er) {
			panic("invalid remainder")
		}

	case opMul:
		var p Int
		p.Mul(&x, &y)

		bx.Mul(bx, by)
		ep, _ := FromBig(bx)

		if !p.Eq(ep) {
			panic("invalid multiplication result")
		}
	}

	return 0
}
<commit_msg>test: Extend the fuzzer<commit_after>// +build gofuzz

package uint256

import (
	"fmt"
	"math/big"
	"reflect"
	"runtime"
)

const (
	opUdivrem = 0
	opMul     = 1
	opLsh     = 2
	opAdd     = 4
	opSub     = 5
)

type opFunc func(*Int, *Int, *Int) *Int
type bigFunc func(*big.Int, *big.Int, *big.Int) *big.Int

func crash(op opFunc, x, y Int, msg string) {
	fn := runtime.FuncForPC(reflect.ValueOf(op).Pointer())
	fnName := fn.Name()
	fnFile, fnLine := fn.FileLine(fn.Entry())
	panic(fmt.Sprintf("%s\nfor %s (%s:%d)\nx: %x\ny: %x", msg, fnName, fnFile, fnLine, &x, &y))
}

func checkOp(op opFunc, bigOp bigFunc, x, y Int) {
	origX := x
	origY := y

	var result Int
	ret := op(&result, &x, &y)
	if ret != &result {
		crash(op, x, y, "returned not the pointer receiver")
	}
	if x != origX {
		crash(op, x, y, "first argument modified")
	}
	if y != origY {
		crash(op, x, y, "second argument modified")
	}

	expected, _ := FromBig(bigOp(new(big.Int), x.ToBig(), y.ToBig()))
	if result != *expected {
		crash(op, x, y, "unexpected result")
	}

	// Test again when the receiver is not zero.
	var garbage Int
	garbage.Xor(&x, &y)
	ret = op(&garbage, &x, &y)
	if ret != &garbage {
		crash(op, x, y, "returned not the pointer receiver")
	}
	if garbage != *expected {
		crash(op, x, y, "unexpected result")
	}
	if x != origX {
		crash(op, x, y, "first argument modified")
	}
	if y != origY {
		crash(op, x, y, "second argument modified")
	}

	// Test again with the receiver aliasing arguments.
	ret = op(&x, &x, &y)
	if ret != &x {
		crash(op, x, y, "returned not the pointer receiver")
	}
	if x != *expected {
		crash(op, x, y, "unexpected result")
	}

	ret = op(&y, &origX, &y)
	if ret != &y {
		crash(op, x, y, "returned not the pointer receiver")
	}
	if y != *expected {
		crash(op, x, y, "unexpected result")
	}
}

func Fuzz(data []byte) int {
	if len(data) != 65 {
		return 0
	}

	op := data[0]

	var x, y Int
	x.SetBytes(data[1:33])
	y.SetBytes(data[33:])

	switch op {
	case opUdivrem:
		if y.IsZero() {
			return 0
		}
		checkOp((*Int).Div, (*big.Int).Div, x, y)
		checkOp((*Int).Mod, (*big.Int).Mod, x, y)

	case opMul:
		checkOp((*Int).Mul, (*big.Int).Mul, x, y)

	case opLsh:
		lsh := func(z, x, y *Int) *Int {
			return z.Lsh(x, uint(y[0]))
		}
		bigLsh := func(z, x, y *big.Int) *big.Int {
			n := uint(y.Uint64())
			if n > 256 {
				n = 256
			}
			return z.Lsh(x, n)
		}
		checkOp(lsh, bigLsh, x, y)

	case opAdd:
		checkOp((*Int).Add, (*big.Int).Add, x, y)

	case opSub:
		checkOp((*Int).Sub, (*big.Int).Sub, x, y)
	}

	return 0
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
)

// Node type
type Node struct {
	Path string // File path
	Size int64  // File size
	Hash string // String form of SHA1 hash
}

func (n *Node) Value() interface{} {
	return n
}

const blockSize = 1024 // Guestimate of a FS block-size for optimal read call

// Calculate hash
func (node *Node) calculateHash(fast bool) string {
	// Open file
	file, err := os.Open(node.Path)
	if err != nil {
		log.Println("WARN", err)
		return ""
	}
	defer file.Close()

	var n int64 // bytes read
	hash := sha1.New()

	if fast && node.Size > blockSize {
		// Make one read call
		_, err = io.CopyN(hash, file, blockSize)

	} else {
		// Filesystem and memory optimal read
		n, err = io.Copy(hash, file)

		// Paranoid sanity check
		if n != node.Size {
			err = errors.New("Partial read: " + node.Path)
			log.Println("WARN", err)
			return ""
		}
	}

	// Check for normal errors
	if err != nil {
		log.Println("WARN", err)
		return ""
	}

	// Add hash value
	return fmt.Sprintf("%0x", hash.Sum(nil))
}
<commit_msg>- Moved dup type definition into node.go and capitalize the type. Dup now embeds Node.<commit_after>package main

import (
	"crypto/sha1"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
)

const blockSize = 1024 // Guestimate of a FS block-size for optimal read call

// Node type
type Node struct {
	Path string // File path
	Size int64  // File size
	Hash string // String form of SHA1 hash
}

func (n *Node) Value() interface{} {
	return n
}

// Calculate hash
func (node *Node) calculateHash(fast bool) string {
	// Open file
	file, err := os.Open(node.Path)
	if err != nil {
		log.Println("WARN", err)
		return ""
	}
	defer file.Close()

	var n int64 // bytes read
	hash := sha1.New()

	if fast && node.Size > blockSize {
		// Make one read call
		_, err = io.CopyN(hash, file, blockSize)

	} else {
		// Filesystem and memory optimal read
		n, err = io.Copy(hash, file)

		// Paranoid sanity check
		if n != node.Size {
			err = errors.New("Partial read: " + node.Path)
			log.Println("WARN", err)
			return ""
		}
	}

	// Check for normal errors
	if err != nil {
		log.Println("WARN", err)
		return ""
	}

	// Add hash value
	return fmt.Sprintf("%0x", hash.Sum(nil))
}

// Dup type describes found duplicate file
type Dup struct {
	Node      // Embed Node type Go type "inheritance"
	Count int // Number of identical copies for the hash
}

// Value implements mapreduce.Value interface
func (d Dup) Value() interface{} {
	return d
}

// Pretty printer
func (d Dup) String() string {
	return fmt.Sprintf("%s:%d:%d:%q", d.Hash, d.Count, d.Size, d.Path)
}
<|endoftext|>