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

package manager

import (
	"flag"
	"fmt"
	"math"
	"sort"
	"sync"
	"time"

	"github.com/docker/docker/pkg/units"
	"github.com/golang/glog"
	"github.com/google/cadvisor/container"
	"github.com/google/cadvisor/info"
	"github.com/google/cadvisor/storage/memory"
	"github.com/google/cadvisor/summary"
	"github.com/google/cadvisor/utils/cpuload"
)

// Housekeeping interval.
var HousekeepingInterval = flag.Duration("housekeeping_interval", 1*time.Second, "Interval between container housekeepings")
var maxHousekeepingInterval = flag.Duration("max_housekeeping_interval", 60*time.Second, "Largest interval to allow between container housekeepings")
var allowDynamicHousekeeping = flag.Bool("allow_dynamic_housekeeping", true, "Whether to allow the housekeeping interval to be dynamic")

// Decay value used for load average smoothing. Interval length of 10 seconds is used.
var loadDecay = math.Exp(float64(-1 * (*HousekeepingInterval).Seconds() / 10))

type containerInfo struct {
	info.ContainerReference
	Subcontainers []info.ContainerReference
	Spec          info.ContainerSpec
}

type containerData struct {
	handler              container.ContainerHandler
	info                 containerInfo
	memoryStorage        *memory.InMemoryStorage
	lock                 sync.Mutex
	loadReader           cpuload.CpuLoadReader
	summaryReader        *summary.StatsSummary
	loadAvg              float64 // smoothed load average seen so far.
	housekeepingInterval time.Duration
	lastUpdatedTime      time.Time
	lastErrorTime        time.Time

	// Whether to log the usage of this container when it is updated.
	logUsage bool

	// Tells the container to stop.
	stop chan bool
}

func (c *containerData) Start() error {
	go c.housekeeping()
	return nil
}

func (c *containerData) Stop() error {
	c.stop <- true
	return nil
}

func (c *containerData) allowErrorLogging() bool {
	if time.Since(c.lastErrorTime) > time.Minute {
		c.lastErrorTime = time.Now()
		return true
	}
	return false
}

func (c *containerData) GetInfo() (*containerInfo, error) {
	// Get spec and subcontainers.
	if time.Since(c.lastUpdatedTime) > 5*time.Second {
		err := c.updateSpec()
		if err != nil {
			return nil, err
		}
		err = c.updateSubcontainers()
		if err != nil {
			return nil, err
		}
		c.lastUpdatedTime = time.Now()
	}
	// Make a copy of the info for the user.
	c.lock.Lock()
	defer c.lock.Unlock()
	return &c.info, nil
}

func (c *containerData) DerivedStats() (info.DerivedStats, error) {
	if c.summaryReader == nil {
		return info.DerivedStats{}, fmt.Errorf("derived stats not enabled for container %q", c.info.Name)
	}
	return c.summaryReader.DerivedStats()
}

func newContainerData(containerName string, memoryStorage *memory.InMemoryStorage, handler container.ContainerHandler, loadReader cpuload.CpuLoadReader, logUsage bool) (*containerData, error) {
	if memoryStorage == nil {
		return nil, fmt.Errorf("nil memory storage")
	}
	if handler == nil {
		return nil, fmt.Errorf("nil container handler")
	}
	ref, err := handler.ContainerReference()
	if err != nil {
		return nil, err
	}

	cont := &containerData{
		handler:              handler,
		memoryStorage:        memoryStorage,
		housekeepingInterval: *HousekeepingInterval,
		loadReader:           loadReader,
		logUsage:             logUsage,
		loadAvg:              -1.0, // negative value indicates uninitialized.
		stop:                 make(chan bool, 1),
	}
	cont.info.ContainerReference = ref

	err = cont.updateSpec()
	if err != nil {
		return nil, err
	}
	cont.summaryReader, err = summary.New(cont.info.Spec)
	if err != nil {
		cont.summaryReader = nil
		glog.Warningf("Failed to create summary reader for %q: %v", ref.Name, err)
	}

	return cont, nil
}

// Determine when the next housekeeping should occur.
func (self *containerData) nextHousekeeping(lastHousekeeping time.Time) time.Time {
	if *allowDynamicHousekeeping {
		var empty time.Time
		stats, err := self.memoryStorage.RecentStats(self.info.Name, empty, empty, 2)
		if err != nil {
			if self.allowErrorLogging() {
				glog.Warningf("Failed to get RecentStats(%q) while determining the next housekeeping: %v", self.info.Name, err)
			}
		} else if len(stats) == 2 {
			// TODO(vishnuk): Use no processes as a signal.
			// Raise the interval if usage hasn't changed in the last housekeeping.
			if stats[0].StatsEq(stats[1]) && (self.housekeepingInterval < *maxHousekeepingInterval) {
				self.housekeepingInterval *= 2
				if self.housekeepingInterval > *maxHousekeepingInterval {
					self.housekeepingInterval = *maxHousekeepingInterval
				}
				glog.V(3).Infof("Raising housekeeping interval for %q to %v", self.info.Name, self.housekeepingInterval)
			} else if self.housekeepingInterval != *HousekeepingInterval {
				// Lower interval back to the baseline.
				self.housekeepingInterval = *HousekeepingInterval
				glog.V(3).Infof("Lowering housekeeping interval for %q to %v", self.info.Name, self.housekeepingInterval)
			}
		}
	}

	return lastHousekeeping.Add(self.housekeepingInterval)
}

func (c *containerData) housekeeping() {
	// Long housekeeping is either 100ms or half of the housekeeping interval.
	longHousekeeping := 100 * time.Millisecond
	if *HousekeepingInterval/2 < longHousekeeping {
		longHousekeeping = *HousekeepingInterval / 2
	}

	// Housekeep every second.
	glog.Infof("Start housekeeping for container %q\n", c.info.Name)
	lastHousekeeping := time.Now()
	for {
		select {
		case <-c.stop:
			// Stop housekeeping when signaled.
			return
		default:
			// Perform housekeeping.
			start := time.Now()
			c.housekeepingTick()

			// Log if housekeeping took too long.
			duration := time.Since(start)
			if duration >= longHousekeeping {
				glog.V(2).Infof("[%s] Housekeeping took %s", c.info.Name, duration)
			}
		}

		// Log usage if asked to do so.
		if c.logUsage {
			const numSamples = 60
			var empty time.Time
			stats, err := c.memoryStorage.RecentStats(c.info.Name, empty, empty, numSamples)
			if err != nil {
				if c.allowErrorLogging() {
					glog.Infof("[%s] Failed to get recent stats for logging usage: %v", c.info.Name, err)
				}
			} else if len(stats) < numSamples {
				// Ignore, not enough stats yet.
			} else {
				usageCpuNs := uint64(0)
				for i := range stats {
					if i > 0 {
						usageCpuNs += (stats[i].Cpu.Usage.Total - stats[i-1].Cpu.Usage.Total)
					}
				}
				usageMemory := stats[numSamples-1].Memory.Usage

				instantUsageInCores := float64(stats[numSamples-1].Cpu.Usage.Total-stats[numSamples-2].Cpu.Usage.Total) / float64(stats[numSamples-1].Timestamp.Sub(stats[numSamples-2].Timestamp).Nanoseconds())
				usageInCores := float64(usageCpuNs) / float64(stats[numSamples-1].Timestamp.Sub(stats[0].Timestamp).Nanoseconds())
				usageInHuman := units.HumanSize(int64(usageMemory))
				glog.Infof("[%s] %.3f cores (average: %.3f cores), %s of memory", c.info.Name, instantUsageInCores, usageInCores, usageInHuman)
			}
		}

		// Schedule the next housekeeping. Sleep until that time.
		nextHousekeeping := c.nextHousekeeping(lastHousekeeping)
		if time.Now().Before(nextHousekeeping) {
			time.Sleep(nextHousekeeping.Sub(time.Now()))
		}
		lastHousekeeping = nextHousekeeping
	}
}

func (c *containerData) housekeepingTick() {
	err := c.updateStats()
	if err != nil {
		if c.allowErrorLogging() {
			glog.Infof("Failed to update stats for container \"%s\": %s", c.info.Name, err)
		}
	}
}

func (c *containerData) updateSpec() error {
	spec, err := c.handler.GetSpec()
	if err != nil {
		// Ignore errors if the container is dead.
		if !c.handler.Exists() {
			return nil
		}
		return err
	}
	c.lock.Lock()
	defer c.lock.Unlock()
	c.info.Spec = spec
	return nil
}

// Calculate new smoothed load average using the new sample of runnable threads.
// The decay used ensures that the load will stabilize on a new constant value within
// 10 seconds.
func (c *containerData) updateLoad(newLoad uint64) {
	if c.loadAvg < 0 {
		c.loadAvg = float64(newLoad) // initialize to the first seen sample for faster stabilization.
	} else {
		c.loadAvg = c.loadAvg*loadDecay + float64(newLoad)*(1.0-loadDecay)
	}
	glog.V(3).Infof("New load for %q: %v. latest sample: %d", c.info.Name, c.loadAvg, newLoad)
}

func (c *containerData) updateStats() error {
	stats, statsErr := c.handler.GetStats()
	if statsErr != nil {
		// Ignore errors if the container is dead.
		if !c.handler.Exists() {
			return nil
		}

		// Stats may be partially populated, push those before we return an error.
		statsErr = fmt.Errorf("%v, continuing to push stats", statsErr)
	}
	if stats == nil {
		return statsErr
	}
	if c.loadReader != nil {
		// TODO(vmarmol): Cache this path.
		path, err := c.handler.GetCgroupPath("cpu")
		if err == nil {
			loadStats, err := c.loadReader.GetCpuLoad(c.info.Name, path)
			if err != nil {
				return fmt.Errorf("failed to get load stat for %q - path %q, error %s", c.info.Name, path, err)
			}
			stats.TaskStats = loadStats
			c.updateLoad(loadStats.NrRunning)
			// convert to 'milliLoad' to avoid floats and preserve precision.
			stats.Cpu.LoadAverage = int32(c.loadAvg * 1000)
		}
	}
	if c.summaryReader != nil {
		err := c.summaryReader.AddSample(*stats)
		if err != nil {
			// Ignore summary errors for now.
			glog.V(2).Infof("failed to add summary stats for %q: %v", c.info.Name, err)
		}
	}
	ref, err := c.handler.ContainerReference()
	if err != nil {
		// Ignore errors if the container is dead.
		if !c.handler.Exists() {
			return nil
		}
		return err
	}
	err = c.memoryStorage.AddStats(ref, stats)
	if err != nil {
		return err
	}
	return statsErr
}

func (c *containerData) updateSubcontainers() error {
	var subcontainers info.ContainerReferenceSlice
	subcontainers, err := c.handler.ListContainers(container.ListSelf)
	if err != nil {
		// Ignore errors if the container is dead.
		if !c.handler.Exists() {
			return nil
		}
		return err
	}
	sort.Sort(subcontainers)
	c.lock.Lock()
	defer c.lock.Unlock()
	c.info.Subcontainers = subcontainers
	return nil
}
<commit_msg>Changes to use new version of Docker packages.<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package manager

