<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"
	"time"

	"strings"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/core/util"
)

var serviceCharge = 5

var logger = shim.NewLogger("ftLogger")

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

// Init initializes the chaincode
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var err error
	if len(args) > 0 {
		return nil, errors.New("Incorrect number of arguments. Expecting 0")
	}

	// Write the state to the ledger
	err = stub.PutState("IBI-CC[init]: "+time.Now().String(), []byte("starting ABI chaincode"))
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Invoke queries another chaincode and updates its own state
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var jsonResp, customer, name, amount, state string
	var response []byte
	var err error

	fmt.Println("Args: ", args)

	if len(args) != 3 {
		return nil, errors.New("Incorrect number of arguments. Expecting 3")
	}

	chaincodeURL := args[0] //https://github.com/sauravhaloi/chaincode/issuer
	operation := args[1]
	customer = args[2]

	switch operation {
	case "GetAccountBalance":
		f := "GetAccountBalance"
		queryArgs := util.ToChaincodeArgs(f, customer)
		response, err = stub.QueryChaincode(chaincodeURL, queryArgs)
		if err != nil {
			errStr := fmt.Sprintf("Failed to query chaincode. Got error: %s", err.Error())
			jsonResp = "{\"Error\":\"" + errStr + "\"}"
			return nil, errors.New(jsonResp)
		}

	case "WithdrawFund":
		f := "Withdraw"
		name = strings.Split(customer, ",")[0]
		amount = strings.Split(customer, ",")[1]
		queryArgs := util.ToChaincodeArgs(f, name, amount)

		fmt.Println("Query Args: ", queryArgs)

		response, err = stub.InvokeChaincode(chaincodeURL, queryArgs)
		if err != nil {
			errStr := fmt.Sprintf("Failed to invoke chaincode. Got error: %s", err.Error())
			jsonResp = "{\"Error\":\"" + errStr + "\"}"
			return nil, errors.New(jsonResp)
		}

		// transaction was successful, charge Issuer
		settlement, err := strconv.Atoi(amount)
		if err != nil {
			return nil, err
		}

		settlement = settlement + serviceCharge

		state = fmt.Sprintf("IBI owes ABI " + strconv.Itoa(settlement))

		// Write amount which IBI owes to ABI back to the ledger
		err = stub.PutState("IBI->ABI", []byte(state))
		if err != nil {
			return nil, err
		}

		fmt.Printf("Invoke chaincode successful. IBI Owes ABI %d\n", settlement)
		return []byte(state), nil

	default:
		jsonResp = "{\"Error\":\"Invalid operaton requested: " + operation + "\"}"
		return nil, errors.New(jsonResp)
	}

	jsonResp = "{\"Response\":\"" + string(response) + "\"}"
	fmt.Printf("Operation: %s | Response: %s", operation, jsonResp)

	return []byte(jsonResp), nil
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if function != "Query" {
		return nil, errors.New("Invalid query function name. Expecting \"Query\"")
	}
	var jsonResp string
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	transactionName := args[0]

	valAsbytes, err := stub.GetState(transactionName)
	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + transactionName + "\"}"
		return nil, errors.New(jsonResp)
	}

	fmt.Printf("Query chaincode successful. Got IBI->ABI %s\n", string(valAsbytes))
	jsonResp = "{\"IBI Owes ABI\":\"" + string(valAsbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return []byte(valAsbytes), nil

}

func main() {
	var err error
	lld, _ := shim.LogLevel("DEBUG")
	fmt.Println(lld)

	logger.SetLevel(lld)
	fmt.Println(logger.IsEnabledFor(lld))

	err = shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("Could not start SimpleChaincode")
	} else {
		fmt.Println("SimpleChaincode successfully started")
	}
}
<commit_msg>logging and bug fixing<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"
	"time"

	"strings"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/core/util"
)

var serviceCharge = 5

var logger = shim.NewLogger("ftLogger")

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

// Init initializes the chaincode
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var err error
	if len(args) > 0 {
		return nil, errors.New("Incorrect number of arguments. Expecting 0")
	}

	// Write the state to the ledger
	err = stub.PutState("IBI-CC[init]: "+time.Now().String(), []byte("starting ABI chaincode"))
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Invoke queries another chaincode and updates its own state
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var jsonResp, customer, name, amount, state string
	var response []byte
	var err error

	fmt.Println("Args: ", args)

	if len(args) != 3 {
		return nil, errors.New("Incorrect number of arguments. Expecting 3")
	}

	chaincodeURL := args[0] //https://github.com/sauravhaloi/chaincode/issuer
	operation := args[1]
	customer = args[2]

	switch operation {
	case "GetAccountBalance":
		f := "GetAccountBalance"
		queryArgs := util.ToChaincodeArgs(f, customer)
		response, err = stub.QueryChaincode(chaincodeURL, queryArgs)
		if err != nil {
			errStr := fmt.Sprintf("Failed to query chaincode. Got error: %s", err.Error())
			jsonResp = "{\"Error\":\"" + errStr + "\"}"
			return nil, errors.New(jsonResp)
		}

	case "WithdrawFund":
		f := "Withdraw"
		name = strings.Split(customer, ",")[0]
		amount = strings.Split(customer, ",")[1]
		queryArgs := util.ToChaincodeArgs(f, name, amount)

		fmt.Println("Query Args: ", queryArgs)

		response, err = stub.InvokeChaincode(chaincodeURL, queryArgs)
		if err != nil {
			errStr := fmt.Sprintf("Failed to invoke chaincode. Got error: %s", err.Error())
			jsonResp = "{\"Error\":\"" + errStr + "\"}"
			return nil, errors.New(jsonResp)
		}

		jsonResp = "{\"Response of WithdrawFund\":\"" + string(response) + "\"}"
		fmt.Printf("Operation: %s | Response: %s", operation, jsonResp)

		// transaction was successful, charge Issuer
		settlement, err := strconv.Atoi(amount)
		if err != nil {
			return nil, err
		}

		settlement = settlement + serviceCharge

		existing, err := stub.GetState("IBI->ABI")
		if err != nil {
			return nil, errors.New("Failed to get state" + err.Error())
		}

		existingSettlement := strings.Split(string(existing), " ")[3]

		pastSettlement, err := strconv.Atoi(existingSettlement)
		if err != nil {
			return nil, err
		}

		state = fmt.Sprintf("IBI owes ABI " + strconv.Itoa(settlement+pastSettlement))

		// Write amount which IBI owes to ABI back to the ledger
		err = stub.PutState("IBI->ABI", []byte(state))
		if err != nil {
			return nil, err
		}

		fmt.Printf("Invoke chaincode successful. IBI Owes ABI %d\n", settlement)
		return []byte(state), nil

	default:
		jsonResp = "{\"Error\":\"Invalid operaton requested: " + operation + "\"}"
		return nil, errors.New(jsonResp)
	}

	jsonResp = "{\"Response\":\"" + string(response) + "\"}"
	fmt.Printf("Operation: %s | Response: %s", operation, jsonResp)

	return []byte(jsonResp), nil
}

// Query callback representing the query of a chaincode
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if function != "Query" {
		return nil, errors.New("Invalid query function name. Expecting \"Query\"")
	}
	var jsonResp string
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	transactionName := args[0]

	valAsbytes, err := stub.GetState(transactionName)
	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + transactionName + "\"}"
		return nil, errors.New(jsonResp)
	}

	fmt.Printf("Query chaincode successful. Got IBI->ABI %s\n", string(valAsbytes))
	jsonResp = "{\"IBI Owes ABI\":\"" + string(valAsbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return []byte(valAsbytes), nil

}

func main() {
	var err error
	lld, _ := shim.LogLevel("DEBUG")
	fmt.Println(lld)

	logger.SetLevel(lld)
	fmt.Println(logger.IsEnabledFor(lld))

	err = shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("Could not start SimpleChaincode")
	} else {
		fmt.Println("SimpleChaincode successfully started")
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 The go-logger Authors. All rights reserved.
// This code is MIT licensed. See the LICENSE file for more info.

package log

import (
	"bytes"
	"fmt"
	"io"
	"math/rand"
	"os"
	"path/filepath"
	"testing"
	"runtime"
	"time"
)

func TestStream(t *testing.T) {
	var buf bytes.Buffer
	logr := New(LEVEL_CRITICAL, os.Stdout, &buf)
	logr.Streams[1] = &buf
	if out := logr.Streams[1]; out != &buf {
		t.Errorf("Stream = %p, want %p", out, &buf)
	}
}

func TestMultiStreams(t *testing.T) {
	rand.Seed(time.Now().UnixNano())
	fPath := filepath.Join(os.TempDir(), fmt.Sprint("go_test_",
		rand.Int()))
	file, err := os.Create(fPath)
	if err != nil {
		t.Error("Create(%q) = %v; want: nil", fPath, err)
	}
	defer file.Close()
	var buf bytes.Buffer
	eLen := 55
	logr := New(LEVEL_DEBUG, file, &buf)
	logr.Debugln("Testing debug output!")
	b := make([]byte, eLen)
	n, err := file.ReadAt(b, 0)
	if n != eLen || err != nil {
		t.Errorf("Read(%d) = %d, %v; want: %d, nil", eLen, n, err,
			eLen)
	}
	if buf.Len() != eLen {
		t.Errorf("buf.Len() = %d; want: %d", buf.Len(), eLen)
	}
}

func TestLongFileFlag(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LlongFileName)

	Debugln("Test long file flag")

	_, file, _, _ := runtime.Caller(0)

	expect := fmt.Sprintf("[DEBUG] %s: Test long file flag\n", file)

	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%s\nGot:\n\t%s\n", expect, buf.String())
	}
}

func TestShortFileFlag(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LshortFileName)

	Debugln("Test short file flag")

	_, file, _, _ := runtime.Caller(0)

	short := file
	for i := len(file) - 1; i > 0; i-- {
		if file[i] == '/' {
			short = file[i+1:]
			break
		}
	}
	file = short

	expect := fmt.Sprintf("[DEBUG] %s: Test short file flag\n", file)

	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%s\nGot:\n\t%s\n", expect, buf.String())
	}
}

var (
	boldPrefix  = AnsiEscape(ANSI_BOLD, "TEST>", ANSI_OFF)
	colorPrefix = AnsiEscape(ANSI_BOLD, ANSI_RED, "TEST>", ANSI_OFF)
	date        = "Mon 20060102 15:04:05"
)

