<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 commands_util

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"unicode"

	"github.com/skelterjohn/overwrite"
)

func PopulateRequestFromFilename(requestObject interface{}, filename string) error {
	var r io.Reader
	var err error
	if filename == "-" {
		r = os.Stdin
	} else {
		r, err = os.Open(filename)
		if err != nil {
			return err
		}
	}
	return json.NewDecoder(r).Decode(requestObject)
}

func OverwriteRequestWithValues(requestObject interface{}, keyValues map[string]string) error {
	for key, val := range keyValues {
		err := overwrite.Overwrite(requestObject, key, val)
		if err != nil {
			return fmt.Errorf("for key \"--%s\": while evaluating %s", key, err)
		}
	}
	return nil
}

func ErrForWrongParams(expectedParams, paramValues, args []string) error {
	value := "value"
	if len(expectedParams) > 1 {
		value += "s"
	}
	expectedArgument := strings.ToUpper(strings.Join(expectedParams, "/"))
	return fmt.Errorf(
		"expected %d %s for %s, but %q has %d.",
		len(expectedParams), value, expectedArgument, args[0], len(paramValues))
}

func ConvertValue_string(s string) (string, error) {
	return s, nil
}

func ConvertValue_int64(s string) (int64, error) {
	return strconv.ParseInt(s, 10, 64)
}

func ConvertValue_uint64(s string) (uint64, error) {
	return strconv.ParseUint(s, 10, 64)
}

func ConvertValue_int32(s string) (int32, error) {
	v, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return 0, err
	}
	return int32(v), err
}

func ConvertValue_uint32(s string) (uint32, error) {
	v, err := strconv.ParseUint(s, 10, 64)
	if err != nil {
		return 0, err
	}
	return uint32(v), err
}

func ConvertValue_float64(s string) (float64, error) {
	return strconv.ParseFloat(s, 64)
}

func ConvertValue_bool(s string) (bool, error) {
	return strconv.ParseBool(s)
}

func PrintResponse(response interface{}) error {
	var buf bytes.Buffer
	enc := json.NewEncoder(&buf)
	if err := enc.Encode(response); err != nil {
		return err
	}
	var indentedBuf bytes.Buffer
	if err := json.Indent(&indentedBuf, buf.Bytes(), "", "  "); err != nil {
		return err
	}
	_, err := fmt.Println(&indentedBuf)
	return err
}

/*
Get each of the tokens from a joined arg. Tokens are considered to be joined
by whatever the first character is. If the first character is in [a-zA-Z0-9],
a slash is assumed.
*/
func SplitParamValues(arg string) (params []string) {
	if len(arg) == 0 {
		return []string{}
	}
	sep := "/"
	firstLetter := rune(arg[0])
	if !(unicode.IsDigit(firstLetter) || unicode.IsLetter(firstLetter)) {
		sep = arg[0:1]
		arg = arg[1:]
	}
	return strings.Split(arg, sep)
}
<commit_msg>Fixed error message in request overwriting.<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 commands_util

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"unicode"

	"github.com/skelterjohn/overwrite"
)

func PopulateRequestFromFilename(requestObject interface{}, filename string) error {
	var r io.Reader
	var err error
	if filename == "-" {
		r = os.Stdin
	} else {
		r, err = os.Open(filename)
		if err != nil {
			return err
		}
	}
	return json.NewDecoder(r).Decode(requestObject)
}

func OverwriteRequestWithValues(requestObject interface{}, keyValues map[string]string) error {
	for key, val := range keyValues {
		err := overwrite.Overwrite(requestObject, key, val)
		if err != nil {
			return fmt.Errorf("for key \"--%s\" while evaluating %s: %s", key, val, err)
		}
	}
	return nil
}

func ErrForWrongParams(expectedParams, paramValues, args []string) error {
	value := "value"
	if len(expectedParams) > 1 {
		value += "s"
	}
	expectedArgument := strings.ToUpper(strings.Join(expectedParams, "/"))
	return fmt.Errorf(
		"expected %d %s for %s, but %q has %d.",
		len(expectedParams), value, expectedArgument, args[0], len(paramValues))
}

func ConvertValue_string(s string) (string, error) {
	return s, nil
}

func ConvertValue_int64(s string) (int64, error) {
	return strconv.ParseInt(s, 10, 64)
}

func ConvertValue_uint64(s string) (uint64, error) {
	return strconv.ParseUint(s, 10, 64)
}

func ConvertValue_int32(s string) (int32, error) {
	v, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return 0, err
	}
	return int32(v), err
}

func ConvertValue_uint32(s string) (uint32, error) {
	v, err := strconv.ParseUint(s, 10, 64)
	if err != nil {
		return 0, err
	}
	return uint32(v), err
}

func ConvertValue_float64(s string) (float64, error) {
	return strconv.ParseFloat(s, 64)
}

func ConvertValue_bool(s string) (bool, error) {
	return strconv.ParseBool(s)
}

func PrintResponse(response interface{}) error {
	var buf bytes.Buffer
	enc := json.NewEncoder(&buf)
	if err := enc.Encode(response); err != nil {
		return err
	}
	var indentedBuf bytes.Buffer
	if err := json.Indent(&indentedBuf, buf.Bytes(), "", "  "); err != nil {
		return err
	}
	_, err := fmt.Println(&indentedBuf)
	return err
}

/*
Get each of the tokens from a joined arg. Tokens are considered to be joined
by whatever the first character is. If the first character is in [a-zA-Z0-9],
a slash is assumed.
*/
func SplitParamValues(arg string) (params []string) {
	if len(arg) == 0 {
		return []string{}
	}
	sep := "/"
	firstLetter := rune(arg[0])
	if !(unicode.IsDigit(firstLetter) || unicode.IsLetter(firstLetter)) {
		sep = arg[0:1]
		arg = arg[1:]
	}
	return strings.Split(arg, sep)
}
<|endoftext|>


<commit_before>package main

import "fmt"

func main() {

	l := LinkedList{}
	l.insert(1)
	l.insert(2)
	l.insert(3)
	l.insert(4)
	l.traverse(print)
	// OUTPUT:
	// 1 false
	// 2 false
	// 3 false
	// 4 true

	l.delete()
	l.delete()
	l.traverse(print)
	// OUTPUT:
	// 1 false
	// 2 true

}

func print(n *node) bool {
	fmt.Println(n.value, n.next == nil)
	return false
}

type node struct {
	value int
	next  *node
}

type LinkedList struct {
	head *node
	tail *node
}

func (l *LinkedList) insert(value int) {
	n := node{value: value}
	if l.head == nil {
		l.head = &n
		l.tail = &n
	}
	l.tail.next = &n
	l.tail = l.tail.next
}

func (l *LinkedList) delete() {
	f := func(n *node) bool {
		if n.next.next == nil {
			l.tail = n
			l.tail.next = nil
			return true
		}
		return false
	}

	l.traverse(f)
}

func (l *LinkedList) traverse(f func(*node) bool) {
	for n := l.head; n != nil; n = n.next {
		if f(n) {
			break
		}
	}
}
<commit_msg>Update linkedListSingle.go: rename insert() to append()<commit_after>package main

import "fmt"

func main() {

	l := LinkedList{}
	l.append(1)
	l.append(2)
	l.append(3)
	l.append(4)
	l.traverse(print)
	// OUTPUT:
	// 1 false
	// 2 false
	// 3 false
	// 4 true

	l.delete()
	l.delete()
	l.traverse(print)
	// OUTPUT:
	// 1 false
	// 2 true

}

func print(n *node) bool {
	fmt.Println(n.value, n.next == nil)
	return false
}

type node struct {
	value int
	next  *node
}

type LinkedList struct {
	head *node
	tail *node
}

func (l *LinkedList) append(value int) {
	n := node{value: value}
	if l.head == nil {
		l.head = &n
		l.tail = &n
	}
	l.tail.next = &n
	l.tail = l.tail.next
}

func (l *LinkedList) delete() {
	f := func(n *node) bool {
		if n.next.next == nil {
			l.tail = n
			l.tail.next = nil
			return true
		}
		return false
	}

	l.traverse(f)
}

func (l *LinkedList) traverse(f func(*node) bool) {
	for n := l.head; n != nil; n = n.next {
		if f(n) {
			break
		}
	}
}
<|endoftext|>


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

package app

import (
	"errors"
	"sync/atomic"
	"time"

	"github.com/tsuru/tsuru/log"
)

type Logger interface {
	Log(string, string, string) error
}

type LogWriter struct {
	App    Logger
	Source string
	msgCh  chan []byte
	doneCh chan bool
	closed int32
}

func (w *LogWriter) Async() {
	w.msgCh = make(chan []byte, 1000)
	w.doneCh = make(chan bool)
	go func() {
		defer close(w.doneCh)
		for msg := range w.msgCh {
			err := w.write(msg)
			if err != nil {
				log.Errorf("[LogWriter] failed to write async logs: %s", err)
				return
			}
		}
	}()
}

func (w *LogWriter) Close() {
	atomic.StoreInt32(&w.closed, 1)
	if w.msgCh != nil {
		close(w.msgCh)
	}
}

func (w *LogWriter) Wait(timeout time.Duration) error {
	if w.msgCh == nil {
		return nil
	}
	select {
	case <-w.doneCh:
	case <-time.After(timeout):
		return errors.New("timeout waiting for writer to finish")
	}
	return nil
}

// Write writes and logs the data.
func (w *LogWriter) Write(data []byte) (int, error) {
	if atomic.LoadInt32(&w.closed) == 1 {
		return len(data), nil
	}
	if w.msgCh == nil {
		return len(data), w.write(data)
	}
	copied := make([]byte, len(data))
	copy(copied, data)
	w.msgCh <- copied
	return len(data), nil
}

func (w *LogWriter) write(data []byte) error {
	source := w.Source
	if source == "" {
		source = "tsuru"
	}
	return w.App.Log(string(data), source, "api")
}
<commit_msg>app: remove return from LogWriter log consumption goroutine<commit_after>// Copyright 2015 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package app

import (
	"errors"
	"sync/atomic"
	"time"

	"github.com/tsuru/tsuru/log"
)

type Logger interface {
	Log(string, string, string) error
}

type LogWriter struct {
	App    Logger
	Source string
	msgCh  chan []byte
	doneCh chan bool
	closed int32
}

func (w *LogWriter) Async() {
	w.msgCh = make(chan []byte, 1000)
	w.doneCh = make(chan bool)
	go func() {
		defer close(w.doneCh)
		for msg := range w.msgCh {
			err := w.write(msg)
			if err != nil {
				log.Errorf("[LogWriter] failed to write async logs: %s", err)
			}
		}
	}()
}

func (w *LogWriter) Close() {
	atomic.StoreInt32(&w.closed, 1)
	if w.msgCh != nil {
		close(w.msgCh)
	}
}

func (w *LogWriter) Wait(timeout time.Duration) error {
	if w.msgCh == nil {
		return nil
	}
	select {
	case <-w.doneCh:
	case <-time.After(timeout):
		return errors.New("timeout waiting for writer to finish")
	}
	return nil
}

// Write writes and logs the data.
func (w *LogWriter) Write(data []byte) (int, error) {
	if atomic.LoadInt32(&w.closed) == 1 {
		return len(data), nil
	}
	if w.msgCh == nil {
		return len(data), w.write(data)
	}
	copied := make([]byte, len(data))
	copy(copied, data)
	w.msgCh <- copied
	return len(data), nil
}

func (w *LogWriter) write(data []byte) error {
	source := w.Source
	if source == "" {
		source = "tsuru"
	}
	return w.App.Log(string(data), source, "api")
}
<|endoftext|>


<commit_before>package main

// Import needed packages
import (
	"encoding/json"
	"github.com/boltdb/bolt"
	"gopkg.in/fsnotify.v1"
	"log"
	"time"
)

type WatchEvent struct {
	Type fsnotify.Event
	File string
}

