<commit_before>package main

import (
 //"math/rand"
 "time"
 "math"
 "fmt"
 //"log"
)
import "github.com/grantHarris/go-nanokontrol2"

//import "github.com/rakyll/portmidi"
import "github.com/lucasb-eyer/go-colorful"
import "github.com/mkb218/go-osc/lib"

// type Fixture struct {
//     b_addr uint8
//     r_addr uint8
//     g_addr uint8
//     b_addr uint8
//     w_addr uint8
// }

// func midiStream() *portmidi.Stream{
//     var stream *portmidi.Stream
//     portmidi.Initialize()
//     if portmidi.CountDevices() == 0{
//         log.Printf("No MIDI controller found")
//     }else{
//         midistream, err := portmidi.NewInputStream(portmidi.DefaultInputDeviceID(), 1024)
//         if err != nil {
//             log.Fatal(err)
//         }
//         stream = midistream
//     }
//     return stream
// }

func makeTimestamp() int64 {
    return time.Now().UnixNano() / (int64(time.Millisecond)/int64(time.Nanosecond))
}

func scale(old_min, old_max, new_min, new_max, value float64) float64{
    return ((value - old_min) / (old_max - old_min) ) * (new_max - new_min) + new_min
}

func main() {

    //in := midiStream()
    n := nanokontrol2.Initialize()

    period := math.Cos(2 * math.Pi) / 2000
    b := make([]byte, 512)

    ip := "127.0.0.1"
    port := "7770"
    address := osc.NewAddress(&ip, &port)

     for{
        // if in != nil{
        //     result, err := in.Poll()
        //     if err != nil {
        //         log.Fatal(err)
        //     }

        //     if result {
        //         msg, err := in.Read(1024)
        //         if err != nil {
        //             log.Fatal(err)
        //         }

        //         for b := range msg {
        //             event := msg[b]
        //             fmt.Println(event.Data1, event.Data2)
        //         }
        //     }
        // }
        fmt.Println(n.Get(16))
        wave := math.Cos(period * float64(makeTimestamp()))
        hue := scale(-1, 1, 0, 360, wave)
        color := colorful.Hsv(hue, 1, 1)

        //fmt.Println(uint8(color.R * 255), uint8(color.G * 255), uint8(color.B * 255))

        b[0] = byte(color.R * 255)
        b[1] = byte(color.G * 255)
        b[2] = byte(color.B * 255)

        message := make(osc.Message, 0)
        message = append(message, osc.Blob(b))

        message.Send(address, "/dmx/universe/1")

        //DMX has a 44Hz max refresh rate
        time.Sleep(time.Second / 44)
    }
}<commit_msg>Fixture struct<commit_after>package main

import (
 //"math/rand"
 "time"
 "math"
 "fmt"
 //"log"
)
import "github.com/grantHarris/go-nanokontrol2"
import "github.com/lucasb-eyer/go-colorful"
import "github.com/mkb218/go-osc/lib"

type Fixture struct {
    R_addr uint8
    G_addr uint8
    B_addr uint8
    W_addr uint8
    brightness_addr uint8
}

func (f *Fixture) Set(buffer []byte, r float64, g float64, b float64){

	if f.brightness_addr != 0{
		buffer[f.brightness_addr] = 255
	}

	/*
		Case where the fixture has a white channel. Subtract the common values
		from each r g b and push to white channel
	*/
	if f.W_addr != 0 && r > 0 && g > 0 && b > 0 {
		common := math.Min(math.Min(r, g), b)
		r = r - common
		g = g - common
		b = b - common
		buffer[f.W_addr] = byte(common * 255)
	}

	buffer[f.R_addr] = byte(r * 255)
	buffer[f.G_addr] = byte(g * 255)
	buffer[f.B_addr] = byte(b * 255)
}

func scale(old_min, old_max, new_min, new_max, value float64) float64{
    return ((value - old_min) / (old_max - old_min) ) * (new_max - new_min) + new_min
}

func main() {
	kitchen_right := Fixture{64, 63, 65, 0, 0}
	kitchen_left := Fixture{74, 73, 75, 0, 0}

    n := nanokontrol2.Initialize()
    b := make([]byte, 512)

    ip := "127.0.0.1"
    port := "7770"

    address := osc.NewAddress(&ip, &port)

    var counter float64
    counter = 0

    var ac float64
    ac = 0

     for{
     	//Hue period
     	per := n.Get(16)
		counter = counter + (per*math.Pi/220)

     	//Hue size
     	width := n.Get(0)
     	width = 360 * width

     	//Alpha period
     	alpha := n.Get(17)
		ac = ac + (alpha*math.Pi/220)

     	//Alpha low
     	alpha_low := n.Get(1)
     	//Alpha high
     	alpha_high := n.Get(2)

        wave := math.Sin(counter) + math.Sin(counter/2)
        hue := scale(-1, 1, 0, width, wave)

        wave_value := math.Sin(ac)
        value := scale(-1, 1, alpha_low, alpha_high, wave_value)

        color := colorful.Hsv(hue, 1, value)
        fmt.Println(uint8(color.R * 255), uint8(color.G * 255), uint8(color.B * 255))

        kitchen_right.Set(b, color.R, color.G, color.B)
        kitchen_left.Set(b, color.R, color.G, color.B)

        message := make(osc.Message, 0)
        message = append(message, osc.Blob(b))
        message.Send(address, "/dmx/universe/1")

        //DMX has a 44Hz max refresh rate
        time.Sleep(time.Second / 44)
    }
}<|endoftext|>


<commit_before>package main

import (
	"errors"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/keybase/client/go/utils"
)

var errKeybaseNotFound = errors.New("failed to find the keybase binary")

// findKeybaseBinary returns the path to a Keybase binary, if it finds it.
func findKeybaseBinary(name string) (string, error) {
	// Is it near the kbnm binary?
	dir, err := utils.BinPath()
	if err == nil {
		path := filepath.Join(dir, name)
		if _, err := os.Stat(path); !os.IsNotExist(err) {
			return path, nil
		}
	}

	// Is it in our PATH?
	path, err := exec.LookPath(name)
	if err == nil {
		return path, nil
	}

	// Last ditch effort!
	path = guessKeybasePath(name)
	if _, err := os.Stat(path); !os.IsNotExist(err) {
		return path, nil
	}

	return "", errKeybaseNotFound
}
<commit_msg>Fix kbnm findBinary (#15841)<commit_after>package main

import (
	"errors"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/keybase/client/go/utils"
)

var errKeybaseNotFound = errors.New("failed to find the keybase binary")

// findKeybaseBinary returns the path to a Keybase binary, if it finds it.
func findKeybaseBinary(name string) (string, error) {
	// Is it near the kbnm binary?
	binPath, err := utils.BinPath()
	if err == nil {
		path := filepath.Join(filepath.Dir(binPath), name)
		if _, err := os.Stat(path); !os.IsNotExist(err) {
			return path, nil
		}
	}

	// Is it in our PATH?
	path, err := exec.LookPath(name)
	if err == nil {
		return path, nil
	}

	// Last ditch effort!
	path = guessKeybasePath(name)
	if _, err := os.Stat(path); !os.IsNotExist(err) {
		return path, nil
	}

	return "", errKeybaseNotFound
}
<|endoftext|>


<commit_before>package lua

var cmdRc = `
func _fallback(name, val)
    if type(val) == 'function' then
        val()
    else
        print val
    end
end

func _is_public(name)
    return _builtins[name] != true and name:sub(1, 1) != '_'
end

func help()
    local funcs = {}
    local vars = {}
    local vkeys = {}
    for name, val in pairs(_G) do
        if _is_public(name) then
            if type(val) == 'function' then
                table.insert(funcs, name)
            else
                vars[name] = val
                table.insert(vkeys, name)
            end
        end
    end
    table.sort(funcs)
    print 'Functions:'
    for _, name in ipairs(funcs) do
        print(name)
    end
    print

    table.sort(vkeys)
    print 'Variables:'
    for _, name in ipairs(vkeys) do
        local val = vars[name]
        print name '=' val
    end
end

func dir()
    local ret = {}
    for name, _ in pairs(_G) do
        if _is_public(name) then
            table.insert(ret, name)
        end
    end
    table.sort(ret)
    return ret
end

local _hook_types = {
    -- TODO: hook memory map?
    -- sys and sys_pre are hardcoded to call hook_sys
    code = cpu.HOOK_CODE,
    block = cpu.HOOK_BLOCK,
    intr = cpu.HOOK_INTR,
    read = cpu.HOOK_MEM_READ,
    write = cpu.HOOK_MEM_WRITE,
    fault = cpu.HOOK_MEM_ERR,
}

func _on_hook(name, fn, start, stop)
    if name == 'sys_pre' then
        return u.hook_sys_add(start, fn, nil)
    end
    if name == 'sys' then
        return u.hook_sys_add(start, nil, fn)
    end
    local type = _hook_types[name]
    if type != nil then
        if start == nil then
            return u.hook_add(type, fn)
        else
            if stop == nil then stop = start end
            return u.hook_add(type, fn, start, stop)
        end
    end
    print 'unimplemented hook type %s' % name
    -- u.on_hook_add(name, fn, start, stop)
end

func off()
    if hh then
        u.hook_del(hh)
        u.hook_sys_del(hh)
        hh = nil
    end
end

func read(addr, size)
    if size == nil then size = 16 end
    return u.mem_read(addr, size)
end

func write(addr, s)
    u.mem_write(addr, s)
end

func maps()
    print 'Memory map:'
    local m = us:Mappings()
    for i in m() do
        print m[i]:String()
    end
end

func map(addr, size, prot)
    if addr == nil then
        maps()
    else
        if prot == nil then prot = cpu.PROT_ALL end
        u.mem_map(addr, size, prot)
    end
end

func asm(src, addr)
    if addr == nil then addr = 0 end
    return u.asm(src, addr)
end

func patch(addr, src)
    local x = asm(src, addr)
    -- autonop
    local total = 0
    for _, ins in pairs(u.dis(addr, x:len() + 16)) do
        total = total + ins.bytes:len()
        if total == x:len() then break end
        if total > x:len() then
            x = x .. asm('nop', 0):rep(total - x:len())
            break
        end
    end
    write(addr, x)
end

func dis(addr, size, indent, count)
    if addr == nil then addr = pc end
    if size == nil then size = 16 end
    if indent == nil then indent = 0 end
    local pad = (' '):rep(indent)
    local d = u.dis(addr, size)
    local width = 0
    for i, ins in ipairs(d) do
        if count != nil and i > count then break end
        local fmt = pad .. '0x%x: %s %s'
        print fmt % {ins.addr, ins.name, ins.op_str}
    end
end

func s(steps)
    if steps == nil then steps = 1 end
    u.step(steps)
end

c = u.continue
func rewind(n)
    if n == nil then n = 1 end
    u.rewind_n(n)
end
rw = rewind
rwaddr = u.rewind_addr

func rwto(insto)
    repeat
        rw 1
    until ins.name == insto
end

func b(baddr)
    local hh = u.hook_add(cpu.HOOK_CODE, func()
        if bskip == baddr then
            bskip = nil
            return
        end
        bskip = baddr
        print 'Breakpoint N hit at 0x%x' % baddr
        u.stop()
    end, baddr, baddr)
    print 'Breakpoint N at 0x%x' % baddr
end

func runto(name)
    on code do
        if ins.name == name then
            print '[-] stopping at "%s"' % name
            dis pc 16 0 1
            u.stop()
            off
        end
    end
    c
end

func regs(name)
    reglist, err = us:RegDump()
    for _, reg in reglist() do
        print reg.Name reg.Val
    end
end
r = regs
`
<commit_msg>repl: add addr argument to maps command<commit_after>package lua

var cmdRc = `
func _fallback(name, val)
    if type(val) == 'function' then
        val()
    else
        print val
    end
end

func _is_public(name)
    return _builtins[name] != true and name:sub(1, 1) != '_'
end

func help()
    local funcs = {}
    local vars = {}
    local vkeys = {}
    for name, val in pairs(_G) do
        if _is_public(name) then
            if type(val) == 'function' then
                table.insert(funcs, name)
            else
                vars[name] = val
                table.insert(vkeys, name)
            end
        end
    end
    table.sort(funcs)
    print 'Functions:'
    for _, name in ipairs(funcs) do
        print(name)
    end
    print

    table.sort(vkeys)
    print 'Variables:'
    for _, name in ipairs(vkeys) do
        local val = vars[name]
        print name '=' val
    end
end

func dir()
    local ret = {}
    for name, _ in pairs(_G) do
        if _is_public(name) then
            table.insert(ret, name)
        end
    end
    table.sort(ret)
    return ret
end

local _hook_types = {
    -- TODO: hook memory map?
    -- sys and sys_pre are hardcoded to call hook_sys
    code = cpu.HOOK_CODE,
    block = cpu.HOOK_BLOCK,
    intr = cpu.HOOK_INTR,
    read = cpu.HOOK_MEM_READ,
    write = cpu.HOOK_MEM_WRITE,
    fault = cpu.HOOK_MEM_ERR,
}

func _on_hook(name, fn, start, stop)
    if name == 'sys_pre' then
        return u.hook_sys_add(start, fn, nil)
    end
    if name == 'sys' then
        return u.hook_sys_add(start, nil, fn)
    end
    local type = _hook_types[name]
    if type != nil then
        if start == nil then
            return u.hook_add(type, fn)
        else
            if stop == nil then stop = start end
            return u.hook_add(type, fn, start, stop)
        end
    end
    print 'unimplemented hook type %s' % name
    -- u.on_hook_add(name, fn, start, stop)
end

func off()
    if hh then
        u.hook_del(hh)
        u.hook_sys_del(hh)
        hh = nil
    end
end

func read(addr, size)
    if size == nil then size = 16 end
    return u.mem_read(addr, size)
end

func write(addr, s)
    u.mem_write(addr, s)
end

func maps(addr)
    print 'Memory map:'
    local m = us:Mappings()
    for i in m() do
        local map = m[i]
        if addr != nil then
            if map:Contains(addr) then
                print map:String()
                print '%#x: %#x+%#x' % {addr, map.Addr, addr-map.Addr}
                return
            end
        else
            print map:String()
        end
    end
    if addr != nil then
        print '%#x not found.' % addr
    end
end

func map(addr, size, prot)
    if addr == nil then
        maps()
    else
        if prot == nil then prot = cpu.PROT_ALL end
        u.mem_map(addr, size, prot)
    end
end

func asm(src, addr)
    if addr == nil then addr = 0 end
    return u.asm(src, addr)
end

func patch(addr, src)
    local x = asm(src, addr)
    -- autonop
    local total = 0
    for _, ins in pairs(u.dis(addr, x:len() + 16)) do
        total = total + ins.bytes:len()
        if total == x:len() then break end
        if total > x:len() then
            x = x .. asm('nop', 0):rep(total - x:len())
            break
        end
    end
    write(addr, x)
end

func dis(addr, size, indent, count)
    if addr == nil then addr = pc end
    if size == nil then size = 16 end
    if indent == nil then indent = 0 end
    local pad = (' '):rep(indent)
    local d = u.dis(addr, size)
    local width = 0
    for i, ins in ipairs(d) do
        if count != nil and i > count then break end
        local fmt = pad .. '0x%x: %s %s'
        print fmt % {ins.addr, ins.name, ins.op_str}
    end
end

func s(steps)
    if steps == nil then steps = 1 end
    u.step(steps)
end

c = u.continue
func rewind(n)
    if n == nil then n = 1 end
    u.rewind_n(n)
end
rw = rewind
rwaddr = u.rewind_addr

func rwto(insto)
    repeat
        rw 1
    until ins.name == insto
end

func b(baddr)
    local hh = u.hook_add(cpu.HOOK_CODE, func()
        if bskip == baddr then
            bskip = nil
            return
        end
        bskip = baddr
        print 'Breakpoint N hit at 0x%x' % baddr
        u.stop()
    end, baddr, baddr)
    print 'Breakpoint N at 0x%x' % baddr
end

func runto(name)
    on code do
        if ins.name == name then
            print '[-] stopping at "%s"' % name
            dis pc 16 0 1
            u.stop()
            off
        end
    end
    c
end

func regs(name)
    reglist, err = us:RegDump()
    for _, reg in reglist() do
        print reg.Name reg.Val
    end
end
r = regs
`
<|endoftext|>


<commit_before>package models

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"

	"github.com/bnagy/gapstone"
	ks "github.com/keystone-engine/keystone/bindings/go/keystone"
)