var outputTests = []struct {
	template   string
	prefix     string
	level      level
	dateFormat string
	flags      int
	text       string
	want       string
	wantErr    bool
}{

	// The %s format specifier is the placeholder for the date.
	{logFmt, boldPrefix, LEVEL_ALL, date, LstdFlags, "test number 1",
		"%s \x1b[1mTEST>\x1b[0m test number 1", false},

	{logFmt, colorPrefix, LEVEL_ALL, date, LstdFlags, "test number 2",
		"%s \x1b[1m\x1b[31mTEST>\x1b[0m test number 2", false},

	// Test output with coloring turned off
	{logFmt, AnsiEscape(ANSI_BOLD, "::", ANSI_OFF), LEVEL_ALL, date, Ldate,
		"test number 3", "%s :: test number 3", false},

	{logFmt, defaultPrefixColor, LEVEL_DEBUG, time.RubyDate, LstdFlags,
		"test number 4",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[37m[DEBUG]\x1b[0m test number 4",
		false},

	{logFmt, defaultPrefixColor, LEVEL_INFO, time.RubyDate, LstdFlags,
		"test number 5",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[32m[INFO]\x1b[0m test number 5",
		false},

	{logFmt, defaultPrefixColor, LEVEL_WARNING, time.RubyDate, LstdFlags,
		"test number 6",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[33m[WARNING]\x1b[0m test number 6",
		false},

	{logFmt, defaultPrefixColor, LEVEL_ERROR, time.RubyDate, LstdFlags,
		"test number 7",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[35m[ERROR]\x1b[0m test number 7",
		false},

	{logFmt, defaultPrefixColor, LEVEL_CRITICAL, time.RubyDate, LstdFlags,
		"test number 8",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[31m[CRITICAL]\x1b[0m test number 8",
		false},

	// Test date format
	{logFmt, defaultPrefixColor, LEVEL_ALL, "Mon 20060102 15:04:05",
		Ldate, "test number 9",
		"%s :: test number 9", false},
}

func TestOutput(t *testing.T) {
	for i, k := range outputTests {
		var buf bytes.Buffer
		logr := New(LEVEL_DEBUG, &buf)
		logr.Prefix = k.prefix
		logr.DateFormat = k.dateFormat
		logr.Flags = k.flags
		logr.Level = k.level
		d := time.Now().Format(logr.DateFormat)
		n, err := logr.Fprint(k.level, 1, k.text, &buf)
		if n != buf.Len() {
			t.Error("Error: ", io.ErrShortWrite)
		}
		want := fmt.Sprintf(k.want, d)
		if buf.String() != want || err != nil && !k.wantErr {
			t.Errorf("Print test %d failed, \ngot:  %q\nwant: "+
				"%q", i+1, buf.String(), want)
			continue
		}
	}
}

func TestLevel(t *testing.T) {
	var buf bytes.Buffer
	logr := New(LEVEL_CRITICAL, &buf)
	logr.Debug("This level should produce no output")
	if buf.Len() != 0 {
		t.Errorf("Debug() produced output at LEVEL_CRITICAL logging level")
	}
	logr.Level = LEVEL_DEBUG
	logr.Debug("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the LEVEL_DEBUG logging level")
	}
	buf.Reset()
	logr.Level = LEVEL_CRITICAL
	logr.Println("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the ALL logging level")
	}
	buf.Reset()
	logr.Level = LEVEL_ALL
	logr.Debug("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the ALL logging level")
	}
}

func TestPrefixNewline(t *testing.T) {
	var buf bytes.Buffer

	c, err := buf.ReadString('\n')

	// If text sent with the logging functions is prepended with newlines,
	// these newlines must be prepended to the output and stripped from the
	// text. First we will make sure the two nl's are at the beginning of
	// the output.
	if c[0] != '\n' {
		t.Errorf(`First byte should be "\n", found "%s"`, string(c[0]))
	}

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)

	c, err = buf.ReadString('\n')
	if err != nil {
		t.Error("ReadString unexpected EOF")
	}

	// Since nl should be stripped from the text and prepended to the
	// output, we must make sure the nl is still not in the middle where it
	// would be if it had not been stripped.
	nlPos := strings.Index(buf.String(), "] ") + 1
	if buf.Bytes()[nlPos+1] == '\n' {
		t.Errorf(`"\n" found at position %d.`, nlPos+1)
	}
}

func TestFlagsDate(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)

	Debugln("This output should not have a date.")

	expect := "[DEBUG] This output should not have a date.\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%s\nGot:\n\t%s\n", expect, buf.String())
	}
}

func TestFlagsFunctionName(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LfunctionName)

	Debugln("This output should have a function name.")
	expect := "[DEBUG] TestFlagsFunction: This output should have a function name.\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%s\nGot:\n\t%s\n", expect, buf.String())
	}
}
<commit_msg>logger_test.go: Change %s to %q in expect output<commit_after>// Copyright 2013 The go-logger Authors. All rights reserved.
// This code is MIT licensed. See the LICENSE file for more info.

package log

import (
	"bytes"
	"fmt"
	"io"
	"math/rand"
	"os"
	"path/filepath"
	"testing"
	"runtime"
	"time"
)

func TestStream(t *testing.T) {
	var buf bytes.Buffer
	logr := New(LEVEL_CRITICAL, os.Stdout, &buf)
	logr.Streams[1] = &buf
	if out := logr.Streams[1]; out != &buf {
		t.Errorf("Stream = %p, want %p", out, &buf)
	}
}

func TestMultiStreams(t *testing.T) {
	rand.Seed(time.Now().UnixNano())
	fPath := filepath.Join(os.TempDir(), fmt.Sprint("go_test_",
		rand.Int()))
	file, err := os.Create(fPath)
	if err != nil {
		t.Error("Create(%q) = %v; want: nil", fPath, err)
	}
	defer file.Close()
	var buf bytes.Buffer
	eLen := 55
	logr := New(LEVEL_DEBUG, file, &buf)
	logr.Debugln("Testing debug output!")
	b := make([]byte, eLen)
	n, err := file.ReadAt(b, 0)
	if n != eLen || err != nil {
		t.Errorf("Read(%d) = %d, %v; want: %d, nil", eLen, n, err,
			eLen)
	}
	if buf.Len() != eLen {
		t.Errorf("buf.Len() = %d; want: %d", buf.Len(), eLen)
	}
}

func TestLongFileFlag(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LlongFileName)

	Debugln("Test long file flag")

	_, file, _, _ := runtime.Caller(0)

	expect := fmt.Sprintf("[DEBUG] %s: Test long file flag\n", file)

	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestShortFileFlag(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LshortFileName)

	Debugln("Test short file flag")

	_, file, _, _ := runtime.Caller(0)

	short := file
	for i := len(file) - 1; i > 0; i-- {
		if file[i] == '/' {
			short = file[i+1:]
			break
		}
	}
	file = short

	expect := fmt.Sprintf("[DEBUG] %s: Test short file flag\n", file)

	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

var (
	boldPrefix  = AnsiEscape(ANSI_BOLD, "TEST>", ANSI_OFF)
	colorPrefix = AnsiEscape(ANSI_BOLD, ANSI_RED, "TEST>", ANSI_OFF)
	date        = "Mon 20060102 15:04:05"
)

var outputTests = []struct {
	template   string
	prefix     string
	level      level
	dateFormat string
	flags      int
	text       string
	want       string
	wantErr    bool
}{

	// The %s format specifier is the placeholder for the date.
	{logFmt, boldPrefix, LEVEL_ALL, date, LstdFlags, "test number 1",
		"%s \x1b[1mTEST>\x1b[0m test number 1", false},

	{logFmt, colorPrefix, LEVEL_ALL, date, LstdFlags, "test number 2",
		"%s \x1b[1m\x1b[31mTEST>\x1b[0m test number 2", false},

	// Test output with coloring turned off
	{logFmt, AnsiEscape(ANSI_BOLD, "::", ANSI_OFF), LEVEL_ALL, date, Ldate,
		"test number 3", "%s :: test number 3", false},

	{logFmt, defaultPrefixColor, LEVEL_DEBUG, time.RubyDate, LstdFlags,
		"test number 4",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[37m[DEBUG]\x1b[0m test number 4",
		false},

	{logFmt, defaultPrefixColor, LEVEL_INFO, time.RubyDate, LstdFlags,
		"test number 5",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[32m[INFO]\x1b[0m test number 5",
		false},

	{logFmt, defaultPrefixColor, LEVEL_WARNING, time.RubyDate, LstdFlags,
		"test number 6",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[33m[WARNING]\x1b[0m test number 6",
		false},

	{logFmt, defaultPrefixColor, LEVEL_ERROR, time.RubyDate, LstdFlags,
		"test number 7",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[35m[ERROR]\x1b[0m test number 7",
		false},

	{logFmt, defaultPrefixColor, LEVEL_CRITICAL, time.RubyDate, LstdFlags,
		"test number 8",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[31m[CRITICAL]\x1b[0m test number 8",
		false},

	// Test date format
	{logFmt, defaultPrefixColor, LEVEL_ALL, "Mon 20060102 15:04:05",
		Ldate, "test number 9",
		"%s :: test number 9", false},
}

func TestOutput(t *testing.T) {
	for i, k := range outputTests {
		var buf bytes.Buffer
		logr := New(LEVEL_DEBUG, &buf)
		logr.Prefix = k.prefix
		logr.DateFormat = k.dateFormat
		logr.Flags = k.flags
		logr.Level = k.level
		d := time.Now().Format(logr.DateFormat)
		n, err := logr.Fprint(k.level, 1, k.text, &buf)
		if n != buf.Len() {
			t.Error("Error: ", io.ErrShortWrite)
		}
		want := fmt.Sprintf(k.want, d)
		if buf.String() != want || err != nil && !k.wantErr {
			t.Errorf("Print test %d failed, \ngot:  %q\nwant: "+
				"%q", i+1, buf.String(), want)
			continue
		}
	}
}

func TestLevel(t *testing.T) {
	var buf bytes.Buffer
	logr := New(LEVEL_CRITICAL, &buf)
	logr.Debug("This level should produce no output")
	if buf.Len() != 0 {
		t.Errorf("Debug() produced output at LEVEL_CRITICAL logging level")
	}
	logr.Level = LEVEL_DEBUG
	logr.Debug("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the LEVEL_DEBUG logging level")
	}
	buf.Reset()
	logr.Level = LEVEL_CRITICAL
	logr.Println("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the ALL logging level")
	}
	buf.Reset()
	logr.Level = LEVEL_ALL
	logr.Debug("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the ALL logging level")
	}
}

func TestPrefixNewline(t *testing.T) {
	var buf bytes.Buffer

	c, err := buf.ReadString('\n')

	// If text sent with the logging functions is prepended with newlines,
	// these newlines must be prepended to the output and stripped from the
	// text. First we will make sure the two nl's are at the beginning of
	// the output.
	if c[0] != '\n' {
		t.Errorf(`First byte should be "\n", found "%s"`, string(c[0]))
	}

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)

	c, err = buf.ReadString('\n')
	if err != nil {
		t.Error("ReadString unexpected EOF")
	}

	// Since nl should be stripped from the text and prepended to the
	// output, we must make sure the nl is still not in the middle where it
	// would be if it had not been stripped.
	nlPos := strings.Index(buf.String(), "] ") + 1
	if buf.Bytes()[nlPos+1] == '\n' {
		t.Errorf(`"\n" found at position %d.`, nlPos+1)
	}
}

func TestFlagsDate(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)

	Debugln("This output should not have a date.")

	expect := "[DEBUG] This output should not have a date.\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestFlagsFunctionName(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LfunctionName)

	Debugln("This output should have a function name.")
	expect := "[DEBUG] TestFlagsFunction: This output should have a function name.\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}
<|endoftext|>


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

package xormadapter

import (
	"log"
	"testing"

	"github.com/casbin/casbin"
	"github.com/casbin/casbin/util"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
)

func testGetPolicy(t *testing.T, e *casbin.Enforcer, res [][]string) {
	myRes := e.GetPolicy()
	log.Print("Policy: ", myRes)

	if !util.Array2DEquals(res, myRes) {
		t.Error("Policy: ", myRes, ", supposed to be ", res)
	}
}

func TestMySQLAdapter(t *testing.T) {
	// Because the MySQL DB is empty at first,
	// so we need to load the policy from the file adapter (.CSV) first.
	e := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")

	a := NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
	// This is a trick to save the current policy to the MySQL DB.
	// We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
	// The current policy means the policy in the Casbin enforcer (aka in memory).
	err := a.SavePolicy(e.GetModel())
	if err != nil {
		panic(err)
	}

	// Clear the current policy.
	e.ClearPolicy()
	testGetPolicy(t, e, [][]string{})

	// Load the policy from MySQL DB.
	err = a.LoadPolicy(e.GetModel())
	if err != nil {
		panic(err)
	}
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})

	// Note: you don't need to look at the above code
	// if you already have a working MySQL DB with policy inside.

	// Now the MySQL DB has policy, so we can provide a normal use case.
	// Create an adapter and an enforcer.
	// NewEnforcer() will load the policy automatically.
	a = NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
	e = casbin.NewEnforcer("examples/rbac_model.conf", a)
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}

func TestPostgresAdapter(t *testing.T) {
	// Because the Postgres DB is empty at first,
	// so we need to load the policy from the file adapter (.CSV) first.
	e := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")

	a := NewAdapter("postgres", "user=postgres host=127.0.0.1 port=5432 sslmode=disable")
	// This is a trick to save the current policy to the Postgres DB.
	// We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
	// The current policy means the policy in the Casbin enforcer (aka in memory).
	err := a.SavePolicy(e.GetModel())
	if err != nil {
		panic(err)
	}

	// Clear the current policy.
	e.ClearPolicy()
	testGetPolicy(t, e, [][]string{})

	// Load the policy from Postgres DB.
	err = a.LoadPolicy(e.GetModel())
	if err != nil {
		panic(err)
	}
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})

	// Note: you don't need to look at the above code
	// if you already have a working Postgres DB with policy inside.

	// Now the Postgres DB has policy, so we can provide a normal use case.
	// Create an adapter and an enforcer.
	// NewEnforcer() will load the policy automatically.
	a = NewAdapter("postgres", "user=postgres host=127.0.0.1 port=5432 sslmode=disable")
	e = casbin.NewEnforcer("examples/rbac_model.conf", a)
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}

func TestAutoSave(t *testing.T) {
	// Because the MySQL DB is empty at first,
	// so we need to load the policy from the file adapter (.CSV) first.
	e := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")

	a := NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
	// This is a trick to save the current policy to the MySQL DB.
	// We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
	// The current policy means the policy in the Casbin enforcer (aka in memory).
	err := a.SavePolicy(e.GetModel())
	if err != nil {
		panic(err)
	}

	// Clear the current policy.
	e.ClearPolicy()
	testGetPolicy(t, e, [][]string{})

	// Load the policy from MySQL DB.
	err = a.LoadPolicy(e.GetModel())
	if err != nil {
		panic(err)
	}
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})

	// Note: you don't need to look at the above code
	// if you already have a working MySQL DB with policy inside.

	// Now the MySQL DB has policy, so we can provide a normal use case.
	// Create an adapter and an enforcer.
	// NewEnforcer() will load the policy automatically.
	a = NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
	e = casbin.NewEnforcer("examples/rbac_model.conf", a)

	// AutoSave is enabled by default.
	// Now we disable it.
	e.EnableAutoSave(false)

	// Because AutoSave is disabled, the policy change only affects the policy in Casbin enforcer,
	// it doesn't affect the policy in the storage.
	e.AddPolicy("alice", "data1", "write")
	// Reload the policy from the storage to see the effect.
	e.LoadPolicy()
	// This is still the original policy.
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})

	// Now we enable the AutoSave.
	e.EnableAutoSave(true)

	// Because AutoSave is enabled, the policy change not only affects the policy in Casbin enforcer,
	// but also affects the policy in the storage.
	e.AddPolicy("alice", "data1", "write")
	// Reload the policy from the storage to see the effect.
	e.LoadPolicy()
	// The policy has a new rule: "alice", "data1", "write"
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}, {"alice", "data1", "write"}})
}
<commit_msg>Refactor out initMySQLPolicy() and initPostgresPolicy().<commit_after>// Copyright 2017 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package xormadapter