func ExampleNewWatcher(db *bolt.DB) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				log.Println("event:", event)
				if event.Op&fsnotify.Write == fsnotify.Write {

					watchEvent := &WatchEvent{
						Type: event,
						File: event.Name,
					}
					db.Update(func(tx *bolt.Tx) error {
						b, err := tx.CreateBucketIfNotExists([]byte("events"))
						if err != nil {
							return err
						}
						encoded, err := json.Marshal(watchEvent)
						if err != nil {
							return err
						}
						return b.Put([]byte(time.Now().Format(time.RFC3339)), encoded)
					})
					log.Println("modified file:", event.Name)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = watcher.Add("/tmp")
	if err != nil {
		log.Fatal(err)
	}
	<-done
}

func main() {
	db, err := bolt.Open("/tmp.db", 0644, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	ExampleNewWatcher(db)
}
<commit_msg>Changed the wording around as a test commit to associate with issue #1.<commit_after>package main

// Import needed packages
import (
	"encoding/json"
	"github.com/boltdb/bolt"
	"gopkg.in/fsnotify.v1"
	"log"
	"time"
)

type WatchEvent struct {
	Type fsnotify.Event
	File string
}

func ExampleNewWatcher(db *bolt.DB) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				log.Println("event:", event)
				if event.Op&fsnotify.Write == fsnotify.Write {

					watchEvent := &WatchEvent{
						Type: event,
						File: event.Name,
					}
					db.Update(func(tx *bolt.Tx) error {
						b, err := tx.CreateBucketIfNotExists([]byte("events"))
						if err != nil {
							return err
						}
						encoded, err := json.Marshal(watchEvent)
						if err != nil {
							return err
						}
						return b.Put([]byte(time.Now().Format(time.RFC3339)), encoded)
					})
					log.Println("file modified:", event.Name)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = watcher.Add("/tmp")
	if err != nil {
		log.Fatal(err)
	}
	<-done
}

func main() {
	db, err := bolt.Open("/tmp.db", 0644, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	ExampleNewWatcher(db)
}
<|endoftext|>


<commit_before>package goshopify

import (
	"reflect"
	"testing"
	"time"

	"github.com/shopspring/decimal"
	"gopkg.in/jarcoal/httpmock.v1"
)

// recurringApplicationChargeTests tests if the fields are properly parsed.
func recurringApplicationChargeTests(t *testing.T, charge RecurringApplicationCharge) {
	var (
		nilTime *time.Time
		nilTest *bool
	)

	cases := []struct {
		field    string
		expected interface{}
		actual   interface{}
	}{
		{"ID", 1029266948, charge.ID},
		{"Name", "Super Duper Plan", charge.Name},
		{"APIClientID", 755357713, charge.APIClientID},
		{"Price", decimal.NewFromFloat(10.00).String(), charge.Price.String()},
		{"Status", "pending", charge.Status},
		{"ReturnURL", "http://super-duper.shopifyapps.com/", charge.ReturnURL},
		{"BillingOn", nilTime, charge.BillingOn},
		{"CreatedAt", "2018-05-07T15:47:10-04:00", charge.CreatedAt.Format(time.RFC3339)},
		{"UpdatedAt", "2018-05-07T15:47:10-04:00", charge.UpdatedAt.Format(time.RFC3339)},
		{"Test", nilTest, charge.Test},
		{"ActivatedOn", nilTime, charge.ActivatedOn},
		{"TrialEndsOn", nilTime, charge.TrialEndsOn},
		{"CancelledOn", nilTime, charge.CancelledOn},
		{"TrialDays", 0, charge.TrialDays},
		{
			"DecoratedReturnURL",
			"http://super-duper.shopifyapps.com/?charge_id=1029266948",
			charge.DecoratedReturnURL,
		},
		{
			"ConfirmationURL",
			"https://apple.myshopify.com/admin/charges/1029266948/confirm_recurring_application_c" +
				"harge?signature=BAhpBAReWT0%3D--b51a6db06a3792c4439783fcf0f2e89bf1c9df68",
			charge.ConfirmationURL,
		},
	}

	for _, c := range cases {
		if c.expected != c.actual {
			t.Errorf("RecurringApplicationCharge.%s returned %v, expected %v", c.field, c.actual,
				c.expected)
		}
	}
}

func TestRecurringApplicationChargeServiceOp_Create(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"POST",
		"https://fooshop.myshopify.com/admin/recurring_application_charges.json",
		httpmock.NewBytesResponder(200, loadFixture("reccuringapplicationcharge.json")),
	)

	p := decimal.NewFromFloat(10.0)
	charge := RecurringApplicationCharge{
		Name:      "Super Duper Plan",
		Price:     &p,
		ReturnURL: "http://super-duper.shopifyapps.com",
	}

	returnedCharge, err := client.RecurringApplicationCharge.Create(charge)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.Create returned an error: %v", err)
	}

	recurringApplicationChargeTests(t, *returnedCharge)
}

func TestRecurringApplicationChargeServiceOp_Get(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"GET",
		"https://fooshop.myshopify.com/admin/recurring_application_charges/1.json",
		httpmock.NewStringResponder(200, `{"recurring_application_charge": {"id":1}}`),
	)

	charge, err := client.RecurringApplicationCharge.Get(1, nil)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.Get returned an error: %v", err)
	}

	expected := &RecurringApplicationCharge{ID: 1}
	if !reflect.DeepEqual(charge, expected) {
		t.Errorf("RecurringApplicationCharge.Get returned %+v, expected %+v", charge, expected)
	}
}

func TestRecurringApplicationChargeServiceOp_List(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"GET",
		"https://fooshop.myshopify.com/admin/recurring_application_charges.json",
		httpmock.NewStringResponder(200, `{"recurring_application_charges": [{"id":1},{"id":2}]}`),
	)

	charges, err := client.RecurringApplicationCharge.List(nil)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.List returned an error: %v", err)
	}

	expected := []RecurringApplicationCharge{{ID: 1}, {ID: 2}}
	if !reflect.DeepEqual(charges, expected) {
		t.Errorf("RecurringApplicationCharge.List returned %+v, expected %+v", charges, expected)
	}
}

func TestRecurringApplicationChargeServiceOp_Activate(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"POST",
		"https://fooshop.myshopify.com/admin/recurring_application_charges/455696195/activate.json",
		httpmock.NewStringResponder(
			200,
			`{"recurring_application_charge":{"id":455696195,"status":"active"}}`,
		),
	)

	charge := RecurringApplicationCharge{
		ID:     455696195,
		Status: "accepted",
	}

	returnedCharge, err := client.RecurringApplicationCharge.Activate(charge)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.Activate returned an error: %v", err)
	}

	expected := &RecurringApplicationCharge{ID: 455696195, Status: "active"}
	if !reflect.DeepEqual(returnedCharge, expected) {
		t.Errorf("RecurringApplicationCharge.Activate returned %+v, expected %+v", charge, expected)
	}
}

func TestRecurringApplicationChargeServiceOp_Delete(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"DELETE",
		"https://fooshop.myshopify.com/admin/recurring_application_charges/1.json",
		httpmock.NewStringResponder(200, "{}"),
	)

	if err := client.RecurringApplicationCharge.Delete(1); err != nil {
		t.Errorf("RecurringApplicationCharge.Delete returned an error: %v", err)
	}
}

func TestRecurringApplicationChargeServiceOp_Update(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"PUT",
		"https://fooshop.myshopify.com/admin/recurring_application_charges/455696195/customize.jso"+
			"n?recurring_application_charge[capped_amount]=100",
		httpmock.NewStringResponder(
			200,
			`{"recurring_application_charge":{"id":455696195,"capped_amount":"100.00"}}`,
		),
	)

	charge, err := client.RecurringApplicationCharge.Update(455696195, 100)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.Update returned an error: %v", err)
	}

	ca := decimal.NewFromFloat(100.00)
	expected := &RecurringApplicationCharge{ID: 455696195, CappedAmount: &ca}
	if !reflect.DeepEqual(charge, expected) {
		t.Errorf("RecurringApplicationCharge.Update returned %+v, expected %+v", charge, expected)
	}
}
<commit_msg>Fix build due to updated decimal library (#102)<commit_after>package goshopify

import (
	"reflect"
	"testing"
	"time"

	"github.com/shopspring/decimal"
	"gopkg.in/jarcoal/httpmock.v1"
)

// recurringApplicationChargeTests tests if the fields are properly parsed.
func recurringApplicationChargeTests(t *testing.T, charge RecurringApplicationCharge) {
	var (
		nilTime *time.Time
		nilTest *bool
	)

	cases := []struct {
		field    string
		expected interface{}
		actual   interface{}
	}{
		{"ID", 1029266948, charge.ID},
		{"Name", "Super Duper Plan", charge.Name},
		{"APIClientID", 755357713, charge.APIClientID},
		{"Price", decimal.NewFromFloat(10.00).String(), charge.Price.String()},
		{"Status", "pending", charge.Status},
		{"ReturnURL", "http://super-duper.shopifyapps.com/", charge.ReturnURL},
		{"BillingOn", nilTime, charge.BillingOn},
		{"CreatedAt", "2018-05-07T15:47:10-04:00", charge.CreatedAt.Format(time.RFC3339)},
		{"UpdatedAt", "2018-05-07T15:47:10-04:00", charge.UpdatedAt.Format(time.RFC3339)},
		{"Test", nilTest, charge.Test},
		{"ActivatedOn", nilTime, charge.ActivatedOn},
		{"TrialEndsOn", nilTime, charge.TrialEndsOn},
		{"CancelledOn", nilTime, charge.CancelledOn},
		{"TrialDays", 0, charge.TrialDays},
		{
			"DecoratedReturnURL",
			"http://super-duper.shopifyapps.com/?charge_id=1029266948",
			charge.DecoratedReturnURL,
		},
		{
			"ConfirmationURL",
			"https://apple.myshopify.com/admin/charges/1029266948/confirm_recurring_application_c" +
				"harge?signature=BAhpBAReWT0%3D--b51a6db06a3792c4439783fcf0f2e89bf1c9df68",
			charge.ConfirmationURL,
		},
	}

	for _, c := range cases {
		if c.expected != c.actual {
			t.Errorf("RecurringApplicationCharge.%s returned %v, expected %v", c.field, c.actual,
				c.expected)
		}
	}
}

func TestRecurringApplicationChargeServiceOp_Create(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"POST",
		"https://fooshop.myshopify.com/admin/recurring_application_charges.json",
		httpmock.NewBytesResponder(200, loadFixture("reccuringapplicationcharge.json")),
	)

	p := decimal.NewFromFloat(10.0)
	charge := RecurringApplicationCharge{
		Name:      "Super Duper Plan",
		Price:     &p,
		ReturnURL: "http://super-duper.shopifyapps.com",
	}

	returnedCharge, err := client.RecurringApplicationCharge.Create(charge)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.Create returned an error: %v", err)
	}

	recurringApplicationChargeTests(t, *returnedCharge)
}

func TestRecurringApplicationChargeServiceOp_Get(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"GET",
		"https://fooshop.myshopify.com/admin/recurring_application_charges/1.json",
		httpmock.NewStringResponder(200, `{"recurring_application_charge": {"id":1}}`),
	)

	charge, err := client.RecurringApplicationCharge.Get(1, nil)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.Get returned an error: %v", err)
	}

	expected := &RecurringApplicationCharge{ID: 1}
	if !reflect.DeepEqual(charge, expected) {
		t.Errorf("RecurringApplicationCharge.Get returned %+v, expected %+v", charge, expected)
	}
}

func TestRecurringApplicationChargeServiceOp_List(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"GET",
		"https://fooshop.myshopify.com/admin/recurring_application_charges.json",
		httpmock.NewStringResponder(200, `{"recurring_application_charges": [{"id":1},{"id":2}]}`),
	)

	charges, err := client.RecurringApplicationCharge.List(nil)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.List returned an error: %v", err)
	}

	expected := []RecurringApplicationCharge{{ID: 1}, {ID: 2}}
	if !reflect.DeepEqual(charges, expected) {
		t.Errorf("RecurringApplicationCharge.List returned %+v, expected %+v", charges, expected)
	}
}