import (
	"flag"
	"fmt"
	"math"
	"sort"
	"sync"
	"time"

	"github.com/docker/docker/pkg/units"
	"github.com/golang/glog"
	"github.com/google/cadvisor/container"
	"github.com/google/cadvisor/info"
	"github.com/google/cadvisor/storage/memory"
	"github.com/google/cadvisor/summary"
	"github.com/google/cadvisor/utils/cpuload"
)

// Housekeeping interval.
var HousekeepingInterval = flag.Duration("housekeeping_interval", 1*time.Second, "Interval between container housekeepings")
var maxHousekeepingInterval = flag.Duration("max_housekeeping_interval", 60*time.Second, "Largest interval to allow between container housekeepings")
var allowDynamicHousekeeping = flag.Bool("allow_dynamic_housekeeping", true, "Whether to allow the housekeeping interval to be dynamic")

// Decay value used for load average smoothing. Interval length of 10 seconds is used.
var loadDecay = math.Exp(float64(-1 * (*HousekeepingInterval).Seconds() / 10))

type containerInfo struct {
	info.ContainerReference
	Subcontainers []info.ContainerReference
	Spec          info.ContainerSpec
}

type containerData struct {
	handler              container.ContainerHandler
	info                 containerInfo
	memoryStorage        *memory.InMemoryStorage
	lock                 sync.Mutex
	loadReader           cpuload.CpuLoadReader
	summaryReader        *summary.StatsSummary
	loadAvg              float64 // smoothed load average seen so far.
	housekeepingInterval time.Duration
	lastUpdatedTime      time.Time
	lastErrorTime        time.Time

	// Whether to log the usage of this container when it is updated.
	logUsage bool

	// Tells the container to stop.
	stop chan bool
}

func (c *containerData) Start() error {
	go c.housekeeping()
	return nil
}

func (c *containerData) Stop() error {
	c.stop <- true
	return nil
}

func (c *containerData) allowErrorLogging() bool {
	if time.Since(c.lastErrorTime) > time.Minute {
		c.lastErrorTime = time.Now()
		return true
	}
	return false
}

func (c *containerData) GetInfo() (*containerInfo, error) {
	// Get spec and subcontainers.
	if time.Since(c.lastUpdatedTime) > 5*time.Second {
		err := c.updateSpec()
		if err != nil {
			return nil, err
		}
		err = c.updateSubcontainers()
		if err != nil {
			return nil, err
		}
		c.lastUpdatedTime = time.Now()
	}
	// Make a copy of the info for the user.
	c.lock.Lock()
	defer c.lock.Unlock()
	return &c.info, nil
}

func (c *containerData) DerivedStats() (info.DerivedStats, error) {
	if c.summaryReader == nil {
		return info.DerivedStats{}, fmt.Errorf("derived stats not enabled for container %q", c.info.Name)
	}
	return c.summaryReader.DerivedStats()
}

func newContainerData(containerName string, memoryStorage *memory.InMemoryStorage, handler container.ContainerHandler, loadReader cpuload.CpuLoadReader, logUsage bool) (*containerData, error) {
	if memoryStorage == nil {
		return nil, fmt.Errorf("nil memory storage")
	}
	if handler == nil {
		return nil, fmt.Errorf("nil container handler")
	}
	ref, err := handler.ContainerReference()
	if err != nil {
		return nil, err
	}

	cont := &containerData{
		handler:              handler,
		memoryStorage:        memoryStorage,
		housekeepingInterval: *HousekeepingInterval,
		loadReader:           loadReader,
		logUsage:             logUsage,
		loadAvg:              -1.0, // negative value indicates uninitialized.
		stop:                 make(chan bool, 1),
	}
	cont.info.ContainerReference = ref

	err = cont.updateSpec()
	if err != nil {
		return nil, err
	}
	cont.summaryReader, err = summary.New(cont.info.Spec)
	if err != nil {
		cont.summaryReader = nil
		glog.Warningf("Failed to create summary reader for %q: %v", ref.Name, err)
	}

	return cont, nil
}

// Determine when the next housekeeping should occur.
func (self *containerData) nextHousekeeping(lastHousekeeping time.Time) time.Time {
	if *allowDynamicHousekeeping {
		var empty time.Time
		stats, err := self.memoryStorage.RecentStats(self.info.Name, empty, empty, 2)
		if err != nil {
			if self.allowErrorLogging() {
				glog.Warningf("Failed to get RecentStats(%q) while determining the next housekeeping: %v", self.info.Name, err)
			}
		} else if len(stats) == 2 {
			// TODO(vishnuk): Use no processes as a signal.
			// Raise the interval if usage hasn't changed in the last housekeeping.
			if stats[0].StatsEq(stats[1]) && (self.housekeepingInterval < *maxHousekeepingInterval) {
				self.housekeepingInterval *= 2
				if self.housekeepingInterval > *maxHousekeepingInterval {
					self.housekeepingInterval = *maxHousekeepingInterval
				}
				glog.V(3).Infof("Raising housekeeping interval for %q to %v", self.info.Name, self.housekeepingInterval)
			} else if self.housekeepingInterval != *HousekeepingInterval {
				// Lower interval back to the baseline.
				self.housekeepingInterval = *HousekeepingInterval
				glog.V(3).Infof("Lowering housekeeping interval for %q to %v", self.info.Name, self.housekeepingInterval)
			}
		}
	}

	return lastHousekeeping.Add(self.housekeepingInterval)
}

func (c *containerData) housekeeping() {
	// Long housekeeping is either 100ms or half of the housekeeping interval.
	longHousekeeping := 100 * time.Millisecond
	if *HousekeepingInterval/2 < longHousekeeping {
		longHousekeeping = *HousekeepingInterval / 2
	}

	// Housekeep every second.
	glog.Infof("Start housekeeping for container %q\n", c.info.Name)
	lastHousekeeping := time.Now()
	for {
		select {
		case <-c.stop:
			// Stop housekeeping when signaled.
			return
		default:
			// Perform housekeeping.
			start := time.Now()
			c.housekeepingTick()

			// Log if housekeeping took too long.
			duration := time.Since(start)
			if duration >= longHousekeeping {
				glog.V(2).Infof("[%s] Housekeeping took %s", c.info.Name, duration)
			}
		}

		// Log usage if asked to do so.
		if c.logUsage {
			const numSamples = 60
			var empty time.Time
			stats, err := c.memoryStorage.RecentStats(c.info.Name, empty, empty, numSamples)
			if err != nil {
				if c.allowErrorLogging() {
					glog.Infof("[%s] Failed to get recent stats for logging usage: %v", c.info.Name, err)
				}
			} else if len(stats) < numSamples {
				// Ignore, not enough stats yet.
			} else {
				usageCpuNs := uint64(0)
				for i := range stats {
					if i > 0 {
						usageCpuNs += (stats[i].Cpu.Usage.Total - stats[i-1].Cpu.Usage.Total)
					}
				}
				usageMemory := stats[numSamples-1].Memory.Usage

				instantUsageInCores := float64(stats[numSamples-1].Cpu.Usage.Total-stats[numSamples-2].Cpu.Usage.Total) / float64(stats[numSamples-1].Timestamp.Sub(stats[numSamples-2].Timestamp).Nanoseconds())
				usageInCores := float64(usageCpuNs) / float64(stats[numSamples-1].Timestamp.Sub(stats[0].Timestamp).Nanoseconds())
				usageInHuman := units.HumanSize(float64(usageMemory))
				glog.Infof("[%s] %.3f cores (average: %.3f cores), %s of memory", c.info.Name, instantUsageInCores, usageInCores, usageInHuman)
			}
		}

		// Schedule the next housekeeping. Sleep until that time.
		nextHousekeeping := c.nextHousekeeping(lastHousekeeping)
		if time.Now().Before(nextHousekeeping) {
			time.Sleep(nextHousekeeping.Sub(time.Now()))
		}
		lastHousekeeping = nextHousekeeping
	}
}

func (c *containerData) housekeepingTick() {
	err := c.updateStats()
	if err != nil {
		if c.allowErrorLogging() {
			glog.Infof("Failed to update stats for container \"%s\": %s", c.info.Name, err)
		}
	}
}

func (c *containerData) updateSpec() error {
	spec, err := c.handler.GetSpec()
	if err != nil {
		// Ignore errors if the container is dead.
		if !c.handler.Exists() {
			return nil
		}
		return err
	}
	c.lock.Lock()
	defer c.lock.Unlock()
	c.info.Spec = spec
	return nil
}

// Calculate new smoothed load average using the new sample of runnable threads.
// The decay used ensures that the load will stabilize on a new constant value within
// 10 seconds.
func (c *containerData) updateLoad(newLoad uint64) {
	if c.loadAvg < 0 {
		c.loadAvg = float64(newLoad) // initialize to the first seen sample for faster stabilization.
	} else {
		c.loadAvg = c.loadAvg*loadDecay + float64(newLoad)*(1.0-loadDecay)
	}
	glog.V(3).Infof("New load for %q: %v. latest sample: %d", c.info.Name, c.loadAvg, newLoad)
}

func (c *containerData) updateStats() error {
	stats, statsErr := c.handler.GetStats()
	if statsErr != nil {
		// Ignore errors if the container is dead.
		if !c.handler.Exists() {
			return nil
		}

		// Stats may be partially populated, push those before we return an error.
		statsErr = fmt.Errorf("%v, continuing to push stats", statsErr)
	}
	if stats == nil {
		return statsErr
	}
	if c.loadReader != nil {
		// TODO(vmarmol): Cache this path.
		path, err := c.handler.GetCgroupPath("cpu")
		if err == nil {
			loadStats, err := c.loadReader.GetCpuLoad(c.info.Name, path)
			if err != nil {
				return fmt.Errorf("failed to get load stat for %q - path %q, error %s", c.info.Name, path, err)
			}
			stats.TaskStats = loadStats
			c.updateLoad(loadStats.NrRunning)
			// convert to 'milliLoad' to avoid floats and preserve precision.
			stats.Cpu.LoadAverage = int32(c.loadAvg * 1000)
		}
	}
	if c.summaryReader != nil {
		err := c.summaryReader.AddSample(*stats)
		if err != nil {
			// Ignore summary errors for now.
			glog.V(2).Infof("failed to add summary stats for %q: %v", c.info.Name, err)
		}
	}
	ref, err := c.handler.ContainerReference()
	if err != nil {
		// Ignore errors if the container is dead.
		if !c.handler.Exists() {
			return nil
		}
		return err
	}
	err = c.memoryStorage.AddStats(ref, stats)
	if err != nil {
		return err
	}
	return statsErr
}

func (c *containerData) updateSubcontainers() error {
	var subcontainers info.ContainerReferenceSlice
	subcontainers, err := c.handler.ListContainers(container.ListSelf)
	if err != nil {
		// Ignore errors if the container is dead.
		if !c.handler.Exists() {
			return nil
		}
		return err
	}
	sort.Sort(subcontainers)
	c.lock.Lock()
	defer c.lock.Unlock()
	c.info.Subcontainers = subcontainers
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"net/http"
	"testing"
)

func TestReconstructRequest(t *testing.T) {
	req, _ := http.NewRequest("GET", "http://example.com", nil)

	// changing payload so we don't have to call middleware
	request := requestDetails{
		Path:        "/random-path",
		Method:      "POST",
		Query:       "?foo=bar",
		Destination: "changed.destination.com",
	}
	payload := Payload{Request: request}

	c := NewConstructor(req, payload)
	newRequest := c.reconstructRequest()
	expect(t, newRequest.Method, "POST")
	expect(t, newRequest.URL.Path, "/random-path")
	expect(t, newRequest.Host, "changed.destination.com")
	expect(t, newRequest.URL.RawQuery, "?foo=bar")
}