import (
	"log"
	"testing"

	"github.com/casbin/casbin"
	"github.com/casbin/casbin/util"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
)

func testGetPolicy(t *testing.T, e *casbin.Enforcer, res [][]string) {
	myRes := e.GetPolicy()
	log.Print("Policy: ", myRes)

	if !util.Array2DEquals(res, myRes) {
		t.Error("Policy: ", myRes, ", supposed to be ", res)
	}
}

func initMySQLPolicy(t *testing.T) {
	// Because the MySQL DB is empty at first,
	// so we need to load the policy from the file adapter (.CSV) first.
	e := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")

	a := NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
	// This is a trick to save the current policy to the MySQL DB.
	// We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
	// The current policy means the policy in the Casbin enforcer (aka in memory).
	err := a.SavePolicy(e.GetModel())
	if err != nil {
		panic(err)
	}

	// Clear the current policy.
	e.ClearPolicy()
	testGetPolicy(t, e, [][]string{})

	// Load the policy from MySQL DB.
	err = a.LoadPolicy(e.GetModel())
	if err != nil {
		panic(err)
	}
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}

func initPostgresPolicy(t *testing.T) {
	// Because the Postgres DB is empty at first,
	// so we need to load the policy from the file adapter (.CSV) first.
	e := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")

	a := NewAdapter("postgres", "user=postgres host=127.0.0.1 port=5432 sslmode=disable")
	// This is a trick to save the current policy to the Postgres DB.
	// We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
	// The current policy means the policy in the Casbin enforcer (aka in memory).
	err := a.SavePolicy(e.GetModel())
	if err != nil {
		panic(err)
	}

	// Clear the current policy.
	e.ClearPolicy()
	testGetPolicy(t, e, [][]string{})

	// Load the policy from Postgres DB.
	err = a.LoadPolicy(e.GetModel())
	if err != nil {
		panic(err)
	}
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}

func TestMySQLAdapter(t *testing.T) {
	// Initialize some policy in DB.
	initMySQLPolicy(t)
	// Note: you don't need to look at the above code
	// if you already have a working MySQL DB with policy inside.

	// Now the MySQL DB has policy, so we can provide a normal use case.
	// Create an adapter and an enforcer.
	// NewEnforcer() will load the policy automatically.
	a := NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
	e := casbin.NewEnforcer("examples/rbac_model.conf", a)
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}

func TestPostgresAdapter(t *testing.T) {
	// Initialize some policy in DB.
	initPostgresPolicy(t)
	// Note: you don't need to look at the above code
	// if you already have a working Postgres DB with policy inside.

	// Now the Postgres DB has policy, so we can provide a normal use case.
	// Create an adapter and an enforcer.
	// NewEnforcer() will load the policy automatically.
	a := NewAdapter("postgres", "user=postgres host=127.0.0.1 port=5432 sslmode=disable")
	e := casbin.NewEnforcer("examples/rbac_model.conf", a)
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}

func TestAutoSave(t *testing.T) {
	// Initialize some policy in DB.
	initMySQLPolicy(t)
	// Note: you don't need to look at the above code
	// if you already have a working MySQL DB with policy inside.

	// Now the MySQL DB has policy, so we can provide a normal use case.
	// Create an adapter and an enforcer.
	// NewEnforcer() will load the policy automatically.
	a := NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
	e := casbin.NewEnforcer("examples/rbac_model.conf", a)

	// AutoSave is enabled by default.
	// Now we disable it.
	e.EnableAutoSave(false)

	// Because AutoSave is disabled, the policy change only affects the policy in Casbin enforcer,
	// it doesn't affect the policy in the storage.
	e.AddPolicy("alice", "data1", "write")
	// Reload the policy from the storage to see the effect.
	e.LoadPolicy()
	// This is still the original policy.
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})

	// Now we enable the AutoSave.
	e.EnableAutoSave(true)

	// Because AutoSave is enabled, the policy change not only affects the policy in Casbin enforcer,
	// but also affects the policy in the storage.
	e.AddPolicy("alice", "data1", "write")
	// Reload the policy from the storage to see the effect.
	e.LoadPolicy()
	// The policy has a new rule: "alice", "data1", "write"
	testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}, {"alice", "data1", "write"}})
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go 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 builtin provides documentation for Go's predeclared identifiers.
	The items documented here are not actually in package builtin
	but their descriptions here allow godoc to present documentation
	for the language's special identifiers.
*/
package builtin

// bool is the set of boolean values, true and false.
type bool bool

// true and false are the two untyped boolean values.
const (
	true  = 0 == 0 // Untyped bool.
	false = 0 != 0 // Untyped bool.
)

// uint8 is the set of all unsigned 8-bit integers.
// Range: 0 through 255.
type uint8 uint8

// uint16 is the set of all unsigned 16-bit integers.
// Range: 0 through 65535.
type uint16 uint16

// uint32 is the set of all unsigned 32-bit integers.
// Range: 0 through 4294967295.
type uint32 uint32

// uint64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type uint64 uint64

// int8 is the set of all signed 8-bit integers.
// Range: -128 through 127.
type int8 int8

// int16 is the set of all signed 16-bit integers.
// Range: -32768 through 32767.
type int16 int16

// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type int32 int32

// int64 is the set of all signed 64-bit integers.
// Range: -9223372036854775808 through 9223372036854775807.
type int64 int64

// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type float32 float32

// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type float64 float64

// complex64 is the set of all complex numbers with float32 real and
// imaginary parts.
type complex64 complex64

// complex128 is the set of all complex numbers with float64 real and
// imaginary parts.
type complex128 complex128

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string

// int is a signed integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, int32.
type int int

// uint is an unsigned integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, uint32.
type uint uint

// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte byte

// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune rune

// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
// const declaration. It is zero-indexed.
const iota = 0 // Untyped int.

// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type

// Type is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int

// Type1 is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type1 int

// IntegerType is here for the purposes of documentation only. It is a stand-in
// for any integer type: int, uint, int8 etc.
type IntegerType int

// FloatType is here for the purposes of documentation only. It is a stand-in
// for either float type: float32 or float64.
type FloatType float32

// ComplexType is here for the purposes of documentation only. It is a
// stand-in for either complex type: complex64 or complex128.
type ComplexType complex64

// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
//	slice = append(slice, elem1, elem2)
//	slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
//	slice = append([]byte("hello "), "world"...)
func append(slice []Type, elems ...Type) []Type

// The copy built-in function copies elements from a source slice into a
// destination slice. (As a special case, it also will copy bytes from a
// string to a slice of bytes.) The source and destination may overlap. Copy
// returns the number of elements copied, which will be the minimum of
// len(src) and len(dst).
func copy(dst, src []Type) int

// The delete built-in function deletes the element with the specified key
// (m[key]) from the map. If m is nil or there is no such element, delete
// is a no-op.
func delete(m map[Type]Type1, key Type)

// The len built-in function returns the length of v, according to its type:
//	Array: the number of elements in v.
//	Pointer to array: the number of elements in *v (even if v is nil).
//	Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
//	String: the number of bytes in v.
//	Channel: the number of elements queued (unread) in the channel buffer;
//	if v is nil, len(v) is zero.
func len(v Type) int