func TestRecurringApplicationChargeServiceOp_Activate(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"POST",
		"https://fooshop.myshopify.com/admin/recurring_application_charges/455696195/activate.json",
		httpmock.NewStringResponder(
			200,
			`{"recurring_application_charge":{"id":455696195,"status":"active"}}`,
		),
	)

	charge := RecurringApplicationCharge{
		ID:     455696195,
		Status: "accepted",
	}

	returnedCharge, err := client.RecurringApplicationCharge.Activate(charge)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.Activate returned an error: %v", err)
	}

	expected := &RecurringApplicationCharge{ID: 455696195, Status: "active"}
	if !reflect.DeepEqual(returnedCharge, expected) {
		t.Errorf("RecurringApplicationCharge.Activate returned %+v, expected %+v", charge, expected)
	}
}

func TestRecurringApplicationChargeServiceOp_Delete(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"DELETE",
		"https://fooshop.myshopify.com/admin/recurring_application_charges/1.json",
		httpmock.NewStringResponder(200, "{}"),
	)

	if err := client.RecurringApplicationCharge.Delete(1); err != nil {
		t.Errorf("RecurringApplicationCharge.Delete returned an error: %v", err)
	}
}

func TestRecurringApplicationChargeServiceOp_Update(t *testing.T) {
	setup()
	defer teardown()

	httpmock.RegisterResponder(
		"PUT",
		"https://fooshop.myshopify.com/admin/recurring_application_charges/455696195/customize.jso"+
			"n?recurring_application_charge[capped_amount]=100",
		httpmock.NewStringResponder(
			200,
			`{"recurring_application_charge":{"id":455696195,"capped_amount":"100.00"}}`,
		),
	)

	charge, err := client.RecurringApplicationCharge.Update(455696195, 100)
	if err != nil {
		t.Errorf("RecurringApplicationCharge.Update returned an error: %v", err)
	}

	ca := decimal.NewFromFloat(100.00)
	expected := &RecurringApplicationCharge{ID: 455696195, CappedAmount: &ca}

	if charge.CappedAmount.String() != expected.CappedAmount.String() {
		t.Errorf("RecurringApplicationCharge.Update returned %#v\n, expected %#v", charge, expected)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/hex"
	"fmt"
	"getcommandline"
	"hash"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"tokenize"
)

/*
  REVISION HISTORY
  ----------------
   6 Apr 13 -- First modified version of module.  I will use VLI to compare all digits of the hashes.
  23 Apr 13 -- Fixed problem of a single line in the hashes file, that does not contain an EOL character, causes
                an immediate return without processing of the characters just read in.
  24 Apr 13 -- Added output of which file either matches or does not match.
  19 Sep 16 -- Finished conversion to Go, that was started 13 Sep 16.  Added the removed of '*' which is part of a std linux formated hash file.  And I forgot that
                 the routine allowed either order in the file.  If the token has a '.' I assume it is a filename, else it is a hash value.
  21 Sep 16 -- Fixed the case issue in tokenize.GetToken.  Edited code here to correspond to this fix.
  25 Nov 16 -- Need to not panic when target file is not found, only panic when hash file is not found.
                 And added a LastCompiled message and string.
  13 Oct 17 -- No changes here, but tokenize was changed so that horizontal tab char is now a delim.
  14 Oct 17 -- Tweaked output a bit.  And added executable timestamp code.
  19 Oct 17 -- Added ability to ignore the * that standard hash files for linux use.
*/

const LastCompiled = "19 Oct 2017"

//* ************************* MAIN ***************************************************************
func main() {

	const K = 1024
	const M = 1024 * 1024

	const (
		md5hash = iota
		sha1hash
		sha256hash
		sha384hash
		sha512hash
		HashType
	)

	const ReadBufferSize = M
	//  const ReadBufferSize = 80 * M;

	var HashName = [...]string{"md5", "sha1", "sha256", "sha384", "sha512"}
	var inbuf string
	var WhichHash int
	var readErr error
	var TargetFilename, HashValueReadFromFile, HashValueComputedStr string
	var hasher hash.Hash
	var FileSize int64

	if len(os.Args) <= 1 {
		fmt.Println(" Usage: comparehashes <hashFileName.ext> where .ext = [.md5|.sha1|.sha256|.sha384|.sha512]")
		os.Exit(0)
	}
	inbuf = getcommandline.GetCommandLineString()

	extension := filepath.Ext(inbuf)
	extension = strings.ToLower(extension)
	switch extension {
	case ".md5":
		WhichHash = md5hash
	case ".sha1":
		WhichHash = sha1hash
	case ".sha256":
		WhichHash = sha256hash
	case ".sha384":
		WhichHash = sha384hash
	case ".sha512":
		WhichHash = sha512hash
	default:
		fmt.Println()
		fmt.Println()
		fmt.Println(" Not a recognized hash extension.  Will assume sha1.")
		WhichHash = sha1hash
	} // switch case on extension for HashType

	fmt.Println()
	fmt.Print(" comparehashes written in Go.  GOOS =", runtime.GOOS, ".  ARCH=", runtime.GOARCH)

	fmt.Println(".  Last compiled ", LastCompiled)
	//            fmt.Println(".  HashType = md5, sha1, sha256, sha384, sha512.  WhichHash = ",HashName[WhichHash]);
	workingdir, _ := os.Getwd()
	execname, _ := os.Executable()
	ExecFI, _ := os.Stat(execname)
	LastLinkedTimeStamp := ExecFI.ModTime().Format("Mon Jan 2 2006 15:04:05 MST")
	fmt.Printf("%s has timestamp of %s.  Working directory is %s.  Full name of executable is %s.\n", ExecFI.Name(), LastLinkedTimeStamp, workingdir, execname)
	fmt.Println()

	// Read and parse the file with the hashes.

	HashesFile, err := os.Open(inbuf)
	if os.IsNotExist(err) {
		fmt.Println(inbuf, " does not exist.")
		os.Exit(1)
	} else { // we know that the file exists
		check(err, " Error opening hashes file.")
	}
	check(err, "Cannot open HashesFile.  Does it exist?  ")
	defer HashesFile.Close()

	scanner := bufio.NewScanner(HashesFile)
	scanner.Split(bufio.ScanLines) // I believe this is the default.  I may experiment to see if I need this line for my code to work, AFTER I debug it as it is.

	for { /* to read multiple lines */
		FileSize = 0
		readSuccess := scanner.Scan()
		if !readSuccess {
			break
		} // end main reading loop

		inputline := scanner.Text()
		if readErr = scanner.Err(); readErr != nil {
			if readErr == io.EOF {
				break
			} // reached EOF condition, so there are no more lines to read.
			fmt.Fprintln(os.Stderr, "Unknown error while reading from the HashesFile :", readErr)
			os.Exit(1)
		}

		if strings.HasPrefix(inputline, ";") || strings.HasPrefix(inputline, "#") || (len(inputline) <= 10) {
			continue
		} /* allow comments and essentially blank lines */

		tokenize.INITKN(inputline)
		tokenize.SetMapDelim('*') // to ignore this character that begins the filename field.  Don't know why it's there.

		FirstToken, EOL := tokenize.GetTokenString(false)

		if EOL {
			fmt.Errorf(" Error while getting 1st token in the hashing file.  Skipping")
			continue
		}

		if strings.ContainsRune(FirstToken.Str, '.') { /* have filename first on line */
			TargetFilename = FirstToken.Str
			SecondToken, EOL := tokenize.GetTokenString(false) // Get hash string from the line in the file
			if EOL {
				fmt.Errorf(" Got EOL while getting HashValue (2nd) token in the hashing file.  Skipping \n")
				continue
			} /* if EOL */
			HashValueReadFromFile = SecondToken.Str

		} else { /* have hash first on line */
			HashValueReadFromFile = FirstToken.Str
			SecondToken, EOL := tokenize.GetTokenString(false) // Get name of file on which to compute the hash
			if EOL {
				fmt.Errorf(" Error while gatting TargetFilename token in the hashing file.  Skipping \n")
				continue
			} /* if EOL */

			if strings.ContainsRune(SecondToken.Str, '*') { // If it contains a *, it will be the first position.
				SecondToken.Str = SecondToken.Str[1:]
				if strings.ContainsRune(SecondToken.Str, '*') { // this should not happen
					fmt.Println(" Filename token still contains a * character.  Str:", SecondToken.Str, "  Skipping.")
					continue
				}
			}
			TargetFilename = (SecondToken.Str)
		} /* if have filename first or hash value first */

		/*
		   now to compute the hash, compare them, and output results
		*/
		/* Create Hash Section */
		TargetFile, err := os.Open(TargetFilename)
		//    exists := true;
		if os.IsNotExist(err) {
			fmt.Println(TargetFilename, " does not exist.")
			continue
		} else { // we know that the file exists
			check(err, " Error opening TargetFilename.")
		}

		defer TargetFile.Close()

		switch WhichHash { // Initialing case switch on WhichHash
		case md5hash:
			hasher = md5.New()
		case sha1hash:
			hasher = sha1.New()
		case sha256hash:
			hasher = sha256.New()
		case sha384hash:
			hasher = sha512.New384()
		case sha512hash:
			hasher = sha512.New()
		default:
			hasher = sha256.New()
		} /* initializing switch case on WhichHash */

		/*    This loop works, but there is a much shorter way.  I got this after asking for help on the mailing list.
		      FileReadBuffer := make([]byte,ReadBufferSize);
		      for {   // Repeat Until eof loop.
		        n,err := TargetFile.Read(FileReadBuffer);
		        if n == 0 || err == io.EOF { break }
		        check(err," Unexpected error while reading the target file on which to compute the hash,");
		        hasher.Write(FileReadBuffer[:n]);
		        FileSize += int64(n);
		      } // Repeat Until TargetFile.eof loop;
		*/

		FileSize, readErr = io.Copy(hasher, TargetFile)
		HashValueComputedStr = hex.EncodeToString(hasher.Sum(nil))

		// I got the idea to use the different base64 versions and my own hex converter code, just to see.
		// And I can also use sfprintf with the %x verb.  base64 versions are not useful as they use a larger
		// character set than hex.  I deleted all references to the base64 versions.  And the hex encoded and
		// sprintf using %x were the same, so I removed the sprintf code.
		//    HashValueComputedSprintf := fmt.Sprintf("%x",hasher.Sum(nil));

		//		fmt.Println(" Filename  = ", TargetFilename, ", FileSize = ", FileSize, ", ", HashName[WhichHash], " computed hash string -- ")
		fmt.Printf(" Filename  = %s, filesize = %d, using hash %s.\n", TargetFilename, FileSize, HashName[WhichHash])
		fmt.Println("       Read From File:", HashValueReadFromFile)
		fmt.Println(" Computed hex encoded:", HashValueComputedStr)
		//    fmt.Println(" Computed sprintf:",HashValueComputedSprintf);

		if HashValueReadFromFile == HashValueComputedStr {
			fmt.Print(" Matched.")
		} else {
			fmt.Print(" Not matched.")
		} /* if hashes */
		TargetFile.Close() // Close the handle to allow opening a target from the next line, if there is one.
		fmt.Println()
		fmt.Println()
		fmt.Println()
	} /* outer LOOP to read multiple lines */

	HashesFile.Close() // Don't really need this because of the defer statement.
	fmt.Println()
} // Main for comparehashes.go.

// ------------------------------------------------------- check -------------------------------
func check(e error, msg string) {
	if e != nil {
		fmt.Errorf("%s : ", msg)
		panic(e)
	}
}
<commit_msg>modified:   comparehashes/comparehashes.go -- added filepicker<commit_after>package main

import (
	"bufio"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/hex"
	"filepicker"
	"fmt"
	"getcommandline"
	"hash"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"tokenize"
)

/*
  REVISION HISTORY
  ----------------
   6 Apr 13 -- First modified version of module.  I will use VLI to compare all digits of the hashes.
  23 Apr 13 -- Fixed problem of a single line in the hashes file, that does not contain an EOL character, causes
                an immediate return without processing of the characters just read in.
  24 Apr 13 -- Added output of which file either matches or does not match.
  19 Sep 16 -- Finished conversion to Go, that was started 13 Sep 16.  Added the removed of '*' which is part of a std linux formated hash file.  And I forgot that
                 the routine allowed either order in the file.  If the token has a '.' I assume it is a filename, else it is a hash value.
  21 Sep 16 -- Fixed the case issue in tokenize.GetToken.  Edited code here to correspond to this fix.
  25 Nov 16 -- Need to not panic when target file is not found, only panic when hash file is not found.
                 And added a LastCompiled message and string.
  13 Oct 17 -- No changes here, but tokenize was changed so that horizontal tab char is now a delim.
  14 Oct 17 -- Tweaked output a bit.  And added executable timestamp code.
  19 Oct 17 -- Added ability to ignore the * that standard hash files for linux use.
  21 Oct 17 -- Added filepicker.
*/

const LastCompiled = "21 Oct 2017"

//* ************************* MAIN ***************************************************************
func main() {

	const K = 1024
	const M = 1024 * 1024

	const (
		md5hash = iota
		sha1hash
		sha256hash
		sha384hash
		sha512hash
		HashType
	)

	const ReadBufferSize = M
	//  const ReadBufferSize = 80 * M;

	var HashName = [...]string{"md5", "sha1", "sha256", "sha384", "sha512"}
	var inbuf, ans, Filename string
	var WhichHash int
	var readErr error
	var TargetFilename, HashValueReadFromFile, HashValueComputedStr string
	var hasher hash.Hash
	var FileSize int64

	fmt.Print(" comparehashes written in Go.  GOOS =", runtime.GOOS, ".  ARCH=", runtime.GOARCH)

	fmt.Println(".  Last compiled ", LastCompiled)
	//            fmt.Println(".  HashType = md5, sha1, sha256, sha384, sha512.  WhichHash = ",HashName[WhichHash]);
	workingdir, _ := os.Getwd()
	execname, _ := os.Executable()
	ExecFI, _ := os.Stat(execname)
	LastLinkedTimeStamp := ExecFI.ModTime().Format("Mon Jan 2 2006 15:04:05 MST")
	fmt.Printf("%s has timestamp of %s.  Working directory is %s.  Full name of executable is %s.\n", ExecFI.Name(), LastLinkedTimeStamp, workingdir, execname)
	fmt.Println()

	// filepicker stuff.

	if len(os.Args) <= 1 { // need to use filepicker
		filenames := filepicker.GetFilenames("*.sha*")
		for i := 0; i < min(len(filenames), 10); i++ {
			fmt.Println("filename[", i, "] is", filenames[i])
		}
		fmt.Print(" Enter filename choice : ")
		fmt.Scanln(&ans)
		if len(ans) == 0 {
			ans = "0"
		}
		i, err := strconv.Atoi(ans)
		if err == nil {
			Filename = filenames[i]
		} else {
			s := strings.ToUpper(ans)
			s = strings.TrimSpace(s)
			s0 := s[0]
			i = int(s0 - 'A')
			Filename = filenames[i]
		}
		fmt.Println(" Picked filename is", Filename)
	} else { // will use filename entered on commandline
		Filename = getcommandline.GetCommandLineString()
	}

	fmt.Println()

	// process extension

	extension := filepath.Ext(Filename)
	extension = strings.ToLower(extension)
	switch extension {
	case ".md5":
		WhichHash = md5hash
	case ".sha1":
		WhichHash = sha1hash
	case ".sha256":
		WhichHash = sha256hash
	case ".sha384":
		WhichHash = sha384hash
	case ".sha512":
		WhichHash = sha512hash
	default:
		fmt.Println()
		fmt.Println()
		fmt.Println(" Not a recognized hash extension.  Will assume sha1.")
		WhichHash = sha1hash
	} // switch case on extension for HashType

	fmt.Println()

	// Read and parse the file with the hashes.

	HashesFile, err := os.Open(Filename)
	if os.IsNotExist(err) {
		fmt.Println(inbuf, " does not exist.")
		os.Exit(1)
	} else { // we know that the file exists
		check(err, " Error opening hashes file.")
	}
	defer HashesFile.Close()

	scanner := bufio.NewScanner(HashesFile)
	//	scanner.Split(bufio.ScanLines) // I believe this is the default.  I may experiment to see if I need this line for my code to work, AFTER I debug it as it is.

	for { /* to read multiple lines */
		FileSize = 0
		readSuccess := scanner.Scan()
		if !readSuccess {
			break
		} // end main reading loop

		inputline := scanner.Text()
		if readErr = scanner.Err(); readErr != nil {
			if readErr == io.EOF {
				break
			} // reached EOF condition, so there are no more lines to read.
			fmt.Fprintln(os.Stderr, "Unknown error while reading from the HashesFile :", readErr)
			os.Exit(1)
		}

		if strings.HasPrefix(inputline, ";") || strings.HasPrefix(inputline, "#") || (len(inputline) <= 10) {
			continue
		} /* allow comments and essentially blank lines */

		tokenize.INITKN(inputline)
		tokenize.SetMapDelim('*') // to ignore this character that begins the filename field.  Don't know why it's there.

		FirstToken, EOL := tokenize.GetTokenString(false)

		if EOL {
			fmt.Errorf(" Error while getting 1st token in the hashing file.  Skipping")
			continue
		}

		if strings.ContainsRune(FirstToken.Str, '.') { /* have filename first on line */
			TargetFilename = FirstToken.Str
			SecondToken, EOL := tokenize.GetTokenString(false) // Get hash string from the line in the file
			if EOL {
				fmt.Errorf(" Got EOL while getting HashValue (2nd) token in the hashing file.  Skipping \n")
				continue
			} /* if EOL */
			HashValueReadFromFile = SecondToken.Str

		} else { /* have hash first on line */
			HashValueReadFromFile = FirstToken.Str
			SecondToken, EOL := tokenize.GetTokenString(false) // Get name of file on which to compute the hash
			if EOL {
				fmt.Errorf(" Error while gatting TargetFilename token in the hashing file.  Skipping \n")
				continue
			} /* if EOL */

			if strings.ContainsRune(SecondToken.Str, '*') { // If it contains a *, it will be the first position.
				SecondToken.Str = SecondToken.Str[1:]
				if strings.ContainsRune(SecondToken.Str, '*') { // this should not happen
					fmt.Println(" Filename token still contains a * character.  Str:", SecondToken.Str, "  Skipping.")
					continue
				}
			}
			TargetFilename = (SecondToken.Str)
		} /* if have filename first or hash value first */

		/*
		   now to compute the hash, compare them, and output results
		*/
		/* Create Hash Section */
		TargetFile, err := os.Open(TargetFilename)
		//    exists := true;
		if os.IsNotExist(err) {
			fmt.Println(TargetFilename, " does not exist.")
			continue
		} else { // we know that the file exists
			check(err, " Error opening TargetFilename.")
		}

		defer TargetFile.Close()

		switch WhichHash { // Initialing case switch on WhichHash
		case md5hash:
			hasher = md5.New()
		case sha1hash:
			hasher = sha1.New()
		case sha256hash:
			hasher = sha256.New()
		case sha384hash:
			hasher = sha512.New384()
		case sha512hash:
			hasher = sha512.New()
		default:
			hasher = sha256.New()
		} /* initializing switch case on WhichHash */

		/*    This loop works, but there is a much shorter way.  I got this after asking for help on the mailing list.
		      FileReadBuffer := make([]byte,ReadBufferSize);
		      for {   // Repeat Until eof loop.
		        n,err := TargetFile.Read(FileReadBuffer);
		        if n == 0 || err == io.EOF { break }
		        check(err," Unexpected error while reading the target file on which to compute the hash,");
		        hasher.Write(FileReadBuffer[:n]);
		        FileSize += int64(n);
		      } // Repeat Until TargetFile.eof loop;
		*/

		FileSize, readErr = io.Copy(hasher, TargetFile)
		HashValueComputedStr = hex.EncodeToString(hasher.Sum(nil))

		// I got the idea to use the different base64 versions and my own hex converter code, just to see.
		// And I can also use sfprintf with the %x verb.  base64 versions are not useful as they use a larger
		// character set than hex.  I deleted all references to the base64 versions.  And the hex encoded and
		// sprintf using %x were the same, so I removed the sprintf code.
		//    HashValueComputedSprintf := fmt.Sprintf("%x",hasher.Sum(nil));

		//		fmt.Println(" Filename  = ", TargetFilename, ", FileSize = ", FileSize, ", ", HashName[WhichHash], " computed hash string -- ")
		fmt.Printf(" Filename  = %s, filesize = %d, using hash %s.\n", TargetFilename, FileSize, HashName[WhichHash])
		fmt.Println("       Read From File:", HashValueReadFromFile)
		fmt.Println(" Computed hex encoded:", HashValueComputedStr)
		//    fmt.Println(" Computed sprintf:",HashValueComputedSprintf);

		if HashValueReadFromFile == HashValueComputedStr {
			fmt.Print(" Matched.")
		} else {
			fmt.Print(" Not matched.")
		} /* if hashes */
		TargetFile.Close() // Close the handle to allow opening a target from the next line, if there is one.
		fmt.Println()
		fmt.Println()
		fmt.Println()
	} /* outer LOOP to read multiple lines */

	HashesFile.Close() // Don't really need this because of the defer statement.
	fmt.Println()
} // Main for comparehashes.go.

// ------------------------------------------------------- check -------------------------------
func check(e error, msg string) {
	if e != nil {
		fmt.Errorf("%s : ", msg)
		panic(e)
	}
}

// ------------------------------------------------------- min ---------------------------------
func min(a, b int) int {
	if a < b {
		return a
	} else {
		return b
	}
}
<|endoftext|>


<commit_before>package paypalsdk

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

type webprofileTestServer struct {
	t *testing.T
}

// ServeHTTP implements http.Handler
func (ts *webprofileTestServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ts.t.Log(r.RequestURI)
	if r.RequestURI == "/v1/payment-experience/web-profiles" {
		if r.Method == http.MethodPost {
			ts.create(w, r)
		}
		if r.Method == http.MethodGet {
			ts.list(w, r)
		}
	}
	if r.RequestURI == "/v1/payment-experience/web-profiles/XP-CP6S-W9DY-96H8-MVN2" {
		if r.Method == http.MethodGet {
			ts.getvalid(w, r)
		}
		if r.Method == http.MethodPut {
			ts.updatevalid(w, r)
		}
		if r.Method == http.MethodDelete {
			ts.deletevalid(w, r)
		}
	}
	if r.RequestURI == "/v1/payment-experience/web-profiles/foobar" {
		if r.Method == http.MethodGet {
			ts.getinvalid(w, r)
		}
		if r.Method == http.MethodPut {
			ts.updateinvalid(w, r)
		}
		if r.Method == http.MethodDelete {
			ts.deleteinvalid(w, r)
		}
	}
}

func (ts *webprofileTestServer) create(w http.ResponseWriter, r *http.Request) {
	var data map[string]interface{}

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

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	err = json.Unmarshal(body, &data)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	var raw map[string]string

	w.Header().Set("Content-Type", "application/json")

	if name, ok := data["name"]; !ok || name == "" {
		raw = map[string]string{
			"name":    "VALIDATION_ERROR",
			"message": "should have name",
		}
		w.WriteHeader(http.StatusBadRequest)
	} else {
		raw = map[string]string{
			"id": "XP-CP6S-W9DY-96H8-MVN2",
		}
		w.WriteHeader(http.StatusCreated)
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) updatevalid(w http.ResponseWriter, r *http.Request) {
	var data map[string]interface{}

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

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	err = json.Unmarshal(body, &data)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	if ID, ok := data["id"]; !ok || ID != "XP-CP6S-W9DY-96H8-MVN2" {
		raw := map[string]string{
			"name":    "INVALID_RESOURCE_ID",
			"message": "id invalid",
		}
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		res, _ := json.Marshal(raw)
		w.Write(res)
		return
	}

	if name, ok := data["name"]; !ok || name == "" {
		raw := map[string]string{
			"name":    "VALIDATION_ERROR",
			"message": "should have name",
		}
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		res, _ := json.Marshal(raw)
		w.Write(res)
		return
	}

	w.WriteHeader(http.StatusNoContent)

}

func (ts *webprofileTestServer) updateinvalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusNotFound)

	raw := map[string]interface{}{
		"name":    "INVALID_RESOURCE_ID",
		"message": "foobar not found",
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) getvalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)

	raw := map[string]interface{}{
		"id":   "XP-CP6S-W9DY-96H8-MVN2",
		"name": "YeowZa! T-Shirt Shop",
		"presentation": map[string]interface{}{
			"brand_name":  "YeowZa! Paypal",
			"logo_image":  "http://www.yeowza.com",
			"locale_code": "US",
		},

		"input_fields": map[string]interface{}{
			"allow_note":       true,
			"no_shipping":      0,
			"address_override": 1,
		},

		"flow_config": map[string]interface{}{
			"landing_page_type":    "Billing",
			"bank_txn_pending_url": "http://www.yeowza.com",
		},
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) getinvalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusNotFound)

	raw := map[string]interface{}{
		"name":    "INVALID_RESOURCE_ID",
		"message": "foobar not found",
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) list(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)

	raw := []interface{}{
		map[string]interface{}{
			"id":   "XP-CP6S-W9DY-96H8-MVN2",
			"name": "YeowZa! T-Shirt Shop",
		},
		map[string]interface{}{
			"id":   "XP-96H8-MVN2-CP6S-W9DY",
			"name": "Shop T-Shirt YeowZa! ",
		},
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) deleteinvalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusNotFound)

	raw := map[string]interface{}{
		"name":    "INVALID_RESOURCE_ID",
		"message": "foobar not found",
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) deletevalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusNoContent)
}