var demangleRe = regexp.MustCompile(`^[^(]+`)
var demangleCache = make(map[string]string)
var demangleLock sync.RWMutex

func demangleMiss(name string) string {
	if strings.HasPrefix(name, "__Z") {
		name = name[1:]
	} else if !strings.HasPrefix(name, "_Z") {
		return name
	}
	cmd := exec.Command("c++filt", "-n")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return name
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return name
	}
	if err = cmd.Start(); err != nil {
		fmt.Fprintf(os.Stderr, "cmd error", err)
		return name
	}
	stdin.Write([]byte(name + "\n"))
	stdin.Close()
	out, err := ioutil.ReadAll(stdout)
	out = bytes.Trim(out, "\t\r\n ")
	result := name
	if err != nil || len(out) == 0 {
		return name
	}
	cmd.Wait()
	out = demangleRe.FindSubmatch(out)[0]
	result = string(out)
	return result
}

func Demangle(name string) string {
	demangleLock.RLock()
	if hit, ok := demangleCache[name]; ok {
		demangleLock.RUnlock()
		return hit
	}
	demangleLock.RUnlock()
	result := demangleMiss(name)
	demangleLock.Lock()
	demangleCache[name] = result
	demangleLock.Unlock()
	return result
}

func Assemble(asm string, addr uint64, arch *Arch) ([]byte, error) {
	if arch.ks == nil {
		engine, err := ks.New(arch.KS_ARCH, arch.KS_MODE)
		if err != nil {
			return nil, err
		}
		arch.ks = engine
	}
	out, _, ok := arch.ks.Assemble(asm, addr)
	if !ok {
		return nil, arch.ks.LastError()
	}
	return out, nil
}

var discache = make(map[string]string)
var discacheLock sync.RWMutex

func Disas(mem []byte, addr uint64, arch *Arch, pad ...int) (string, error) {
	var asm []gapstone.Instruction
	cacheKey := fmt.Sprintf("%d|%s", addr, mem)
	if len(mem) == 0 {
		return "", nil
	}
	discacheLock.RLock()
	if cached, ok := discache[cacheKey]; ok {
		discacheLock.RUnlock()
		return cached, nil
	}
	discacheLock.RUnlock()
	if arch.cs == nil {
		engine, err := gapstone.New(arch.CS_ARCH, arch.CS_MODE)
		if err != nil {
			return "", err
		}
		arch.cs = &engine
	}
	asm, err := arch.cs.Disasm(mem, addr, 0)
	if err != nil {
		return "", err
	}
	var width uint
	if len(pad) > 0 {
		width = uint(pad[0])
	}
	for _, insn := range asm {
		if insn.Size > width {
			width = insn.Size
		}
	}
	var out []string
	for _, insn := range asm {
		pad := strings.Repeat(" ", int(width-insn.Size)*2)
		data := pad + hex.EncodeToString(insn.Bytes)
		out = append(out, fmt.Sprintf("0x%x: %s %s %s", insn.Address, data, insn.Mnemonic, insn.OpStr))
	}
	ret := strings.Join(out, "\n")
	discacheLock.Lock()
	discache[cacheKey] = ret
	discacheLock.Unlock()
	return ret, nil
}

func Repr(p []byte, strsize int) string {
	if len(p) > strsize && strsize > 0 {
		p = p[:strsize]
	}
	tmp := make([]byte, 0, len(p))
	for _, b := range p {
		if b >= 0x20 && b <= 0x7e {
			tmp = append(tmp, b)
		} else {
			var repr string
			switch b {
			case 0:
				repr = "\\0"
			case '\b':
				repr = "\\b"
			case '\r':
				repr = "\\r"
			case '\n':
				repr = "\\n"
			case '\t':
				repr = "\\t"
			default:
				repr = fmt.Sprintf("\\x%02x", b)
			}
			tmp = append(tmp, repr...)
		}
	}
	out := string(tmp)
	if strsize > 0 && len(out) > strsize {
		out = string(tmp[:strsize-3])
		return "\"" + out + "\"..."
	}
	return "\"" + out + "\""
}

func HexDump(base uint64, mem []byte, bits int) []string {
	var clean = func(p []byte) string {
		o := make([]byte, len(p))
		for i, c := range p {
			if c >= 0x20 && c <= 0x7e {
				o[i] = c
			} else {
				o[i] = '.'
			}
		}
		return string(o)
	}
	bsz := bits / 8
	hexFmt := fmt.Sprintf("0x%%0%dx:", bsz*2)
	padBlock := strings.Repeat(" ", bsz*2)
	padTail := strings.Repeat(" ", bsz)

	width := 80
	addrSize := bsz*2 + 4
	blockCount := ((width - addrSize) * 3 / 4) / ((bsz + 1) * 2)
	lineSize := blockCount * bsz
	var out []string
	blocks := make([]string, blockCount)
	tail := make([]string, blockCount)
	for i := 0; i < len(mem); i += lineSize {
		memLine := mem[i:]
		for j := 0; j < blockCount; j++ {
			if j*bsz < len(memLine) {
				end := (j + 1) * bsz
				var block []byte
				if end > len(memLine) {
					block = memLine[j*bsz:]
				} else {
					block = memLine[j*bsz : end]
				}
				blocks[j] = hex.EncodeToString(block)
				tail[j] = clean(block)
				// if block was too short, pad with spaces
				if end > len(memLine) {
					pad := end - len(memLine)
					blocks[j] += strings.Repeat("  ", pad)
					tail[j] += strings.Repeat(" ", pad)
				}
			} else {
				blocks[j] = padBlock
				tail[j] = padTail
			}
		}
		line := []string{fmt.Sprintf(hexFmt, base+uint64(i))}
		line = append(line, strings.Join(blocks, " "))
		line = append(line, fmt.Sprintf("[%s]", strings.Join(tail, " ")))
		out = append(out, strings.Join(line, " "))
	}
	return out
}
<commit_msg>tweak string truncation in Repr<commit_after>package models

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"

	"github.com/bnagy/gapstone"
	ks "github.com/keystone-engine/keystone/bindings/go/keystone"
)

var demangleRe = regexp.MustCompile(`^[^(]+`)
var demangleCache = make(map[string]string)
var demangleLock sync.RWMutex

func demangleMiss(name string) string {
	if strings.HasPrefix(name, "__Z") {
		name = name[1:]
	} else if !strings.HasPrefix(name, "_Z") {
		return name
	}
	cmd := exec.Command("c++filt", "-n")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return name
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return name
	}
	if err = cmd.Start(); err != nil {
		fmt.Fprintf(os.Stderr, "cmd error", err)
		return name
	}
	stdin.Write([]byte(name + "\n"))
	stdin.Close()
	out, err := ioutil.ReadAll(stdout)
	out = bytes.Trim(out, "\t\r\n ")
	result := name
	if err != nil || len(out) == 0 {
		return name
	}
	cmd.Wait()
	out = demangleRe.FindSubmatch(out)[0]
	result = string(out)
	return result
}

func Demangle(name string) string {
	demangleLock.RLock()
	if hit, ok := demangleCache[name]; ok {
		demangleLock.RUnlock()
		return hit
	}
	demangleLock.RUnlock()
	result := demangleMiss(name)
	demangleLock.Lock()
	demangleCache[name] = result
	demangleLock.Unlock()
	return result
}

func Assemble(asm string, addr uint64, arch *Arch) ([]byte, error) {
	if arch.ks == nil {
		engine, err := ks.New(arch.KS_ARCH, arch.KS_MODE)
		if err != nil {
			return nil, err
		}
		arch.ks = engine
	}
	out, _, ok := arch.ks.Assemble(asm, addr)
	if !ok {
		return nil, arch.ks.LastError()
	}
	return out, nil
}

var discache = make(map[string]string)
var discacheLock sync.RWMutex

func Disas(mem []byte, addr uint64, arch *Arch, pad ...int) (string, error) {
	var asm []gapstone.Instruction
	cacheKey := fmt.Sprintf("%d|%s", addr, mem)
	if len(mem) == 0 {
		return "", nil
	}
	discacheLock.RLock()
	if cached, ok := discache[cacheKey]; ok {
		discacheLock.RUnlock()
		return cached, nil
	}
	discacheLock.RUnlock()
	if arch.cs == nil {
		engine, err := gapstone.New(arch.CS_ARCH, arch.CS_MODE)
		if err != nil {
			return "", err
		}
		arch.cs = &engine
	}
	asm, err := arch.cs.Disasm(mem, addr, 0)
	if err != nil {
		return "", err
	}
	var width uint
	if len(pad) > 0 {
		width = uint(pad[0])
	}
	for _, insn := range asm {
		if insn.Size > width {
			width = insn.Size
		}
	}
	var out []string
	for _, insn := range asm {
		pad := strings.Repeat(" ", int(width-insn.Size)*2)
		data := pad + hex.EncodeToString(insn.Bytes)
		out = append(out, fmt.Sprintf("0x%x: %s %s %s", insn.Address, data, insn.Mnemonic, insn.OpStr))
	}
	ret := strings.Join(out, "\n")
	discacheLock.Lock()
	discache[cacheKey] = ret
	discacheLock.Unlock()
	return ret, nil
}

func Repr(p []byte, strsize int) string {
	trunc := false
	if len(p) > strsize && strsize > 0 {
		// factor quotes into strsize
		strsize -= 2
		p = p[:strsize-3]
		trunc = true
	}
	tmp := make([]byte, 0, len(p))
	for _, b := range p {
		if b >= 0x20 && b <= 0x7e {
			tmp = append(tmp, b)
		} else {
			var repr string
			switch b {
			case 0:
				repr = "\\0"
			case '\b':
				repr = "\\b"
			case '\r':
				repr = "\\r"
			case '\n':
				repr = "\\n"
			case '\t':
				repr = "\\t"
			default:
				repr = fmt.Sprintf("\\x%02x", b)
			}
			if strsize > 0 && len(tmp)+len(repr) <= strsize {
				tmp = append(tmp, repr...)
			}
		}
	}
	out := string(tmp)
	if strsize > 0 && len(out) > strsize {
		out = string(tmp[:strsize-3])
		trunc = true
	}
	if trunc {
		return "\"" + out + "\"..."
	}
	return "\"" + out + "\""
}