// The cap built-in function returns the capacity of v, according to its type:
//	Array: the number of elements in v (same as len(v)).
//	Pointer to array: the number of elements in *v (same as len(v)).
//	Slice: the maximum length the slice can reach when resliced;
//	if v is nil, cap(v) is zero.
//	Channel: the channel buffer capacity, in units of elements;
//	if v is nil, cap(v) is zero.
func cap(v Type) int

// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
//	Slice: The size specifies the length. The capacity of the slice is
//	equal to its length. A second integer argument may be provided to
//	specify a different capacity; it must be no smaller than the
//	length, so make([]int, 0, 10) allocates a slice of length 0 and
//	capacity 10.
//	Map: An empty map is allocated with enough space to hold the
//	specified number of elements. The size may be omitted, in which case
//	a small starting size is allocated.
//	Channel: The channel's buffer is initialized with the specified
//	buffer capacity. If zero, or the size is omitted, the channel is
//	unbuffered.
func make(Type, size IntegerType) Type

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type

// The complex built-in function constructs a complex value from two
// floating-point values. The real and imaginary parts must be of the same
// size, either float32 or float64 (or assignable to them), and the return
// value will be the corresponding complex type (complex64 for float32,
// complex128 for float64).
func complex(r, i FloatType) ComplexType

// The real built-in function returns the real part of the complex number c.
// The return value will be floating point type corresponding to the type of c.
func real(c ComplexType) FloatType

// The imag built-in function returns the imaginary part of the complex
// number c. The return value will be floating point type corresponding to
// the type of c.
func imag(c ComplexType) FloatType

// The close built-in function closes a channel, which must be either
// bidirectional or send-only. It should be executed only by the sender,
// never the receiver, and has the effect of shutting down the channel after
// the last sent value is received. After the last value has been received
// from a closed channel c, any receive from c will succeed without
// blocking, returning the zero value for the channel element. The form
//	x, ok := <-c
// will also set ok to false for a closed channel.
func close(c chan<- Type)

// The panic built-in function stops normal execution of the current
// goroutine. When a function F calls panic, normal execution of F stops
// immediately. Any functions whose execution was deferred by F are run in
// the usual way, and then F returns to its caller. To the caller G, the
// invocation of F then behaves like a call to panic, terminating G's
// execution and running any deferred functions. This continues until all
// functions in the executing goroutine have stopped, in reverse order. At
// that point, the program is terminated and the error condition is reported,
// including the value of the argument to panic. This termination sequence
// is called panicking and can be controlled by the built-in function
// recover.
func panic(v interface{})

// The recover built-in function allows a program to manage behavior of a
// panicking goroutine. Executing a call to recover inside a deferred
// function (but not any function called by it) stops the panicking sequence
// by restoring normal execution and retrieves the error value passed to the
// call of panic. If recover is called outside the deferred function it will
// not stop a panicking sequence. In this case, or when the goroutine is not
// panicking, or if the argument supplied to panic was nil, recover returns
// nil. Thus the return value from recover reports whether the goroutine is
// panicking.
func recover() interface{}

// The print built-in function formats its arguments in an
// implementation-specific way and writes the result to standard error.
// Print is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language.
func print(args ...Type)

// The println built-in function formats its arguments in an
// implementation-specific way and writes the result to standard error.
// Spaces are always added between arguments and a newline is appended.
// Println is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language.
func println(args ...Type)

// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
	Error() string
}
<commit_msg>builtin: fix signature of the builtin function make<commit_after>// Copyright 2011 The Go 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 builtin provides documentation for Go's predeclared identifiers.
	The items documented here are not actually in package builtin
	but their descriptions here allow godoc to present documentation
	for the language's special identifiers.
*/
package builtin

// bool is the set of boolean values, true and false.
type bool bool

// true and false are the two untyped boolean values.
const (
	true  = 0 == 0 // Untyped bool.
	false = 0 != 0 // Untyped bool.
)

// uint8 is the set of all unsigned 8-bit integers.
// Range: 0 through 255.
type uint8 uint8

// uint16 is the set of all unsigned 16-bit integers.
// Range: 0 through 65535.
type uint16 uint16

// uint32 is the set of all unsigned 32-bit integers.
// Range: 0 through 4294967295.
type uint32 uint32

// uint64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type uint64 uint64

// int8 is the set of all signed 8-bit integers.
// Range: -128 through 127.
type int8 int8

// int16 is the set of all signed 16-bit integers.
// Range: -32768 through 32767.
type int16 int16

// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type int32 int32

// int64 is the set of all signed 64-bit integers.
// Range: -9223372036854775808 through 9223372036854775807.
type int64 int64

// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type float32 float32

// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type float64 float64

// complex64 is the set of all complex numbers with float32 real and
// imaginary parts.
type complex64 complex64

// complex128 is the set of all complex numbers with float64 real and
// imaginary parts.
type complex128 complex128

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string

// int is a signed integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, int32.
type int int

// uint is an unsigned integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, uint32.
type uint uint

// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte byte

// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune rune

// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
// const declaration. It is zero-indexed.
const iota = 0 // Untyped int.

// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type

// Type is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int

// Type1 is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type1 int

// IntegerType is here for the purposes of documentation only. It is a stand-in
// for any integer type: int, uint, int8 etc.
type IntegerType int

// FloatType is here for the purposes of documentation only. It is a stand-in
// for either float type: float32 or float64.
type FloatType float32

// ComplexType is here for the purposes of documentation only. It is a
// stand-in for either complex type: complex64 or complex128.
type ComplexType complex64

// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
//	slice = append(slice, elem1, elem2)
//	slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
//	slice = append([]byte("hello "), "world"...)
func append(slice []Type, elems ...Type) []Type

// The copy built-in function copies elements from a source slice into a
// destination slice. (As a special case, it also will copy bytes from a
// string to a slice of bytes.) The source and destination may overlap. Copy
// returns the number of elements copied, which will be the minimum of
// len(src) and len(dst).
func copy(dst, src []Type) int

// The delete built-in function deletes the element with the specified key
// (m[key]) from the map. If m is nil or there is no such element, delete
// is a no-op.
func delete(m map[Type]Type1, key Type)

// The len built-in function returns the length of v, according to its type:
//	Array: the number of elements in v.
//	Pointer to array: the number of elements in *v (even if v is nil).
//	Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
//	String: the number of bytes in v.
//	Channel: the number of elements queued (unread) in the channel buffer;
//	if v is nil, len(v) is zero.
func len(v Type) int

// The cap built-in function returns the capacity of v, according to its type:
//	Array: the number of elements in v (same as len(v)).
//	Pointer to array: the number of elements in *v (same as len(v)).
//	Slice: the maximum length the slice can reach when resliced;
//	if v is nil, cap(v) is zero.
//	Channel: the channel buffer capacity, in units of elements;
//	if v is nil, cap(v) is zero.
func cap(v Type) int

// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
//	Slice: The size specifies the length. The capacity of the slice is
//	equal to its length. A second integer argument may be provided to
//	specify a different capacity; it must be no smaller than the
//	length, so make([]int, 0, 10) allocates a slice of length 0 and
//	capacity 10.
//	Map: An empty map is allocated with enough space to hold the
//	specified number of elements. The size may be omitted, in which case
//	a small starting size is allocated.
//	Channel: The channel's buffer is initialized with the specified
//	buffer capacity. If zero, or the size is omitted, the channel is
//	unbuffered.
func make(t Type, size ...IntegerType) Type

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type

// The complex built-in function constructs a complex value from two
// floating-point values. The real and imaginary parts must be of the same
// size, either float32 or float64 (or assignable to them), and the return
// value will be the corresponding complex type (complex64 for float32,
// complex128 for float64).
func complex(r, i FloatType) ComplexType

// The real built-in function returns the real part of the complex number c.
// The return value will be floating point type corresponding to the type of c.
func real(c ComplexType) FloatType

// The imag built-in function returns the imaginary part of the complex
// number c. The return value will be floating point type corresponding to
// the type of c.
func imag(c ComplexType) FloatType

// The close built-in function closes a channel, which must be either
// bidirectional or send-only. It should be executed only by the sender,
// never the receiver, and has the effect of shutting down the channel after
// the last sent value is received. After the last value has been received
// from a closed channel c, any receive from c will succeed without
// blocking, returning the zero value for the channel element. The form
//	x, ok := <-c
// will also set ok to false for a closed channel.
func close(c chan<- Type)

// The panic built-in function stops normal execution of the current
// goroutine. When a function F calls panic, normal execution of F stops
// immediately. Any functions whose execution was deferred by F are run in
// the usual way, and then F returns to its caller. To the caller G, the
// invocation of F then behaves like a call to panic, terminating G's
// execution and running any deferred functions. This continues until all
// functions in the executing goroutine have stopped, in reverse order. At
// that point, the program is terminated and the error condition is reported,
// including the value of the argument to panic. This termination sequence
// is called panicking and can be controlled by the built-in function
// recover.
func panic(v interface{})

// The recover built-in function allows a program to manage behavior of a
// panicking goroutine. Executing a call to recover inside a deferred
// function (but not any function called by it) stops the panicking sequence
// by restoring normal execution and retrieves the error value passed to the
// call of panic. If recover is called outside the deferred function it will
// not stop a panicking sequence. In this case, or when the goroutine is not
// panicking, or if the argument supplied to panic was nil, recover returns
// nil. Thus the return value from recover reports whether the goroutine is
// panicking.
func recover() interface{}

// The print built-in function formats its arguments in an
// implementation-specific way and writes the result to standard error.
// Print is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language.
func print(args ...Type)

// The println built-in function formats its arguments in an
// implementation-specific way and writes the result to standard error.
// Spaces are always added between arguments and a newline is appended.
// Println is useful for bootstrapping and debugging; it is not guaranteed
// to stay in the language.
func println(args ...Type)

// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
	Error() string
}
<|endoftext|>


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

// The package u32 provides basic function for the uint32 type.
package lzma

/* Naming conventions follows the CodeReviewComments in the Go Wiki. */

// ntzConst is used by the functions NTZ and NLZ.
const ntzConst = 0x04d7651f

// Helper table for de Bruijn algorithm by Danny Dubé. See Henry S.
// Warren, Jr. "Hacker's Delight" section 5-1 figure 5-26.
var ntzTable = [32]int8{
	0, 1, 2, 24, 3, 19, 6, 25,
	22, 4, 20, 10, 16, 7, 12, 26,
	31, 23, 18, 5, 21, 9, 15, 11,
	30, 17, 8, 14, 29, 13, 28, 27}

// ntz32 computes the number of trailing zeros for an unsigned 32-bit integer.
func ntz32(x uint32) int {
	if x == 0 {
		return 32
	}
	x = (x & -x) * ntzConst
	return int(ntzTable[x>>27])
}

// nlz32 computes the number of leading zeros for an unsigned 32-bit integer.
func nlz32(x uint32) int {
	// Smear left most bit to the right
	x |= x >> 1
	x |= x >> 2
	x |= x >> 4
	x |= x >> 8
	x |= x >> 16
	// Use ntz mechanism to calculate nlz.
	x++
	if x == 0 {
		return 0
	}
	x *= ntzConst
	return 32 - int(ntzTable[x>>27])
}
<commit_msg>lzma: fixed comments and formatting in bitops.go<commit_after>// Copyright 2015 Ulrich Kunitz. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lzma