func TestReconstructRequestBodyPayload(t *testing.T) {
	req, _ := http.NewRequest("GET", "http://example.com", nil)

	payload := Payload{}
	c := NewConstructor(req, payload)
	c.payload.Request.Method = "OPTIONS"
	c.payload.Request.Destination = "newdestination"
	c.payload.Request.Body = "new request body here"

	newRequest := c.reconstructRequest()

	expect(t, newRequest.Method, "OPTIONS")
	expect(t, newRequest.Host, "newdestination")

	body, err := ioutil.ReadAll(newRequest.Body)

	expect(t, err, nil)
	expect(t, string(body), "new request body here")
}
<commit_msg>covering header creation with tests<commit_after>package main

import (
	"io/ioutil"
	"net/http"
	"testing"
)

func TestReconstructRequest(t *testing.T) {
	req, _ := http.NewRequest("GET", "http://example.com", nil)

	// changing payload so we don't have to call middleware
	request := requestDetails{
		Path:        "/random-path",
		Method:      "POST",
		Query:       "?foo=bar",
		Destination: "changed.destination.com",
	}
	payload := Payload{Request: request}

	c := NewConstructor(req, payload)
	newRequest := c.reconstructRequest()
	expect(t, newRequest.Method, "POST")
	expect(t, newRequest.URL.Path, "/random-path")
	expect(t, newRequest.Host, "changed.destination.com")
	expect(t, newRequest.URL.RawQuery, "?foo=bar")
}

func TestReconstructRequestBodyPayload(t *testing.T) {
	req, _ := http.NewRequest("GET", "http://example.com", nil)

	payload := Payload{}
	c := NewConstructor(req, payload)
	c.payload.Request.Method = "OPTIONS"
	c.payload.Request.Destination = "newdestination"
	c.payload.Request.Body = "new request body here"

	newRequest := c.reconstructRequest()

	expect(t, newRequest.Method, "OPTIONS")
	expect(t, newRequest.Host, "newdestination")

	body, err := ioutil.ReadAll(newRequest.Body)

	expect(t, err, nil)
	expect(t, string(body), "new request body here")
}

func TestReconstructRequestHeadersPayload(t *testing.T) {
	req, _ := http.NewRequest("GET", "http://example.com", nil)

	req.Header.Set("Header", "ValueX")

	payload := Payload{}
	c := NewConstructor(req, payload)
	c.payload.Request.Headers = req.Header

	newRequest := c.reconstructRequest()

	expect(t, newRequest.Header.Get("Header"), "ValueX")
}

func TestReconstructResponseHeadersPayload(t *testing.T) {
	req, _ := http.NewRequest("GET", "http://example.com", nil)

	payload := Payload{}

	payload.Response.Status = 201
	payload.Response.Body = "body here"

	headers := make(map[string][]string)
	headers["Header"] = []string{"one"}

	payload.Response.Headers = headers

	c := NewConstructor(req, payload)

	response := c.reconstructResponse()

	expect(t, response.Header.Get("Header"), headers["Header"][0])

}
<|endoftext|>


<commit_before>package queue

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"sync"
	"time"

	"github.com/StackExchange/tcollector/opentsdb"
)

var l = log.New(os.Stdout, "", log.LstdFlags)

type Queue struct {
	sync.Mutex
	host  string
	queue opentsdb.MultiDataPoint
	c     chan *opentsdb.DataPoint
}

// Creates and starts a new Queue.
func New(host string, c chan *opentsdb.DataPoint) *Queue {
	q := Queue{
		host: host,
		c:    c,
	}

	go func() {
		for dp := range c {
			q.Lock()
			q.queue = append(q.queue, dp)
			q.Unlock()
		}
	}()
	go q.send()
	return &q
}

const MAX_PERSEC = 50

func (q *Queue) send() {
	for {
		if len(q.queue) > 0 {
			q.Lock()
			i := len(q.queue)
			if i > MAX_PERSEC {
				i = MAX_PERSEC
			}
			sending := q.queue[:i]
			q.queue = q.queue[i:]
			go q.sendBatch(sending)
			q.Unlock()
		} else {
			time.Sleep(time.Second)
		}
	}
}

func (q *Queue) sendBatch(batch opentsdb.MultiDataPoint) {
	fmt.Println("sending", len(batch))
	b, err := batch.Json()
	if err != nil {
		l.Println(err)
		// bad JSON encoding, just give up
		return
	}
	resp, err := http.Post(q.host, "application/json", bytes.NewReader(b))
	if err != nil {
		l.Println(err)
		goto Err
	}
	if resp.StatusCode != http.StatusNoContent {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			l.Println(err)
		} else if len(body) > 0 {
			l.Println(string(body))
		}
		goto Err
	}
	return
Err:
	l.Println("error, restoring", len(batch))
	for _, dp := range batch {
		q.c <- dp
	}
}
<commit_msg>cmd/scollector: Use log instead of fmt<commit_after>package queue

import (
	"bytes"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"sync"
	"time"

	"github.com/StackExchange/tcollector/opentsdb"
)

var l = log.New(os.Stdout, "", log.LstdFlags)

type Queue struct {
	sync.Mutex
	host  string
	queue opentsdb.MultiDataPoint
	c     chan *opentsdb.DataPoint
}

// Creates and starts a new Queue.
func New(host string, c chan *opentsdb.DataPoint) *Queue {
	q := Queue{
		host: host,
		c:    c,
	}

	go func() {
		for dp := range c {
			q.Lock()
			q.queue = append(q.queue, dp)
			q.Unlock()
		}
	}()
	go q.send()
	return &q
}

const MAX_PERSEC = 50

func (q *Queue) send() {
	for {
		if len(q.queue) > 0 {
			q.Lock()
			i := len(q.queue)
			if i > MAX_PERSEC {
				i = MAX_PERSEC
			}
			sending := q.queue[:i]
			q.queue = q.queue[i:]
			go q.sendBatch(sending)
			q.Unlock()
		} else {
			time.Sleep(time.Second)
		}
	}
}

func (q *Queue) sendBatch(batch opentsdb.MultiDataPoint) {
	l.Println("sending", len(batch))
	b, err := batch.Json()
	if err != nil {
		l.Println(err)
		// bad JSON encoding, just give up
		return
	}
	resp, err := http.Post(q.host, "application/json", bytes.NewReader(b))
	if err != nil {
		l.Println(err)
		goto Err
	}
	if resp.StatusCode != http.StatusNoContent {
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			l.Println(err)
		} else if len(body) > 0 {
			l.Println(string(body))
		}
		goto Err
	}
	return
Err:
	l.Println("error, restoring", len(batch))
	for _, dp := range batch {
		q.c <- dp
	}
}
<|endoftext|>


<commit_before>package common

import (
	"crypto/tls"
	"net"
	"strings"
	"time"

	"github.com/docker/swarmkit/api"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

// Dial establishes a connection and creates a client.
// It infers connection parameters from CLI options.
func Dial(cmd *cobra.Command) (api.ControlClient, error) {
	conn, err := DialConn(cmd)
	if err != nil {
		return nil, err
	}

	return api.NewControlClient(conn), nil
}

// DialConn establishes a connection to SwarmKit.
func DialConn(cmd *cobra.Command) (*grpc.ClientConn, error) {
	addr, err := cmd.Flags().GetString("socket")
	if err != nil {
		return nil, err
	}

	opts := []grpc.DialOption{}
	insecureCreds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
	opts = append(opts, grpc.WithTransportCredentials(insecureCreds))
	opts = append(opts, grpc.WithDialer(
		func(addr string, timeout time.Duration) (net.Conn, error) {
			return net.DialTimeout("unix", addr, timeout)
		}))
	conn, err := grpc.Dial(addr, opts...)
	if err != nil {
		return nil, err
	}

	return conn, nil
}

// Context returns a request context based on CLI arguments.
func Context(cmd *cobra.Command) context.Context {
	// TODO(aluzzardi): Actually create a context.
	return context.TODO()
}

// ParseLogDriverFlags parses a silly string format for log driver and options.
// Fully baked log driver config should be returned.
//
// If no log driver is available, nil, nil will be returned.
func ParseLogDriverFlags(flags *pflag.FlagSet) (*api.Driver, error) {
	if !flags.Changed("log-driver") {
		return nil, nil
	}

	name, err := flags.GetString("log-driver")
	if err != nil {
		return nil, err
	}

	var opts map[string]string
	if flags.Changed("log-opt") {
		rawOpts, err := flags.GetStringSlice("log-opt")
		if err != nil {
			return nil, err
		}

		opts = make(map[string]string, len(rawOpts))
		for _, rawOpt := range rawOpts {
			parts := strings.SplitN(rawOpt, "=", 2)
			if len(parts) == 1 {
				opts[parts[0]] = ""
				continue
			}

			opts[parts[0]] = parts[1]
		}
	}

	return &api.Driver{
		Name:    name,
		Options: opts,
	}, nil
}
<commit_msg>use xnet.DialTimeoutLocal for swarmctl grpc Dialer<commit_after>package common

import (
	"crypto/tls"
	"net"
	"strings"
	"time"

	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/xnet"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

// Dial establishes a connection and creates a client.
// It infers connection parameters from CLI options.
func Dial(cmd *cobra.Command) (api.ControlClient, error) {
	conn, err := DialConn(cmd)
	if err != nil {
		return nil, err
	}

	return api.NewControlClient(conn), nil
}

// DialConn establishes a connection to SwarmKit.
func DialConn(cmd *cobra.Command) (*grpc.ClientConn, error) {
	addr, err := cmd.Flags().GetString("socket")
	if err != nil {
		return nil, err
	}

	opts := []grpc.DialOption{}
	insecureCreds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
	opts = append(opts, grpc.WithTransportCredentials(insecureCreds))
	opts = append(opts, grpc.WithDialer(
		func(addr string, timeout time.Duration) (net.Conn, error) {
			return xnet.DialTimeoutLocal(addr, timeout)
		}))
	conn, err := grpc.Dial(addr, opts...)
	if err != nil {
		return nil, err
	}

	return conn, nil
}

// Context returns a request context based on CLI arguments.
func Context(cmd *cobra.Command) context.Context {
	// TODO(aluzzardi): Actually create a context.
	return context.TODO()
}

// ParseLogDriverFlags parses a silly string format for log driver and options.
// Fully baked log driver config should be returned.
//
// If no log driver is available, nil, nil will be returned.
func ParseLogDriverFlags(flags *pflag.FlagSet) (*api.Driver, error) {
	if !flags.Changed("log-driver") {
		return nil, nil
	}

	name, err := flags.GetString("log-driver")
	if err != nil {
		return nil, err
	}

	var opts map[string]string
	if flags.Changed("log-opt") {
		rawOpts, err := flags.GetStringSlice("log-opt")
		if err != nil {
			return nil, err
		}

		opts = make(map[string]string, len(rawOpts))
		for _, rawOpt := range rawOpts {
			parts := strings.SplitN(rawOpt, "=", 2)
			if len(parts) == 1 {
				opts[parts[0]] = ""
				continue
			}

			opts[parts[0]] = parts[1]
		}
	}

	return &api.Driver{
		Name:    name,
		Options: opts,
	}, nil
}
<|endoftext|>


<commit_before>package matrix

import (
	"fmt"
)

// Foreach performs an operation over all elements in a Matrix.
// It takes a parameter of type func(int, int) error
func (m Matrix) Foreach(op func(int, int) error) {
	// Iterate over rows
	for y, vy := range m {
		// Iterate over columns
		for x, _ := range vy {
			// Apply operation to matrix element
			op(y, x)
		}
	}
	return
}

// Add adds an int, float64 or Matrix to an existing Matrix.
// For int and float64, the operation is performed on each element.
func (A Matrix) Add(in ...interface{}) (Matrix, error) {
	var mat Matrix
	var err error
	switch in[0].(type) {
	case Matrix:
		B := in[0].(Matrix)
		sA := A.Size()
		sB := B.Size()
		if (sA.Y != sB.Y) || (sA.X != sB.X) {
			return mat, fmt.Errorf("go.iccp/matrix: Matrix dimensions mis-match.")
		}

		mat, _ = New(sA)
		mat.Foreach(func(y, x int) error {
			mat[y][x] = A[y][x] + B[y][x]
			return nil
		})
	case float64:
		a := in[0].(float64)
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) error {
			mat[y][x] = A[y][x] + a
			return nil
		})
	case int:
		a := float64(in[0].(int))
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) error {
			mat[y][x] = A[y][x] + a
			return nil
		})
	default:
		err = fmt.Errorf("go.iccp/matrix: Invalid input for method Add.")
	}
	return mat, err
}