func HexDump(base uint64, mem []byte, bits int) []string {
	var clean = func(p []byte) string {
		o := make([]byte, len(p))
		for i, c := range p {
			if c >= 0x20 && c <= 0x7e {
				o[i] = c
			} else {
				o[i] = '.'
			}
		}
		return string(o)
	}
	bsz := bits / 8
	hexFmt := fmt.Sprintf("0x%%0%dx:", bsz*2)
	padBlock := strings.Repeat(" ", bsz*2)
	padTail := strings.Repeat(" ", bsz)

	width := 80
	addrSize := bsz*2 + 4
	blockCount := ((width - addrSize) * 3 / 4) / ((bsz + 1) * 2)
	lineSize := blockCount * bsz
	var out []string
	blocks := make([]string, blockCount)
	tail := make([]string, blockCount)
	for i := 0; i < len(mem); i += lineSize {
		memLine := mem[i:]
		for j := 0; j < blockCount; j++ {
			if j*bsz < len(memLine) {
				end := (j + 1) * bsz
				var block []byte
				if end > len(memLine) {
					block = memLine[j*bsz:]
				} else {
					block = memLine[j*bsz : end]
				}
				blocks[j] = hex.EncodeToString(block)
				tail[j] = clean(block)
				// if block was too short, pad with spaces
				if end > len(memLine) {
					pad := end - len(memLine)
					blocks[j] += strings.Repeat("  ", pad)
					tail[j] += strings.Repeat(" ", pad)
				}
			} else {
				blocks[j] = padBlock
				tail[j] = padTail
			}
		}
		line := []string{fmt.Sprintf(hexFmt, base+uint64(i))}
		line = append(line, strings.Join(blocks, " "))
		line = append(line, fmt.Sprintf("[%s]", strings.Join(tail, " ")))
		out = append(out, strings.Join(line, " "))
	}
	return out
}
<|endoftext|>


<commit_before>// Copyright (c) 2014, Kevin Walsh.  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 auth

import (
	"bytes"
	"fmt"
)

// LogicElement is any element of the authorization logic, i.e. a formula, a
// term, or a principal extension.
type LogicElement interface {

	// Marshal writes a binary encoding of the element into b.
	Marshal(b *Buffer)

	// String returns verbose pretty-printing text for the element.
	String() string

	// ShortString returns short debug-printing text for the element.
	ShortString() string

	// fmt.Formatter is satisfied by all elements. Using format %v will result in
	// verbose pretty-printing, using format %s will result in short
	// debug-printing, and other formats will use an unspecified format.
	fmt.Formatter // Format(out fmt.State, verb rune)

	isLogicElement() // marker
}

// isLogicElement ensures only appropriate types can be assigned to an
// LogicElement.
func (t Prin) isLogicElement()      {}
func (t PrinTail) isLogicElement()  {}
func (t SubPrin) isLogicElement()   {}
func (t Str) isLogicElement()       {}
func (t Bytes) isLogicElement()     {}
func (t Int) isLogicElement()       {}
func (t TermVar) isLogicElement()   {}
func (f Pred) isLogicElement()      {}
func (f Const) isLogicElement()     {}
func (f Not) isLogicElement()       {}
func (f And) isLogicElement()       {}
func (f Or) isLogicElement()        {}
func (f Implies) isLogicElement()   {}
func (f Speaksfor) isLogicElement() {}
func (f Says) isLogicElement()      {}
func (f Forall) isLogicElement()    {}
func (f Exists) isLogicElement()    {}

// These declarations ensure all the appropriate types can be assigned to an
// LogicElement.
var _ LogicElement = Prin{}
var _ LogicElement = PrinTail{}
var _ LogicElement = SubPrin{}
var _ LogicElement = Str("")
var _ LogicElement = Bytes(nil)
var _ LogicElement = Int(0)
var _ LogicElement = TermVar("X")
var _ LogicElement = Pred{}
var _ LogicElement = Const(false)
var _ LogicElement = Not{}
var _ LogicElement = And{}
var _ LogicElement = Or{}
var _ LogicElement = Implies{}
var _ LogicElement = Speaksfor{}
var _ LogicElement = Says{}
var _ LogicElement = Forall{}
var _ LogicElement = Exists{}

// These declarations ensure all the appropriate types can be assigned to a
// fmt.Scanner.
var _ fmt.Scanner = &Prin{}
var _ fmt.Scanner = &PrinTail{}
var _ fmt.Scanner = &SubPrin{}
var _ fmt.Scanner = new(Str)
var _ fmt.Scanner = new(Bytes)
var _ fmt.Scanner = new(Int)
var _ fmt.Scanner = new(TermVar)
var _ fmt.Scanner = &Pred{}
var _ fmt.Scanner = new(Const)
var _ fmt.Scanner = &Not{}
var _ fmt.Scanner = &And{}
var _ fmt.Scanner = &Or{}
var _ fmt.Scanner = &Implies{}
var _ fmt.Scanner = &Speaksfor{}
var _ fmt.Scanner = &Says{}
var _ fmt.Scanner = &Forall{}
var _ fmt.Scanner = &Exists{}
var _ fmt.Scanner = &AnyForm{}
var _ fmt.Scanner = &AnyTerm{}

// Prin uniquely identifies a principal by a public key, used to verify
// signatures on credentials issued by the principal, and a sequence of zero or
// more extensions to identify the subprincipal of that key.
type Prin struct {
	Type string  // The keyword of a principal token, e.g. "key" or "tpm".
	Key  Term    // TermVar or Bytes with marshalled CryptoKey protobuf structure with purpose CryptoKey.VERIFYING. Or this can be a marshalled TPM AIK, or a X.509 certificate, marshalled as ASN.1 DER.
	Ext  SubPrin // zero or more extensions for descendents
}

func (p *Prin) Parent() *Prin {
	if len(p.Ext) == 0 {
		return nil
	}
	ext := make([]PrinExt, len(p.Ext)-1)
	for i := 0; i < len(p.Ext)-1; i++ {
		ext[i] = p.Ext[i]
	}
	return &Prin{p.Type, p.Key, ext}
}

// PrinExt is an extension of a principal.
type PrinExt struct {
	Name string // [A-Z][a-zA-Z0-9_]*
	Arg  []Term
}

// SubPrin is a series of extensions of a principal.
type SubPrin []PrinExt

// A PrinTail is a Term that represents a free-floating sequence of PrinExt
// values. It represents the tail of a list of Prin extensions. Its textual
// representation always starts with the keyword "ext".
type PrinTail struct {
	Ext SubPrin // one or more extensions
}

// Term is an argument to a predicate or a principal extension.
type Term interface {
	LogicElement
	Identical(other Term) bool
	isTerm() // marker
}

// isTerm ensures only appropriate types can be assigned to a Term.
func (t Prin) isTerm()     {}
func (t PrinTail) isTerm() {}
func (t Str) isTerm()      {}
func (t Bytes) isTerm()    {}
func (t Int) isTerm()      {}
func (t TermVar) isTerm()  {}

// Str is a string used as a Term.
type Str string

// Bytes is a byte slice used as a Term.
type Bytes []byte

// Int is an int used as a Term.
type Int int

// TermVar is a term-valued variable.
type TermVar string

// Form is a formula in the Tao authorization logic.
type Form interface {
	LogicElement
	isForm() // marker
}

// isForm ensures only appropriate types can be assigned to a Form.
func (f Pred) isForm()      {}
func (f Const) isForm()     {}
func (f Not) isForm()       {}
func (f And) isForm()       {}
func (f Or) isForm()        {}
func (f Implies) isForm()   {}
func (f Speaksfor) isForm() {}
func (f Says) isForm()      {}
func (f Forall) isForm()    {}
func (f Exists) isForm()    {}

// Pred is a predicate, i.e. a boolean-valued (pure) function.
type Pred struct {
	Name string // [A-Z][a-zA-Z0-9_]*
	Arg  []Term
}

// Const conveys formula "true" or formula "false"
type Const bool

// Not conveys formula "not Negand"
type Not struct {
	Negand Form
}

// And conveys formula "Conjunct[0] and Conjunct[1] and ... and Conjunct[n]"
type And struct {
	Conjunct []Form
}

// Or conveys formula "Disjunct[0] or Disjunct[1] or ... or Disjunct[n]"
type Or struct {
	Disjunct []Form
}

// Implies conveys formula "Antecedent implies Consequent"
type Implies struct {
	Antecedent Form
	Consequent Form
}

// Speaksfor conveys formula "Delegate speaksfor Delegator"
type Speaksfor struct {
	Delegate  Term
	Delegator Term
}

// Says conveys formula "Speaker from Time until Expiration says Message"
type Says struct {
	Speaker    Term
	Time       *int64 // nil to omit
	Expiration *int64 // nil to omit
	Message    Form
}

// Commences checks if statement f has a commencement time.
func (f Says) Commences() bool {
	return f.Time != nil
}

// Expires checks if statement f has an expiration time.
func (f Says) Expires() bool {
	return f.Expiration != nil
}

// Active checks if time t is within the bounds defined by the expiration and
// commencement times of statement f.
func (f Says) Active(t int64) bool {
	return (f.Time == nil || t >= *f.Time) && (f.Expiration == nil || t < *f.Expiration)
}

// Forall conveys formula "(forall Var : Body)" where Var ranges over Terms.
type Forall struct {
	Var  string
	Body Form
}

// Exists conveys formula "(exists Var : Body)" where Var ranges over Terms.
type Exists struct {
	Var  string
	Body Form
}

// Identical checks if an Int is identical to another Term.
func (t Int) Identical(other Term) bool {
	return t == other
}

// Identical checks if a Str is identical to another Term.
func (t Str) Identical(other Term) bool {
	return t == other
}

// Identical checks if a Bytes is identical to another Term.
func (t Bytes) Identical(other Term) bool {
	// other must be type Bytes or *Bytes
	var b *Bytes
	if ptr, ok := other.(*Bytes); ok {
		b = ptr
	} else if val, ok := other.(Bytes); ok {
		b = &val
	} else {
		return false
	}
	return bytes.Equal([]byte(t), []byte(*b))
}

// Identical checks if a Prin is identical to another Term.
func (t Prin) Identical(other Term) bool {
	// other must be type Prin or *Prin
	var p *Prin
	if ptr, ok := other.(*Prin); ok {
		p = ptr
	} else if val, ok := other.(Prin); ok {
		p = &val
	} else {
		return false
	}
	return t.Type == p.Type && t.Key.Identical(p.Key) && t.Ext.Identical(p.Ext)
}

// Identical checks if a PrinTail is identical to another Term.
func (t PrinTail) Identical(other Term) bool {
	// other must be type PrinTail or *PrinTail
	var p *PrinTail
	if ptr, ok := other.(*PrinTail); ok {
		p = ptr
	} else if val, ok := other.(PrinTail); ok {
		p = &val
	} else {
		return false
	}
	return t.Ext.Identical(p.Ext)
}

// Identical checks if a TermVar is identical to another Term.
func (t TermVar) Identical(other Term) bool {
	return t == other
}

// Identical checks if one PrinExt is identical to another.
func (e PrinExt) Identical(other PrinExt) bool {
	if e.Name != other.Name || len(e.Arg) != len(other.Arg) {
		return false
	}
	for i, a := range e.Arg {
		if !a.Identical(other.Arg[i]) {
			return false
		}
	}
	return true
}

// Identical checks if one SubPrin is identical to another.
func (t SubPrin) Identical(other SubPrin) bool {
	if len(t) != len(other) {
		return false
	}
	for i, e := range t {
		if !e.Identical(other[i]) {
			return false
		}
	}
	return true
}

// SubprinOrIdentical checks whether child is a subprincipal of parent or is
// identical to parent.
func SubprinOrIdentical(child, parent Term) bool {
	// Both must be type Prin or *Prin
	var c, p *Prin
	if ptr, ok := child.(*Prin); ok {
		c = ptr
	} else if val, ok := child.(Prin); ok {
		c = &val
	} else {
		return false
	}
	if ptr, ok := parent.(*Prin); ok {
		p = ptr
	} else if val, ok := parent.(Prin); ok {
		p = &val
	} else {
		return false
	}
	if p.Type != c.Type || !p.Key.Identical(c.Key) || len(p.Ext) > len(c.Ext) {
		return false
	}
	for i, a := range p.Ext {
		if !a.Identical(c.Ext[i]) {
			return false
		}
	}
	return true
}

// MakeSubprincipal creates principal p.e... given principal p and extensions e.
func (t Prin) MakeSubprincipal(e SubPrin) Prin {
	other := Prin{Type: t.Type, Key: t.Key, Ext: append([]PrinExt{}, t.Ext...)}
	other.Ext = append(other.Ext, []PrinExt(e)...)
	return other
}