/* Naming conventions follows the CodeReviewComments in the Go Wiki. */

// ntz32Const is used by the functions NTZ and NLZ.
const ntz32Const = 0x04d7651f

// ntz32Table is a helper table for de Bruijn algorithm by Danny Dubé.
// See Henry S. Warren, Jr. "Hacker's Delight" section 5-1 figure 5-26.
var ntz32Table = [32]int8{
	0, 1, 2, 24, 3, 19, 6, 25,
	22, 4, 20, 10, 16, 7, 12, 26,
	31, 23, 18, 5, 21, 9, 15, 11,
	30, 17, 8, 14, 29, 13, 28, 27,
}

// ntz32 computes the number of trailing zeros for an unsigned 32-bit integer.
func ntz32(x uint32) int {
	if x == 0 {
		return 32
	}
	x = (x & -x) * ntz32Const
	return int(ntz32Table[x>>27])
}

// nlz32 computes the number of leading zeros for an unsigned 32-bit integer.
func nlz32(x uint32) int {
	// Smear left most bit to the right
	x |= x >> 1
	x |= x >> 2
	x |= x >> 4
	x |= x >> 8
	x |= x >> 16
	// Use ntz mechanism to calculate nlz.
	x++
	if x == 0 {
		return 0
	}
	x *= ntz32Const
	return 32 - int(ntz32Table[x>>27])
}
<|endoftext|>


<commit_before>package lzma

import "io"

var (
	errOffset       = newError("offset outside buffer range")
	errAgain        = newError("buffer exceeded; repeat")
	errNegLen       = newError("length is negative")
	errNrOverflow   = newError("number overflow")
	errCapacity     = newError("capacity must be larger than zero")
	errClosedBuffer = newError("buffer is closed for writing")
)

type buffer struct {
	data       []byte
	start      int64
	cursor     int64
	end        int64
	writeLimit int
	closed     bool
}

func (b *buffer) Cap() int {
	return len(b.data)
}

func (b *buffer) Len() int {
	return int(b.end - b.start)
}

func (b *buffer) Readable() int {
	return int(b.end - b.cursor)
}

func (b *buffer) Writable() int {
	return int(b.cursor + int64(b.writeLimit) - b.end)
}

func (b *buffer) setEnd(x int64) {
	if x < 0 {
		panic("b.end overflow?")
	}
	b.end = x
	b.start = x - int64(len(b.data))
	if b.start < 0 {
		b.start = 0
	}
}

func (b *buffer) index(off int64) int {
	if off < 0 {
		panic("negative offsets are not supported")
	}
	return int(off % int64(len(b.data)))
}

func initBuffer(b *buffer, capacity int) error {
	if capacity <= 0 {
		return errCapacity
	}
	*b = buffer{data: make([]byte, capacity), writeLimit: capacity}
	return nil
}

func newBuffer(capacity int) (b *buffer, err error) {
	b = new(buffer)
	err = initBuffer(b, capacity)
	return
}

func (b *buffer) verifyOffset(off int64) error {
	if !(b.start <= off && off <= b.end) {
		return errOffset
	}
	return nil
}

func (b *buffer) readOff(p []byte, off int64) {
	for len(p) > 0 {
		s := b.index(off)
		m := copy(p, b.data[s:])
		off += int64(m)
		p = p[m:]
	}
}

func (b *buffer) ReadAt(p []byte, off int64) (n int, err error) {
	if off < b.start {
		return 0, errOffset
	}
	k := b.end - off
	n = len(p)
	if k < int64(n) {
		if k < 0 {
			return 0, errOffset
		}
		if b.closed {
			err = io.EOF
		} else {
			err = errAgain
		}
		n = int(k)
	}
	b.readOff(p[:n], off)
	return
}

func (b *buffer) Read(p []byte) (n int, err error) {
	k := b.end - b.cursor
	n = len(p)
	if k < int64(n) {
		if k < 0 {
			panic("wrong b.cursor")
		}
		if k == 0 && b.closed {
			return 0, io.EOF
		}
		n = int(k)
	}
	b.readOff(p[:n], b.cursor)
	b.cursor += int64(n)
	return
}

func (b *buffer) Discard(n int) (discarded int, err error) {
	if n < 0 {
		return 0, errNegLen
	}
	k := b.end - b.cursor
	if k < int64(n) {
		if k < 0 {
			panic("wrong b.cursor")
		}
		if b.closed {
			err = io.EOF
		} else {
			err = errAgain
		}
		n = int(k)
	}
	discarded = n
	b.cursor += int64(n)
	return
}

func (b *buffer) copyNOff(w io.Writer, n int, off int64) (copied int, err error) {
	start, end := off, off+int64(n)
	e := b.index(end)
	for off < end {
		s := b.index(off)
		var q []byte
		if s < e {
			q = b.data[s:e]
		} else {
			q = b.data[s:]
		}
		var m int
		m, err = w.Write(q)
		off += int64(m)
		if err != nil {
			break
		}
	}
	return int(off - start), err
}

func (b *buffer) CopyAt(w io.Writer, n int, off int64) (copied int, err error) {
	if n < 0 {
		return 0, errNegLen
	}
	if off < b.start {
		return 0, errOffset
	}
	k := b.end - off
	if k < int64(n) {
		if k < 0 {
			return 0, errOffset
		}
		if b.closed {
			err = io.EOF
		} else {
			err = errAgain
		}
		n = int(k)
	}
	var cerr error
	copied, cerr = b.copyNOff(w, n, off)
	if cerr != nil {
		err = cerr
	}
	return
}

func (b *buffer) Copy(w io.Writer, n int) (copied int, err error) {
	if n < 0 {
		return 0, errNegLen
	}
	k := b.end - b.cursor
	if k < int64(n) {
		if k < 0 {
			panic("wrong b.cursor")
		}
		if k == 0 && b.closed {
			return 0, io.EOF
		}
		n = int(k)
	}
	copied, err = b.copyNOff(w, n, b.cursor)
	b.cursor += int64(copied)
	return
}

func (b *buffer) ReadByteAt(off int64) (c byte, err error) {
	if !(b.start <= off && off <= b.end) {
		return 0, errOffset
	}
	if off == b.end {
		if b.closed {
			return 0, io.EOF
		}
		return 0, errAgain
	}
	i := b.index(off)
	return b.data[i], nil
}

func (b *buffer) ReadByte() (c byte, err error) {
	if b.cursor == b.end {
		if b.closed {
			return 0, io.EOF
		}
		return 0, errAgain
	}
	i := b.index(b.cursor)
	b.cursor++
	return b.data[i], nil
}

func (b *buffer) writeSlice(p []byte) {
	off := b.end
	for len(p) > 0 {
		i := b.index(off)
		m := copy(b.data[i:], p)
		off += int64(m)
		if off < 0 {
			panic("overflow b.end")
		}
		p = p[m:]
	}
	b.setEnd(off)
}

func (b *buffer) Write(p []byte) (n int, err error) {
	if b.closed {
		return 0, errClosedBuffer
	}
	n = b.Writable()
	if n < len(p) {
		err = errAgain
		p = p[:n]
	}
	b.writeSlice(p)
	return
}

func (b *buffer) WriteByte(c byte) error {
	if b.closed {
		return errClosedBuffer
	}
	if b.Writable() < 1 {
		return errAgain
	}
	i := b.index(b.end)
	b.data[i] = c
	b.setEnd(b.end + 1)
	return nil
}

func (b *buffer) WriteRepOff(n int, off int64) (written int, err error) {
	if n < 0 {
		return 0, errNegLen
	}
	if b.closed {
		return 0, errClosedBuffer
	}
	if !(b.start <= off && off < b.end) {
		return 0, errOffset
	}
	if b.Writable() < n {
		return 0, errAgain
	}
	end := off + int64(n)
	e := b.index(end)
	for off < end {
		s := b.index(off)
		var t int
		if end > b.end {
			t = b.index(b.end)
		} else {
			t = e
		}
		var q []byte
		if s < t {
			q = b.data[s:t]
		} else {
			q = b.data[s:]
		}
		b.writeSlice(q)
		off += int64(len(q))
	}
	return n, nil
}

func (b *buffer) Close() error {
	b.closed = true
	return nil
}

func (b *buffer) EqualBytes(off1, off2 int64, max int) int {
	if off1 < b.start || off2 < b.start {
		return 0
	}
	n := b.end - off1
	if n < int64(max) {
		if n < 1 {
			return 0
		}
		max = int(n)
	}
	n = b.end - off2
	if n < int64(max) {
		if n < 1 {
			return 0
		}
		max = int(n)
	}
	for k := 0; k < max; k++ {
		i, j := b.index(off1+int64(k)), b.index(off2+int64(k))
		if b.data[i] != b.data[j] {
			return k
		}
	}
	return max
}
<commit_msg>lzma: added documentation to the buffer code<commit_after>package lzma

import "io"

// buffer implements a ring buffer with features to support an LZMA reader and
// writer dictionary.
//
// The ring buffer supports writing at the end offset and writing at the cursor
// offset. The field start stores the start offset of the buffer, but could be
// computed by b.end - b.Cap().
//
// The reader dictionary will have the head at the end offset the writer
// dictionary will have the head at the cursor offset.
type buffer struct {
	// plain constant length field to store the data
	data []byte
	// start offset of the buffer; b.end - len(b.data)
	start int64
	// offset for reading
	cursor int64
	// end offset of the current buffer window; use setEnd method for
	// updates
	end int64
	// writeLimit gives the maximum distance between end and cursor
	writeLimit int
	// marks the buffer as closed for writing
	closed bool
}

// errors generated by the ring buffer functions
var (
	errOffset       = newError("offset outside buffer range")
	errAgain        = newError("buffer exceeded; repeat")
	errNegLen       = newError("length is negative")
	errNrOverflow   = newError("number overflow")
	errCapacity     = newError("capacity must be larger than zero")
	errClosedBuffer = newError("buffer is closed for writing")
)

// Cap returns the capacity of the ring buffer.
func (b *buffer) Cap() int {
	return len(b.data)
}

// Len returns the data amount currently stored in the buffer. It will grow
// from zero to the capacity of the buffer.
func (b *buffer) Len() int {
	return int(b.end - b.start)
}

// Readable returns the number of bytes that are currently available for
// reading.
func (b *buffer) Readable() int {
	return int(b.end - b.cursor)
}

// Writable returns the number of byte that are curently available for writing.
func (b *buffer) Writable() int {
	return int(b.cursor + int64(b.writeLimit) - b.end)
}

// setEnd updates the start and end fields. Use it always to update the end
// field.
func (b *buffer) setEnd(x int64) {
	if x < 0 {
		panic("b.end overflow?")
	}
	b.end = x
	b.start = x - int64(len(b.data))
	if b.start < 0 {
		b.start = 0
	}
}

// index computes the index into the data slice for a particular offset.
func (b *buffer) index(off int64) int {
	if off < 0 {
		panic("negative offsets are not supported")
	}
	return int(off % int64(len(b.data)))
}