func TestCreateWebProfile_valid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{
		Name: "YeowZa! T-Shirt Shop",
		Presentation: Presentation{
			BrandName:  "YeowZa! Paypal",
			LogoImage:  "http://www.yeowza.com",
			LocaleCode: "US",
		},

		InputFields: InputFields{
			AllowNote:       true,
			NoShipping:      NoShippingDisplay,
			AddressOverride: AddrOverrideFromCall,
		},

		FlowConfig: FlowConfig{
			LandingPageType:   LandingPageTypeBilling,
			BankTXNPendingURL: "http://www.yeowza.com",
		},
	}

	res, err := c.CreateWebProfile(wp)

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

	if res.ID != "XP-CP6S-W9DY-96H8-MVN2" {
		t.Fatalf("expecting response to have ID = `XP-CP6S-W9DY-96H8-MVN2` got `%s`", res.ID)
	}
}

func TestCreateWebProfile_invalid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{}

	_, err := c.CreateWebProfile(wp)

	if err == nil {
		t.Fatalf("expecting an error got nil")
	}
}

func TestGetWebProfile_valid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	res, err := c.GetWebProfile("XP-CP6S-W9DY-96H8-MVN2")

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

	if res.ID != "XP-CP6S-W9DY-96H8-MVN2" {
		t.Fatalf("expecting res.ID to have value = `XP-CP6S-W9DY-96H8-MVN2` but got `%s`", res.ID)
	}

	if res.Name != "YeowZa! T-Shirt Shop" {
		t.Fatalf("expecting res.Name to have value = `YeowZa! T-Shirt Shop` but got `%s`", res.Name)
	}
}