// Subtract subtracts an int, float64 or Matrix from an existing Matrix.
// For int and float64, the operation is performed on each element.
func (A Matrix) Subtract(in ...interface{}) (Matrix, error) {
	var mat Matrix
	var err error
	switch in[0].(type) {
	case Matrix:
		B := in[0].(Matrix)
		sA := A.Size()
		sB := B.Size()
		if (sA.Y != sB.Y) || (sA.X != sB.X) {
			return mat, fmt.Errorf("go.iccp/matrix: Matrix dimensions mis-match.")
		}

		mat, _ = New(sA)
		mat.Foreach(func(y, x int) error {
			mat[y][x] = A[y][x] - B[y][x]
			return nil
		})
	case float64:
		a := in[0].(float64)
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) error {
			mat[y][x] = A[y][x] - a
			return nil
		})
	case int:
		a := float64(in[0].(int))
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) error {
			mat[y][x] = A[y][x] - a
			return nil
		})
	default:
		err = fmt.Errorf("go.iccp/matrix: Invalid input for method Subtract.")
	}
	return mat, err
}

// Multiply multiplies an int, float64 or Matrix to an existing Matrix.
// For int and float64, the operation is performed on each element.
func (A Matrix) Multiply(in ...interface{}) (Matrix, error) {
	var mat Matrix
	var err error
	switch in[0].(type) {
	case Matrix:
		B := in[0].(Matrix)
		sA := A.Size()
		sB := B.Size()
		if sA.X != sB.Y {
			return mat, fmt.Errorf("go.iccp/matrix: Matrix dimensions mis-match.")
		}
		// New matrix of new dimensions
		mat, _ = New(sA.Y, sB.X)

		// Loop through rows of new matrix
		for y, yv := range mat {
			// columns
			for x, _ := range yv {
				// Multiplication operation
				for i := 0; i < sA.X; i++ {
					mat[y][x] += A[y][i] * B[i][x]
				}
			}
		}
	case float64:
		a := in[0].(float64)
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) error {
			mat[y][x] = a * A[y][x]
			return nil
		})
	case int:
		a := float64(in[0].(int))
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) error {
			mat[y][x] = a * A[y][x]
			return nil
		})
	default:
		err = fmt.Errorf("go.iccp/matrix: Invalid input for method Subtract.")
	}
	return mat, err
}

func (A Matrix) Transpose() Matrix {
	sA := A.Size()
	B, _ := New(sA.X, sA.Y)
	A.Foreach(func(r, c int) error {
		B[c][r] = A[r][c]
		return nil
	})
	return B
}

func (A Matrix) OuterProduct(B Matrix) (Matrix, error) {
	return A.Multiply(B.Transpose())
}
<commit_msg>Add ScalarProduct<commit_after>package matrix

import (
	"fmt"
)

// Foreach performs an operation over all elements in a Matrix.
// It takes a parameter of type func(int, int) error
func (m Matrix) Foreach(op func(int, int)) {
	// Iterate over rows
	for y, vy := range m {
		// Iterate over columns
		for x, _ := range vy {
			// Apply operation to matrix element
			op(y, x)
		}
	}
	return
}

// Add adds an int, float64 or Matrix to an existing Matrix.
// For int and float64, the operation is performed on each element.
func (A Matrix) Add(in ...interface{}) (Matrix, error) {
	var mat Matrix
	var err error
	switch in[0].(type) {
	case Matrix:
		B := in[0].(Matrix)
		sA := A.Size()
		sB := B.Size()
		if (sA.Y != sB.Y) || (sA.X != sB.X) {
			return mat, fmt.Errorf("go.iccp/matrix: Matrix dimensions mis-match.")
		}

		mat, _ = New(sA)
		mat.Foreach(func(y, x int) {
			mat[y][x] = A[y][x] + B[y][x]
		})
	case float64:
		a := in[0].(float64)
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) {
			mat[y][x] = A[y][x] + a
		})
	case int:
		a := float64(in[0].(int))
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) {
			mat[y][x] = A[y][x] + a
		})
	default:
		err = fmt.Errorf("go.iccp/matrix: Invalid input for method Add.")
	}
	return mat, err
}

// Subtract subtracts an int, float64 or Matrix from an existing Matrix.
// For int and float64, the operation is performed on each element.
func (A Matrix) Subtract(in ...interface{}) (Matrix, error) {
	var mat Matrix
	var err error
	switch in[0].(type) {
	case Matrix:
		B := in[0].(Matrix)
		sA := A.Size()
		sB := B.Size()
		if (sA.Y != sB.Y) || (sA.X != sB.X) {
			return mat, fmt.Errorf("go.iccp/matrix: Matrix dimensions mis-match.")
		}

		mat, _ = New(sA)
		mat.Foreach(func(y, x int) {
			mat[y][x] = A[y][x] - B[y][x]
		})
	case float64:
		a := in[0].(float64)
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) {
			mat[y][x] = A[y][x] - a
		})
	case int:
		a := float64(in[0].(int))
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) {
			mat[y][x] = A[y][x] - a
		})
	default:
		err = fmt.Errorf("go.iccp/matrix: Invalid input for method Subtract.")
	}
	return mat, err
}

// Multiply multiplies an int, float64 or Matrix to an existing Matrix.
// For int and float64, the operation is performed on each element.
func (A Matrix) Multiply(in ...interface{}) (Matrix, error) {
	var mat Matrix
	var err error
	switch in[0].(type) {
	case Matrix:
		B := in[0].(Matrix)
		sA := A.Size()
		sB := B.Size()
		if sA.X != sB.Y {
			return mat, fmt.Errorf("go.iccp/matrix: Matrix dimensions mis-match.")
		}
		// New matrix of new dimensions
		mat, _ = New(sA.Y, sB.X)

		// Loop through rows of new matrix
		for y, yv := range mat {
			// columns
			for x, _ := range yv {
				// Multiplication operation
				for i := 0; i < sA.X; i++ {
					mat[y][x] += A[y][i] * B[i][x]
				}
			}
		}
	case float64:
		a := in[0].(float64)
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) {
			mat[y][x] = a * A[y][x]
		})
	case int:
		a := float64(in[0].(int))
		mat, _ = New(A.Size())
		mat.Foreach(func(y, x int) {
			mat[y][x] = a * A[y][x]
		})
	default:
		err = fmt.Errorf("go.iccp/matrix: Invalid input for method Subtract.")
	}
	return mat, err
}

func (A Matrix) Transpose() Matrix {
	sA := A.Size()
	B, _ := New(sA.X, sA.Y)
	A.Foreach(func(r, c int) {
		B[c][r] = A[r][c]
	})
	return B
}

func (A Matrix) OuterProduct(B Matrix) (Matrix, error) {
	return A.Multiply(B.Transpose())
}

func (A Matrix) ScalarProduct(B Matrix) (float64, error) {
	var sum float64
	sA := A.Size()
	sB := B.Size()
	if (sA.Y != sB.Y) || (sA.X != sB.X) {
		return sum, fmt.Errorf("go.iccp/matrix: Matrix dimensions mis-match.")
	}

	A.Foreach(func(r, c int) {
		sum += A[r][c] * B[r][c]
	})
	return sum, nil
}
<|endoftext|>


<commit_before>package acracensor

import log "github.com/sirupsen/logrus"

type AcraCensor struct {
	handlers []QueryHandlerInterface

}

func (acraCensor *AcraCensor) AddHandler(handler QueryHandlerInterface) {
	acraCensor.handlers = append(acraCensor.handlers, handler)
}

func (acraCensor *AcraCensor) RemoveHandler(handler QueryHandlerInterface) {
	for index, handlerFromRange := range acraCensor.handlers {
		if handlerFromRange == handler {
			acraCensor.handlers = append(acraCensor.handlers[:index], acraCensor.handlers[index+1:]...)
		}
	}
}

func (acraCensor *AcraCensor) HandleQuery(query string) error {
	for _, handler := range acraCensor.handlers {
		if err := handler.CheckQuery(query); err != nil {
			return err
		}
	}
	log.Infof("Acra' censor passed")
	return nil
}
<commit_msg>Add raw query string to main log stream<commit_after>package acracensor

import log "github.com/sirupsen/logrus"

type AcraCensor struct {
	handlers []QueryHandlerInterface

}

func (acraCensor *AcraCensor) AddHandler(handler QueryHandlerInterface) {
	acraCensor.handlers = append(acraCensor.handlers, handler)
}

func (acraCensor *AcraCensor) RemoveHandler(handler QueryHandlerInterface) {
	for index, handlerFromRange := range acraCensor.handlers {
		if handlerFromRange == handler {
			acraCensor.handlers = append(acraCensor.handlers[:index], acraCensor.handlers[index+1:]...)
		}
	}
}

func (acraCensor *AcraCensor) HandleQuery(query string) error {
	for _, handler := range acraCensor.handlers {
		if err := handler.CheckQuery(query); err != nil {
			log.Errorf("Forbidden query: '%s'", query)
			return err
		}
	}
	log.Infof("Allowed query: '%s'", query)
	return nil
}
<|endoftext|>


<commit_before>package collect

import (
	"container/heap"
	"sync"
	"time"
)

type timedQueueEntry struct {
	timeSec int64
	value   interface{}
}

type timedQueueImpl []*timedQueueEntry

func (queue timedQueueImpl) Len() int {
	return len(queue)
}

func (queue timedQueueImpl) Less(i, j int) bool {
	return queue[i].timeSec < queue[j].timeSec
}

func (queue timedQueueImpl) Swap(i, j int) {
	tmp := queue[i]
	queue[i] = queue[j]
	queue[j] = tmp
}