// initBuffer initializes an already allocated buffer.
func initBuffer(b *buffer, capacity int) error {
	if capacity <= 0 {
		return errCapacity
	}
	*b = buffer{data: make([]byte, capacity), writeLimit: capacity}
	return nil
}

// newBuffer creates a new buffer instance.
func newBuffer(capacity int) (b *buffer, err error) {
	b = new(buffer)
	err = initBuffer(b, capacity)
	return
}

// readOff is a helper method for the ReadAt and Read methods.
func (b *buffer) readOff(p []byte, off int64) {
	for len(p) > 0 {
		s := b.index(off)
		m := copy(p, b.data[s:])
		off += int64(m)
		p = p[m:]
	}
}

// ReadAt reads data into p at the specified offset. The offset must be inside
// the buffer. It the slice cannot be completely filed errAgain is reported
// unless the buffer is not closed. In that case the function returns io.EOF.
func (b *buffer) ReadAt(p []byte, off int64) (n int, err error) {
	if off < b.start {
		return 0, errOffset
	}
	k := b.end - off
	n = len(p)
	if k < int64(n) {
		if k < 0 {
			return 0, errOffset
		}
		if b.closed {
			err = io.EOF
		} else {
			err = errAgain
		}
		n = int(k)
	}
	b.readOff(p[:n], off)
	return
}

// Read tries to read data into the buffer. No error is returned if n < len(p).
func (b *buffer) Read(p []byte) (n int, err error) {
	k := b.end - b.cursor
	n = len(p)
	if k < int64(n) {
		if k < 0 {
			panic("wrong b.cursor")
		}
		if k == 0 && b.closed {
			return 0, io.EOF
		}
		n = int(k)
	}
	b.readOff(p[:n], b.cursor)
	b.cursor += int64(n)
	return
}

// Discard skips n bytes of reading bytes. If less than n bytes are skipped
// errAgain or io.EOF if closed is returned.
func (b *buffer) Discard(n int) (discarded int, err error) {
	if n < 0 {
		return 0, errNegLen
	}
	k := b.end - b.cursor
	if k < int64(n) {
		if k < 0 {
			panic("wrong b.cursor")
		}
		if b.closed {
			err = io.EOF
		} else {
			err = errAgain
		}
		n = int(k)
	}
	discarded = n
	b.cursor += int64(n)
	return
}

// copyNOff is a helper method for CopyAt and Copy.
func (b *buffer) copyNOff(w io.Writer, n int, off int64) (copied int, err error) {
	start, end := off, off+int64(n)
	e := b.index(end)
	for off < end {
		s := b.index(off)
		var q []byte
		if s < e {
			q = b.data[s:e]
		} else {
			q = b.data[s:]
		}
		var m int
		m, err = w.Write(q)
		off += int64(m)
		if err != nil {
			break
		}
	}
	return int(off - start), err
}

// CopyAt behaves like ReadAt but writes the data into the writer.
func (b *buffer) CopyAt(w io.Writer, n int, off int64) (copied int, err error) {
	if n < 0 {
		return 0, errNegLen
	}
	if off < b.start {
		return 0, errOffset
	}
	k := b.end - off
	if k < int64(n) {
		if k < 0 {
			return 0, errOffset
		}
		if b.closed {
			err = io.EOF
		} else {
			err = errAgain
		}
		n = int(k)
	}
	var cerr error
	copied, cerr = b.copyNOff(w, n, off)
	if cerr != nil {
		err = cerr
	}
	return
}

// Copy behaves like read but the data is written into the writer.
func (b *buffer) Copy(w io.Writer, n int) (copied int, err error) {
	if n < 0 {
		return 0, errNegLen
	}
	k := b.end - b.cursor
	if k < int64(n) {
		if k < 0 {
			panic("wrong b.cursor")
		}
		if k == 0 && b.closed {
			return 0, io.EOF
		}
		n = int(k)
	}
	copied, err = b.copyNOff(w, n, b.cursor)
	b.cursor += int64(copied)
	return
}

// ReadByteAt reads a single byte at the given offset.
func (b *buffer) ReadByteAt(off int64) (c byte, err error) {
	if !(b.start <= off && off <= b.end) {
		return 0, errOffset
	}
	if off == b.end {
		if b.closed {
			return 0, io.EOF
		}
		return 0, errAgain
	}
	i := b.index(off)
	return b.data[i], nil
}

// ReadByte reads a single byte.
func (b *buffer) ReadByte() (c byte, err error) {
	if b.cursor == b.end {
		if b.closed {
			return 0, io.EOF
		}
		return 0, errAgain
	}
	i := b.index(b.cursor)
	b.cursor++
	return b.data[i], nil
}

// writeSlice writes the slice p unconditionally into the buffer.
func (b *buffer) writeSlice(p []byte) {
	off := b.end
	for len(p) > 0 {
		i := b.index(off)
		m := copy(b.data[i:], p)
		off += int64(m)
		if off < 0 {
			panic("overflow b.end")
		}
		p = p[m:]
	}
	b.setEnd(off)
}

// Writes data into the buffer. If n < len(p) errAgain is returned. If the
// buffer is closed errClosedBuffer is returned.
func (b *buffer) Write(p []byte) (n int, err error) {
	if b.closed {
		return 0, errClosedBuffer
	}
	n = b.Writable()
	if n < len(p) {
		err = errAgain
		p = p[:n]
	}
	b.writeSlice(p)
	return
}

// Writes a single byte into the buffer.
func (b *buffer) WriteByte(c byte) error {
	if b.closed {
		return errClosedBuffer
	}
	if b.Writable() < 1 {
		return errAgain
	}
	i := b.index(b.end)
	b.data[i] = c
	b.setEnd(b.end + 1)
	return nil
}

// WriteRepOff writes a match at the given offset into the buffer.
func (b *buffer) WriteRepOff(n int, off int64) (written int, err error) {
	if n < 0 {
		return 0, errNegLen
	}
	if b.closed {
		return 0, errClosedBuffer
	}
	if !(b.start <= off && off < b.end) {
		return 0, errOffset
	}
	if b.Writable() < n {
		return 0, errAgain
	}
	end := off + int64(n)
	e := b.index(end)
	for off < end {
		s := b.index(off)
		var t int
		if end > b.end {
			t = b.index(b.end)
		} else {
			t = e
		}
		var q []byte
		if s < t {
			q = b.data[s:t]
		} else {
			q = b.data[s:]
		}
		b.writeSlice(q)
		off += int64(len(q))
	}
	return n, nil
}

// Close closes the buffer.
func (b *buffer) Close() error {
	b.closed = true
	return nil
}

// EqualBytes count the equal bytes at off1 and off2 until max is reached.
func (b *buffer) EqualBytes(off1, off2 int64, max int) int {
	if off1 < b.start || off2 < b.start {
		return 0
	}
	if max < 0 {
		return 0
	}
	n := b.end - off1
	if n < int64(max) {
		if n < 1 {
			return 0
		}
		max = int(n)
	}
	n = b.end - off2
	if n < int64(max) {
		if n < 1 {
			return 0
		}
		max = int(n)
	}
	for k := 0; k < max; k++ {
		i, j := b.index(off1+int64(k)), b.index(off2+int64(k))
		if b.data[i] != b.data[j] {
			return k
		}
	}
	return max
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"log"
	"net"
	"net/mail"
	"os"
	"strings"

	"github.com/mhale/smtpd"
	"github.com/nlopes/slack"
	"github.com/veqryn/go-email/email"
)

var (
	port         = os.Getenv("PORT")
	slackToken   = os.Getenv("SLACK_TOKEN")
	slackChannel = os.Getenv("SLACK_CHANNEL")
	domainList   = os.Getenv("DOMAIN_LIST")
	filetype     string
)

func mailHandler(origin net.Addr, from string, to []string, data []byte) {
	msg, _ := email.ParseMessage(bytes.NewReader(data))
	subject := msg.Header.Get("Subject")
	sender := msg.Header.Get("From")
	recipient := msg.Header.Get("To")

	// If we have been given a list of recipient domains, filter on these
	if len(domainList) > 0 {
		domains := strings.Split(domainList, ",")
		rcpt, _ := mail.ParseAddress(recipient)
		recipientDomain := strings.Split(rcpt.Address, "@")[1]
		ok := false
		for i := 0; i < len(domains); i++ {
			if recipientDomain == domains[i] {
				ok = true
				break
			}
		}
		if !ok {
			return
		}
	}
	api := slack.New(slackToken)
	for _, part := range msg.MessagesContentTypePrefix("text/plain") {
		uploadparams := slack.FileUploadParameters{
			Channels:       []string{slackChannel},
			Title:          fmt.Sprintf("Subject: %s", subject),
			Filetype:       "text",
			Content:        string(part.Body),
			InitialComment: fmt.Sprintf("To: %s\nFrom: %s", recipient, sender),
		}
		file, err := api.UploadFile(uploadparams)
		if err != nil {
			log.Fatal(err)
			return
		}
		log.Printf("Message successfully sent to channel %s as text file %s", slackChannel, file.Name)
	}
	for _, part := range msg.MessagesContentTypePrefix("text/html") {
		uploadparams := slack.FileUploadParameters{
			Channels:       []string{slackChannel},
			Title:          fmt.Sprintf("Subject: %s", subject),
			Filetype:       "html",
			Content:        string(part.Body),
			InitialComment: fmt.Sprintf("To: %s\nFrom: %s", recipient, sender),
		}
		file, err := api.UploadFile(uploadparams)
		if err != nil {
			log.Fatal(err)
			return
		}
		log.Printf("Message successfully sent to channel %s as HTML file %s", slackChannel, file.Name)
	}
}

func main() {
	if port == "" {
		port = "2525"
		log.Printf("No PORT found, defaulting to %s", port)
	}
	if slackToken == "" {
		log.Fatal("No SLACK_TOKEN found")
		return
	}
	if slackChannel == "" {
		log.Fatal("No SLACK_CHANNEL found")
		return
	}
	log.Printf("Listening for mail on port %s", port)
	smtpd.ListenAndServe(fmt.Sprintf("0.0.0.0:%s", port), mailHandler, "Sendmail 8.11.3", "")
}
<commit_msg>add better error handling<commit_after>package main

import (
	"bytes"
	"fmt"
	"log"
	"net"
	"net/mail"
	"os"
	"strings"

	"github.com/mhale/smtpd"
	"github.com/nlopes/slack"
	"github.com/veqryn/go-email/email"
)

var (
	port         = os.Getenv("PORT")
	slackToken   = os.Getenv("SLACK_TOKEN")
	slackChannel = os.Getenv("SLACK_CHANNEL")
	domainList   = os.Getenv("DOMAIN_LIST")
	filetype     string
)