func TestGetWebProfile_invalid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	_, err := c.GetWebProfile("foobar")

	if err == nil {
		t.Fatalf("expecting an error got nil")
	}
}

func TestGetWebProfiles(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	res, err := c.GetWebProfiles()

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

	if len(res) != 2 {
		t.Fatalf("expecting two results got %d", len(res))
	}
}

func TestSetWebProfile_valid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{
		ID:   "XP-CP6S-W9DY-96H8-MVN2",
		Name: "Shop T-Shirt YeowZa!",
	}

	err := c.SetWebProfile(wp)

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

}

func TestSetWebProfile_invalid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{
		ID: "foobar",
	}

	err := c.SetWebProfile(wp)

	if err == nil {
		t.Fatal(err)
	}

	wp = WebProfile{}

	err = c.SetWebProfile(wp)

	if err == nil {
		t.Fatal(err)
	}
}

func TestDeleteWebProfile_valid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{
		ID:   "XP-CP6S-W9DY-96H8-MVN2",
		Name: "Shop T-Shirt YeowZa!",
	}

	err := c.SetWebProfile(wp)

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

}

func TestDeleteWebProfile_invalid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	err := c.DeleteWebProfile("foobar")

	if err == nil {
		t.Fatal(err)
	}

}
<commit_msg>remove http method constants from tests<commit_after>package paypalsdk

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

type webprofileTestServer struct {
	t *testing.T
}

// ServeHTTP implements http.Handler
func (ts *webprofileTestServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ts.t.Log(r.RequestURI)
	if r.RequestURI == "/v1/payment-experience/web-profiles" {
		if r.Method == "POST" {
			ts.create(w, r)
		}
		if r.Method == "GET" {
			ts.list(w, r)
		}
	}
	if r.RequestURI == "/v1/payment-experience/web-profiles/XP-CP6S-W9DY-96H8-MVN2" {
		if r.Method == "GET" {
			ts.getvalid(w, r)
		}
		if r.Method == "PUT" {
			ts.updatevalid(w, r)
		}
		if r.Method == "DELETE" {
			ts.deletevalid(w, r)
		}
	}
	if r.RequestURI == "/v1/payment-experience/web-profiles/foobar" {
		if r.Method == "GET" {
			ts.getinvalid(w, r)
		}
		if r.Method == "PUT" {
			ts.updateinvalid(w, r)
		}
		if r.Method == "DELETE" {
			ts.deleteinvalid(w, r)
		}
	}
}

func (ts *webprofileTestServer) create(w http.ResponseWriter, r *http.Request) {
	var data map[string]interface{}

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

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	err = json.Unmarshal(body, &data)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	var raw map[string]string

	w.Header().Set("Content-Type", "application/json")

	if name, ok := data["name"]; !ok || name == "" {
		raw = map[string]string{
			"name":    "VALIDATION_ERROR",
			"message": "should have name",
		}
		w.WriteHeader(http.StatusBadRequest)
	} else {
		raw = map[string]string{
			"id": "XP-CP6S-W9DY-96H8-MVN2",
		}
		w.WriteHeader(http.StatusCreated)
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) updatevalid(w http.ResponseWriter, r *http.Request) {
	var data map[string]interface{}

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

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	err = json.Unmarshal(body, &data)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	if ID, ok := data["id"]; !ok || ID != "XP-CP6S-W9DY-96H8-MVN2" {
		raw := map[string]string{
			"name":    "INVALID_RESOURCE_ID",
			"message": "id invalid",
		}
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		res, _ := json.Marshal(raw)
		w.Write(res)
		return
	}

	if name, ok := data["name"]; !ok || name == "" {
		raw := map[string]string{
			"name":    "VALIDATION_ERROR",
			"message": "should have name",
		}
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		res, _ := json.Marshal(raw)
		w.Write(res)
		return
	}

	w.WriteHeader(http.StatusNoContent)

}

func (ts *webprofileTestServer) updateinvalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusNotFound)

	raw := map[string]interface{}{
		"name":    "INVALID_RESOURCE_ID",
		"message": "foobar not found",
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) getvalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)

	raw := map[string]interface{}{
		"id":   "XP-CP6S-W9DY-96H8-MVN2",
		"name": "YeowZa! T-Shirt Shop",
		"presentation": map[string]interface{}{
			"brand_name":  "YeowZa! Paypal",
			"logo_image":  "http://www.yeowza.com",
			"locale_code": "US",
		},

		"input_fields": map[string]interface{}{
			"allow_note":       true,
			"no_shipping":      0,
			"address_override": 1,
		},

		"flow_config": map[string]interface{}{
			"landing_page_type":    "Billing",
			"bank_txn_pending_url": "http://www.yeowza.com",
		},
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) getinvalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusNotFound)

	raw := map[string]interface{}{
		"name":    "INVALID_RESOURCE_ID",
		"message": "foobar not found",
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) list(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)

	raw := []interface{}{
		map[string]interface{}{
			"id":   "XP-CP6S-W9DY-96H8-MVN2",
			"name": "YeowZa! T-Shirt Shop",
		},
		map[string]interface{}{
			"id":   "XP-96H8-MVN2-CP6S-W9DY",
			"name": "Shop T-Shirt YeowZa! ",
		},
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) deleteinvalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusNotFound)

	raw := map[string]interface{}{
		"name":    "INVALID_RESOURCE_ID",
		"message": "foobar not found",
	}

	res, _ := json.Marshal(raw)
	w.Write(res)
}

func (ts *webprofileTestServer) deletevalid(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusNoContent)
}

func TestCreateWebProfile_valid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{
		Name: "YeowZa! T-Shirt Shop",
		Presentation: Presentation{
			BrandName:  "YeowZa! Paypal",
			LogoImage:  "http://www.yeowza.com",
			LocaleCode: "US",
		},

		InputFields: InputFields{
			AllowNote:       true,
			NoShipping:      NoShippingDisplay,
			AddressOverride: AddrOverrideFromCall,
		},

		FlowConfig: FlowConfig{
			LandingPageType:   LandingPageTypeBilling,
			BankTXNPendingURL: "http://www.yeowza.com",
		},
	}

	res, err := c.CreateWebProfile(wp)

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

	if res.ID != "XP-CP6S-W9DY-96H8-MVN2" {
		t.Fatalf("expecting response to have ID = `XP-CP6S-W9DY-96H8-MVN2` got `%s`", res.ID)
	}
}

func TestCreateWebProfile_invalid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{}

	_, err := c.CreateWebProfile(wp)

	if err == nil {
		t.Fatalf("expecting an error got nil")
	}
}

func TestGetWebProfile_valid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	res, err := c.GetWebProfile("XP-CP6S-W9DY-96H8-MVN2")

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

	if res.ID != "XP-CP6S-W9DY-96H8-MVN2" {
		t.Fatalf("expecting res.ID to have value = `XP-CP6S-W9DY-96H8-MVN2` but got `%s`", res.ID)
	}

	if res.Name != "YeowZa! T-Shirt Shop" {
		t.Fatalf("expecting res.Name to have value = `YeowZa! T-Shirt Shop` but got `%s`", res.Name)
	}
}

func TestGetWebProfile_invalid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	_, err := c.GetWebProfile("foobar")

	if err == nil {
		t.Fatalf("expecting an error got nil")
	}
}

func TestGetWebProfiles(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	res, err := c.GetWebProfiles()

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

	if len(res) != 2 {
		t.Fatalf("expecting two results got %d", len(res))
	}
}

func TestSetWebProfile_valid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{
		ID:   "XP-CP6S-W9DY-96H8-MVN2",
		Name: "Shop T-Shirt YeowZa!",
	}

	err := c.SetWebProfile(wp)

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

}

func TestSetWebProfile_invalid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{
		ID: "foobar",
	}

	err := c.SetWebProfile(wp)

	if err == nil {
		t.Fatal(err)
	}

	wp = WebProfile{}

	err = c.SetWebProfile(wp)

	if err == nil {
		t.Fatal(err)
	}
}

func TestDeleteWebProfile_valid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	wp := WebProfile{
		ID:   "XP-CP6S-W9DY-96H8-MVN2",
		Name: "Shop T-Shirt YeowZa!",
	}

	err := c.SetWebProfile(wp)

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

}

func TestDeleteWebProfile_invalid(t *testing.T) {
	ts := httptest.NewServer(&webprofileTestServer{t: t})
	defer ts.Close()

	c, _ := NewClient("foo", "bar", ts.URL)

	err := c.DeleteWebProfile("foobar")

	if err == nil {
		t.Fatal(err)
	}

}
<|endoftext|>


<commit_before>//go:build linux && seccomp
// +build linux,seccomp

package chroot

import (
	"fmt"
	"io/ioutil"

	"github.com/containers/common/pkg/seccomp"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	libseccomp "github.com/seccomp/libseccomp-golang"
	"github.com/sirupsen/logrus"
)