// MakePredicate creates a predicate with the given name and arguments.
// Arguments can be Prin, Int (or integer types that be coerced to it), Str (or
// string), or PrinTail. Anything else is coerced to Str.
func MakePredicate(name string, arg ...interface{}) Pred {
	terms := make([]Term, len(arg))
	for i, a := range arg {
		switch a := a.(type) {
		case Int:
			terms[i] = a
		case Str:
			terms[i] = a
		case Bytes:
			terms[i] = a
		case Prin:
			terms[i] = a
		case PrinTail:
			terms[i] = a
		case *Int:
			terms[i] = a
		case *Str:
			terms[i] = a
		case *Bytes:
			terms[i] = a
		case *Prin:
			terms[i] = a
		case *PrinTail:
			terms[i] = a
		case int:
			terms[i] = Int(a)
		case int32:
			terms[i] = Int(int(a))
		case int16:
			terms[i] = Int(int(a))
		case byte:
			terms[i] = Int(int(a))
		case string:
			terms[i] = Str(a)
		case []byte:
			terms[i] = Bytes(a)
		default:
			terms[i] = Str(fmt.Sprintf("%v", a))
		}
	}
	return Pred{name, terms}
}

// NewKeyPrin returns a new Prin of type "key" with the given key material.
func NewKeyPrin(material []byte) Prin {
	return Prin{Type: "key", Key: Bytes(material)}
}
<commit_msg>helpers for making subprins<commit_after>// Copyright (c) 2014, Kevin Walsh.  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 auth

import (
	"bytes"
	"fmt"
)

// LogicElement is any element of the authorization logic, i.e. a formula, a
// term, or a principal extension.
type LogicElement interface {

	// Marshal writes a binary encoding of the element into b.
	Marshal(b *Buffer)

	// String returns verbose pretty-printing text for the element.
	String() string

	// ShortString returns short debug-printing text for the element.
	ShortString() string

	// fmt.Formatter is satisfied by all elements. Using format %v will result in
	// verbose pretty-printing, using format %s will result in short
	// debug-printing, and other formats will use an unspecified format.
	fmt.Formatter // Format(out fmt.State, verb rune)

	isLogicElement() // marker
}

// isLogicElement ensures only appropriate types can be assigned to an
// LogicElement.
func (t Prin) isLogicElement()      {}
func (t PrinTail) isLogicElement()  {}
func (t SubPrin) isLogicElement()   {}
func (t Str) isLogicElement()       {}
func (t Bytes) isLogicElement()     {}
func (t Int) isLogicElement()       {}
func (t TermVar) isLogicElement()   {}
func (f Pred) isLogicElement()      {}
func (f Const) isLogicElement()     {}
func (f Not) isLogicElement()       {}
func (f And) isLogicElement()       {}
func (f Or) isLogicElement()        {}
func (f Implies) isLogicElement()   {}
func (f Speaksfor) isLogicElement() {}
func (f Says) isLogicElement()      {}
func (f Forall) isLogicElement()    {}
func (f Exists) isLogicElement()    {}

// These declarations ensure all the appropriate types can be assigned to an
// LogicElement.
var _ LogicElement = Prin{}
var _ LogicElement = PrinTail{}
var _ LogicElement = SubPrin{}
var _ LogicElement = Str("")
var _ LogicElement = Bytes(nil)
var _ LogicElement = Int(0)
var _ LogicElement = TermVar("X")
var _ LogicElement = Pred{}
var _ LogicElement = Const(false)
var _ LogicElement = Not{}
var _ LogicElement = And{}
var _ LogicElement = Or{}
var _ LogicElement = Implies{}
var _ LogicElement = Speaksfor{}
var _ LogicElement = Says{}
var _ LogicElement = Forall{}
var _ LogicElement = Exists{}

// These declarations ensure all the appropriate types can be assigned to a
// fmt.Scanner.
var _ fmt.Scanner = &Prin{}
var _ fmt.Scanner = &PrinTail{}
var _ fmt.Scanner = &SubPrin{}
var _ fmt.Scanner = new(Str)
var _ fmt.Scanner = new(Bytes)
var _ fmt.Scanner = new(Int)
var _ fmt.Scanner = new(TermVar)
var _ fmt.Scanner = &Pred{}
var _ fmt.Scanner = new(Const)
var _ fmt.Scanner = &Not{}
var _ fmt.Scanner = &And{}
var _ fmt.Scanner = &Or{}
var _ fmt.Scanner = &Implies{}
var _ fmt.Scanner = &Speaksfor{}
var _ fmt.Scanner = &Says{}
var _ fmt.Scanner = &Forall{}
var _ fmt.Scanner = &Exists{}
var _ fmt.Scanner = &AnyForm{}
var _ fmt.Scanner = &AnyTerm{}

// Prin uniquely identifies a principal by a public key, used to verify
// signatures on credentials issued by the principal, and a sequence of zero or
// more extensions to identify the subprincipal of that key.
type Prin struct {
	Type string  // The keyword of a principal token, e.g. "key" or "tpm".
	Key  Term    // TermVar or Bytes with marshalled CryptoKey protobuf structure with purpose CryptoKey.VERIFYING. Or this can be a marshalled TPM AIK, or a X.509 certificate, marshalled as ASN.1 DER.
	Ext  SubPrin // zero or more extensions for descendents
}

func (p *Prin) Parent() *Prin {
	if len(p.Ext) == 0 {
		return nil
	}
	ext := make([]PrinExt, len(p.Ext)-1)
	for i := 0; i < len(p.Ext)-1; i++ {
		ext[i] = p.Ext[i]
	}
	return &Prin{p.Type, p.Key, ext}
}

// PrinExt is an extension of a principal.
type PrinExt struct {
	Name string // [A-Z][a-zA-Z0-9_]*
	Arg  []Term
}

// SubPrin is a series of extensions of a principal.
type SubPrin []PrinExt

// A PrinTail is a Term that represents a free-floating sequence of PrinExt
// values. It represents the tail of a list of Prin extensions. Its textual
// representation always starts with the keyword "ext".
type PrinTail struct {
	Ext SubPrin // one or more extensions
}

// Term is an argument to a predicate or a principal extension.
type Term interface {
	LogicElement
	Identical(other Term) bool
	isTerm() // marker
}

// isTerm ensures only appropriate types can be assigned to a Term.
func (t Prin) isTerm()     {}
func (t PrinTail) isTerm() {}
func (t Str) isTerm()      {}
func (t Bytes) isTerm()    {}
func (t Int) isTerm()      {}
func (t TermVar) isTerm()  {}

// Str is a string used as a Term.
type Str string

// Bytes is a byte slice used as a Term.
type Bytes []byte

// Int is an int used as a Term.
type Int int

// TermVar is a term-valued variable.
type TermVar string

// Form is a formula in the Tao authorization logic.
type Form interface {
	LogicElement
	isForm() // marker
}

// isForm ensures only appropriate types can be assigned to a Form.
func (f Pred) isForm()      {}
func (f Const) isForm()     {}
func (f Not) isForm()       {}
func (f And) isForm()       {}
func (f Or) isForm()        {}
func (f Implies) isForm()   {}
func (f Speaksfor) isForm() {}
func (f Says) isForm()      {}
func (f Forall) isForm()    {}
func (f Exists) isForm()    {}

// Pred is a predicate, i.e. a boolean-valued (pure) function.
type Pred struct {
	Name string // [A-Z][a-zA-Z0-9_]*
	Arg  []Term
}

// Const conveys formula "true" or formula "false"
type Const bool

// Not conveys formula "not Negand"
type Not struct {
	Negand Form
}

// And conveys formula "Conjunct[0] and Conjunct[1] and ... and Conjunct[n]"
type And struct {
	Conjunct []Form
}

// Or conveys formula "Disjunct[0] or Disjunct[1] or ... or Disjunct[n]"
type Or struct {
	Disjunct []Form
}

// Implies conveys formula "Antecedent implies Consequent"
type Implies struct {
	Antecedent Form
	Consequent Form
}

// Speaksfor conveys formula "Delegate speaksfor Delegator"
type Speaksfor struct {
	Delegate  Term
	Delegator Term
}

// Says conveys formula "Speaker from Time until Expiration says Message"
type Says struct {
	Speaker    Term
	Time       *int64 // nil to omit
	Expiration *int64 // nil to omit
	Message    Form
}

// Commences checks if statement f has a commencement time.
func (f Says) Commences() bool {
	return f.Time != nil
}

// Expires checks if statement f has an expiration time.
func (f Says) Expires() bool {
	return f.Expiration != nil
}

// Active checks if time t is within the bounds defined by the expiration and
// commencement times of statement f.
func (f Says) Active(t int64) bool {
	return (f.Time == nil || t >= *f.Time) && (f.Expiration == nil || t < *f.Expiration)
}

// Forall conveys formula "(forall Var : Body)" where Var ranges over Terms.
type Forall struct {
	Var  string
	Body Form
}

// Exists conveys formula "(exists Var : Body)" where Var ranges over Terms.
type Exists struct {
	Var  string
	Body Form
}

// Identical checks if an Int is identical to another Term.
func (t Int) Identical(other Term) bool {
	return t == other
}

// Identical checks if a Str is identical to another Term.
func (t Str) Identical(other Term) bool {
	return t == other
}

// Identical checks if a Bytes is identical to another Term.
func (t Bytes) Identical(other Term) bool {
	// other must be type Bytes or *Bytes
	var b *Bytes
	if ptr, ok := other.(*Bytes); ok {
		b = ptr
	} else if val, ok := other.(Bytes); ok {
		b = &val
	} else {
		return false
	}
	return bytes.Equal([]byte(t), []byte(*b))
}

// Identical checks if a Prin is identical to another Term.
func (t Prin) Identical(other Term) bool {
	// other must be type Prin or *Prin
	var p *Prin
	if ptr, ok := other.(*Prin); ok {
		p = ptr
	} else if val, ok := other.(Prin); ok {
		p = &val
	} else {
		return false
	}
	return t.Type == p.Type && t.Key.Identical(p.Key) && t.Ext.Identical(p.Ext)
}

// Identical checks if a PrinTail is identical to another Term.
func (t PrinTail) Identical(other Term) bool {
	// other must be type PrinTail or *PrinTail
	var p *PrinTail
	if ptr, ok := other.(*PrinTail); ok {
		p = ptr
	} else if val, ok := other.(PrinTail); ok {
		p = &val
	} else {
		return false
	}
	return t.Ext.Identical(p.Ext)
}

// Identical checks if a TermVar is identical to another Term.
func (t TermVar) Identical(other Term) bool {
	return t == other
}

// Identical checks if one PrinExt is identical to another.
func (e PrinExt) Identical(other PrinExt) bool {
	if e.Name != other.Name || len(e.Arg) != len(other.Arg) {
		return false
	}
	for i, a := range e.Arg {
		if !a.Identical(other.Arg[i]) {
			return false
		}
	}
	return true
}

// Identical checks if one SubPrin is identical to another.
func (t SubPrin) Identical(other SubPrin) bool {
	if len(t) != len(other) {
		return false
	}
	for i, e := range t {
		if !e.Identical(other[i]) {
			return false
		}
	}
	return true
}

// SubprinOrIdentical checks whether child is a subprincipal of parent or is
// identical to parent.
func SubprinOrIdentical(child, parent Term) bool {
	// Both must be type Prin or *Prin
	var c, p *Prin
	if ptr, ok := child.(*Prin); ok {
		c = ptr
	} else if val, ok := child.(Prin); ok {
		c = &val
	} else {
		return false
	}
	if ptr, ok := parent.(*Prin); ok {
		p = ptr
	} else if val, ok := parent.(Prin); ok {
		p = &val
	} else {
		return false
	}
	if p.Type != c.Type || !p.Key.Identical(c.Key) || len(p.Ext) > len(c.Ext) {
		return false
	}
	for i, a := range p.Ext {
		if !a.Identical(c.Ext[i]) {
			return false
		}
	}
	return true
}

// MakeSubprincipal creates principal p.e... given principal p and extensions e.
func (t Prin) MakeSubprincipal(e SubPrin) Prin {
	other := Prin{Type: t.Type, Key: t.Key, Ext: append([]PrinExt{}, t.Ext...)}
	other.Ext = append(other.Ext, []PrinExt(e)...)
	return other
}

// MakeTerms converts each argument into a Term and returns the resulting list.
// Arguments can be Prin, Int (or integer types that be coerced to it), Str (or
// string), or PrinTail. Anything else is coerced to Str.
func MakeTerms(arg ...interface{}) []Term {
	terms := make([]Term, len(arg))
	for i, a := range arg {
		switch a := a.(type) {
		case Int:
			terms[i] = a
		case Str:
			terms[i] = a
		case Bytes:
			terms[i] = a
		case Prin:
			terms[i] = a
		case PrinTail:
			terms[i] = a
		case *Int:
			terms[i] = a
		case *Str:
			terms[i] = a
		case *Bytes:
			terms[i] = a
		case *Prin:
			terms[i] = a
		case *PrinTail:
			terms[i] = a
		case int:
			terms[i] = Int(a)
		case int32:
			terms[i] = Int(int(a))
		case int16:
			terms[i] = Int(int(a))
		case byte:
			terms[i] = Int(int(a))
		case string:
			terms[i] = Str(a)
		case []byte:
			terms[i] = Bytes(a)
		default:
			terms[i] = Str(fmt.Sprintf("%v", a))
		}
	}
	return terms
}