func (queue *timedQueueImpl) Push(value interface{}) {
	entry := value.(*timedQueueEntry)
	*queue = append(*queue, entry)
}

func (queue *timedQueueImpl) Pop() interface{} {
	old := *queue
	n := len(old)
	v := old[n-1]
	*queue = old[:n-1]
	return v
}

type TimedQueue struct {
	queue   timedQueueImpl
	access  sync.RWMutex
	removed chan interface{}
}

func NewTimedQueue(updateInterval int) *TimedQueue {
	queue := &TimedQueue{
		queue:   make([]*timedQueueEntry, 0, 256),
		removed: make(chan interface{}, 16),
		access:  sync.RWMutex{},
	}
	go queue.cleanup(time.Tick(time.Duration(updateInterval) * time.Second))
	return queue
}

func (queue *TimedQueue) Add(value interface{}, time2Remove int64) {
	queue.access.Lock()
	heap.Push(&queue.queue, &timedQueueEntry{
		timeSec: time2Remove,
		value:   value,
	})
	queue.access.Unlock()
}

func (queue *TimedQueue) RemovedEntries() <-chan interface{} {
	return queue.removed
}

func (queue *TimedQueue) cleanup(tick <-chan time.Time) {
	for {
		now := <-tick
		queue.access.RLock()
		queueLen := queue.queue.Len()
		queue.access.RUnlock()
		if queueLen == 0 {
			continue
		}
		nowSec := now.UTC().Unix()
		queue.access.RLock()
		firstEntryTime := queue.queue[0].timeSec
		queue.access.RUnlock()
		if firstEntryTime > nowSec {
			continue
		}
		queue.access.Lock()
		firstEntryValue := heap.Pop(&queue.queue).(*timedQueueEntry).value
		queue.access.Unlock()

		queue.removed <- firstEntryValue
	}
}
<commit_msg>Release element ealier<commit_after>package collect

import (
	"container/heap"
	"sync"
	"time"
)

type timedQueueEntry struct {
	timeSec int64
	value   interface{}
}

type timedQueueImpl []*timedQueueEntry

func (queue timedQueueImpl) Len() int {
	return len(queue)
}

func (queue timedQueueImpl) Less(i, j int) bool {
	return queue[i].timeSec < queue[j].timeSec
}

func (queue timedQueueImpl) Swap(i, j int) {
	tmp := queue[i]
	queue[i] = queue[j]
	queue[j] = tmp
}

func (queue *timedQueueImpl) Push(value interface{}) {
	entry := value.(*timedQueueEntry)
	*queue = append(*queue, entry)
}

func (queue *timedQueueImpl) Pop() interface{} {
	old := *queue
	n := len(old)
	v := old[n-1]
	old[n-1] = nil
	*queue = old[:n-1]
	return v
}

type TimedQueue struct {
	queue   timedQueueImpl
	access  sync.RWMutex
	removed chan interface{}
}

func NewTimedQueue(updateInterval int) *TimedQueue {
	queue := &TimedQueue{
		queue:   make([]*timedQueueEntry, 0, 256),
		removed: make(chan interface{}, 16),
		access:  sync.RWMutex{},
	}
	go queue.cleanup(time.Tick(time.Duration(updateInterval) * time.Second))
	return queue
}

func (queue *TimedQueue) Add(value interface{}, time2Remove int64) {
	queue.access.Lock()
	heap.Push(&queue.queue, &timedQueueEntry{
		timeSec: time2Remove,
		value:   value,
	})
	queue.access.Unlock()
}

func (queue *TimedQueue) RemovedEntries() <-chan interface{} {
	return queue.removed
}

func (queue *TimedQueue) cleanup(tick <-chan time.Time) {
	for {
		now := <-tick
		queue.access.RLock()
		queueLen := queue.queue.Len()
		queue.access.RUnlock()
		if queueLen == 0 {
			continue
		}
		nowSec := now.UTC().Unix()
		queue.access.RLock()
		firstEntryTime := queue.queue[0].timeSec
		queue.access.RUnlock()
		if firstEntryTime > nowSec {
			continue
		}
		queue.access.Lock()
		firstEntryValue := heap.Pop(&queue.queue).(*timedQueueEntry).value
		queue.access.Unlock()

		queue.removed <- firstEntryValue
	}
}
<|endoftext|>


<commit_before>package olehandler

import (
	"errors"
	"fmt"
	"sync"

	"github.com/go-ole/go-ole"
	"github.com/go-ole/go-ole/oleutil"
)

type OleHandler struct {
	App      *ole.IUnknown
	Handle   *ole.IDispatch
	parent   *OleHandler
	children []*OleHandler

	closed     bool
	closedChan chan struct{}
	m          *sync.RWMutex
	wg         *sync.WaitGroup
	once       *sync.Once
}

func CreateRootOleHandler(programID string) (*OleHandler, error) {
	app, err := oleutil.CreateObject(programID)
	if err != nil {
		return nil, err
	}

	handle, err := app.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		app.Release()
		return nil, err
	}

	handler := &OleHandler{
		App:      app,
		Handle:   handle,
		children: []*OleHandler{},

		closed:     false,
		closedChan: make(chan struct{}),
		m:          new(sync.RWMutex),
		wg:         new(sync.WaitGroup),
		once:       new(sync.Once),
	}

	return handler, nil
}

func CreateOleHandler(parent *OleHandler, handle *ole.IDispatch) *OleHandler {
	if parent != nil {
		parent.wg.Add(1)
	}
	return &OleHandler{
		Handle:   handle,
		parent:   parent,
		children: []*OleHandler{},

		closed:     false,
		closedChan: make(chan struct{}),
		m:          new(sync.RWMutex),
		wg:         new(sync.WaitGroup),
		once:       new(sync.Once),
	}
}

func (o *OleHandler) Close() {
	o.once.Do(func() {
		o.m.Lock()

		close(o.closedChan)
		o.closed = true
		children := o.children
		o.children = []*OleHandler{}

		for _, child := range children {
			child.Close()
		}

		o.m.Unlock()

		o.wg.Wait()
		o.Handle.Release()

		if o.parent != nil {
			if len(o.parent.children) != 0 {
				o.parent.m.Lock()
				// remove self from parent
				children := o.parent.children
				if children != nil {
					for i, child := range children {
						if child == o {
							last := len(children) - 1
							children[i] = children[last]
							o.parent.children = children[:last]
							break
						}
					}
				}
				o.parent.m.Unlock()
			}
			o.parent.wg.Done()
		}

		if o.App != nil {
			o.App.Release()
		}
	})
}

func (o *OleHandler) Closed() <-chan struct{} {
	return o.closedChan
}

func (o *OleHandler) SafeAccess(fn func() error) error {
	o.m.RLock()
	defer o.m.RUnlock()
	if o.closed {
		return errors.New("OleHandler is already closed.")
	}

	return fn()
}

func (o *OleHandler) GetOleHandler(property string) (handler *OleHandler, err error) {
	err = o.GetOleHandlerWithCallbackAndArgs(property, func(h *OleHandler) error {
		handler = h
		return nil
	})

	return handler, err
}

func (o *OleHandler) GetOleHandlerWithArgs(property string, args ...interface{}) (handler *OleHandler, err error) {
	err = o.GetOleHandlerWithCallbackAndArgs(property, func(h *OleHandler) error {
		handler = h
		return nil
	}, args...)

	return handler, err
}

func (o *OleHandler) GetOleHandlerWithCallback(property string, fn func(*OleHandler) error) error {
	return o.GetOleHandlerWithCallbackAndArgs(property, fn)
}

func (o *OleHandler) GetOleHandlerWithCallbackAndArgs(property string, fn func(*OleHandler) error, args ...interface{}) error {
	return o.SafeAccess(func() error {
		v, err := o.Handle.GetProperty(property, args...)
		if err != nil {
			return err
		}
		handle := v.ToIDispatch()
		if handle == nil {
			return errors.New(fmt.Sprintf("%v is not handle.", property))
		}

		handler := CreateOleHandler(o, handle)
		err = fn(handler)
		if err != nil {
			handler.Close()
			return err
		}

		o.children = append(o.children, handler)
		return nil
	})
}

func (o *OleHandler) GetProperty(property string, args ...interface{}) (result *ole.VARIANT, err error) {
	o.SafeAccess(func() error {
		result, err = o.Handle.GetProperty(property, args...)
		return err
	})

	return result, err
}

func (o *OleHandler) GetIntProperty(property string, args ...interface{}) (int, error) {
	v, err := o.GetProperty(property, args...)
	if err != nil {
		return 0, err
	}

	return int(v.Val), nil
}

func (o *OleHandler) GetStringProperty(property string, args ...interface{}) (string, error) {
	v, err := o.GetProperty(property, args...)
	if err != nil {
		return "", err
	}

	return v.ToString(), nil
}

func (o *OleHandler) GetBoolProperty(property string, args ...interface{}) (bool, error) {
	v, err := o.GetProperty(property, args...)
	if err != nil {
		return false, err
	}

	return v.Value().(bool), nil
}

func (o *OleHandler) PutProperty(property string, args ...interface{}) error {
	return o.SafeAccess(func() error {
		_, err := o.Handle.PutProperty(property, args...)
		return err
	})
}

func (o *OleHandler) CallMethod(property string, args ...interface{}) error {
	return o.SafeAccess(func() error {
		_, err := o.Handle.CallMethod(property, args...)
		return err
	})
}
<commit_msg>fix error message<commit_after>package olehandler

import (
	"errors"
	"fmt"
	"sync"

	"github.com/go-ole/go-ole"
	"github.com/go-ole/go-ole/oleutil"
)

type OleHandler struct {
	App      *ole.IUnknown
	Handle   *ole.IDispatch
	parent   *OleHandler
	children []*OleHandler

	closed     bool
	closedChan chan struct{}
	m          *sync.RWMutex
	wg         *sync.WaitGroup
	once       *sync.Once
}

func CreateRootOleHandler(programID string) (*OleHandler, error) {
	app, err := oleutil.CreateObject(programID)
	if err != nil {
		return nil, err
	}

	handle, err := app.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		app.Release()
		return nil, err
	}

	handler := &OleHandler{
		App:      app,
		Handle:   handle,
		children: []*OleHandler{},

		closed:     false,
		closedChan: make(chan struct{}),
		m:          new(sync.RWMutex),
		wg:         new(sync.WaitGroup),
		once:       new(sync.Once),
	}

	return handler, nil
}

func CreateOleHandler(parent *OleHandler, handle *ole.IDispatch) *OleHandler {
	if parent != nil {
		parent.wg.Add(1)
	}
	return &OleHandler{
		Handle:   handle,
		parent:   parent,
		children: []*OleHandler{},

		closed:     false,
		closedChan: make(chan struct{}),
		m:          new(sync.RWMutex),
		wg:         new(sync.WaitGroup),
		once:       new(sync.Once),
	}
}

func (o *OleHandler) Close() {
	o.once.Do(func() {
		o.m.Lock()

		close(o.closedChan)
		o.closed = true
		children := o.children
		o.children = []*OleHandler{}

		for _, child := range children {
			child.Close()
		}

		o.m.Unlock()

		o.wg.Wait()
		o.Handle.Release()

		if o.parent != nil {
			if len(o.parent.children) != 0 {
				o.parent.m.Lock()
				// remove self from parent
				children := o.parent.children
				if children != nil {
					for i, child := range children {
						if child == o {
							last := len(children) - 1
							children[i] = children[last]
							o.parent.children = children[:last]
							break
						}
					}
				}
				o.parent.m.Unlock()
			}
			o.parent.wg.Done()
		}

		if o.App != nil {
			o.App.Release()
		}
	})
}