// setSeccomp sets the seccomp filter for ourselves and any processes that we'll start.
func setSeccomp(spec *specs.Spec) error {
	logrus.Debugf("setting seccomp configuration")
	if spec.Linux.Seccomp == nil {
		return nil
	}
	mapAction := func(specAction specs.LinuxSeccompAction, errnoRet *uint) libseccomp.ScmpAction {
		switch specAction {
		case specs.ActKill:
			return libseccomp.ActKillThread
		case specs.ActTrap:
			return libseccomp.ActTrap
		case specs.ActErrno:
			action := libseccomp.ActErrno
			if errnoRet != nil {
				action = action.SetReturnCode(int16(*errnoRet))
			}
			return action
		case specs.ActTrace:
			return libseccomp.ActTrace
		case specs.ActAllow:
			return libseccomp.ActAllow
		case specs.ActLog:
			return libseccomp.ActLog
		case specs.ActKillProcess:
			return libseccomp.ActKillProcess
		default:
			logrus.Errorf("unmappable action %v", specAction)
		}
		return libseccomp.ActInvalid
	}
	mapArch := func(specArch specs.Arch) libseccomp.ScmpArch {
		switch specArch {
		case specs.ArchX86:
			return libseccomp.ArchX86
		case specs.ArchX86_64:
			return libseccomp.ArchAMD64
		case specs.ArchX32:
			return libseccomp.ArchX32
		case specs.ArchARM:
			return libseccomp.ArchARM
		case specs.ArchAARCH64:
			return libseccomp.ArchARM64
		case specs.ArchMIPS:
			return libseccomp.ArchMIPS
		case specs.ArchMIPS64:
			return libseccomp.ArchMIPS64
		case specs.ArchMIPS64N32:
			return libseccomp.ArchMIPS64N32
		case specs.ArchMIPSEL:
			return libseccomp.ArchMIPSEL
		case specs.ArchMIPSEL64:
			return libseccomp.ArchMIPSEL64
		case specs.ArchMIPSEL64N32:
			return libseccomp.ArchMIPSEL64N32
		case specs.ArchPPC:
			return libseccomp.ArchPPC
		case specs.ArchPPC64:
			return libseccomp.ArchPPC64
		case specs.ArchPPC64LE:
			return libseccomp.ArchPPC64LE
		case specs.ArchS390:
			return libseccomp.ArchS390
		case specs.ArchS390X:
			return libseccomp.ArchS390X
		case specs.ArchPARISC:
			/* fallthrough */ /* for now */
		case specs.ArchPARISC64:
			/* fallthrough */ /* for now */
		default:
			logrus.Errorf("unmappable arch %v", specArch)
		}
		return libseccomp.ArchInvalid
	}
	mapOp := func(op specs.LinuxSeccompOperator) libseccomp.ScmpCompareOp {
		switch op {
		case specs.OpNotEqual:
			return libseccomp.CompareNotEqual
		case specs.OpLessThan:
			return libseccomp.CompareLess
		case specs.OpLessEqual:
			return libseccomp.CompareLessOrEqual
		case specs.OpEqualTo:
			return libseccomp.CompareEqual
		case specs.OpGreaterEqual:
			return libseccomp.CompareGreaterEqual
		case specs.OpGreaterThan:
			return libseccomp.CompareGreater
		case specs.OpMaskedEqual:
			return libseccomp.CompareMaskedEqual
		default:
			logrus.Errorf("unmappable op %v", op)
		}
		return libseccomp.CompareInvalid
	}

	filter, err := libseccomp.NewFilter(mapAction(spec.Linux.Seccomp.DefaultAction, nil))
	if err != nil {
		return fmt.Errorf("error creating seccomp filter with default action %q: %w", spec.Linux.Seccomp.DefaultAction, err)
	}
	for _, arch := range spec.Linux.Seccomp.Architectures {
		if err = filter.AddArch(mapArch(arch)); err != nil {
			return fmt.Errorf("error adding architecture %q(%q) to seccomp filter: %w", arch, mapArch(arch), err)
		}
	}
	for _, rule := range spec.Linux.Seccomp.Syscalls {
		scnames := make(map[libseccomp.ScmpSyscall]string)
		for _, name := range rule.Names {
			scnum, err := libseccomp.GetSyscallFromName(name)
			if err != nil {
				logrus.Debugf("error mapping syscall %q to a syscall, ignoring %q rule for %q", name, rule.Action, name)
				continue
			}
			scnames[scnum] = name
		}
		for scnum := range scnames {
			if len(rule.Args) == 0 {
				if err = filter.AddRule(scnum, mapAction(rule.Action, rule.ErrnoRet)); err != nil {
					return fmt.Errorf("error adding a rule (%q:%q) to seccomp filter: %w", scnames[scnum], rule.Action, err)
				}
				continue
			}
			var conditions []libseccomp.ScmpCondition
			opsAreAllEquality := true
			for _, arg := range rule.Args {
				condition, err := libseccomp.MakeCondition(arg.Index, mapOp(arg.Op), arg.Value, arg.ValueTwo)
				if err != nil {
					return fmt.Errorf("error building a seccomp condition %d:%v:%d:%d: %w", arg.Index, arg.Op, arg.Value, arg.ValueTwo, err)
				}
				if arg.Op != specs.OpEqualTo {
					opsAreAllEquality = false
				}
				conditions = append(conditions, condition)
			}
			if err = filter.AddRuleConditional(scnum, mapAction(rule.Action, rule.ErrnoRet), conditions); err != nil {
				// Okay, if the rules specify multiple equality
				// checks, assume someone thought that they
				// were OR'd, when in fact they're ordinarily
				// supposed to be AND'd.  Break them up into
				// different rules to get that OR effect.
				if len(rule.Args) > 1 && opsAreAllEquality && err.Error() == "two checks on same syscall argument" {
					for i := range conditions {
						if err = filter.AddRuleConditional(scnum, mapAction(rule.Action, rule.ErrnoRet), conditions[i:i+1]); err != nil {
							return fmt.Errorf("error adding a conditional rule (%q:%q[%d]) to seccomp filter: %w", scnames[scnum], rule.Action, i, err)
						}
					}
				} else {
					return fmt.Errorf("error adding a conditional rule (%q:%q) to seccomp filter: %w", scnames[scnum], rule.Action, err)
				}
			}
		}
	}
	if err = filter.SetNoNewPrivsBit(spec.Process.NoNewPrivileges); err != nil {
		return fmt.Errorf("error setting no-new-privileges bit to %v: %w", spec.Process.NoNewPrivileges, err)
	}
	err = filter.Load()
	filter.Release()
	if err != nil {
		return fmt.Errorf("error activating seccomp filter: %w", err)
	}
	return nil
}

func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error {
	switch seccompProfilePath {
	case "unconfined":
		spec.Linux.Seccomp = nil
	case "":
		seccompConfig, err := seccomp.GetDefaultProfile(spec)
		if err != nil {
			return fmt.Errorf("loading default seccomp profile failed: %w", err)
		}
		spec.Linux.Seccomp = seccompConfig
	default:
		seccompProfile, err := ioutil.ReadFile(seccompProfilePath)
		if err != nil {
			return fmt.Errorf("opening seccomp profile (%s) failed: %w", seccompProfilePath, err)
		}
		seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), spec)
		if err != nil {
			return fmt.Errorf("loading seccomp profile (%s) failed: %w", seccompProfilePath, err)
		}
		spec.Linux.Seccomp = seccompConfig
	}
	return nil
}
<commit_msg>chroot: honor DefaultErrnoRet<commit_after>//go:build linux && seccomp
// +build linux,seccomp

package chroot

import (
	"fmt"
	"io/ioutil"

	"github.com/containers/common/pkg/seccomp"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	libseccomp "github.com/seccomp/libseccomp-golang"
	"github.com/sirupsen/logrus"
)

// setSeccomp sets the seccomp filter for ourselves and any processes that we'll start.
func setSeccomp(spec *specs.Spec) error {
	logrus.Debugf("setting seccomp configuration")
	if spec.Linux.Seccomp == nil {
		return nil
	}
	mapAction := func(specAction specs.LinuxSeccompAction, errnoRet *uint) libseccomp.ScmpAction {
		switch specAction {
		case specs.ActKill:
			return libseccomp.ActKillThread
		case specs.ActTrap:
			return libseccomp.ActTrap
		case specs.ActErrno:
			action := libseccomp.ActErrno
			if errnoRet != nil {
				action = action.SetReturnCode(int16(*errnoRet))
			}
			return action
		case specs.ActTrace:
			return libseccomp.ActTrace
		case specs.ActAllow:
			return libseccomp.ActAllow
		case specs.ActLog:
			return libseccomp.ActLog
		case specs.ActKillProcess:
			return libseccomp.ActKillProcess
		default:
			logrus.Errorf("unmappable action %v", specAction)
		}
		return libseccomp.ActInvalid
	}
	mapArch := func(specArch specs.Arch) libseccomp.ScmpArch {
		switch specArch {
		case specs.ArchX86:
			return libseccomp.ArchX86
		case specs.ArchX86_64:
			return libseccomp.ArchAMD64
		case specs.ArchX32:
			return libseccomp.ArchX32
		case specs.ArchARM:
			return libseccomp.ArchARM
		case specs.ArchAARCH64:
			return libseccomp.ArchARM64
		case specs.ArchMIPS:
			return libseccomp.ArchMIPS
		case specs.ArchMIPS64:
			return libseccomp.ArchMIPS64
		case specs.ArchMIPS64N32:
			return libseccomp.ArchMIPS64N32
		case specs.ArchMIPSEL:
			return libseccomp.ArchMIPSEL
		case specs.ArchMIPSEL64:
			return libseccomp.ArchMIPSEL64
		case specs.ArchMIPSEL64N32:
			return libseccomp.ArchMIPSEL64N32
		case specs.ArchPPC:
			return libseccomp.ArchPPC
		case specs.ArchPPC64:
			return libseccomp.ArchPPC64
		case specs.ArchPPC64LE:
			return libseccomp.ArchPPC64LE
		case specs.ArchS390:
			return libseccomp.ArchS390
		case specs.ArchS390X:
			return libseccomp.ArchS390X
		case specs.ArchPARISC:
			/* fallthrough */ /* for now */
		case specs.ArchPARISC64:
			/* fallthrough */ /* for now */
		default:
			logrus.Errorf("unmappable arch %v", specArch)
		}
		return libseccomp.ArchInvalid
	}
	mapOp := func(op specs.LinuxSeccompOperator) libseccomp.ScmpCompareOp {
		switch op {
		case specs.OpNotEqual:
			return libseccomp.CompareNotEqual
		case specs.OpLessThan:
			return libseccomp.CompareLess
		case specs.OpLessEqual:
			return libseccomp.CompareLessOrEqual
		case specs.OpEqualTo:
			return libseccomp.CompareEqual
		case specs.OpGreaterEqual:
			return libseccomp.CompareGreaterEqual
		case specs.OpGreaterThan:
			return libseccomp.CompareGreater
		case specs.OpMaskedEqual:
			return libseccomp.CompareMaskedEqual
		default:
			logrus.Errorf("unmappable op %v", op)
		}
		return libseccomp.CompareInvalid
	}

	filter, err := libseccomp.NewFilter(mapAction(spec.Linux.Seccomp.DefaultAction, spec.Linux.Seccomp.DefaultErrnoRet))
	if err != nil {
		return fmt.Errorf("error creating seccomp filter with default action %q: %w", spec.Linux.Seccomp.DefaultAction, err)
	}
	for _, arch := range spec.Linux.Seccomp.Architectures {
		if err = filter.AddArch(mapArch(arch)); err != nil {
			return fmt.Errorf("error adding architecture %q(%q) to seccomp filter: %w", arch, mapArch(arch), err)
		}
	}
	for _, rule := range spec.Linux.Seccomp.Syscalls {
		scnames := make(map[libseccomp.ScmpSyscall]string)
		for _, name := range rule.Names {
			scnum, err := libseccomp.GetSyscallFromName(name)
			if err != nil {
				logrus.Debugf("error mapping syscall %q to a syscall, ignoring %q rule for %q", name, rule.Action, name)
				continue
			}
			scnames[scnum] = name
		}
		for scnum := range scnames {
			if len(rule.Args) == 0 {
				if err = filter.AddRule(scnum, mapAction(rule.Action, rule.ErrnoRet)); err != nil {
					return fmt.Errorf("error adding a rule (%q:%q) to seccomp filter: %w", scnames[scnum], rule.Action, err)
				}
				continue
			}
			var conditions []libseccomp.ScmpCondition
			opsAreAllEquality := true
			for _, arg := range rule.Args {
				condition, err := libseccomp.MakeCondition(arg.Index, mapOp(arg.Op), arg.Value, arg.ValueTwo)
				if err != nil {
					return fmt.Errorf("error building a seccomp condition %d:%v:%d:%d: %w", arg.Index, arg.Op, arg.Value, arg.ValueTwo, err)
				}
				if arg.Op != specs.OpEqualTo {
					opsAreAllEquality = false
				}
				conditions = append(conditions, condition)
			}
			if err = filter.AddRuleConditional(scnum, mapAction(rule.Action, rule.ErrnoRet), conditions); err != nil {
				// Okay, if the rules specify multiple equality
				// checks, assume someone thought that they
				// were OR'd, when in fact they're ordinarily
				// supposed to be AND'd.  Break them up into
				// different rules to get that OR effect.
				if len(rule.Args) > 1 && opsAreAllEquality && err.Error() == "two checks on same syscall argument" {
					for i := range conditions {
						if err = filter.AddRuleConditional(scnum, mapAction(rule.Action, rule.ErrnoRet), conditions[i:i+1]); err != nil {
							return fmt.Errorf("error adding a conditional rule (%q:%q[%d]) to seccomp filter: %w", scnames[scnum], rule.Action, i, err)
						}
					}
				} else {
					return fmt.Errorf("error adding a conditional rule (%q:%q) to seccomp filter: %w", scnames[scnum], rule.Action, err)
				}
			}
		}
	}
	if err = filter.SetNoNewPrivsBit(spec.Process.NoNewPrivileges); err != nil {
		return fmt.Errorf("error setting no-new-privileges bit to %v: %w", spec.Process.NoNewPrivileges, err)
	}
	err = filter.Load()
	filter.Release()
	if err != nil {
		return fmt.Errorf("error activating seccomp filter: %w", err)
	}
	return nil
}