// MakePredicate creates a predicate with the given name and arguments.
// Arguments can be Prin, Int (or integer types that be coerced to it), Str (or
// string), or PrinTail. Anything else is coerced to Str.
func MakePredicate(name string, arg ...interface{}) Pred {
	return Pred{name, MakeTerms(arg...)}
}

// MakePrinExt creates a subprincipal extension with the given name and arguments.
// Arguments can be Prin, Int (or integer types that be coerced to it), Str (or
// string), or PrinTail. Anything else is coerced to Str.
func MakePrinExt(name string, arg ...interface{}) PrinExt {
	return PrinExt{name, MakeTerms(arg...)}
}

// NewKeyPrin returns a new Prin of type "key" with the given key material.
func NewKeyPrin(material []byte) Prin {
	return Prin{Type: "key", Key: Bytes(material)}
}
<|endoftext|>


<commit_before>package gobundle

import (
    "bufio"
    "encoding/json"
    "io"
    "io/ioutil"
    "log"
    "os"
    "path/filepath"
    "regexp"
    "strconv"
    "strings"
)

// Structures

type NpmPackage struct {
    Name, Main, Version string
}

type Resolver struct {
    Path string
}

type ModRef struct {
    Path, Name string
}

type ModRefGraph struct {
    RootPath string
    EntryFile string
    Nodes map[string][][]string
}

var RequireStmt = regexp.MustCompile(`` +
        `(?i)` +        // Set case-insensitive flag
        `require\(` +
        `(?:"|')` +     // Single or double quote non-capture group
        `([a-z0-9\./\\-]+)` +
        `(?:"|')` +     // Single or double quote non-capture group
        `\)`)

//

func Bundle(entryFile string) ModRefGraph {
    absPath, _ := filepath.Abs(entryFile)
    entryFile = absPath

    rootPath := filepath.Dir(entryFile)
    r := Resolver{Path: rootPath}

    modPath := r.relPath(entryFile)
    return r.graph(rootPath, modPath)
}

func WriteBundle(b *os.File, bundle ModRefGraph) {
    r := Resolver{Path: bundle.RootPath}

    id := makeIdFunc()

    b.WriteString("(function(L, entry) {")
    b.WriteString(    "var cache = {};")
    b.WriteString(    "function run(id) {")
    b.WriteString(        "if (cache[id]) return cache[id];")
    b.WriteString(        "var m = {exports:{}},")
    b.WriteString(            "fn = L[id][0],")
    b.WriteString(            "deps = L[id][1];")
    b.WriteString(        "function require(name) {")
    b.WriteString(            "return run(deps[name]);")
    b.WriteString(        "}")
    b.WriteString(        "cache[id] = m.exports;");
    b.WriteString(        "fn(require, m, m.exports);");
    b.WriteString(        "return m.exports;");
    b.WriteString(    "}")
    b.WriteString(    "run(entry);")
    b.WriteString("}(")

    i := 0
    b.WriteString("{")
    log.Println(bundle.Nodes)
    // TODO: Filter list beforehand
    for path, children := range bundle.Nodes {
        // TODO: Investigate why empty/nil children are being added here.
        // NOTE: Comma appears at the tail end of list if null entry is last
        if len(path) == 0 {
            continue
        }

        modRef := r.loadModule(path)
        if modRef == nil {
            log.Panic("Unable to load module at", path)
        }

        b.WriteString(strconv.Itoa(id(path)))
        b.WriteString(":[")
        b.WriteString("function(require,module,exports){")
        modRef.writeContents(b)
        b.WriteString("},")

        b.WriteString("{")
        for j, pathTuple := range children {
            childPath := pathTuple[0]
            childRelPath := pathTuple[1]
            b.WriteString("'")
            b.WriteString(childPath)
            b.WriteString("':")
            b.WriteString(strconv.Itoa(id(childRelPath)))
            if j < len(children) - 1 {
                b.WriteString(",")
            }
        }
        b.WriteString("}")

        b.WriteString("]")
        if i < len(bundle.Nodes) - 1 {
            b.WriteString(",")
        }
        i++
    }
    b.WriteString("},")
    b.WriteString(strconv.Itoa(id(bundle.EntryFile)))
    b.WriteString("));\n")
}

//

func (self Resolver) loadModule(name string) *ModRef {
    return self.loadModuleRelativeTo(self.Path, name)
}

func (self Resolver) loadModuleRelativeTo(path, name string) *ModRef {
    log.Println("Trying to load", name, "from", path)
    // NOTE: This important to prevent the case where you have a file name
    // that matches an NPM module. (Ex. you have "shim/jquery.js" which
    // requires "jquery")
    if isRelative(name) {
        if result := self.loadFile(path, name); result != nil {
            return result
        }
        if result := self.loadFolder(path, name); result != nil {
            return result
        }
    }
    if result := self.loadNodeModule(path, name); result != nil {
        return result
    }
    return nil
}

func loadPackage(path string) (*NpmPackage, error) {
    pkg := NpmPackage{}
    data, err := ioutil.ReadFile(path)
    if err != nil {
        return &pkg, err
    }
    err = json.Unmarshal(data, &pkg)
    if err != nil {
        return &pkg, err
    }
    return &pkg, nil
}

func (self Resolver) loadFile(path , name string) *ModRef {
    dir := filepath.Dir(filepath.Join(path, name))
    base := filepath.Base(name)

    file := filepath.Join(dir, base)
    if exists(file) {
        return &ModRef{Path: dir, Name: base}
    }

    file = filepath.Join(dir, base + ".js")
    if exists(file) {
        return &ModRef{Path: dir, Name: base + ".js"}
    }

    file = filepath.Join(dir, base + ".json")
    if exists(file) {
        return &ModRef{Path: dir, Name: base + ".json"}
    }

    return nil
}

func (self Resolver) loadFolder(path, name string) *ModRef {
    dirPath := filepath.Join(path, name)
    pkgFile := filepath.Join(dirPath, "package.json")
    if exists(pkgFile) {
        pkg, err := loadPackage(pkgFile)
        if err != nil {
            log.Panic("Invalid package.json format ", pkgFile)
        }
        if len(pkg.Main) > 0 {
            return self.loadFile(dirPath, pkg.Main)
        }
    }

    file := filepath.Join(dirPath, "index.js")
    if exists(file) {
        return &ModRef{Path: dirPath, Name: "index.js"}
    }

    file = filepath.Join(dirPath, "index.json")
    if exists(file) {
        return &ModRef{Path: dirPath, Name: "index.json"}
    }

    return nil
}

func (self Resolver) loadNodeModule(path, name string) *ModRef {
    absPath, _ := filepath.Abs(path)
    dirPaths := nodeModulePaths(absPath)
    for _, dirPath := range dirPaths {
        log.Println("Trying to load NPM module", name, "from", path)
        if result := self.loadFile(dirPath, name); result != nil {
            return result
        }
        if result := self.loadFolder(dirPath, name); result != nil {
            return result
        }
    }
    return nil
}

func (self Resolver) graph(rootPath, modPath string) ModRefGraph {
    result := ModRefGraph{
        RootPath: rootPath,
        EntryFile: modPath,
        Nodes: make(map[string][][]string),
    }
    self.graph2(result, self.Path, modPath)
    return result
}

func (self Resolver) graph2(result ModRefGraph, relPath, modPath string) *ModRef {
    modRef := self.loadModuleRelativeTo(relPath, modPath)
    if modRef == nil {
        log.Panic("Could not load module: ", modPath, " from ", relPath)
    }

    k := self.relPath(modRef.fullPath())

    if _, exists := result.Nodes[k]; !exists {
        children := modRef.parse()
        // Placeholder to prevent recursive loops.
        // Note: Do we need this if graph never allows for cyclical deps?
        result.Nodes[k] = nil
        childPaths := make([][]string, 0)
        for _, childPath := range children {
            childRef := self.graph2(result, modRef.Path, childPath)
            childRelPath := self.relPath(childRef.fullPath())
            childPaths = append(childPaths, []string{childPath, childRelPath})
        }
        result.Nodes[k] = childPaths
    }
    return modRef
}

func (self Resolver) relPath(path string) string {
    result, _ := filepath.Rel(self.Path, path)
    return result
}

func (self ModRef) fullPath() string {
    return filepath.Join(self.Path, self.Name)
}

// Return map of {moduleName: path, ...} for all dependencies referenced
// by this module.
func (self ModRef) parse() []string {
    fp, _ := os.Open(self.fullPath())
    defer fp.Close()

    scanner := bufio.NewScanner(bufio.NewReader(fp))
    scanner.Split(bufio.ScanLines)

    result := make([]string, 0)
    for scanner.Scan() {
        matches := RequireStmt.FindAllStringSubmatch(scanner.Text(), -1)
        for _, match := range matches {
            // Skip first match (entire unmatched line).
            for _, moduleName := range match[1:] {
                result = append(result, moduleName)
            }
        }
    }
    return result
}

func (self ModRef) writeContents(writer *os.File) {
    fp, _ := os.Open(self.fullPath())
    defer fp.Close()
    io.Copy(writer, fp)
}

// Helpers

func isRelative(name string) bool {
    return strings.HasPrefix(name, "./") || strings.HasPrefix(name, "../")
}

// Return true if a file exists at `path`.
func exists(path string) bool {
    f, err := os.Stat(path)
    if err != nil {
        return false
    }
    return !f.IsDir()
}

func nodeModulePaths(path string) []string {
    result := []string{}
    prevPath := ""
    for ; path != prevPath; {
        result = append(result, filepath.Join(path, "node_modules"))
        prevPath = path
        path = filepath.Dir(path)
    }
    return result
}
<commit_msg>Add support for bundling JSON files<commit_after>package gobundle

import (
    "bufio"
    "encoding/json"
    "io"
    "io/ioutil"
    "log"
    "os"
    "path/filepath"
    "regexp"
    "strconv"
    "strings"
)

// Structures

type NpmPackage struct {
    Name, Main, Version string
}

type Resolver struct {
    Path string
}

type ModRef struct {
    Path, Name string
}

type ModRefGraph struct {
    RootPath string
    EntryFile string
    Nodes map[string][][]string
}

var RequireStmt = regexp.MustCompile(`` +
        `(?i)` +        // Set case-insensitive flag
        `require\(` +
        `(?:"|')` +     // Single or double quote non-capture group
        `([a-z0-9\./\\-]+)` +
        `(?:"|')` +     // Single or double quote non-capture group
        `\)`)

//

func Bundle(entryFile string) ModRefGraph {
    absPath, _ := filepath.Abs(entryFile)
    entryFile = absPath

    rootPath := filepath.Dir(entryFile)
    r := Resolver{Path: rootPath}

    modPath := r.relPath(entryFile)
    return r.graph(rootPath, modPath)
}

func WriteBundle(b *os.File, bundle ModRefGraph) {
    r := Resolver{Path: bundle.RootPath}

    id := makeIdFunc()

    b.WriteString("(function(L, entry) {")
    b.WriteString(    "var cache = {};")
    b.WriteString(    "function run(id) {")
    b.WriteString(        "if (cache[id]) return cache[id];")
    b.WriteString(        "var m = {exports:{}},")
    b.WriteString(            "fn = L[id][0],")
    b.WriteString(            "deps = L[id][1];")
    b.WriteString(        "function require(name) {")
    b.WriteString(            "return run(deps[name]);")
    b.WriteString(        "}")
    b.WriteString(        "cache[id] = m.exports;");
    b.WriteString(        "fn(require, m, m.exports);");
    b.WriteString(        "return m.exports;");
    b.WriteString(    "}")
    b.WriteString(    "run(entry);")
    b.WriteString("}(")

    i := 0
    b.WriteString("{")
    log.Println(bundle.Nodes)
    // TODO: Filter list beforehand
    for path, children := range bundle.Nodes {
        // TODO: Investigate why empty/nil children are being added here.
        // NOTE: Comma appears at the tail end of list if null entry is last
        if len(path) == 0 {
            continue
        }

        modRef := r.loadModule(path)
        if modRef == nil {
            log.Panic("Unable to load module at ", path)
        }

        b.WriteString(strconv.Itoa(id(path)))
        b.WriteString(":[")
        b.WriteString("function(require,module,exports){")
        modRef.writeContents(b)
        b.WriteString("},")

        b.WriteString("{")
        for j, pathTuple := range children {
            childPath := pathTuple[0]
            childRelPath := pathTuple[1]
            b.WriteString("'")
            b.WriteString(childPath)
            b.WriteString("':")
            b.WriteString(strconv.Itoa(id(childRelPath)))
            if j < len(children) - 1 {
                b.WriteString(",")
            }
        }
        b.WriteString("}")

        b.WriteString("]")
        if i < len(bundle.Nodes) - 1 {
            b.WriteString(",")
        }
        i++
    }
    b.WriteString("},")
    b.WriteString(strconv.Itoa(id(bundle.EntryFile)))
    b.WriteString("));\n")
}