func mailHandler(origin net.Addr, from string, to []string, data []byte) {
	msg, err := email.ParseMessage(bytes.NewReader(data))
	if err != nil {
		log.Printf("error parsing message: %s", err)
		return
	}
	subject := msg.Header.Get("Subject")
	sender := msg.Header.Get("From")
	recipient := msg.Header.Get("To")

	// If we have been given a list of recipient domains, filter on these
	if len(domainList) > 0 {
		domains := strings.Split(domainList, ",")
		rcpt, err := mail.ParseAddress(recipient)
		if err != nil {
			log.Printf("error parsing recipient email '%s' : %s", recipient, err)
			return
		}
		recipientDomain := strings.Split(rcpt.Address, "@")[1]
		ok := false
		for i := 0; i < len(domains); i++ {
			if recipientDomain == domains[i] {
				ok = true
				break
			}
		}
		if !ok {
			log.Printf("skipping, as recipient domain '%s' is not in whitelist", recipientDomain)
			return
		}
	}
	api := slack.New(slackToken)
	for _, part := range msg.MessagesContentTypePrefix("text/plain") {
		uploadparams := slack.FileUploadParameters{
			Channels:       []string{slackChannel},
			Title:          fmt.Sprintf("Subject: %s", subject),
			Filetype:       "text",
			Content:        string(part.Body),
			InitialComment: fmt.Sprintf("To: %s\nFrom: %s", recipient, sender),
		}
		file, err := api.UploadFile(uploadparams)
		if err != nil {
			log.Printf("failed to upload plaintext file: %s", err)
			return
		}
		log.Printf("Message successfully sent to channel %s as text file %s", slackChannel, file.Name)
	}
	for _, part := range msg.MessagesContentTypePrefix("text/html") {
		uploadparams := slack.FileUploadParameters{
			Channels:       []string{slackChannel},
			Title:          fmt.Sprintf("Subject: %s", subject),
			Filetype:       "html",
			Content:        string(part.Body),
			InitialComment: fmt.Sprintf("To: %s\nFrom: %s", recipient, sender),
		}
		file, err := api.UploadFile(uploadparams)
		if err != nil {
			log.Printf("failed to upload html file: %s", err)
			return
		}
		log.Printf("Message successfully sent to channel %s as HTML file %s", slackChannel, file.Name)
	}
}

func main() {
	if port == "" {
		port = "2525"
		log.Printf("No PORT found, defaulting to %s", port)
	}
	if slackToken == "" {
		log.Fatal("No SLACK_TOKEN found")
	}
	if slackChannel == "" {
		log.Fatal("No SLACK_CHANNEL found")
	}
	log.Printf("Listening for mail on port %s", port)
	smtpd.ListenAndServe(fmt.Sprintf("0.0.0.0:%s", port), mailHandler, "Sendmail 8.11.3", "")
}
<|endoftext|>


<commit_before>package admin

import (
	"github.com/qor/qor"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/rules"

	"reflect"
	"regexp"
	"strings"
)

type resourcer interface {
	AllAttrs() []*resource.Meta
}

func ConvertMapToMetaValues(values map[string]interface{}, res resourcer) (metaValues *resource.MetaValues) {
	metas := make(map[string]resource.Metaor)
	if res != nil {
		for _, attr := range res.AllAttrs() {
			metas[attr.Name] = attr
		}
	}

	metaValues = new(resource.MetaValues)
	for key, value := range values {
		meta := metas[key]
		if str, ok := value.(string); ok {
			metaValue := &resource.MetaValue{Name: key, Value: str, Meta: meta}
			metaValues.Values = append(metaValues.Values, metaValue)
		} else {
			var res resourcer
			if meta != nil && meta.GetMeta() != nil && meta.GetMeta().Resource != nil {
				res, _ = meta.GetMeta().Resource.(resourcer)
			}

			if vs, ok := value.(map[string]interface{}); ok {
				children := ConvertMapToMetaValues(vs, res)
				metaValue := &resource.MetaValue{Name: key, Meta: meta, MetaValues: children}
				metaValues.Values = append(metaValues.Values, metaValue)
			} else if vs, ok := value.([]interface{}); ok {
				for _, v := range vs {
					if mv, ok := v.(map[string]interface{}); ok {
						children := ConvertMapToMetaValues(mv, res)
						metaValue := &resource.MetaValue{Name: key, Meta: meta, MetaValues: children}
						metaValues.Values = append(metaValues.Values, metaValue)
					} else if meta != nil {
						metaValue := &resource.MetaValue{Name: key, Value: vs, Meta: meta}
						metaValues.Values = append(metaValues.Values, metaValue)
						break
					}
				}
			} else {
				switch reflect.ValueOf(value).Kind() {
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
					metaValue := &resource.MetaValue{Name: key, Value: str, Meta: meta}
					metaValues.Values = append(metaValues.Values, metaValue)
				default:
					panic("doesn't support this type")
				}
			}
		}
	}
	return
}

func ConvertFormToMetaValues(context *qor.Context, prefix string, res *Resource) (metaValues *resource.MetaValues) {
	request := context.Request
	convertedMap := make(map[string]bool)
	metas := make(map[string]resource.Metaor)
	if res != nil {
		for _, attr := range res.AllAttrs() {
			metas[attr.Name] = attr
		}
	}

	metaValues = new(resource.MetaValues)
	for key := range request.Form {
		if strings.HasPrefix(key, prefix) {
			key = strings.TrimPrefix(key, prefix)
			isCurrent := regexp.MustCompile("^[^.]+$")
			isNext := regexp.MustCompile(`^(([^.\[\]]+)(\[\d+\])?)(?:\.([^.]+)+)$`)

			if matches := isCurrent.FindStringSubmatch(key); len(matches) > 0 {
				meta := metas[matches[0]]
				metaValue := &resource.MetaValue{Name: matches[0], Value: request.Form[prefix+key], Meta: meta}
				metaValues.Values = append(metaValues.Values, metaValue)
			} else if matches := isNext.FindStringSubmatch(key); len(matches) > 0 {
				if _, ok := convertedMap[matches[1]]; !ok {
					convertedMap[matches[1]] = true
					meta := metas[matches[2]]
					var res *Resource
					if meta != nil && meta.GetMeta() != nil {
						res = meta.GetMeta().Resource.(*Resource)
					}
					children := ConvertFormToMetaValues(context, prefix+matches[1]+".", res)
					metaValue := &resource.MetaValue{Name: matches[2], Meta: meta, MetaValues: children}
					metaValues.Values = append(metaValues.Values, metaValue)
				}
			}
		}
	}

	if request.MultipartForm != nil {
		// for key, header := range request.MultipartForm.File {
		// xxxxx
		// }
	}
	return
}

func ConvertObjectToMap(context *qor.Context, object interface{}, res *Resource) interface{} {
	reflectValue := reflect.Indirect(reflect.ValueOf(object))
	switch reflectValue.Kind() {
	case reflect.Slice:
		len := reflectValue.Len()
		values := []interface{}{}
		for i := 0; i < len; i++ {
			values = append(values, ConvertObjectToMap(context, reflectValue.Index(i).Interface(), res))
		}
		return values
	case reflect.Struct:
		values := map[string]interface{}{}
		metas := res.ShowMetas()
		for _, meta := range metas {
			if meta.HasPermission(rules.Read, context) {
				value := meta.Value(object, context)
				if res, ok := meta.Resource.(*Resource); ok {
					value = ConvertObjectToMap(context, value, res)
				}
				values[meta.Name] = value
			}
		}
		return values
	default:
		panic("can't convert object to map")
	}
}
<commit_msg>Fix ConvertMapToMetaValues for some data type<commit_after>package admin

import (
	"github.com/qor/qor"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/rules"

	"reflect"
	"regexp"
	"strings"
)

type resourcer interface {
	AllAttrs() []*resource.Meta
}

func ConvertMapToMetaValues(values map[string]interface{}, res resourcer) (metaValues *resource.MetaValues) {
	metas := make(map[string]resource.Metaor)
	if res != nil {
		for _, attr := range res.AllAttrs() {
			metas[attr.Name] = attr
		}
	}

	metaValues = new(resource.MetaValues)
	for key, value := range values {
		meta := metas[key]
		if str, ok := value.(string); ok {
			metaValue := &resource.MetaValue{Name: key, Value: str, Meta: meta}
			metaValues.Values = append(metaValues.Values, metaValue)
		} else {
			var res resourcer
			if meta != nil && meta.GetMeta() != nil && meta.GetMeta().Resource != nil {
				res, _ = meta.GetMeta().Resource.(resourcer)
			}

			if vs, ok := value.(map[string]interface{}); ok {
				children := ConvertMapToMetaValues(vs, res)
				metaValue := &resource.MetaValue{Name: key, Meta: meta, MetaValues: children}
				metaValues.Values = append(metaValues.Values, metaValue)
			} else if vs, ok := value.([]interface{}); ok {
				for _, v := range vs {
					if mv, ok := v.(map[string]interface{}); ok {
						children := ConvertMapToMetaValues(mv, res)
						metaValue := &resource.MetaValue{Name: key, Meta: meta, MetaValues: children}
						metaValues.Values = append(metaValues.Values, metaValue)
					} else if meta != nil {
						metaValue := &resource.MetaValue{Name: key, Value: vs, Meta: meta}
						metaValues.Values = append(metaValues.Values, metaValue)
						break
					}
				}
			} else {
				switch reflect.ValueOf(value).Kind() {
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
					metaValue := &resource.MetaValue{Name: key, Value: value, Meta: meta}
					metaValues.Values = append(metaValues.Values, metaValue)
				default:
					panic("doesn't support this type")
				}
			}
		}
	}
	return
}

func ConvertFormToMetaValues(context *qor.Context, prefix string, res *Resource) (metaValues *resource.MetaValues) {
	request := context.Request
	convertedMap := make(map[string]bool)
	metas := make(map[string]resource.Metaor)
	if res != nil {
		for _, attr := range res.AllAttrs() {
			metas[attr.Name] = attr
		}
	}

	metaValues = new(resource.MetaValues)
	for key := range request.Form {
		if strings.HasPrefix(key, prefix) {
			key = strings.TrimPrefix(key, prefix)
			isCurrent := regexp.MustCompile("^[^.]+$")
			isNext := regexp.MustCompile(`^(([^.\[\]]+)(\[\d+\])?)(?:\.([^.]+)+)$`)

			if matches := isCurrent.FindStringSubmatch(key); len(matches) > 0 {
				meta := metas[matches[0]]
				metaValue := &resource.MetaValue{Name: matches[0], Value: request.Form[prefix+key], Meta: meta}
				metaValues.Values = append(metaValues.Values, metaValue)
			} else if matches := isNext.FindStringSubmatch(key); len(matches) > 0 {
				if _, ok := convertedMap[matches[1]]; !ok {
					convertedMap[matches[1]] = true
					meta := metas[matches[2]]
					var res *Resource
					if meta != nil && meta.GetMeta() != nil {
						res = meta.GetMeta().Resource.(*Resource)
					}
					children := ConvertFormToMetaValues(context, prefix+matches[1]+".", res)
					metaValue := &resource.MetaValue{Name: matches[2], Meta: meta, MetaValues: children}
					metaValues.Values = append(metaValues.Values, metaValue)
				}
			}
		}
	}

	if request.MultipartForm != nil {
		// for key, header := range request.MultipartForm.File {
		// xxxxx
		// }
	}
	return
}