func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error {
	switch seccompProfilePath {
	case "unconfined":
		spec.Linux.Seccomp = nil
	case "":
		seccompConfig, err := seccomp.GetDefaultProfile(spec)
		if err != nil {
			return fmt.Errorf("loading default seccomp profile failed: %w", err)
		}
		spec.Linux.Seccomp = seccompConfig
	default:
		seccompProfile, err := ioutil.ReadFile(seccompProfilePath)
		if err != nil {
			return fmt.Errorf("opening seccomp profile (%s) failed: %w", seccompProfilePath, err)
		}
		seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), spec)
		if err != nil {
			return fmt.Errorf("loading seccomp profile (%s) failed: %w", seccompProfilePath, err)
		}
		spec.Linux.Seccomp = seccompConfig
	}
	return nil
}
<|endoftext|>


<commit_before>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2021 IBM, Inc.
 *
 */

package api

import (
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

	"kubevirt.io/client-go/kubecli"
	"kubevirt.io/kubevirt/tools/perfscale-load-generator/config"
)

type LoadGenerator interface {
	Run(kubecli.KubevirtClient, *config.Workload)
	Delete(kubecli.KubevirtClient, *config.Workload)
}

type Job interface {
	CreateWorkload()
	DeleteWorkload()
	Watch(*unstructured.Unstructured, bool)
	Wait()
}
<commit_msg>tools:perfscale-load-generator: update function name to plural<commit_after>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2021 IBM, Inc.
 *
 */

package api

import (
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

	"kubevirt.io/client-go/kubecli"
	"kubevirt.io/kubevirt/tools/perfscale-load-generator/config"
)

type LoadGenerator interface {
	Run(kubecli.KubevirtClient, *config.Workload)
	Delete(kubecli.KubevirtClient, *config.Workload)
}

type Job interface {
	CreateWorkloads()
	DeleteWorkloads()
	Watch(*unstructured.Unstructured, bool)
	Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"encoding/hex"
	"os"
	"path/filepath"
	"time"
)

// ChecksumRecord stores checksum and metadata for a file.
type ChecksumRecord struct {
	Checksum string    `json:"checksum"`
	ModTime  time.Time `json:"mod_time"`
}

// Manifest of all files under a path.
type Manifest struct {
	Path      string                    `json:"path"`
	CreatedAt time.Time                 `json:"created_at"`
	Entries   map[string]ChecksumRecord `json:"entries"`
}

// ManifestComparison of two Manifests, showing paths that have been deleted,
// added, modified, or flagged for suspicious checksum changes.
type ManifestComparison struct {
	DeletedPaths  []string
	AddedPaths    []string
	ModifiedPaths []string
	FlaggedPaths  []string
}

// NewManifest generates a Manifest from a directory path.
func NewManifest(path string, config *Config) *Manifest {
	return &Manifest{
		Path:      path,
		CreatedAt: time.Now().UTC(),
		Entries:   directoryChecksums(path, config),
	}
}

// CompareManifests generates a comparison between new and old Manifests.
func CompareManifests(oldManifest, newManifest *Manifest) *ManifestComparison {
	comparison := &ManifestComparison{}
	checkAddedPaths(oldManifest, newManifest, comparison)
	checkChangedPaths(oldManifest, newManifest, comparison)
	return comparison
}

// Private functions

func generateChecksum(file string) string {
	// TODO: experiment with varying buffer to determine optimal size
	bufferSize := 10 * 1024 * 1024 // 10MiB buffer
	reader := newSha1Reader(file, bufferSize)
	sum, err := reader.SHA1Sum()
	check(err)
	return hex.EncodeToString(sum)
}

func checksumHexString(data *[]byte) string {
	sum := sha1.Sum(*data)
	return hex.EncodeToString(sum[:])
}

func directoryChecksums(path string, config *Config) map[string]ChecksumRecord {
	records := map[string]ChecksumRecord{}
	filepath.Walk(path, func(entryPath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if config.isIgnoredPath(entryPath) {
			return nil
		}

		if info.Mode().IsRegular() {
			var relPath string
			relPath, err = filepath.Rel(path, entryPath)
			check(err)
			records[relPath] = ChecksumRecord{
				Checksum: generateChecksum(entryPath),
				ModTime:  info.ModTime().UTC(),
			}
		}

		return nil
	})
	return records
}

func checkAddedPaths(oldManifest, newManifest *Manifest, comparison *ManifestComparison) {
	for path := range newManifest.Entries {
		_, oldEntryPresent := oldManifest.Entries[path]
		if !oldEntryPresent {
			comparison.AddedPaths = append(comparison.AddedPaths, path)
		}
	}
}

func checkChangedPaths(oldManifest, newManifest *Manifest, comparison *ManifestComparison) {
	for path, oldEntry := range oldManifest.Entries {
		newEntry, newEntryPresent := newManifest.Entries[path]
		if newEntryPresent {
			checkModifiedPath(path, &oldEntry, &newEntry, comparison)
		} else {
			comparison.DeletedPaths = append(comparison.DeletedPaths, path)
		}
	}
}

func checkModifiedPath(path string, oldEntry, newEntry *ChecksumRecord, comparison *ManifestComparison) {
	if newEntry.Checksum != oldEntry.Checksum {
		if newEntry.ModTime != oldEntry.ModTime {
			comparison.ModifiedPaths = append(comparison.ModifiedPaths, path)
		} else {
			comparison.FlaggedPaths = append(comparison.FlaggedPaths, path)
		}
	}
}
<commit_msg>Normalize Unicode combining characters in paths<commit_after>package main

import (
	"crypto/sha1"
	"encoding/hex"
	"golang.org/x/text/unicode/norm"
	"os"
	"path/filepath"
	"time"
)

// ChecksumRecord stores checksum and metadata for a file.
type ChecksumRecord struct {
	Checksum string    `json:"checksum"`
	ModTime  time.Time `json:"mod_time"`
}

// Manifest of all files under a path.
type Manifest struct {
	Path      string                    `json:"path"`
	CreatedAt time.Time                 `json:"created_at"`
	Entries   map[string]ChecksumRecord `json:"entries"`
}

// ManifestComparison of two Manifests, showing paths that have been deleted,
// added, modified, or flagged for suspicious checksum changes.
type ManifestComparison struct {
	DeletedPaths  []string
	AddedPaths    []string
	ModifiedPaths []string
	FlaggedPaths  []string
}

// NewManifest generates a Manifest from a directory path.
func NewManifest(path string, config *Config) *Manifest {
	return &Manifest{
		Path:      path,
		CreatedAt: time.Now().UTC(),
		Entries:   directoryChecksums(path, config),
	}
}

// CompareManifests generates a comparison between new and old Manifests.
func CompareManifests(oldManifest, newManifest *Manifest) *ManifestComparison {
	comparison := &ManifestComparison{}
	checkAddedPaths(oldManifest, newManifest, comparison)
	checkChangedPaths(oldManifest, newManifest, comparison)
	return comparison
}

// Private functions

func generateChecksum(file string) string {
	// TODO: experiment with varying buffer to determine optimal size
	bufferSize := 10 * 1024 * 1024 // 10MiB buffer
	reader := newSha1Reader(file, bufferSize)
	sum, err := reader.SHA1Sum()
	check(err)
	return hex.EncodeToString(sum)
}

func checksumHexString(data *[]byte) string {
	sum := sha1.Sum(*data)
	return hex.EncodeToString(sum[:])
}

func directoryChecksums(path string, config *Config) map[string]ChecksumRecord {
	records := map[string]ChecksumRecord{}
	filepath.Walk(path, func(entryPath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if config.isIgnoredPath(entryPath) {
			return nil
		}

		if info.Mode().IsRegular() {
			var relPath string
			relPath, err = filepath.Rel(path, entryPath)
			check(err)
			// Normalize Unicode combining characters
			relPath = norm.NFC.String(relPath)
			records[relPath] = ChecksumRecord{
				Checksum: generateChecksum(entryPath),
				ModTime:  info.ModTime().UTC(),
			}
		}

		return nil
	})
	return records
}

func checkAddedPaths(oldManifest, newManifest *Manifest, comparison *ManifestComparison) {
	for path := range newManifest.Entries {
		_, oldEntryPresent := oldManifest.Entries[path]
		if !oldEntryPresent {
			comparison.AddedPaths = append(comparison.AddedPaths, path)
		}
	}
}

func checkChangedPaths(oldManifest, newManifest *Manifest, comparison *ManifestComparison) {
	for path, oldEntry := range oldManifest.Entries {
		newEntry, newEntryPresent := newManifest.Entries[path]
		if newEntryPresent {
			checkModifiedPath(path, &oldEntry, &newEntry, comparison)
		} else {
			comparison.DeletedPaths = append(comparison.DeletedPaths, path)
		}
	}
}

func checkModifiedPath(path string, oldEntry, newEntry *ChecksumRecord, comparison *ManifestComparison) {
	if newEntry.Checksum != oldEntry.Checksum {
		if newEntry.ModTime != oldEntry.ModTime {
			comparison.ModifiedPaths = append(comparison.ModifiedPaths, path)
		} else {
			comparison.FlaggedPaths = append(comparison.FlaggedPaths, path)
		}
	}
}
<|endoftext|>


<commit_before>/*
   Copyright 2012 the go.wde authors

   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 win

import (
	"errors"
	"github.com/AllenDang/w32"
	"github.com/skelterjohn/go.wde"
	"image"
	"runtime"
	"unsafe"
)

func init() {
	wde.BackendNewWindow = func(width, height int) (w wde.Window, err error) {
		w, err = NewWindow(width, height)
		return
	}
	ch := make(chan struct{}, 1)
	wde.BackendRun = func() {
		<-ch
	}
	wde.BackendStop = func() {
		ch <- struct{}{}
	}
}

const (
	WIN_CLASSNAME = "wde_win"
)

type Window struct {
	EventData

	hwnd       w32.HWND
	buffer     *DIB
	bufferback *DIB
	events     chan interface{}
}

/*
go func(ready chan struct{}) {
		w, err = win.NewWindow(width, height)
		ready <- struct{}{}
		if winw, ok := w.(*win.Window); ok {
			winw.HandleWndMessages()
		} else {
			panic("windows wgen returned non windows window")
		}
	}(ready)
	<-ready
*/