//

func (self Resolver) loadModule(name string) *ModRef {
    return self.loadModuleRelativeTo(self.Path, name)
}

func (self Resolver) loadModuleRelativeTo(path, name string) *ModRef {
    log.Println("Trying to load", name, "from", path)
    // NOTE: This important to prevent the case where you have a file name
    // that matches an NPM module. (Ex. you have "shim/jquery.js" which
    // requires "jquery")
    if isRelative(name) {
        if result := self.loadFile(path, name); result != nil {
            return result
        }
        if result := self.loadFolder(path, name); result != nil {
            return result
        }
    }
    if result := self.loadNodeModule(path, name); result != nil {
        return result
    }
    return nil
}

func loadPackage(path string) (*NpmPackage, error) {
    pkg := NpmPackage{}
    data, err := ioutil.ReadFile(path)
    if err != nil {
        return &pkg, err
    }
    err = json.Unmarshal(data, &pkg)
    if err != nil {
        return &pkg, err
    }
    return &pkg, nil
}

func (self Resolver) loadFile(path , name string) *ModRef {
    dir := filepath.Dir(filepath.Join(path, name))
    base := filepath.Base(name)

    file := filepath.Join(dir, base)
    if exists(file) {
        return &ModRef{Path: dir, Name: base}
    }

    file = filepath.Join(dir, base + ".js")
    if exists(file) {
        return &ModRef{Path: dir, Name: base + ".js"}
    }

    file = filepath.Join(dir, base + ".json")
    if exists(file) {
        return &ModRef{Path: dir, Name: base + ".json"}
    }

    return nil
}

func (self Resolver) loadFolder(path, name string) *ModRef {
    dirPath := filepath.Join(path, name)
    pkgFile := filepath.Join(dirPath, "package.json")
    if exists(pkgFile) {
        pkg, err := loadPackage(pkgFile)
        if err != nil {
            log.Panic("Invalid package.json format ", pkgFile)
        }
        if len(pkg.Main) > 0 {
            return self.loadFile(dirPath, pkg.Main)
        }
    }

    file := filepath.Join(dirPath, "index.js")
    if exists(file) {
        return &ModRef{Path: dirPath, Name: "index.js"}
    }

    file = filepath.Join(dirPath, "index.json")
    if exists(file) {
        return &ModRef{Path: dirPath, Name: "index.json"}
    }

    return nil
}

func (self Resolver) loadNodeModule(path, name string) *ModRef {
    absPath, _ := filepath.Abs(path)
    dirPaths := nodeModulePaths(absPath)
    for _, dirPath := range dirPaths {
        log.Println("Trying to load NPM module", name, "from", path)
        if result := self.loadFile(dirPath, name); result != nil {
            return result
        }
        if result := self.loadFolder(dirPath, name); result != nil {
            return result
        }
    }
    return nil
}

func (self Resolver) graph(rootPath, modPath string) ModRefGraph {
    result := ModRefGraph{
        RootPath: rootPath,
        EntryFile: modPath,
        Nodes: make(map[string][][]string),
    }
    self.graph2(result, self.Path, modPath)
    return result
}

func (self Resolver) graph2(result ModRefGraph, relPath, modPath string) *ModRef {
    modRef := self.loadModuleRelativeTo(relPath, modPath)
    if modRef == nil {
        log.Panic("Could not load module: ", modPath, " from ", relPath)
    }

    k := self.relPath(modRef.fullPath())

    if _, exists := result.Nodes[k]; !exists {
        children := modRef.parse()
        // Placeholder to prevent recursive loops.
        // Note: Do we need this if graph never allows for cyclical deps?
        result.Nodes[k] = nil
        childPaths := make([][]string, 0)
        for _, childPath := range children {
            childRef := self.graph2(result, modRef.Path, childPath)
            childRelPath := self.relPath(childRef.fullPath())
            childPaths = append(childPaths, []string{childPath, childRelPath})
        }
        result.Nodes[k] = childPaths
    }
    return modRef
}

func (self Resolver) relPath(path string) string {
    result, _ := filepath.Rel(self.Path, path)
    return result
}

func (self ModRef) fullPath() string {
    return filepath.Join(self.Path, self.Name)
}

// Return map of {moduleName: path, ...} for all dependencies referenced
// by this module.
func (self ModRef) parse() []string {
    fp, _ := os.Open(self.fullPath())
    defer fp.Close()

    scanner := bufio.NewScanner(bufio.NewReader(fp))
    scanner.Split(bufio.ScanLines)

    result := make([]string, 0)
    for scanner.Scan() {
        matches := RequireStmt.FindAllStringSubmatch(scanner.Text(), -1)
        for _, match := range matches {
            // Skip first match (entire unmatched line).
            for _, moduleName := range match[1:] {
                result = append(result, moduleName)
            }
        }
    }
    return result
}

func (self ModRef) writeContents(writer *os.File) {
    fp, _ := os.Open(self.fullPath())
    defer fp.Close()
    if strings.HasSuffix(self.Name, ".json") {
        writer.WriteString("module.exports=")
        io.Copy(writer, fp)
        writer.WriteString(";")
    } else {
        io.Copy(writer, fp)
    }
}

// Helpers

func isRelative(name string) bool {
    return strings.HasPrefix(name, "./") || strings.HasPrefix(name, "../")
}

// Return true if a file exists at `path`.
func exists(path string) bool {
    f, err := os.Stat(path)
    if err != nil {
        return false
    }
    return !f.IsDir()
}

func nodeModulePaths(path string) []string {
    result := []string{}
    prevPath := ""
    for ; path != prevPath; {
        result = append(result, filepath.Join(path, "node_modules"))
        prevPath = path
        path = filepath.Dir(path)
    }
    return result
}
<|endoftext|>


<commit_before>
<commit_msg>Update gocloud.go<commit_after>package gocloud

import (
	"fmt"
	awsAuth "github.com/cloudlibz/gocloud/auth"
	digioceanAuth "github.com/cloudlibz/gocloud/digioceanauth"
	"github.com/cloudlibz/gocloud/aws"
	"github.com/cloudlibz/gocloud/google"
	"github.com/cloudlibz/gocloud/openstack"
	"github.com/cloudlibz/gocloud/azure"
	"github.com/cloudlibz/gocloud/digiocean"
)

// Gocloud is a interface which hides the difference between different cloud providers.
type Gocloud interface {
	Createnode(request interface{}) (resp interface{}, err error)
	Startnode(request interface{}) (resp interface{}, err error)
	Stopnode(request interface{}) (resp interface{}, err error)
	Deletenode(request interface{}) (resp interface{}, err error)
	Rebootnode(request interface{}) (resp interface{}, err error)
	Createdisk(request interface{}) (resp interface{}, err error)
	Deletedisk(request interface{}) (resp interface{}, err error)
	Createsnapshot(request interface{}) (resp interface{}, err error)
	Deletesnapshot(request interface{}) (resp interface{}, err error)
	Attachdisk(request interface{}) (resp interface{}, err error)
	Detachdisk(request interface{}) (resp interface{}, err error)
	Creatloadbalancer(request interface{}) (resp interface{}, err error)
	Deleteloadbalancer(request interface{}) (resp interface{}, err error)
	Listloadbalancer(request interface{}) (resp interface{}, err error)
	Attachnodewithloadbalancer(request interface{}) (resp interface{}, err error)
	Detachnodewithloadbalancer(request interface{}) (resp interface{}, err error)
	Createcluster(request interface{}) (resp interface{}, err error)
	Deletecluster(request interface{}) (resp interface{}, err error)
	Createservice(request interface{}) (resp interface{}, err error)
	Runtask(request interface{}) (resp interface{}, err error)
	Deleteservice(request interface{}) (resp interface{}, err error)
	Stoptask(request interface{}) (resp interface{}, err error)
	Starttask(request interface{}) (resp interface{}, err error)
	Listdns(request interface{}) (resp interface{}, err error)
	Createdns(request interface{}) (resp interface{}, err error)
	Deletedns(request interface{}) (resp interface{}, err error)
	ListResourcednsRecordSets(request interface{}) (resp interface{}, err error)
}

const (
	// Amazonprovider represents Amazon cloud.
	Amazonprovider = "aws"

	// Googleprovider represents Google cloud.
	Googleprovider = "google"

	// Openstackprovider represents Openstack cloud.
	Openstackprovider = "openstack"

	// Azureprovider represents Openstack cloud.
	Azureprovider = "azure"

	// Digioceanprovider represents Digital Ocean cloud.
	Digioceanprovider = "digiocean"
)

// CloudProvider returns the instance of respective cloud and maps it to Gocloud so that we can call
// the method like Createnode on CloudProvider instance.
// This is a delegation of CloudProvider.
func CloudProvider(provider string) (Gocloud, error) {

	switch provider {
	case Amazonprovider:
		// Calls authentication procedure for AWS
		awsAuth.LoadConfig()
		return new(aws.AWS), nil

	case Googleprovider:
		return new(google.Google), nil

	case Openstackprovider:
		return new(openstack.Openstack), nil

	case Digioceanprovider:
		// Calls authentication procedure for Digital Ocean.
		digioceanAuth.LoadConfig()
		return new(digiocean.DigitalOcean), nil

	case Azureprovider:
		return new(azure.Azure), nil

	default:
		return nil, fmt.Errorf("provider %s not recognized", provider)
	}

}
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// 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 ebiten

import (
	"math"
	"sync/atomic"

	"github.com/hajimehoshi/ebiten/internal/graphics"
	"github.com/hajimehoshi/ebiten/internal/opengl"
	"github.com/hajimehoshi/ebiten/internal/restorable"
	"github.com/hajimehoshi/ebiten/internal/ui"
)

func newGraphicsContext(f func(*Image) error) *graphicsContext {
	return &graphicsContext{
		f: f,
	}
}

type graphicsContext struct {
	f           func(*Image) error
	offscreen   *Image
	offscreen2  *Image // TODO: better name
	screen      *Image
	screenScale float64
	initialized int32
	invalidated bool // browser only
}

func (c *graphicsContext) GLContext() *opengl.Context {
	if atomic.LoadInt32(&c.initialized) == 0 {
		return nil
	}
	return ui.GLContext()
}

func (c *graphicsContext) Invalidate() {
	// Note that this is called only on browsers so far.
	// TODO: On mobiles, this function is not called and instead IsTexture is called
	// to detect if the context is lost. This is simple but might not work on some platforms.
	// Should Invalidate be called explicitly?
	c.invalidated = true
}

func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale float64) error {
	if c.screen != nil {
		if err := c.screen.Dispose(); err != nil {
			return err
		}
	}
	if c.offscreen != nil {
		if err := c.offscreen.Dispose(); err != nil {
			return err
		}
	}
	if c.offscreen2 != nil {
		if err := c.offscreen2.Dispose(); err != nil {
			return err
		}
	}
	offscreen, err := newVolatileImage(screenWidth, screenHeight, FilterNearest)
	if err != nil {
		return err
	}

	intScreenScale := int(math.Ceil(screenScale))
	w := screenWidth * intScreenScale
	h := screenHeight * intScreenScale
	offscreen2, err := newVolatileImage(w, h, FilterLinear)
	if err != nil {
		return err
	}

	w = int(float64(screenWidth) * screenScale)
	h = int(float64(screenHeight) * screenScale)
	c.screen, err = newImageWithScreenFramebuffer(w, h)
	if err != nil {
		return err
	}
	if err := c.screen.Clear(); err != nil {
		return err
	}

	c.offscreen = offscreen
	c.offscreen2 = offscreen2
	c.screenScale = screenScale
	return nil
}

func (c *graphicsContext) initializeIfNeeded(context *opengl.Context) error {
	if atomic.LoadInt32(&c.initialized) == 0 {
		if err := graphics.Reset(context); err != nil {
			return err
		}
		atomic.StoreInt32(&c.initialized, 1)
	}
	r, err := c.needsRestoring(context)
	if err != nil {
		return err
	}
	if !r {
		return nil
	}
	if err := c.restore(context); err != nil {
		return err
	}
	return nil
}

func drawWithFittingScale(dst *Image, src *Image) {
	wd, hd := dst.Size()
	ws, hs := src.Size()
	sw := float64(wd) / float64(ws)
	sh := float64(hd) / float64(hs)
	op := &DrawImageOptions{}
	op.GeoM.Scale(sw, sh)
	_ = dst.DrawImage(src, op)
}

func (c *graphicsContext) drawToDefaultRenderTarget(context *opengl.Context) error {
	_ = c.screen.Clear()
	drawWithFittingScale(c.screen, c.offscreen2)
	if err := graphics.FlushCommands(context); err != nil {
		return err
	}
	return nil
}

func (c *graphicsContext) UpdateAndDraw(context *opengl.Context, updateCount int) error {
	if err := c.initializeIfNeeded(context); err != nil {
		return err
	}
	// TODO: Is it OK to restore images here? The images can be in 'stale' state after c.f().
	// (#357)
	if err := restorable.ResolveStalePixels(context); err != nil {
		return err
	}
	for i := 0; i < updateCount; i++ {
		restorable.ClearVolatileImages()
		setRunningSlowly(i < updateCount-1)
		if err := c.f(c.offscreen); err != nil {
			return err
		}
	}
	if 0 < updateCount {
		drawWithFittingScale(c.offscreen2, c.offscreen)
	}
	if err := c.drawToDefaultRenderTarget(context); err != nil {
		return err
	}
	return nil
}