func (o *OleHandler) Closed() <-chan struct{} {
	return o.closedChan
}

func (o *OleHandler) SafeAccess(fn func() error) error {
	o.m.RLock()
	defer o.m.RUnlock()
	if o.closed {
		return errors.New("OleHandler is already closed.")
	}

	return fn()
}

func (o *OleHandler) GetOleHandler(property string) (handler *OleHandler, err error) {
	err = o.GetOleHandlerWithCallbackAndArgs(property, func(h *OleHandler) error {
		handler = h
		return nil
	})

	return handler, err
}

func (o *OleHandler) GetOleHandlerWithArgs(property string, args ...interface{}) (handler *OleHandler, err error) {
	err = o.GetOleHandlerWithCallbackAndArgs(property, func(h *OleHandler) error {
		handler = h
		return nil
	}, args...)

	return handler, err
}

func (o *OleHandler) GetOleHandlerWithCallback(property string, fn func(*OleHandler) error) error {
	return o.GetOleHandlerWithCallbackAndArgs(property, fn)
}

func (o *OleHandler) GetOleHandlerWithCallbackAndArgs(property string, fn func(*OleHandler) error, args ...interface{}) error {
	return o.SafeAccess(func() error {
		v, err := o.Handle.GetProperty(property, args...)
		if err != nil {
			return err
		}
		handle := v.ToIDispatch()
		if handle == nil {
			return errors.New(fmt.Sprintf("%v handle is nil.", property))
		}

		handler := CreateOleHandler(o, handle)
		err = fn(handler)
		if err != nil {
			handler.Close()
			return err
		}

		o.children = append(o.children, handler)
		return nil
	})
}

func (o *OleHandler) GetProperty(property string, args ...interface{}) (result *ole.VARIANT, err error) {
	o.SafeAccess(func() error {
		result, err = o.Handle.GetProperty(property, args...)
		return err
	})

	return result, err
}

func (o *OleHandler) GetIntProperty(property string, args ...interface{}) (int, error) {
	v, err := o.GetProperty(property, args...)
	if err != nil {
		return 0, err
	}

	return int(v.Val), nil
}

func (o *OleHandler) GetStringProperty(property string, args ...interface{}) (string, error) {
	v, err := o.GetProperty(property, args...)
	if err != nil {
		return "", err
	}

	return v.ToString(), nil
}

func (o *OleHandler) GetBoolProperty(property string, args ...interface{}) (bool, error) {
	v, err := o.GetProperty(property, args...)
	if err != nil {
		return false, err
	}

	return v.Value().(bool), nil
}

func (o *OleHandler) PutProperty(property string, args ...interface{}) error {
	return o.SafeAccess(func() error {
		_, err := o.Handle.PutProperty(property, args...)
		return err
	})
}

func (o *OleHandler) CallMethod(property string, args ...interface{}) error {
	return o.SafeAccess(func() error {
		_, err := o.Handle.CallMethod(property, args...)
		return err
	})
}
<|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
//
//      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 ga4gh

import (
	"fmt"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/dgrijalva/jwt-go"
	"github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/testkeys"
)

func TestNewVisaFromData(t *testing.T) {
	d, j := fakeVisaDataAndJWT(t)

	v, err := NewVisaFromData(d, RS256, testkeys.Default.Private, testkeys.Default.ID)
	if err != nil {
		t.Fatalf("NewVisaFromData(%v) failed: %v", d, err)
	}
	got := v.JWT()

	want := j
	if diff := cmp.Diff(want, got); diff != "" {
		t.Fatalf("NewVisaFromData(%v) returned diff (-want +got):\n%s", d, diff)
	}
}

func TestNewVisaFromJWT(t *testing.T) {
	d, j := fakeVisaDataAndJWT(t)

	v, err := NewVisaFromJWT(j)
	if err != nil {
		t.Fatalf("NewVisaFromJWT(%v) failed: %v", j, err)
	}
	got := v.Data()

	want := d
	if diff := cmp.Diff(want, got); diff != "" {
		t.Fatalf("NewVisaFromJWT(%v) returned diff (-want +got):\n%s", j, diff)
	}
}

func TestVisaJSONFormat(t *testing.T) {
	_, j := fakeVisaDataAndJWT(t)
	got, err := payloadFromJWT(string(j))
	if err != nil {
		t.Fatalf("payloadFromJWT(%v) failed: %v", j, err)
	}
	want := fakeVisaDataJSON()
	if diff := cmp.Diff(jsontxt(want), jsontxt(got), cmp.Transformer("", jsontxtCanonical)); diff != "" {
		t.Fatalf("JSON(%v) returned diff (-want +got):\n%s", j, diff)
	}
}

func TestVisaVerify(t *testing.T) {
	d, _ := fakeVisaDataAndJWT(t)

	p, err := NewVisaFromData(d, RS256, testkeys.Default.Private, testkeys.Default.ID)
	if err != nil {
		t.Fatalf("NewPassportFromData(%v) failed: %v", d, err)
	}

	if err := p.Verify(testkeys.Default.Public); err != nil {
		t.Fatalf("Verify(_) failed: %v", err)
	}
}

func fakeVisaDataAndJWT(t *testing.T) (*VisaData, VisaJWT) {
	t.Helper()

	d := fakeVisaData()
	token := jwt.NewWithClaims(RS256, d)
	token.Header[jwtHeaderKeyID] = testkeys.Default.ID
	signed, err := token.SignedString(testkeys.Default.Private)
	if err != nil {
		t.Fatalf("token.SignedString(_) failed: %v", err)
	}
	j := VisaJWT(signed)

	t.Logf("Data: %#v", d)
	t.Logf("JWT: %v", j)
	t.Logf("You can verify the Data and JWT match on https://jwt.io/")

	return d, j
}

func fakeStart() int64 { return time.Date(2000, 8, 7, 6, 5, 4, 3, time.UTC).Unix() }

func fakeEnd() int64 { return time.Date(9999, 8, 7, 6, 5, 4, 3, time.UTC).Unix() }

func fakeVisaData() *VisaData {
	return &VisaData{
		StdClaims: StdClaims{
			Issuer:    "fake-visa-issuer",
			ExpiresAt: fakeEnd(),
		},
		Assertion: Assertion{
			Type:     "fake-visa-type",
			Value:    "fake-visa-value",
			Source:   "fake-visa-source",
			Asserted: fakeStart(),
			By:       "fake-visa-by",
			Conditions: [][]Condition{
				{
					{
						Type:   "AffiliationAndRole",
						Value:  "const:faculty@fake-institution.edu",
						Source: "",
						By:     "const:so",
					},
					{
						Type:   "AcceptedTermsAndPolicies",
						Value:  "",
						Source: "",
						By:     "",
					},
				},
				{
					{
						Type:   "AffiliationAndRole",
						Value:  "glob:faculty@*",
						Source: "const:https://fake-broker.org",
						By:     "const:system",
					},
					{
						Type:   "AcceptedTermsAndPolicies",
						Value:  "",
						Source: "",
						By:     "",
					},
				},
			},
		},
	}
}

func fakeVisaDataJSON() string {
	return `{
  "exp": ` + fmt.Sprintf("%v", fakeEnd()) + `,
  "iss": "fake-visa-issuer",
  "ga4gh_visa_v1": {
    "type": "fake-visa-type",
    "value": "fake-visa-value",
    "source": "fake-visa-source",
    "asserted": ` + fmt.Sprintf("%v", fakeStart()) + `,
    "by": "fake-visa-by",
    "conditions": [
      [
        {
          "type": "AffiliationAndRole",
          "value": "const:faculty@fake-institution.edu",
          "by": "const:so"
        },
        {
          "type": "AcceptedTermsAndPolicies"
        }
      ],
      [
        {
          "type": "AffiliationAndRole",
          "value": "glob:faculty@*",
          "source": "const:https://fake-broker.org",
          "by": "const:system"
        },
        {
          "type": "AcceptedTermsAndPolicies"
        }
      ]
    ]
  }
}`
}
<commit_msg>replace t.Logf with glog.Infof<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
//
//      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 ga4gh

import (
	"fmt"
	"testing"
	"time"

	glog "github.com/golang/glog"
	"github.com/google/go-cmp/cmp"
	"github.com/dgrijalva/jwt-go"
	"github.com/GoogleCloudPlatform/healthcare-federated-access-services/lib/testkeys"
)

func TestNewVisaFromData(t *testing.T) {
	d, j := fakeVisaDataAndJWT(t)

	v, err := NewVisaFromData(d, RS256, testkeys.Default.Private, testkeys.Default.ID)
	if err != nil {
		t.Fatalf("NewVisaFromData(%v) failed: %v", d, err)
	}
	got := v.JWT()

	want := j
	if diff := cmp.Diff(want, got); diff != "" {
		t.Fatalf("NewVisaFromData(%v) returned diff (-want +got):\n%s", d, diff)
	}
}

func TestNewVisaFromJWT(t *testing.T) {
	d, j := fakeVisaDataAndJWT(t)

	v, err := NewVisaFromJWT(j)
	if err != nil {
		t.Fatalf("NewVisaFromJWT(%v) failed: %v", j, err)
	}
	got := v.Data()

	want := d
	if diff := cmp.Diff(want, got); diff != "" {
		t.Fatalf("NewVisaFromJWT(%v) returned diff (-want +got):\n%s", j, diff)
	}
}

func TestVisaJSONFormat(t *testing.T) {
	_, j := fakeVisaDataAndJWT(t)
	got, err := payloadFromJWT(string(j))
	if err != nil {
		t.Fatalf("payloadFromJWT(%v) failed: %v", j, err)
	}
	want := fakeVisaDataJSON()
	if diff := cmp.Diff(jsontxt(want), jsontxt(got), cmp.Transformer("", jsontxtCanonical)); diff != "" {
		t.Fatalf("JSON(%v) returned diff (-want +got):\n%s", j, diff)
	}
}

func TestVisaVerify(t *testing.T) {
	d, _ := fakeVisaDataAndJWT(t)

	p, err := NewVisaFromData(d, RS256, testkeys.Default.Private, testkeys.Default.ID)
	if err != nil {
		t.Fatalf("NewPassportFromData(%v) failed: %v", d, err)
	}

	if err := p.Verify(testkeys.Default.Public); err != nil {
		t.Fatalf("Verify(_) failed: %v", err)
	}
}

func fakeVisaDataAndJWT(t *testing.T) (*VisaData, VisaJWT) {
	t.Helper()

	d := fakeVisaData()
	token := jwt.NewWithClaims(RS256, d)
	token.Header[jwtHeaderKeyID] = testkeys.Default.ID
	signed, err := token.SignedString(testkeys.Default.Private)
	if err != nil {
		t.Fatalf("token.SignedString(_) failed: %v", err)
	}
	j := VisaJWT(signed)

	glog.Infof("Data: %#v", d)
	glog.Infof("JWT: %v", j)
	glog.Infof("You can verify the Data and JWT match on https://jwt.io/")

	return d, j
}