func makeTheWindow(width, height int) (w *Window, err error) {

	err = RegClassOnlyOnce(WIN_CLASSNAME)
	if err != nil {
		return
	}

	cr := &w32.RECT{
		w32.CW_USEDEFAULT,
		w32.CW_USEDEFAULT,
		w32.CW_USEDEFAULT + int32(width),
		w32.CW_USEDEFAULT + int32(height),
	}
	w32.AdjustWindowRectEx(cr, w32.WS_OVERLAPPEDWINDOW, false, w32.WS_EX_CLIENTEDGE)
	width = int(cr.Right - cr.Left)
	height = int(cr.Bottom - cr.Top)
	hwnd, err := CreateWindow(WIN_CLASSNAME, nil, w32.WS_EX_CLIENTEDGE, w32.WS_OVERLAPPEDWINDOW, width, height)
	if err != nil {
		return
	}

	w = &Window{
		hwnd:       hwnd,
		buffer:     NewDIB(image.Rect(0, 0, width, height)),
		bufferback: NewDIB(image.Rect(0, 0, width, height)),
		events:     make(chan interface{}, 16),
	}
	w.InitEventData()

	RegMsgHandler(w)

	w.Center()

	return
}

func NewWindow(width, height int) (w *Window, err error) {
	ready := make(chan error, 1)

	go func(ready chan error) {
		runtime.LockOSThread()
		var err error
		w, err = makeTheWindow(width, height)
		ready <- err
		w.HandleWndMessages()
	}(ready)

	err = <-ready
	return
}

func (this *Window) SetTitle(title string) {
	w32.SetWindowText(this.hwnd, title)
}

func (this *Window) SetSize(width, height int) {
	x, y := this.Pos()
	w32.MoveWindow(this.hwnd, x, y, width, height, true)
}

func (this *Window) Size() (width, height int) {
	bounds := this.buffer.Bounds()
	return bounds.Dx(), bounds.Dy()
}

func (w *Window) LockSize(lock bool) {
	prevStyle := int(w32.GetWindowLongPtr(w.hwnd, w32.GWL_STYLE))
	if lock {
		prevStyle &= ^(w32.WS_MAXIMIZEBOX | w32.WS_SIZEBOX)
	} else {
		prevStyle |= w32.WS_MAXIMIZEBOX | w32.WS_SIZEBOX
	}
	w32.SetWindowLongPtr(w.hwnd, w32.GWL_STYLE, uintptr(prevStyle))
}

func (this *Window) Show() {
	w32.ShowWindow(this.hwnd, w32.SW_SHOWDEFAULT)
}

func (this *Window) Screen() wde.Image {
	return this.buffer
}

func (this *Window) FlushImage(bounds ...image.Rectangle) {
	this.bufferback = NewDIB(this.buffer.Bounds())
	*this.bufferback = *this.buffer

	hdc := w32.GetDC(this.hwnd)
	this.blitImage(hdc, this.buffer)
	w32.DeleteDC(hdc)
}

func (this *Window) EventChan() <-chan interface{} {
	return this.events
}

func (this *Window) Close() error {
	err := w32.SendMessage(this.hwnd, w32.WM_CLOSE, 0, 0)
	if err != 0 {
		return errors.New("Error closing window")
	}
	return nil
}

/////////////////////////////
// Non - interface methods
/////////////////////////////

func (this *Window) blitImage(hdc w32.HDC, buffer *DIB) {
	bounds := buffer.Bounds()
	width := bounds.Dx()
	height := bounds.Dy()

	var bi w32.BITMAPINFO
	bi.BmiHeader.BiSize = uint32(unsafe.Sizeof(bi.BmiHeader))
	bi.BmiHeader.BiWidth = int32(width)
	bi.BmiHeader.BiHeight = int32(-height)
	bi.BmiHeader.BiPlanes = 1
	bi.BmiHeader.BiBitCount = 32
	bi.BmiHeader.BiCompression = w32.BI_RGB

	w32.SetDIBitsToDevice(hdc,
		0, 0,
		width, height,
		0, 0,
		0, uint(height),
		buffer.Pix, &bi,
		w32.DIB_RGB_COLORS,
	)
}

func (this *Window) HandleWndMessages() {
	var m w32.MSG

	for w32.GetMessage(&m, this.hwnd, 0, 0) != 0 {
		w32.TranslateMessage(&m)
		w32.DispatchMessage(&m)
	}
}

func (this *Window) Pos() (x, y int) {
	rect := w32.GetWindowRect(this.hwnd)
	return int(rect.Left), int(rect.Top)
}

func (this *Window) SetPos(x, y int) {
	w, h := this.Size()
	if w == 0 {
		w = 100
	}
	if h == 0 {
		h = 25
	}
	w32.MoveWindow(this.hwnd, x, y, w, h, true)
}

func (this *Window) Center() {
	sWidth := w32.GetSystemMetrics(w32.SM_CXFULLSCREEN)
	sHeight := w32.GetSystemMetrics(w32.SM_CYFULLSCREEN)

	if sWidth != 0 && sHeight != 0 {
		w, h := this.Size()
		this.SetPos((sWidth/2)-(w/2), (sHeight/2)-(h/2))
	}
}

func (this *Window) Repaint() {
	hdc := w32.GetDC(this.hwnd)
	this.blitImage(hdc, this.bufferback)
	w32.DeleteDC(hdc)
}
<commit_msg>Update win_windows.go<commit_after>/*
   Copyright 2012 the go.wde authors

   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 win

import (
	"errors"
	"github.com/AllenDang/w32"
	"github.com/skelterjohn/go.wde"
	"image"
	"runtime"
	"unsafe"
)

func init() {
	wde.BackendNewWindow = func(width, height int) (w wde.Window, err error) {
		w, err = NewWindow(width, height)
		return
	}
	ch := make(chan struct{}, 1)
	wde.BackendRun = func() {
		<-ch
	}
	wde.BackendStop = func() {
		ch <- struct{}{}
	}
}

const (
	WIN_CLASSNAME = "wde_win"
)

type Window struct {
	EventData

	hwnd       w32.HWND
	buffer     *DIB
	bufferback *DIB
	events     chan interface{}
}

/*
go func(ready chan struct{}) {
		w, err = win.NewWindow(width, height)
		ready <- struct{}{}
		if winw, ok := w.(*win.Window); ok {
			winw.HandleWndMessages()
		} else {
			panic("windows wgen returned non windows window")
		}
	}(ready)
	<-ready
*/

func makeTheWindow(width, height int) (w *Window, err error) {

	err = RegClassOnlyOnce(WIN_CLASSNAME)
	if err != nil {
		return
	}

	cr := &w32.RECT{
		w32.CW_USEDEFAULT,
		w32.CW_USEDEFAULT,
		w32.CW_USEDEFAULT + int32(width),
		w32.CW_USEDEFAULT + int32(height),
	}
	w32.AdjustWindowRectEx(cr, w32.WS_OVERLAPPEDWINDOW, false, w32.WS_EX_CLIENTEDGE)
	width = int(cr.Right - cr.Left)
	height = int(cr.Bottom - cr.Top)
	hwnd, err := CreateWindow(WIN_CLASSNAME, nil, w32.WS_EX_CLIENTEDGE, w32.WS_OVERLAPPEDWINDOW, width, height)
	if err != nil {
		return
	}

	w = &Window{
		hwnd:       hwnd,
		buffer:     NewDIB(image.Rect(0, 0, width, height)),
		bufferback: NewDIB(image.Rect(0, 0, width, height)),
		events:     make(chan interface{}, 16),
	}
	w.InitEventData()

	RegMsgHandler(w)

	w.Center()

	return
}

func NewWindow(width, height int) (w *Window, err error) {
	ready := make(chan error, 1)

	go func(ready chan error) {
		runtime.LockOSThread()
		var err error
		w, err = makeTheWindow(width, height)
		ready <- err
		w.HandleWndMessages()
	}(ready)

	err = <-ready
	return
}

func (this *Window) SetTitle(title string) {
	w32.SetWindowText(this.hwnd, title)
}

func (this *Window) SetSize(width, height int) {
	x, y := this.Pos()
	w32.MoveWindow(this.hwnd, x, y, width, height, true)
}

func (this *Window) Size() (width, height int) {
	bounds := this.buffer.Bounds()
	return bounds.Dx(), bounds.Dy()
}

func (w *Window) LockSize(lock bool) {
	prevStyle := int(w32.GetWindowLongPtr(w.hwnd, w32.GWL_STYLE))
	if lock {
		prevStyle &= ^(w32.WS_MAXIMIZEBOX | w32.WS_SIZEBOX)
	} else {
		prevStyle |= w32.WS_MAXIMIZEBOX | w32.WS_SIZEBOX
	}
	w32.SetWindowLongPtr(w.hwnd, w32.GWL_STYLE, uintptr(prevStyle))
}

func (this *Window) Show() {
	w32.ShowWindow(this.hwnd, w32.SW_SHOWDEFAULT)
}

func (this *Window) Screen() wde.Image {
	return this.buffer
}

func (this *Window) FlushImage(bounds ...image.Rectangle) {
	this.bufferback = NewDIB(this.buffer.Bounds())
	*this.bufferback = *this.buffer

	hdc := w32.GetDC(this.hwnd)
	this.blitImage(hdc, this.buffer)
	w32.DeleteDC(hdc)
}

func (this *Window) EventChan() <-chan interface{} {
	return this.events
}

func (this *Window) Close() error {
	this.UnRegMsgHandler(hwnd)
	w32.DestroyWindow(this.hwnd)
	if err == false {
		return errors.New("Error closing window")
	}
	return nil
}

/////////////////////////////
// Non - interface methods
/////////////////////////////

func (this *Window) blitImage(hdc w32.HDC, buffer *DIB) {
	bounds := buffer.Bounds()
	width := bounds.Dx()
	height := bounds.Dy()

	var bi w32.BITMAPINFO
	bi.BmiHeader.BiSize = uint32(unsafe.Sizeof(bi.BmiHeader))
	bi.BmiHeader.BiWidth = int32(width)
	bi.BmiHeader.BiHeight = int32(-height)
	bi.BmiHeader.BiPlanes = 1
	bi.BmiHeader.BiBitCount = 32
	bi.BmiHeader.BiCompression = w32.BI_RGB

	w32.SetDIBitsToDevice(hdc,
		0, 0,
		width, height,
		0, 0,
		0, uint(height),
		buffer.Pix, &bi,
		w32.DIB_RGB_COLORS,
	)
}

func (this *Window) HandleWndMessages() {
	var m w32.MSG

	for w32.GetMessage(&m, this.hwnd, 0, 0) != 0 {
		w32.TranslateMessage(&m)
		w32.DispatchMessage(&m)
	}
}

func (this *Window) Pos() (x, y int) {
	rect := w32.GetWindowRect(this.hwnd)
	return int(rect.Left), int(rect.Top)
}

func (this *Window) SetPos(x, y int) {
	w, h := this.Size()
	if w == 0 {
		w = 100
	}
	if h == 0 {
		h = 25
	}
	w32.MoveWindow(this.hwnd, x, y, w, h, true)
}

func (this *Window) Center() {
	sWidth := w32.GetSystemMetrics(w32.SM_CXFULLSCREEN)
	sHeight := w32.GetSystemMetrics(w32.SM_CYFULLSCREEN)

	if sWidth != 0 && sHeight != 0 {
		w, h := this.Size()
		this.SetPos((sWidth/2)-(w/2), (sHeight/2)-(h/2))
	}
}

func (this *Window) Repaint() {
	hdc := w32.GetDC(this.hwnd)
	this.blitImage(hdc, this.bufferback)
	w32.DeleteDC(hdc)
}
<|endoftext|>