func (c *graphicsContext) restore(context *opengl.Context) error {
	if err := graphics.Reset(context); err != nil {
		return err
	}
	if err := restorable.Restore(context); err != nil {
		return err
	}
	c.invalidated = false
	return nil
}
<commit_msg>graphics: Bug fix: restoring needs to be done after main logic execution (#357)<commit_after>// Copyright 2014 Hajime Hoshi
//
// 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 ebiten

import (
	"math"
	"sync/atomic"

	"github.com/hajimehoshi/ebiten/internal/graphics"
	"github.com/hajimehoshi/ebiten/internal/opengl"
	"github.com/hajimehoshi/ebiten/internal/restorable"
	"github.com/hajimehoshi/ebiten/internal/ui"
)

func newGraphicsContext(f func(*Image) error) *graphicsContext {
	return &graphicsContext{
		f: f,
	}
}

type graphicsContext struct {
	f           func(*Image) error
	offscreen   *Image
	offscreen2  *Image // TODO: better name
	screen      *Image
	screenScale float64
	initialized int32
	invalidated bool // browser only
}

func (c *graphicsContext) GLContext() *opengl.Context {
	if atomic.LoadInt32(&c.initialized) == 0 {
		return nil
	}
	return ui.GLContext()
}

func (c *graphicsContext) Invalidate() {
	// Note that this is called only on browsers so far.
	// TODO: On mobiles, this function is not called and instead IsTexture is called
	// to detect if the context is lost. This is simple but might not work on some platforms.
	// Should Invalidate be called explicitly?
	c.invalidated = true
}

func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale float64) error {
	if c.screen != nil {
		if err := c.screen.Dispose(); err != nil {
			return err
		}
	}
	if c.offscreen != nil {
		if err := c.offscreen.Dispose(); err != nil {
			return err
		}
	}
	if c.offscreen2 != nil {
		if err := c.offscreen2.Dispose(); err != nil {
			return err
		}
	}
	offscreen, err := newVolatileImage(screenWidth, screenHeight, FilterNearest)
	if err != nil {
		return err
	}

	intScreenScale := int(math.Ceil(screenScale))
	w := screenWidth * intScreenScale
	h := screenHeight * intScreenScale
	offscreen2, err := newVolatileImage(w, h, FilterLinear)
	if err != nil {
		return err
	}

	w = int(float64(screenWidth) * screenScale)
	h = int(float64(screenHeight) * screenScale)
	c.screen, err = newImageWithScreenFramebuffer(w, h)
	if err != nil {
		return err
	}
	if err := c.screen.Clear(); err != nil {
		return err
	}

	c.offscreen = offscreen
	c.offscreen2 = offscreen2
	c.screenScale = screenScale
	return nil
}

func (c *graphicsContext) initializeIfNeeded(context *opengl.Context) error {
	if atomic.LoadInt32(&c.initialized) == 0 {
		if err := graphics.Reset(context); err != nil {
			return err
		}
		atomic.StoreInt32(&c.initialized, 1)
	}
	r, err := c.needsRestoring(context)
	if err != nil {
		return err
	}
	if !r {
		return nil
	}
	if err := c.restore(context); err != nil {
		return err
	}
	return nil
}

func drawWithFittingScale(dst *Image, src *Image) {
	wd, hd := dst.Size()
	ws, hs := src.Size()
	sw := float64(wd) / float64(ws)
	sh := float64(hd) / float64(hs)
	op := &DrawImageOptions{}
	op.GeoM.Scale(sw, sh)
	_ = dst.DrawImage(src, op)
}

func (c *graphicsContext) drawToDefaultRenderTarget(context *opengl.Context) error {
	_ = c.screen.Clear()
	drawWithFittingScale(c.screen, c.offscreen2)
	if err := graphics.FlushCommands(context); err != nil {
		return err
	}
	return nil
}

func (c *graphicsContext) UpdateAndDraw(context *opengl.Context, updateCount int) error {
	if err := c.initializeIfNeeded(context); err != nil {
		return err
	}
	for i := 0; i < updateCount; i++ {
		restorable.ClearVolatileImages()
		setRunningSlowly(i < updateCount-1)
		if err := c.f(c.offscreen); err != nil {
			return err
		}
	}
	if 0 < updateCount {
		drawWithFittingScale(c.offscreen2, c.offscreen)
	}
	if err := c.drawToDefaultRenderTarget(context); err != nil {
		return err
	}
	// TODO: Add tests to check if this behavior is correct (#357)
	if err := restorable.ResolveStalePixels(context); err != nil {
		return err
	}
	return nil
}

func (c *graphicsContext) restore(context *opengl.Context) error {
	if err := graphics.Reset(context); err != nil {
		return err
	}
	if err := restorable.Restore(context); err != nil {
		return err
	}
	c.invalidated = false
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Brian J. Downs
//
// 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 main

import (
	"bufio"
	"bytes"
	"fmt"
	"math/rand"
	"os"
	"os/exec"
	"os/signal"
	"time"
)

const wordsLocation = "/usr/share/dict/words"

var err error
var foundWord string
var wordLength int
var playerGuess string
var gameWord string
var signalChan = make(chan os.Signal, 1) // channel to catch ctrl-c

// clearScreen runs a shell clear command
func clearScreen() {
	c := exec.Command("clear")
	c.Stdout = os.Stdout
	c.Run()
}

type game struct {
	word       string
	guessed    map[int]string
	blankWord  string
	maxGuesses int
}

func (g *game) wordLength() int { return len(g.word) }

func (g *game) genStats() {
	var guessCount int
	var guesses bytes.Buffer
	for _, v := range g.guessed {
		guessCount++
		guesses.Write([]byte(fmt.Sprintf("%s, ", v)))
	}
	fmt.Printf("\nGuesses: %d, Guessed: %s", guessCount, guesses.String())
	os.Exit(1)
}

// selectWord will search the installed dictionary for a word that meets
// the length criteria
func selectWord(length int) (string, error) {
	file, err := os.Open(wordsLocation)
	if err != nil {
		return "", err
	}
	defer file.Close()
	var words []string
	rand.Seed(time.Now().UTC().UnixNano())
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if len(scanner.Text()) == length {
			words = append(words, scanner.Text())
		}
	}
	return words[rand.Intn(len(words))], nil
}

func (g *game) setup() {
	fmt.Print("  Press 0 to enter your own word or 1 to generate one: ")
	var wordSetupAnswer int
	fmt.Scanf("%d", &wordSetupAnswer)
	for {
		switch {
		case wordSetupAnswer == 0:
			fmt.Print("  Enter word: ")
			fmt.Scanf("%s", &gameWord)
			g.word = gameWord
			break
		case wordSetupAnswer == 1:
			fmt.Print("  Enter length of word: ")
			fmt.Scanf("%d", &wordLength)
			if foundWord, err = selectWord(wordLength); err != nil {
				fmt.Println(err)
				continue
			}
			g.word = foundWord
			break
		default:
			fmt.Println("  not a valid entry.  Try again.")
			break
		}
		break
	}
	g.genBlankWord()
}

func (g *game) genBlankWord() {
	var preBlank bytes.Buffer
	preBlank.Write([]byte("\n "))
	for i := 1; i <= g.wordLength(); i++ {
		preBlank.Write([]byte("_ "))
	}
	g.blankWord = preBlank.String()
}

func (g *game) letterInWord(pg string) bool {
	for _, i := range g.word {
		if string(i) == pg {
			return true
		}
	}
	return false
}

func main() {
	clearScreen()
	fmt.Println("+ Hangman +")
	g := game{}
	signal.Notify(signalChan, os.Interrupt)
	// setup go routine to catch a ctrl-c
	go func() {
		for range signalChan {
			g.genStats()
		}
	}()
	g.setup()
	for {
		clearScreen()
		fmt.Println(boards[len(g.guessed)])
		fmt.Println(g.blankWord)
		fmt.Print("\nEnter guess: ")
		fmt.Scanf("%s", &playerGuess)
		if g.letterInWord(playerGuess) {
			//
		} else {
			clearScreen()
			g.guessed[len(g.guessed)+1] = playerGuess
			fmt.Println(boards[len(g.guessed)])
			fmt.Println(g.blankWord)
			continue
		}
	}
	os.Exit(0)
}

// boards is a map that holds the different stages of game play
var boards = map[int]string{
	0: `+ Hangman +

`,
	1: `+ Hangman +

 ____|____
`,
	2: `+ Hangman +

     |/
     |
     |
     |
     |
     |
 ____|____
`,
	3: `+ Hangman +
     _________
     |/
     |
     |
     |
     |
     |
 ____|____
`,
	4: `+ Hangman +
     _________
     |/      |
     |
     |
     |
     |
     |
 ____|____
`,
	5: `+ Hangman +
     _________
     |/      |
     |      (_)
     |
     |
     |
     |
 ____|____
`,
	6: `+ Hangman +
     _________
     |/      |
     |      (_)
     |       |
     |
     |
     |
 ____|____
`,
	7: `+ Hangman +
     _________
     |/      |
     |      (_)
     |       |/
     |
     |
     |
 ____|____
`,
	8: `+ Hangman +
     _________
     |/      |
     |      (_)
     |      \|/
     |
     |
     |
 ____|____
`,
	9: `+ Hangman +
     _________
     |/      |
     |      (_)
     |      \|/
     |       |
     |
     |
 ____|____
`,
	10: `+ Hangman +
     _________
     |/      |
     |      (_)
     |      \|/
     |       |
     |        \
     |
 ____|____
`,
	11: `+ Hangman +
     _________
     |/      |
     |      (_)
     |      \|/
     |       |
     |      / \
     |
 ____|____
`,
}
<commit_msg>clean up<commit_after>// Copyright 2015 Brian J. Downs
//
// 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 main

import (
	"bufio"
	"bytes"
	"fmt"
	"math/rand"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"time"
)

const wordsLocation = "/usr/share/dict/words"
const maxGuesses = 12

var err error
var foundWord string
var wordLength int
var playerGuess string
var wordSetupAnswer int
var gameWord string
var signalChan = make(chan os.Signal, 1) // channel to catch ctrl-c

// clearScreen runs a shell clear command
func clearScreen() {
	c := exec.Command("clear")
	c.Stdout = os.Stdout
	c.Run()
}

type game struct {
	word      string
	guessed   map[int]string
	blankWord string
	guessCnt  int
}

func (g *game) wordLength() int { return len(g.word) }

func (g *game) genStats() {
	if len(g.word) == 0 {
		os.Exit(1)
	}
	var guessCount int
	var guesses bytes.Buffer
	for _, v := range g.guessed {
		guessCount++
		guesses.Write([]byte(fmt.Sprintf("%s, ", v)))
	}
	fmt.Printf("\nWord: %s, Guesses: %d, Guessed: %s\n", g.word, guessCount, guesses.String())
	os.Exit(1)
}

// selectWord will search the installed dictionary for a word that meets
// the length criteria
func selectWord(length int) (string, error) {
	file, err := os.Open(wordsLocation)
	if err != nil {
		return "", err
	}
	defer file.Close()
	var words []string
	rand.Seed(time.Now().UTC().UnixNano())
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if len(scanner.Text()) == length {
			words = append(words, scanner.Text())
		}
	}
	return words[rand.Intn(len(words))], nil
}

func (g *game) setup() {
	fmt.Print("  Press 0 to enter your own word or 1 to generate one: ")
	fmt.Scanf("%d", &wordSetupAnswer)
	for {
		switch {
		case wordSetupAnswer == 0:
			fmt.Print("  Enter word: ")
			fmt.Scanf("%s", &gameWord)
			g.word = strings.ToLower(gameWord)
			break
		case wordSetupAnswer == 1:
			fmt.Print("  Enter length of word: ")
			fmt.Scanf("%d", &wordLength)
			if foundWord, err = selectWord(wordLength); err != nil {
				fmt.Println(err)
				continue
			}
			g.word = strings.ToLower(foundWord)
			break
		default:
			fmt.Println("  not a valid entry.  Try again.")
			break
		}
		break
	}
	g.genBlankWord()
}

func (g *game) genBlankWord() {
	var preBlank bytes.Buffer
	preBlank.Write([]byte("\n "))
	for i := 1; i <= g.wordLength(); i++ {
		preBlank.Write([]byte("_ "))
	}
	g.blankWord = preBlank.String()
}

func (g *game) letterInWord(pg string) bool {
	for _, i := range g.word {
		if string(i) == pg {
			return true
		}
	}
	return false
}