func fakeStart() int64 { return time.Date(2000, 8, 7, 6, 5, 4, 3, time.UTC).Unix() }

func fakeEnd() int64 { return time.Date(9999, 8, 7, 6, 5, 4, 3, time.UTC).Unix() }

func fakeVisaData() *VisaData {
	return &VisaData{
		StdClaims: StdClaims{
			Issuer:    "fake-visa-issuer",
			ExpiresAt: fakeEnd(),
		},
		Assertion: Assertion{
			Type:     "fake-visa-type",
			Value:    "fake-visa-value",
			Source:   "fake-visa-source",
			Asserted: fakeStart(),
			By:       "fake-visa-by",
			Conditions: [][]Condition{
				{
					{
						Type:   "AffiliationAndRole",
						Value:  "const:faculty@fake-institution.edu",
						Source: "",
						By:     "const:so",
					},
					{
						Type:   "AcceptedTermsAndPolicies",
						Value:  "",
						Source: "",
						By:     "",
					},
				},
				{
					{
						Type:   "AffiliationAndRole",
						Value:  "glob:faculty@*",
						Source: "const:https://fake-broker.org",
						By:     "const:system",
					},
					{
						Type:   "AcceptedTermsAndPolicies",
						Value:  "",
						Source: "",
						By:     "",
					},
				},
			},
		},
	}
}

func fakeVisaDataJSON() string {
	return `{
  "exp": ` + fmt.Sprintf("%v", fakeEnd()) + `,
  "iss": "fake-visa-issuer",
  "ga4gh_visa_v1": {
    "type": "fake-visa-type",
    "value": "fake-visa-value",
    "source": "fake-visa-source",
    "asserted": ` + fmt.Sprintf("%v", fakeStart()) + `,
    "by": "fake-visa-by",
    "conditions": [
      [
        {
          "type": "AffiliationAndRole",
          "value": "const:faculty@fake-institution.edu",
          "by": "const:so"
        },
        {
          "type": "AcceptedTermsAndPolicies"
        }
      ],
      [
        {
          "type": "AffiliationAndRole",
          "value": "glob:faculty@*",
          "source": "const:https://fake-broker.org",
          "by": "const:system"
        },
        {
          "type": "AcceptedTermsAndPolicies"
        }
      ]
    ]
  }
}`
}
<|endoftext|>


<commit_before>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------
// +build darwin

package vcl

type NSObject uintptr

// NSObject
//func HandleToPlatformHandle(h types.HWND) NSObject {
//	return NSObject(h)
//}

type (
	// NSWindow
	NSWindow uintptr

	NSURL uintptr
)

/*
var (
	NSWindow_FromForm                      = libvcl.NewProc("NSWindow_FromForm")
	NSWindow_titleVisibility               = libvcl.NewProc("NSWindow_titleVisibility")
	NSWindow_setTitleVisibility            = libvcl.NewProc("NSWindow_setTitleVisibility")
	NSWindow_titlebarAppearsTransparent    = libvcl.NewProc("NSWindow_titlebarAppearsTransparent")
	NSWindow_setTitlebarAppearsTransparent = libvcl.NewProc("NSWindow_setTitlebarAppearsTransparent")
	NSWindow_styleMask                     = libvcl.NewProc("NSWindow_styleMask")
	NSWindow_setStyleMask                  = libvcl.NewProc("NSWindow_setStyleMask")
	NSWindow_setRepresentedURL             = libvcl.NewProc("NSWindow_setRepresentedURL")
)

*/

func (f *TForm) PlatformWindow() NSWindow {
	r, _, _ := NSWindow_FromForm.Call(f.instance)
	return NSWindow(r)
}

func (n NSWindow) TitleVisibility() NSWindowTitleVisibility {
	r, _, _ := NSWindow_titleVisibility.Call(uintptr(n))
	return NSWindowTitleVisibility(r)
}

func (n NSWindow) SetTitleVisibility(flag NSWindowTitleVisibility) {
	NSWindow_setTitleVisibility.Call(uintptr(n), uintptr(flag))
}

func (n NSWindow) TitleBarAppearsTransparent() bool {
	r, _, _ := NSWindow_titlebarAppearsTransparent.Call(uintptr(n))
	return DBoolToGoBool(r)
}

func (n NSWindow) SetTitleBarAppearsTransparent(flag bool) {
	NSWindow_setTitlebarAppearsTransparent.Call(uintptr(n), GoBoolToDBool(flag))
}

func (n NSWindow) SetRepresentedURL(url NSURL) {
	NSWindow_setRepresentedURL.Call(uintptr(n), uintptr(url))
}

func (n NSWindow) StyleMask() uint {
	r, _, _ := NSWindow_styleMask.Call(uintptr(n))
	return uint(r)
}

func (n NSWindow) SetStyleMask(mask uint) {
	NSWindow_setStyleMask.Call(uintptr(n), uintptr(mask))
}

//func (n NSWindow) Release_() {
//		NSWindow_release.Call(uintptr(n))
//}
<commit_msg>Fix imports<commit_after>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------
// +build darwin

package vcl

import (
	. "github.com/ying32/govcl/vcl/api"
	. "github.com/ying32/govcl/vcl/types"
)

type NSObject uintptr

// NSObject
//func HandleToPlatformHandle(h types.HWND) NSObject {
//	return NSObject(h)
//}

type (
	// NSWindow
	NSWindow uintptr

	NSURL uintptr
)

/*
var (
	NSWindow_FromForm                      = libvcl.NewProc("NSWindow_FromForm")
	NSWindow_titleVisibility               = libvcl.NewProc("NSWindow_titleVisibility")
	NSWindow_setTitleVisibility            = libvcl.NewProc("NSWindow_setTitleVisibility")
	NSWindow_titlebarAppearsTransparent    = libvcl.NewProc("NSWindow_titlebarAppearsTransparent")
	NSWindow_setTitlebarAppearsTransparent = libvcl.NewProc("NSWindow_setTitlebarAppearsTransparent")
	NSWindow_styleMask                     = libvcl.NewProc("NSWindow_styleMask")
	NSWindow_setStyleMask                  = libvcl.NewProc("NSWindow_setStyleMask")
	NSWindow_setRepresentedURL             = libvcl.NewProc("NSWindow_setRepresentedURL")
)

*/

func (f *TForm) PlatformWindow() NSWindow {
	r, _, _ := NSWindow_FromForm.Call(f.instance)
	return NSWindow(r)
}

func (n NSWindow) TitleVisibility() NSWindowTitleVisibility {
	r, _, _ := NSWindow_titleVisibility.Call(uintptr(n))
	return NSWindowTitleVisibility(r)
}

func (n NSWindow) SetTitleVisibility(flag NSWindowTitleVisibility) {
	NSWindow_setTitleVisibility.Call(uintptr(n), uintptr(flag))
}

func (n NSWindow) TitleBarAppearsTransparent() bool {
	r, _, _ := NSWindow_titlebarAppearsTransparent.Call(uintptr(n))
	return DBoolToGoBool(r)
}

func (n NSWindow) SetTitleBarAppearsTransparent(flag bool) {
	NSWindow_setTitlebarAppearsTransparent.Call(uintptr(n), GoBoolToDBool(flag))
}

func (n NSWindow) SetRepresentedURL(url NSURL) {
	NSWindow_setRepresentedURL.Call(uintptr(n), uintptr(url))
}

func (n NSWindow) StyleMask() uint {
	r, _, _ := NSWindow_styleMask.Call(uintptr(n))
	return uint(r)
}

func (n NSWindow) SetStyleMask(mask uint) {
	NSWindow_setStyleMask.Call(uintptr(n), uintptr(mask))
}

//func (n NSWindow) Release_() {
//		NSWindow_release.Call(uintptr(n))
//}
<|endoftext|>


<commit_before>package blockwatch

import (
	"errors"
	"testing"

	ethcommon "github.com/ethereum/go-ethereum/common"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

type stubMiniHeaderStore struct {
	headers           []*MiniHeader
	latestErr         error
	sortedByNumberErr error
	insertErr         error
	deleteErr         error
}

func (s *stubMiniHeaderStore) FindLatestMiniHeader() (*MiniHeader, error) {
	if s.latestErr != nil {
		return nil, s.latestErr
	}

	if len(s.headers) == 0 {
		return nil, nil
	}

	return s.headers[len(s.headers)-1], nil
}

func (s *stubMiniHeaderStore) FindAllMiniHeadersSortedByNumber() ([]*MiniHeader, error) {
	if s.sortedByNumberErr != nil {
		return nil, s.sortedByNumberErr
	}

	return s.headers, nil
}

func (s *stubMiniHeaderStore) InsertMiniHeader(header *MiniHeader) error {
	if s.insertErr != nil {
		return s.insertErr
	}

	s.headers = append(s.headers, header)

	return nil
}

func (s *stubMiniHeaderStore) DeleteMiniHeader(hash ethcommon.Hash) error {
	if s.deleteErr != nil {
		return s.deleteErr
	}

	for i, header := range s.headers {
		if header.Hash == hash {
			copy(s.headers[i:], s.headers[i+1:])
			s.headers[len(s.headers)-1] = nil
			s.headers = s.headers[:len(s.headers)-1]
			return nil
		}
	}

	return errors.New("MiniHeader not found")
}

func TestPop(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 10)

	assert := assert.New(t)
	require := require.New(t)

	// Test when store.FindLatestMiniHeader() returns error
	store.latestErr = errors.New("FindLatestMiniHeader error")
	_, err := stack.Pop()
	assert.EqualError(err, store.latestErr.Error())

	// Test when store returns nil MiniHeader
	store.latestErr = nil
	header, err := stack.Pop()
	assert.Nil(header)
	assert.Nil(err)

	h0 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h0"))}
	require.Nil(store.InsertMiniHeader(h0))

	// Test when store.DeleteMiniHeader() returns error
	store.deleteErr = errors.New("DeleteMiniHeader error")
	_, err = stack.Pop()
	assert.EqualError(err, store.deleteErr.Error())

	// Test header popped when size = 1
	store.deleteErr = nil
	header, err = stack.Pop()
	assert.Equal(h0, header)
	assert.Nil(err)
	assert.Equal(0, len(store.headers))

	// Test header popped when size > 1
	h1 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h1"))}
	require.Nil(store.InsertMiniHeader(h0))
	require.Nil(store.InsertMiniHeader(h1))

	header, err = stack.Pop()
	assert.Equal(h1, header)
	assert.Nil(err)
	assert.Equal(1, len(store.headers))
}