func ConvertObjectToMap(context *qor.Context, object interface{}, res *Resource) interface{} {
	reflectValue := reflect.Indirect(reflect.ValueOf(object))
	switch reflectValue.Kind() {
	case reflect.Slice:
		len := reflectValue.Len()
		values := []interface{}{}
		for i := 0; i < len; i++ {
			values = append(values, ConvertObjectToMap(context, reflectValue.Index(i).Interface(), res))
		}
		return values
	case reflect.Struct:
		values := map[string]interface{}{}
		metas := res.ShowMetas()
		for _, meta := range metas {
			if meta.HasPermission(rules.Read, context) {
				value := meta.Value(object, context)
				if res, ok := meta.Resource.(*Resource); ok {
					value = ConvertObjectToMap(context, value, res)
				}
				values[meta.Name] = value
			}
		}
		return values
	default:
		panic("can't convert object to map")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"../interpreter"
	"../lua"
)

func optionParse(L *lua.Lua) bool {
	optionK := flag.String("k", "", "like `cmd /k`")
	optionC := flag.String("c", "", "like `cmd /c`")
	optionF := flag.String("f", "", "run lua script")
	optionE := flag.String("e", "", "run inline-lua-code")

	flag.Parse()

	result := true

	if *optionK != "" {
		interpreter.New().Interpret(*optionK)
	}
	if *optionC != "" {
		interpreter.New().Interpret(*optionC)
		result = false
	}
	if *optionF != "" {
		L.NewTable()
		L.PushString(*optionF)
		L.RawSetI(-2, 0)
		for i, arg1 := range flag.Args() {
			L.PushString(arg1)
			L.RawSetI(-2, lua.Integer(i))
		}
		L.SetGlobal("arg")
		err := L.Source(*optionF)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		result = false
	}
	if *optionE != "" {
		err := L.LoadString(*optionE)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		} else {
			L.Call(0, 0)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
			}
		}
		result = false
	}
	return result
}
<commit_msg>On -f SCRIPTFILE, lua's arg[] was shifted.<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"../interpreter"
	"../lua"
)

func optionParse(L *lua.Lua) bool {
	optionK := flag.String("k", "", "like `cmd /k`")
	optionC := flag.String("c", "", "like `cmd /c`")
	optionF := flag.String("f", "", "run lua script")
	optionE := flag.String("e", "", "run inline-lua-code")

	flag.Parse()

	result := true

	if *optionK != "" {
		interpreter.New().Interpret(*optionK)
	}
	if *optionC != "" {
		interpreter.New().Interpret(*optionC)
		result = false
	}
	if *optionF != "" {
		L.NewTable()
		L.PushString(*optionF)
		L.RawSetI(-2, 0)
		for i, arg1 := range flag.Args() {
			L.PushString(arg1)
			L.RawSetI(-2, lua.Integer(i+1))
		}
		L.SetGlobal("arg")
		err := L.Source(*optionF)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		result = false
	}
	if *optionE != "" {
		err := L.LoadString(*optionE)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		} else {
			L.Call(0, 0)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
			}
		}
		result = false
	}
	return result
}
<|endoftext|>


<commit_before>package network

import (
	"fmt"
	"strings"

	"github.com/quilt/quilt/db"
	"github.com/quilt/quilt/join"
	"github.com/quilt/quilt/minion/ovsdb"
	"github.com/quilt/quilt/stitch"

	log "github.com/Sirupsen/logrus"
)

type aclKey struct {
	drop  bool
	match string
}

func directedACLs(acl ovsdb.ACL) (res []ovsdb.ACL) {
	for _, dir := range []string{"from-lport", "to-lport"} {
		res = append(res, ovsdb.ACL{
			Core: ovsdb.ACLCore{
				Direction: dir,
				Action:    acl.Core.Action,
				Match:     acl.Core.Match,
				Priority:  acl.Core.Priority,
			},
		})
	}
	return res
}

func updateACLs(ovsdbClient ovsdb.Client, connections []db.Connection,
	hostnameToIP map[string]string) {
	ovsdbACLs, err := ovsdbClient.ListACLs()
	if err != nil {
		log.WithError(err).Error("Failed to list ACLs")
		return
	}

	expACLs := directedACLs(ovsdb.ACL{
		Core: ovsdb.ACLCore{
			Action:   "drop",
			Match:    "ip",
			Priority: 0,
		},
	})

	for _, conn := range connections {
		if conn.From == stitch.PublicInternetLabel ||
			conn.To == stitch.PublicInternetLabel {
			continue
		}

		src := hostnameToIP[conn.From]
		dst := hostnameToIP[conn.To]
		if src == "" || dst == "" {
			log.WithField("connection", conn).Warn("Unknown hostname " +
				"in ACL. Ignoring")
			continue
		}

		matchStr := getMatchString(src, dst, conn.MinPort, conn.MaxPort)
		expACLs = append(expACLs, directedACLs(
			ovsdb.ACL{
				Core: ovsdb.ACLCore{
					Action:   "allow",
					Match:    matchStr,
					Priority: 1,
				},
			})...)
	}

	ovsdbKey := func(ovsdbIntf interface{}) interface{} {
		return ovsdbIntf.(ovsdb.ACL).Core
	}
	_, toCreate, toDelete := join.HashJoin(ovsdbACLSlice(expACLs),
		ovsdbACLSlice(ovsdbACLs), ovsdbKey, ovsdbKey)

	for _, acl := range toDelete {
		if err := ovsdbClient.DeleteACL(lSwitch, acl.(ovsdb.ACL)); err != nil {
			log.WithError(err).Warn("Error deleting ACL")
		}
	}

	for _, intf := range toCreate {
		acl := intf.(ovsdb.ACL).Core
		if err := ovsdbClient.CreateACL(lSwitch, acl.Direction,
			acl.Priority, acl.Match, acl.Action); err != nil {
			log.WithError(err).Warn("Error adding ACL")
		}
	}
}

func getMatchString(srcIP, dstIP string, minPort, maxPort int) string {
	return or(
		and(
			and(from(srcIP), to(dstIP)),
			portConstraint(minPort, maxPort, "dst")),
		and(
			and(from(dstIP), to(srcIP)),
			portConstraint(minPort, maxPort, "src")))
}

func portConstraint(minPort, maxPort int, direction string) string {
	return fmt.Sprintf("(icmp || %[1]d <= udp.%[2]s <= %[3]d || "+
		"%[1]d <= tcp.%[2]s <= %[3]d)", minPort, direction, maxPort)
}

func from(ip string) string {
	return fmt.Sprintf("ip4.src == %s", ip)
}

func to(ip string) string {
	return fmt.Sprintf("ip4.dst == %s", ip)
}

func or(predicates ...string) string {
	return "(" + strings.Join(predicates, " || ") + ")"
}

func and(predicates ...string) string {
	return "(" + strings.Join(predicates, " && ") + ")"
}

// ovsdbACLSlice is a wrapper around []ovsdb.ACL to allow us to perform a join
type ovsdbACLSlice []ovsdb.ACL

// Len returns the length of the slice
func (slc ovsdbACLSlice) Len() int {
	return len(slc)
}

// Get returns the element at index i of the slice
func (slc ovsdbACLSlice) Get(i int) interface{} {
	return slc[i]
}
<commit_msg>network: Log unknown hostname error at Debug<commit_after>package network

import (
	"fmt"
	"strings"

	"github.com/quilt/quilt/db"
	"github.com/quilt/quilt/join"
	"github.com/quilt/quilt/minion/ovsdb"
	"github.com/quilt/quilt/stitch"

	log "github.com/Sirupsen/logrus"
)

type aclKey struct {
	drop  bool
	match string
}

func directedACLs(acl ovsdb.ACL) (res []ovsdb.ACL) {
	for _, dir := range []string{"from-lport", "to-lport"} {
		res = append(res, ovsdb.ACL{
			Core: ovsdb.ACLCore{
				Direction: dir,
				Action:    acl.Core.Action,
				Match:     acl.Core.Match,
				Priority:  acl.Core.Priority,
			},
		})
	}
	return res
}

func updateACLs(ovsdbClient ovsdb.Client, connections []db.Connection,
	hostnameToIP map[string]string) {
	ovsdbACLs, err := ovsdbClient.ListACLs()
	if err != nil {
		log.WithError(err).Error("Failed to list ACLs")
		return
	}

	expACLs := directedACLs(ovsdb.ACL{
		Core: ovsdb.ACLCore{
			Action:   "drop",
			Match:    "ip",
			Priority: 0,
		},
	})

	for _, conn := range connections {
		if conn.From == stitch.PublicInternetLabel ||
			conn.To == stitch.PublicInternetLabel {
			continue
		}

		src := hostnameToIP[conn.From]
		dst := hostnameToIP[conn.To]
		if src == "" || dst == "" {
			log.WithField("connection", conn).Debug("Unknown hostname " +
				"in ACL. Ignoring")
			continue
		}

		matchStr := getMatchString(src, dst, conn.MinPort, conn.MaxPort)
		expACLs = append(expACLs, directedACLs(
			ovsdb.ACL{
				Core: ovsdb.ACLCore{
					Action:   "allow",
					Match:    matchStr,
					Priority: 1,
				},
			})...)
	}

	ovsdbKey := func(ovsdbIntf interface{}) interface{} {
		return ovsdbIntf.(ovsdb.ACL).Core
	}
	_, toCreate, toDelete := join.HashJoin(ovsdbACLSlice(expACLs),
		ovsdbACLSlice(ovsdbACLs), ovsdbKey, ovsdbKey)

	for _, acl := range toDelete {
		if err := ovsdbClient.DeleteACL(lSwitch, acl.(ovsdb.ACL)); err != nil {
			log.WithError(err).Warn("Error deleting ACL")
		}
	}

	for _, intf := range toCreate {
		acl := intf.(ovsdb.ACL).Core
		if err := ovsdbClient.CreateACL(lSwitch, acl.Direction,
			acl.Priority, acl.Match, acl.Action); err != nil {
			log.WithError(err).Warn("Error adding ACL")
		}
	}
}

func getMatchString(srcIP, dstIP string, minPort, maxPort int) string {
	return or(
		and(
			and(from(srcIP), to(dstIP)),
			portConstraint(minPort, maxPort, "dst")),
		and(
			and(from(dstIP), to(srcIP)),
			portConstraint(minPort, maxPort, "src")))
}

func portConstraint(minPort, maxPort int, direction string) string {
	return fmt.Sprintf("(icmp || %[1]d <= udp.%[2]s <= %[3]d || "+
		"%[1]d <= tcp.%[2]s <= %[3]d)", minPort, direction, maxPort)
}

func from(ip string) string {
	return fmt.Sprintf("ip4.src == %s", ip)
}

func to(ip string) string {
	return fmt.Sprintf("ip4.dst == %s", ip)
}

func or(predicates ...string) string {
	return "(" + strings.Join(predicates, " || ") + ")"
}

func and(predicates ...string) string {
	return "(" + strings.Join(predicates, " && ") + ")"
}

// ovsdbACLSlice is a wrapper around []ovsdb.ACL to allow us to perform a join
type ovsdbACLSlice []ovsdb.ACL

// Len returns the length of the slice
func (slc ovsdbACLSlice) Len() int {
	return len(slc)
}

// Get returns the element at index i of the slice
func (slc ovsdbACLSlice) Get(i int) interface{} {
	return slc[i]
}
<|endoftext|>


<commit_before><commit_msg>Fixed the multi-line tags and locations meta data pattern (again). The previous version did not stop and recognized locations as tags if the locations preceed the tags.<commit_after><|endoftext|>


<commit_before><commit_msg>fixed unit tests<commit_after><|endoftext|>