func main() {
	clearScreen()
	fmt.Println("+ Hangman +")
	g := game{
		guessed:  make(map[int]string),
		guessCnt: 0,
	}
	signal.Notify(signalChan, os.Interrupt)
	// setup go routine to catch a ctrl-c
	go func() {
		for range signalChan {
			g.genStats()
		}
	}()
	g.setup()
	for {
		if g.guessCnt == maxGuesses {
			g.genStats()
		}
		clearScreen()
		fmt.Println(boards[len(g.guessed)])
		fmt.Println(g.blankWord)
		fmt.Print("\nEnter guess: ")
		fmt.Scanf("%s", &playerGuess)
		if g.letterInWord(playerGuess) {
			g.guessCnt++
			g.guessed[g.guessCnt] = playerGuess
			playerGuess = ""
			continue
		} else {
			clearScreen()
			g.guessed[g.guessCnt] = playerGuess
			fmt.Println(boards[len(g.guessed)])
			fmt.Println(g.blankWord)
			playerGuess = ""
			continue
		}
	}
	os.Exit(0)
}

// boards is a map that holds the different stages of game play
var boards = map[int]string{
	0: `+ Hangman +

`,
	1: `+ Hangman +

 ____|____
`,
	2: `+ Hangman +

     |/
     |
     |
     |
     |
     |
 ____|____
`,
	3: `+ Hangman +
     _________
     |/
     |
     |
     |
     |
     |
 ____|____
`,
	4: `+ Hangman +
     _________
     |/      |
     |
     |
     |
     |
     |
 ____|____
`,
	5: `+ Hangman +
     _________
     |/      |
     |      (_)
     |
     |
     |
     |
 ____|____
`,
	6: `+ Hangman +
     _________
     |/      |
     |      (_)
     |       |
     |
     |
     |
 ____|____
`,
	7: `+ Hangman +
     _________
     |/      |
     |      (_)
     |       |/
     |
     |
     |
 ____|____
`,
	8: `+ Hangman +
     _________
     |/      |
     |      (_)
     |      \|/
     |
     |
     |
 ____|____
`,
	9: `+ Hangman +
     _________
     |/      |
     |      (_)
     |      \|/
     |       |
     |
     |
 ____|____
`,
	10: `+ Hangman +
     _________
     |/      |
     |      (_)
     |      \|/
     |       |
     |        \
     |
 ____|____
`,
	11: `+ Hangman +
     _________
     |/      |
     |      (_)
     |      \|/
     |       |
     |      / \
     |
 ____|____
`,
}
<|endoftext|>


<commit_before>package swarm

import (
	"context"
	"fmt"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	"github.com/libp2p/go-libp2p-core/peer"
)

func getMockDialFunc() (dialWorkerFunc, func(), context.Context, <-chan struct{}) {
	dfcalls := make(chan struct{}, 512) // buffer it large enough that we won't care
	dialctx, cancel := context.WithCancel(context.Background())
	ch := make(chan struct{})
	f := func(p peer.ID, reqch <-chan dialRequest) {
		defer cancel()
		dfcalls <- struct{}{}
		go func() {
			for req := range reqch {
				<-ch
				req.resch <- dialResponse{conn: new(Conn)}
			}
		}()
	}

	var once sync.Once
	return f, func() { once.Do(func() { close(ch) }) }, dialctx, dfcalls
}

func TestBasicDialSync(t *testing.T) {
	df, done, _, callsch := getMockDialFunc()
	dsync := newDialSync(df)
	p := peer.ID("testpeer")

	finished := make(chan struct{}, 2)
	go func() {
		if _, err := dsync.Dial(context.Background(), p); err != nil {
			t.Error(err)
		}
		finished <- struct{}{}
	}()

	go func() {
		if _, err := dsync.Dial(context.Background(), p); err != nil {
			t.Error(err)
		}
		finished <- struct{}{}
	}()

	// short sleep just to make sure we've moved around in the scheduler
	time.Sleep(time.Millisecond * 20)
	done()

	<-finished
	<-finished

	if len(callsch) > 1 {
		t.Fatal("should only have called dial func once!")
	}
}

func TestDialSyncCancel(t *testing.T) {
	df, done, _, dcall := getMockDialFunc()

	dsync := newDialSync(df)

	p := peer.ID("testpeer")

	ctx1, cancel1 := context.WithCancel(context.Background())

	finished := make(chan struct{})
	go func() {
		_, err := dsync.Dial(ctx1, p)
		if err != ctx1.Err() {
			t.Error("should have gotten context error")
		}
		finished <- struct{}{}
	}()

	// make sure the above makes it through the wait code first
	select {
	case <-dcall:
	case <-time.After(time.Second):
		t.Fatal("timed out waiting for dial to start")
	}

	// Add a second dialwait in so two actors are waiting on the same dial
	go func() {
		_, err := dsync.Dial(context.Background(), p)
		if err != nil {
			t.Error(err)
		}
		finished <- struct{}{}
	}()

	time.Sleep(time.Millisecond * 20)

	// cancel the first dialwait, it should not affect the second at all
	cancel1()
	select {
	case <-finished:
	case <-time.After(time.Second):
		t.Fatal("timed out waiting for wait to exit")
	}

	// short sleep just to make sure we've moved around in the scheduler
	time.Sleep(time.Millisecond * 20)
	done()

	<-finished
}

func TestDialSyncAllCancel(t *testing.T) {
	df, done, dctx, _ := getMockDialFunc()

	dsync := newDialSync(df)
	p := peer.ID("testpeer")
	ctx, cancel := context.WithCancel(context.Background())

	finished := make(chan struct{})
	go func() {
		if _, err := dsync.Dial(ctx, p); err != ctx.Err() {
			t.Error("should have gotten context error")
		}
		finished <- struct{}{}
	}()

	// Add a second dialwait in so two actors are waiting on the same dial
	go func() {
		if _, err := dsync.Dial(ctx, p); err != ctx.Err() {
			t.Error("should have gotten context error")
		}
		finished <- struct{}{}
	}()

	cancel()
	for i := 0; i < 2; i++ {
		select {
		case <-finished:
		case <-time.After(time.Second):
			t.Fatal("timed out waiting for wait to exit")
		}
	}

	// the dial should have exited now
	select {
	case <-dctx.Done():
	case <-time.After(time.Second):
		t.Fatal("timed out waiting for dial to return")
	}

	// should be able to successfully dial that peer again
	done()
	if _, err := dsync.Dial(context.Background(), p); err != nil {
		t.Fatal(err)
	}
}

func TestFailFirst(t *testing.T) {
	var count int32
	f := func(p peer.ID, reqch <-chan dialRequest) {
		go func() {
			for {
				req, ok := <-reqch
				if !ok {
					return
				}

				if atomic.LoadInt32(&count) > 0 {
					req.resch <- dialResponse{conn: new(Conn)}
				} else {
					req.resch <- dialResponse{err: fmt.Errorf("gophers ate the modem")}
				}
				atomic.AddInt32(&count, 1)
			}
		}()
	}

	ds := newDialSync(f)
	p := peer.ID("testing")

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()

	if _, err := ds.Dial(ctx, p); err == nil {
		t.Fatal("expected gophers to have eaten the modem")
	}

	c, err := ds.Dial(ctx, p)
	if err != nil {
		t.Fatal(err)
	}
	if c == nil {
		t.Fatal("should have gotten a 'real' conn back")
	}
}

func TestStressActiveDial(t *testing.T) {
	ds := newDialSync(func(p peer.ID, reqch <-chan dialRequest) {
		go func() {
			for {
				req, ok := <-reqch
				if !ok {
					return
				}
				req.resch <- dialResponse{}
			}
		}()
	})

	wg := sync.WaitGroup{}

	pid := peer.ID("foo")

	makeDials := func() {
		for i := 0; i < 10000; i++ {
			ds.Dial(context.Background(), pid)
		}
		wg.Done()
	}

	for i := 0; i < 100; i++ {
		wg.Add(1)
		go makeDials()
	}

	wg.Wait()
}
<commit_msg>swarm: fix race condition in TestFailFirst (#1490)<commit_after>package swarm

import (
	"context"
	"fmt"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	"github.com/libp2p/go-libp2p-core/peer"

	"github.com/stretchr/testify/require"
)

func getMockDialFunc() (dialWorkerFunc, func(), context.Context, <-chan struct{}) {
	dfcalls := make(chan struct{}, 512) // buffer it large enough that we won't care
	dialctx, cancel := context.WithCancel(context.Background())
	ch := make(chan struct{})
	f := func(p peer.ID, reqch <-chan dialRequest) {
		defer cancel()
		dfcalls <- struct{}{}
		go func() {
			for req := range reqch {
				<-ch
				req.resch <- dialResponse{conn: new(Conn)}
			}
		}()
	}

	var once sync.Once
	return f, func() { once.Do(func() { close(ch) }) }, dialctx, dfcalls
}

func TestBasicDialSync(t *testing.T) {
	df, done, _, callsch := getMockDialFunc()
	dsync := newDialSync(df)
	p := peer.ID("testpeer")

	finished := make(chan struct{}, 2)
	go func() {
		if _, err := dsync.Dial(context.Background(), p); err != nil {
			t.Error(err)
		}
		finished <- struct{}{}
	}()

	go func() {
		if _, err := dsync.Dial(context.Background(), p); err != nil {
			t.Error(err)
		}
		finished <- struct{}{}
	}()

	// short sleep just to make sure we've moved around in the scheduler
	time.Sleep(time.Millisecond * 20)
	done()

	<-finished
	<-finished

	if len(callsch) > 1 {
		t.Fatal("should only have called dial func once!")
	}
}

func TestDialSyncCancel(t *testing.T) {
	df, done, _, dcall := getMockDialFunc()

	dsync := newDialSync(df)

	p := peer.ID("testpeer")

	ctx1, cancel1 := context.WithCancel(context.Background())

	finished := make(chan struct{})
	go func() {
		_, err := dsync.Dial(ctx1, p)
		if err != ctx1.Err() {
			t.Error("should have gotten context error")
		}
		finished <- struct{}{}
	}()

	// make sure the above makes it through the wait code first
	select {
	case <-dcall:
	case <-time.After(time.Second):
		t.Fatal("timed out waiting for dial to start")
	}

	// Add a second dialwait in so two actors are waiting on the same dial
	go func() {
		_, err := dsync.Dial(context.Background(), p)
		if err != nil {
			t.Error(err)
		}
		finished <- struct{}{}
	}()

	time.Sleep(time.Millisecond * 20)

	// cancel the first dialwait, it should not affect the second at all
	cancel1()
	select {
	case <-finished:
	case <-time.After(time.Second):
		t.Fatal("timed out waiting for wait to exit")
	}

	// short sleep just to make sure we've moved around in the scheduler
	time.Sleep(time.Millisecond * 20)
	done()

	<-finished
}

func TestDialSyncAllCancel(t *testing.T) {
	df, done, dctx, _ := getMockDialFunc()

	dsync := newDialSync(df)
	p := peer.ID("testpeer")
	ctx, cancel := context.WithCancel(context.Background())

	finished := make(chan struct{})
	go func() {
		if _, err := dsync.Dial(ctx, p); err != ctx.Err() {
			t.Error("should have gotten context error")
		}
		finished <- struct{}{}
	}()

	// Add a second dialwait in so two actors are waiting on the same dial
	go func() {
		if _, err := dsync.Dial(ctx, p); err != ctx.Err() {
			t.Error("should have gotten context error")
		}
		finished <- struct{}{}
	}()

	cancel()
	for i := 0; i < 2; i++ {
		select {
		case <-finished:
		case <-time.After(time.Second):
			t.Fatal("timed out waiting for wait to exit")
		}
	}

	// the dial should have exited now
	select {
	case <-dctx.Done():
	case <-time.After(time.Second):
		t.Fatal("timed out waiting for dial to return")
	}

	// should be able to successfully dial that peer again
	done()
	if _, err := dsync.Dial(context.Background(), p); err != nil {
		t.Fatal(err)
	}
}

func TestFailFirst(t *testing.T) {
	var count int32
	dialErr := fmt.Errorf("gophers ate the modem")
	f := func(p peer.ID, reqch <-chan dialRequest) {
		go func() {
			for {
				req, ok := <-reqch
				if !ok {
					return
				}

				if atomic.CompareAndSwapInt32(&count, 0, 1) {
					req.resch <- dialResponse{err: dialErr}
				} else {
					req.resch <- dialResponse{conn: new(Conn)}
				}
			}
		}()
	}

	ds := newDialSync(f)
	p := peer.ID("testing")

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()

	_, err := ds.Dial(ctx, p)
	require.ErrorIs(t, err, dialErr, "expected gophers to have eaten the modem")

	c, err := ds.Dial(ctx, p)
	require.NoError(t, err)
	require.NotNil(t, c, "should have gotten a 'real' conn back")
}

func TestStressActiveDial(t *testing.T) {
	ds := newDialSync(func(p peer.ID, reqch <-chan dialRequest) {
		go func() {
			for {
				req, ok := <-reqch
				if !ok {
					return
				}
				req.resch <- dialResponse{}
			}
		}()
	})

	wg := sync.WaitGroup{}

	pid := peer.ID("foo")

	makeDials := func() {
		for i := 0; i < 10000; i++ {
			ds.Dial(context.Background(), pid)
		}
		wg.Done()
	}

	for i := 0; i < 100; i++ {
		wg.Add(1)
		go makeDials()
	}

	wg.Wait()
}
<|endoftext|>