func TestPush(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 2)

	assert := assert.New(t)
	require := require.New(t)

	// Test when store.FindAllMiniHeadersSortedByNumber() returns error
	store.sortedByNumberErr = errors.New("FindAllMiniHeadersSortedByNumber error")
	h0 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h0"))}
	err := stack.Push(h0)
	assert.EqualError(err, store.sortedByNumberErr.Error())

	// Test stack at limit and store.DeleteMiniHeader() returns error
	h1 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h1"))}
	require.Nil(store.InsertMiniHeader(h0))
	require.Nil(store.InsertMiniHeader(h1))

	h2 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h2"))}
	store.sortedByNumberErr = nil
	store.deleteErr = errors.New("DeleteMiniHeader error")
	err = stack.Push(h2)
	assert.EqualError(err, store.deleteErr.Error())

	// Test stack at limit, deleted bottom and store.InsertMiniHeader() returns error
	store.deleteErr = nil
	store.insertErr = errors.New("InsertMiniHeader error")
	err = stack.Push(h2)
	assert.EqualError(err, store.insertErr.Error())
	assert.Equal(h1, store.headers[0])
	assert.Equal(1, len(store.headers))

	// Test stack at limit, deleted bottom and header inserted
	store.insertErr = nil
	require.Nil(store.InsertMiniHeader(h2))

	h3 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h3"))}
	err = stack.Push(h3)
	assert.Nil(err)
	assert.Equal(h3, store.headers[len(store.headers)-1])
	assert.Equal(h2, store.headers[0])
	assert.Equal(2, len(store.headers))

	// Test stack not at limit and store.InsertMiniHeader() returns error
	require.Nil(store.DeleteMiniHeader(h2.Hash))

	h4 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h4"))}
	store.insertErr = errors.New("InsertMiniHeader error")
	err = stack.Push(h4)
	assert.EqualError(err, store.insertErr.Error())

	// Test not at limit and header inserted
	store.insertErr = nil
	err = stack.Push(h4)
	assert.Nil(err)
	assert.Equal(h4, store.headers[len(store.headers)-1])
	assert.Equal(2, len(store.headers))
}

func TestPeek(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 10)

	assert := assert.New(t)

	// Test store.FindLatestMiniHeader() returns error
	store.latestErr = errors.New("FindLatestMiniHeader error")
	_, err := stack.Peek()
	assert.EqualError(err, store.latestErr.Error())

	// Test header returned
	h := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h"))}
	require.Nil(t, store.InsertMiniHeader(h))

	store.latestErr = nil
	header, err := stack.Peek()
	assert.Nil(err)
	assert.Equal(h, header)
}

func TestInspect(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 10)

	assert := assert.New(t)

	// Test store.FindAllMiniHeadersSortedByNumber() returns error
	store.sortedByNumberErr = errors.New("FindAllMiniHeadersSortedByNumber error")
	_, err := stack.Inspect()
	assert.EqualError(err, store.sortedByNumberErr.Error())

	// Test headers returned
	h0 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h0"))}
	h1 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h1"))}
	require.Nil(t, store.InsertMiniHeader(h0))
	require.Nil(t, store.InsertMiniHeader(h1))

	store.sortedByNumberErr = nil
	headers, err := stack.Inspect()
	assert.Nil(err)
	assert.Equal(2, len(headers))
	assert.Equal(h0, headers[0])
	assert.Equal(h1, headers[1])
}
<commit_msg>eth: Add concurrency tests for stack<commit_after>package blockwatch

import (
	"errors"
	"sync"
	"testing"

	ethcommon "github.com/ethereum/go-ethereum/common"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

type stubMiniHeaderStore struct {
	headers           []*MiniHeader
	latestErr         error
	sortedByNumberErr error
	insertErr         error
	deleteErr         error
}

func (s *stubMiniHeaderStore) FindLatestMiniHeader() (*MiniHeader, error) {
	if s.latestErr != nil {
		return nil, s.latestErr
	}

	if len(s.headers) == 0 {
		return nil, nil
	}

	return s.headers[len(s.headers)-1], nil
}

func (s *stubMiniHeaderStore) FindAllMiniHeadersSortedByNumber() ([]*MiniHeader, error) {
	if s.sortedByNumberErr != nil {
		return nil, s.sortedByNumberErr
	}

	return s.headers, nil
}

func (s *stubMiniHeaderStore) InsertMiniHeader(header *MiniHeader) error {
	if s.insertErr != nil {
		return s.insertErr
	}

	s.headers = append(s.headers, header)

	return nil
}

func (s *stubMiniHeaderStore) DeleteMiniHeader(hash ethcommon.Hash) error {
	if s.deleteErr != nil {
		return s.deleteErr
	}

	for i, header := range s.headers {
		if header.Hash == hash {
			copy(s.headers[i:], s.headers[i+1:])
			s.headers[len(s.headers)-1] = nil
			s.headers = s.headers[:len(s.headers)-1]
			return nil
		}
	}

	return errors.New("MiniHeader not found")
}

func TestPop(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 10)

	assert := assert.New(t)
	require := require.New(t)

	// Test when store.FindLatestMiniHeader() returns error
	store.latestErr = errors.New("FindLatestMiniHeader error")
	_, err := stack.Pop()
	assert.EqualError(err, store.latestErr.Error())

	// Test when store returns nil MiniHeader
	store.latestErr = nil
	header, err := stack.Pop()
	assert.Nil(header)
	assert.Nil(err)

	h0 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h0"))}
	require.Nil(store.InsertMiniHeader(h0))

	// Test when store.DeleteMiniHeader() returns error
	store.deleteErr = errors.New("DeleteMiniHeader error")
	_, err = stack.Pop()
	assert.EqualError(err, store.deleteErr.Error())

	// Test header popped when size = 1
	store.deleteErr = nil
	header, err = stack.Pop()
	assert.Equal(h0, header)
	assert.Nil(err)
	assert.Equal(0, len(store.headers))

	// Test header popped when size > 1
	h1 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h1"))}
	require.Nil(store.InsertMiniHeader(h0))
	require.Nil(store.InsertMiniHeader(h1))

	header, err = stack.Pop()
	assert.Equal(h1, header)
	assert.Nil(err)
	assert.Equal(1, len(store.headers))
}

func TestPopConcurrent(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 10)

	assert := assert.New(t)
	require := require.New(t)

	// Insert headers into store
	headerMap := make(map[ethcommon.Hash]bool)
	for i := 0; i < 10; i++ {
		hash := ethcommon.BytesToHash([]byte(string(i)))
		headerMap[hash] = true

		require.Nil(store.InsertMiniHeader(&MiniHeader{Hash: hash}))
	}

	// Ensure that headerMap starts off with the correct # of entries
	assert.Equal(10, len(headerMap))

	popCh := make(chan *MiniHeader)

	var wg sync.WaitGroup
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func() {
			header, err := stack.Pop()
			require.Nil(err)

			popCh <- header

			wg.Done()
		}()
	}

	go func() {
		wg.Wait()
		close(popCh)
	}()

	// Mark each header as popped in headerMap
	for h := range popCh {
		_, ok := headerMap[h.Hash]
		assert.True(ok)

		delete(headerMap, h.Hash)
	}

	// headerMap should have 0 entries
	assert.Equal(0, len(headerMap))
	assert.Equal(0, len(store.headers))
}

func TestPush(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 2)

	assert := assert.New(t)
	require := require.New(t)

	// Test when store.FindAllMiniHeadersSortedByNumber() returns error
	store.sortedByNumberErr = errors.New("FindAllMiniHeadersSortedByNumber error")
	h0 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h0"))}
	err := stack.Push(h0)
	assert.EqualError(err, store.sortedByNumberErr.Error())

	// Test stack at limit and store.DeleteMiniHeader() returns error
	h1 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h1"))}
	require.Nil(store.InsertMiniHeader(h0))
	require.Nil(store.InsertMiniHeader(h1))

	h2 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h2"))}
	store.sortedByNumberErr = nil
	store.deleteErr = errors.New("DeleteMiniHeader error")
	err = stack.Push(h2)
	assert.EqualError(err, store.deleteErr.Error())

	// Test stack at limit, deleted bottom and store.InsertMiniHeader() returns error
	store.deleteErr = nil
	store.insertErr = errors.New("InsertMiniHeader error")
	err = stack.Push(h2)
	assert.EqualError(err, store.insertErr.Error())
	assert.Equal(h1, store.headers[0])
	assert.Equal(1, len(store.headers))

	// Test stack at limit, deleted bottom and header inserted
	store.insertErr = nil
	require.Nil(store.InsertMiniHeader(h2))

	h3 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h3"))}
	err = stack.Push(h3)
	assert.Nil(err)
	assert.Equal(h3, store.headers[len(store.headers)-1])
	assert.Equal(h2, store.headers[0])
	assert.Equal(2, len(store.headers))

	// Test stack not at limit and store.InsertMiniHeader() returns error
	require.Nil(store.DeleteMiniHeader(h2.Hash))

	h4 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h4"))}
	store.insertErr = errors.New("InsertMiniHeader error")
	err = stack.Push(h4)
	assert.EqualError(err, store.insertErr.Error())

	// Test not at limit and header inserted
	store.insertErr = nil
	err = stack.Push(h4)
	assert.Nil(err)
	assert.Equal(h4, store.headers[len(store.headers)-1])
	assert.Equal(2, len(store.headers))
}

func TestPushConcurrent(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 10)

	assert := assert.New(t)
	require := require.New(t)

	headerHash := func(i int) ethcommon.Hash {
		return ethcommon.BytesToHash([]byte(string(i)))
	}

	// Insert headers into store
	for i := 0; i < 10; i++ {
		require.Nil(store.InsertMiniHeader(&MiniHeader{Hash: headerHash(i)}))
	}

	// Create headerMap with expected entries after all stack pushes are complete
	headerMap := make(map[ethcommon.Hash]bool)
	for i := 10; i < 20; i++ {
		headerMap[headerHash(i)] = true
	}

	var wg sync.WaitGroup
	wg.Add(10)
	for i := 10; i < 20; i++ {
		go func(i int) {
			err := stack.Push(&MiniHeader{Hash: headerHash(i)})
			require.Nil(err)

			wg.Done()
		}(i)
	}

	wg.Wait()

	headers, err := stack.Inspect()
	require.Nil(err)

	for _, h := range headers {
		_, ok := headerMap[h.Hash]
		assert.True(ok)

		delete(headerMap, h.Hash)
	}

	// headerMap should have 0 entries
	assert.Equal(0, len(headerMap))
	assert.Equal(10, len(store.headers))
}

func TestPeek(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 10)

	assert := assert.New(t)

	// Test store.FindLatestMiniHeader() returns error
	store.latestErr = errors.New("FindLatestMiniHeader error")
	_, err := stack.Peek()
	assert.EqualError(err, store.latestErr.Error())

	// Test header returned
	h := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h"))}
	require.Nil(t, store.InsertMiniHeader(h))

	store.latestErr = nil
	header, err := stack.Peek()
	assert.Nil(err)
	assert.Equal(h, header)
}

func TestInspect(t *testing.T) {
	store := &stubMiniHeaderStore{}
	stack := NewStack(store, 10)

	assert := assert.New(t)

	// Test store.FindAllMiniHeadersSortedByNumber() returns error
	store.sortedByNumberErr = errors.New("FindAllMiniHeadersSortedByNumber error")
	_, err := stack.Inspect()
	assert.EqualError(err, store.sortedByNumberErr.Error())

	// Test headers returned
	h0 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h0"))}
	h1 := &MiniHeader{Hash: ethcommon.BytesToHash([]byte("h1"))}
	require.Nil(t, store.InsertMiniHeader(h0))
	require.Nil(t, store.InsertMiniHeader(h1))

	store.sortedByNumberErr = nil
	headers, err := stack.Inspect()
	assert.Nil(err)
	assert.Equal(2, len(headers))
	assert.Equal(h0, headers[0])
	assert.Equal(h1, headers[1])
}
<|endoftext|>