<commit_before>package main

import (
	"fmt"
	"strconv"
	"unicode"
)

/* XXX eventually i'll need to modify these functions so they take a command struct or a variable
 * number of interfaces so that i can pass arguments.
 */

// normal commands
var normalFns map[int]func(*GlobalState) = map[int]func(*GlobalState){
	'j': normalj,
	'k': normalk,
	'l': normall,
	';': normalSemiColon,
	'p': normalp,
	'P': normalP, // will fix later
	'G': normalG,
	'u': normalu,
	'a': normala,
	'i': normali,
	'o': normalo,
	'O': normalO,
	// 'n':  nextBuffer,
	// 'p':  prevBuffer,
	':': normalColon,
	'-': normalMinus,
	'+': normalPlus,
	'#': normalHash,
	' ': normalSpace,
	'!': normalBang,
	'<': normalLShift,
	'>': normalRShift,
	'$': normalDollar,
	'0': normal0,
	1:   normalCtlA, // ^A
	2:   normalCtlB, // ^B
	// 3: normalCtlC, // ^C
	4:  normalCtlD,   // ^D
	5:  normalCtlE,   // ^E
	6:  normalCtlF,   // ^F
	7:  normalCtlG,   // ^G
	8:  normalCtlH,   // ^H
	9:  normalCtlI,   // ^I
	10: normalCtlJ,   // ^J
	11: normalCtlK,   // ^K
	12: normalCtlL,   // ^L
	13: normalCtlM,   // ^M
	16: normalCtlP,   // ^P
	20: normalCtlT,   // ^T
	21: normalCtlU,   // ^U
	23: normalCtlW,   // ^W
	25: normalCtlY,   // ^Y
	26: normalCtlZ,   // ^Z
	29: normalCtlRSB, // ^] (right square bracket)
	// x: normalCtlCaret
	ESC: cmdClear,
}

func normalj(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// left
		ln := b.line()
		if ln.cursor()-gs.n.cnt < 0 {
			ln.move(0)
			Beep()
		} else {
			ln.move(ln.cursor() - gs.n.cnt)
		}
	}
}

func normalk(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// down
		if b.lno+gs.n.cnt < len(b.lines)-1 {
			b.lno += gs.n.cnt
		} else {
			b.lno = len(b.lines) - 1
			Beep()
		}

		// TODO column needs to be maintained for the down/up commands (even if the line you
		// move to is not long enough).
	}
}

func normall(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// up
		if b.lno-gs.n.cnt > 0 {
			b.lno -= gs.n.cnt
		} else {
			b.lno = 0
			Beep()
		}
	}
}

func normalSemiColon(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// right
		ln := b.line()
		if ln.cursor()+gs.n.cnt < len(ln.raw()) {
			ln.move(ln.cursor() + gs.n.cnt)
		} else {
			ln.move(len(ln.raw()) - 1)
			Beep()
		}
	}
}

func normalp(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// paste
		gs.queueMessage(&Message{
			"paste.",
			false,
		})
	}
}

func normalP(gs *GlobalState) {
}

func normalG(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		b.lno = len(b.lines) - 1
	}
}

func normalu(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// rewind
	}
}

func normala(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// appendInput
		appendInsert(gs)
	}
}

func normali(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		insert(gs)
	}
}

func normalo(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		openInsert(gs)
	}
}

func normalO(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		aboveOpenInsert(gs)
	}
}

func normalColon(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		ex(gs)
	}
}

func normalMinus(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalPlus(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalHash(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalSpace(gs *GlobalState) {
	normalSemiColon(gs)
}

func normalBang(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalLShift(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalRShift(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalDollar(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		cnt := gs.n.cnt - 1
		if b.lno+cnt > len(b.lines)-1 {
			return
		}

		b.lno += cnt
		ln := b.line()
		ln.move(len(ln.raw()) - 1)
	}
}

func normal0(gs *GlobalState) {
}

func normalCtlA(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlB(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlD(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// scroll down
	}
}

func normalCtlE(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlF(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlG(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		mod := "modified"
		if !b.isDirty() {
			mod = "un" + mod
		}
		// XXX This is actual not correct.  When the file is empty, we want to show "empty
		// file" rather than file position information.
		info := "empty file"
		if lns := len(b.lines); lns > 1 || len(b.line().raw()) > 0 {
			lno := b.lno + 1
			per := int((float32(lno) / float32(lns)) * 100)
			info = fmt.Sprintf("line %d of %d [%d%]", lno, lns, per)
		}
		gs.queueMessage(&Message{
			fmt.Sprintf("%s: %s: %s", b.ident(), mod, info),
			false,
		})
	}
}

func normalCtlH(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlI(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlJ(gs *GlobalState) {
	normalj(gs)
}

func normalCtlK(gs *GlobalState) {
	normalk(gs)
}

func normalCtlL(gs *GlobalState) {
	// repaint
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlM(gs *GlobalState) {
	normalPlus(gs)
}

func normalCtlP(gs *GlobalState) {
	normalk(gs)
}

func normalCtlT(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlU(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlW(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

// XXX ^y and ^z are fucked
func normalCtlY(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlZ(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlRSB(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func nextBuffer(gs *GlobalState) {
	r := gs.NextBuffer()
	gs.queueMessage(&Message{
		gs.curBuf().ident(),
		r == nil,
	})
}

func prevBuffer(gs *GlobalState) {
	r := gs.PrevBuffer()
	gs.queueMessage(&Message{
		gs.curBuf().ident(),
		r == nil,
	})
}

func cmdClear(gs *GlobalState) {
	gs.cmd = ""
	gs.n.cnt = 1
}

type Nm struct {
	buf string
	cnt int
}

// normal mode
func NormalMode(gs *GlobalState) {
	gs.Mode = MODENORMAL

	m := NewNormalModeline()
	gs.SetModeline(m)

	// advertise the current buffer
	gs.queueMessage(&Message{
		gs.curBuf().ident(),
		false,
	})

	gs.n = new(Nm)

	buf := ""
	gs.n.cnt = 1
	for {
		window := gs.Window
		window.PaintMapper(0, window.Rows-1, true)
		gs.UpdateCh <- 1
		k := <-gs.InputCh // screen.Window.Getch()

		if !unicode.IsDigit(k) {
			if len(buf) == 0 {
				gs.n.cnt = 1
				buf = string(k)
			} else {
				if cnt, e := strconv.Atoi(buf); e == nil {
					gs.n.cnt = cnt
					buf = string(k)
				}
			}

			if fn, ok := normalFns[k]; ok {
				fn(gs)
			}
			buf = ""
		} else {
			buf += string(k)
		}

		if gs.Mode != MODENORMAL {
			gs.Mode = MODENORMAL
			gs.SetModeline(m)
		}
		m.Key = k
		gs.curbuf.Value.(*EditBuffer).redraw = true
	}
}
<commit_msg>nmcmd<commit_after>package main

import (
	"fmt"
	"strconv"
	"unicode"
)

/* XXX eventually i'll need to modify these functions so they take a command struct or a variable
 * number of interfaces so that i can pass arguments.
 */

type nmcmd struct {
	fn     func(*GlobalState)
	usage  string
	motion bool
}

// normal commands
var normalFns map[int]*nmcmd = map[int]*nmcmd{
	'j': &nmcmd{
		normalj,
		"[count]j",
		false,
	},
	'k': &nmcmd{
		normalk,
		"[count]k",
		false,
	},
	'l': &nmcmd{
		normall,
		"[count]l",
		false,
	},
	';': &nmcmd{
		normalSemiColon,
		"[count];",
		false,
	},
	'p': &nmcmd{
		normalp,
		"",
		false,
	},
	'P': &nmcmd{
		normalP,
		"",
		false,
	},
	'G': &nmcmd{
		normalG,
		"",
		false,
	},
	'u': &nmcmd{
		normalu,
		"",
		false,
	},
	'a': &nmcmd{
		normala,
		"",
		false,
	},
	'i': &nmcmd{
		normali,
		"",
		false,
	},
	'o': &nmcmd{
		normalo,
		"",
		false,
	},
	'O': &nmcmd{
		normalO,
		"",
		false,
	},
	':': &nmcmd{
		normalColon,
		":",
		false,
	},
	'-': &nmcmd{
		normalMinus,
		"",
		false,
	},
	'+': &nmcmd{
		normalPlus,
		"",
		false,
	},
	'#': &nmcmd{
		normalHash,
		"",
		false,
	},
	' ': &nmcmd{
		normalSpace,
		"",
		false,
	},
	'!': &nmcmd{
		normalBang,
		"",
		false,
	},
	'<': &nmcmd{
		normalLShift,
		"",
		false,
	},
	'>': &nmcmd{
		normalRShift,
		"",
		false,
	},
	'$': &nmcmd{
		normalDollar,
		"",
		false,
	},
	'0': &nmcmd{
		normal0,
		"",
		false,
	},
	1: &nmcmd{
		normalCtlA,
		"",
		false,
	}, // ^A
	2: &nmcmd{
		normalCtlB,
		"",
		false,
	}, // ^B
	// 3: normalCtlC, // ^C
	4: &nmcmd{
		normalCtlD,
		"",
		false,
	}, // ^D
	5: &nmcmd{
		normalCtlE,
		"",
		false,
	}, // ^E
	6: &nmcmd{
		normalCtlF,
		"",
		false,
	}, // ^F
	7: &nmcmd{
		normalCtlG,
		"",
		false,
	}, // ^G
	8: &nmcmd{
		normalCtlH,
		"",
		false,
	}, // ^H
	9: &nmcmd{
		normalCtlI,
		"",
		false,
	}, // ^I
	10: &nmcmd{
		normalCtlJ,
		"",
		false,
	}, // ^J
	11: &nmcmd{
		normalCtlK,
		"",
		false,
	}, // ^K
	12: &nmcmd{
		normalCtlL,
		"",
		false,
	}, // ^L
	13: &nmcmd{
		normalCtlM,
		"",
		false,
	}, // ^M
	16: &nmcmd{
		normalCtlP,
		"",
		false,
	}, // ^P
	20: &nmcmd{
		normalCtlT,
		"",
		false,
	}, // ^T
	21: &nmcmd{
		normalCtlU,
		"",
		false,
	}, // ^U
	23: &nmcmd{
		normalCtlW,
		"",
		false,
	}, // ^W
	25: &nmcmd{
		normalCtlY,
		"",
		false,
	}, // ^Y
	26: &nmcmd{
		normalCtlZ,
		"",
		false,
	}, // ^Z
	29: &nmcmd{
		normalCtlRSB,
		"",
		false,
	}, // ^] (right square bracket)
	// x: normalCtlCaret
	ESC: &nmcmd{
		cmdClear,
		"",
		false,
	},
}

func normalj(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// left
		ln := b.line()
		if ln.cursor()-gs.n.cnt < 0 {
			ln.move(0)
			Beep()
		} else {
			ln.move(ln.cursor() - gs.n.cnt)
		}
	}
}

func normalk(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// down
		if b.lno+gs.n.cnt < len(b.lines)-1 {
			b.lno += gs.n.cnt
		} else {
			b.lno = len(b.lines) - 1
			Beep()
		}

		// TODO column needs to be maintained for the down/up commands (even if the line you
		// move to is not long enough).
	}
}

func normall(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// up
		if b.lno-gs.n.cnt > 0 {
			b.lno -= gs.n.cnt
		} else {
			b.lno = 0
			Beep()
		}
	}
}

func normalSemiColon(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// right
		ln := b.line()
		if ln.cursor()+gs.n.cnt < len(ln.raw()) {
			ln.move(ln.cursor() + gs.n.cnt)
		} else {
			ln.move(len(ln.raw()) - 1)
			Beep()
		}
	}
}

func normalp(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// paste
		gs.queueMessage(&Message{
			"paste.",
			false,
		})
	}
}

func normalP(gs *GlobalState) {
}

func normalG(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		b.lno = len(b.lines) - 1
	}
}

func normalu(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// rewind
	}
}

func normala(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// appendInput
		appendInsert(gs)
	}
}

func normali(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		insert(gs)
	}
}

func normalo(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		openInsert(gs)
	}
}

func normalO(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		aboveOpenInsert(gs)
	}
}

func normalColon(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		ex(gs)
	}
}

func normalMinus(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalPlus(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalHash(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalSpace(gs *GlobalState) {
	normalSemiColon(gs)
}

func normalBang(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalLShift(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalRShift(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalDollar(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		cnt := gs.n.cnt - 1
		if b.lno+cnt > len(b.lines)-1 {
			return
		}

		b.lno += cnt
		ln := b.line()
		ln.move(len(ln.raw()) - 1)
	}
}

func normal0(gs *GlobalState) {
}

func normalCtlA(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlB(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlD(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		// scroll down
	}
}

func normalCtlE(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlF(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlG(gs *GlobalState) {
	switch c := gs.curBuf(); b := c.(type) {
	case *EditBuffer:
		mod := "modified"
		if !b.isDirty() {
			mod = "un" + mod
		}
		info := "empty file"
		if lns := len(b.lines); lns > 1 || len(b.line().raw()) > 0 {
			lno := b.lno + 1
			per := int((float32(lno) / float32(lns)) * 100)
			info = fmt.Sprintf("line %d of %d [%d%]", lno, lns, per)
		}
		gs.queueMessage(&Message{
			fmt.Sprintf("%s: %s: %s", b.ident(), mod, info),
			false,
		})
	}
}

func normalCtlH(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlI(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlJ(gs *GlobalState) {
	normalj(gs)
}

func normalCtlK(gs *GlobalState) {
	normalk(gs)
}

func normalCtlL(gs *GlobalState) {
	// repaint
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlM(gs *GlobalState) {
	normalPlus(gs)
}

func normalCtlP(gs *GlobalState) {
	normalk(gs)
}

func normalCtlT(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlU(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlW(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

// XXX ^y and ^z are fucked
func normalCtlY(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlZ(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func normalCtlRSB(gs *GlobalState) {
	gs.queueMessage(&Message{
		"not implemented",
		true,
	})
}

func nextBuffer(gs *GlobalState) {
	r := gs.NextBuffer()
	gs.queueMessage(&Message{
		gs.curBuf().ident(),
		r == nil,
	})
}

func prevBuffer(gs *GlobalState) {
	r := gs.PrevBuffer()
	gs.queueMessage(&Message{
		gs.curBuf().ident(),
		r == nil,
	})
}

func cmdClear(gs *GlobalState) {
	gs.cmd = ""
	gs.n.cnt = 1
}

type Nm struct {
	buf string
	cmd int
	cnt int
	mtn int
}

// normal mode
func NormalMode(gs *GlobalState) {
	gs.Mode = MODENORMAL

	m := NewNormalModeline()
	gs.SetModeline(m)

	// advertise the current buffer
	gs.queueMessage(&Message{
		gs.curBuf().ident(),
		false,
	})

	gs.n = new(Nm)

	buf := ""
	gs.n.cnt = 1
	for {
		window := gs.Window
		window.PaintMapper(0, window.Rows-1, true)
		gs.UpdateCh <- 1
		k := <-gs.InputCh // screen.Window.Getch()

		if !unicode.IsDigit(k) {
			if len(buf) == 0 {
				gs.n.cnt = 1
				buf = string(k)
			} else {
				if cnt, e := strconv.Atoi(buf); e == nil {
					gs.n.cnt = cnt
					buf = string(k)
				}
			}

			if cmd, ok := normalFns[k]; ok {
				// XXX motion
				if cmd.motion {
					m := <-gs.InputCh
					gs.n.mtn = m
				}
				cmd.fn(gs)
			}
			buf = ""
		} else {
			buf += string(k)
		}

		if gs.Mode != MODENORMAL {
			gs.Mode = MODENORMAL
			gs.SetModeline(m)
		}
		m.Key = k
		gs.curbuf.Value.(*EditBuffer).redraw = true
	}
}
<|endoftext|>


<commit_before>/*
 * This file is part of the libvirt-go-xml project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Copyright (C) 2016 Red Hat, Inc.
 *
 */

package libvirtxml

import (
	"encoding/xml"
)

type CapsHostCPUTopology struct {
	Sockets int `xml:"sockets,attr"`
	Cores   int `xml:"cores,attr"`
	Threads int `xml:"threads,attr"`
}

type CapsHostCPUFeature struct {
	Name string `xml:"name,attr"`
}

type CapsHostCPUPageSize struct {
	Size int    `xml:"size,attr"`
	Unit string `xml:"unit,attr"`
}

type CapsHostCPU struct {
	Arch      string                `xml:"arch"`
	Model     string                `xml:"model"`
	Vendor    string                `xml:"vendor"`
	Topology  CapsHostCPUTopology   `xml:"topology"`
	Features  []CapsHostCPUFeature  `xml:"feature"`
	PageSizes []CapsHostCPUPageSize `xml:"pages"`
}

type CapsHostNUMAMemory struct {
	Size int    `xml:"size,attr"`
	Unit string `xml:"unit,attr"`
}

type CapsHostNUMAPageInfo struct {
	Size  int    `xml:"size,attr"`
	Unit  string `xml:"unit,attr"`
	Count int    `xml:",chardata"`
}

type CapsHostNUMACPU struct {
	ID       int    `xml:"id,attr"`
	SocketID int    `xml:"socket_id,attr"`
	CoreID   int    `xml:"core_id,attr"`
	Siblings string `xml:"siblings,attr"`
}

type CapsHostNUMADistance struct {
	ID    int `xml:"id,attr"`
	Value int `xml:"value,attr"`
}

type CapsHostNUMACell struct {
	ID        int                    `xml:"id,attr"`
	Memory    []CapsHostNUMAMemory   `xml:"memory"`
	PageInfo  []CapsHostNUMAPageInfo `xml:"pages"`
	Distances []CapsHostNUMADistance `xml:"distances>sibling"`
	CPUS      []CapsHostNUMACPU      `xml:"cpus>cpu"`
}

type CapsHostNUMATopology struct {
	Cells []CapsHostNUMACell `xml:"cells>cell"`
}

type CapsHostSecModelLabel struct {
	Type  string `xml:"type,attr"`
	Value string `xml:",chardata"`
}

type CapsHostSecModel struct {
	Name   string                  `xml:"model"`
	DOI    string                  `xml:"doi"`
	Labels []CapsHostSecModelLabel `xml:"baselabel"`
}

type CapsHost struct {
	UUID     string                `xml:"uuid"`
	CPU      *CapsHostCPU          `xml:"cpu"`
	NUMA     *CapsHostNUMATopology `xml:"topology"`
	SecModel []CapsHostSecModel    `xml:"secmodel"`
}

type CapsGuestMachine struct {
	Name      string  `xml:",chardata"`
	MaxCPUs   int     `xml:"maxCpus,attr"`
	Canonical *string `xml:"canonical,attr"`
}

type CapsGuestDomain struct {
	Type     string             `xml:"type,attr"`
	Emulator string             `xml:"emulator"`
	Machines []CapsGuestMachine `xml:"machine"`
}

type CapsGuestArch struct {
	Name     string             `xml:"name,attr"`
	WordSize string             `xml:"wordsize"`
	Emulator string             `xml:"emulator"`
	Machines []CapsGuestMachine `xml:"machine"`
	Domains  []CapsGuestDomain  `xml:"domain"`
}

type CapsGuestFeatures struct {
	CPUSelection *struct{} `xml:"cpuselection"`
	DeviceBoot   *struct{} `xml:"deviceboot"`
}

type CapsGuest struct {
	OSType   string             `xml:"os_type"`
	Arch     CapsGuestArch      `xml:"arch"`
	Features *CapsGuestFeatures `xml:"features"`
}

type Caps struct {
	XMLName xml.Name    `xml:"capabilities"`
	Host    CapsHost    `xml:"host"`
	Guests  []CapsGuest `xml:"guest"`
}

func (c *Caps) Unmarshal(doc string) error {
	return xml.Unmarshal([]byte(doc), c)
}

func (c *Caps) Marshal() (string, error) {
	doc, err := xml.MarshalIndent(c, "", "  ")
	if err != nil {
		return "", err
	}
	return string(doc), nil
}
<commit_msg>There is only a single <memory> element per NUMA node<commit_after>/*
 * This file is part of the libvirt-go-xml project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Copyright (C) 2016 Red Hat, Inc.
 *
 */

package libvirtxml

import (
	"encoding/xml"
)

type CapsHostCPUTopology struct {
	Sockets int `xml:"sockets,attr"`
	Cores   int `xml:"cores,attr"`
	Threads int `xml:"threads,attr"`
}

type CapsHostCPUFeature struct {
	Name string `xml:"name,attr"`
}

type CapsHostCPUPageSize struct {
	Size int    `xml:"size,attr"`
	Unit string `xml:"unit,attr"`
}

type CapsHostCPU struct {
	Arch      string                `xml:"arch"`
	Model     string                `xml:"model"`
	Vendor    string                `xml:"vendor"`
	Topology  CapsHostCPUTopology   `xml:"topology"`
	Features  []CapsHostCPUFeature  `xml:"feature"`
	PageSizes []CapsHostCPUPageSize `xml:"pages"`
}

type CapsHostNUMAMemory struct {
	Size int    `xml:"size,attr"`
	Unit string `xml:"unit,attr"`
}

type CapsHostNUMAPageInfo struct {
	Size  int    `xml:"size,attr"`
	Unit  string `xml:"unit,attr"`
	Count int    `xml:",chardata"`
}

type CapsHostNUMACPU struct {
	ID       int    `xml:"id,attr"`
	SocketID int    `xml:"socket_id,attr"`
	CoreID   int    `xml:"core_id,attr"`
	Siblings string `xml:"siblings,attr"`
}

type CapsHostNUMADistance struct {
	ID    int `xml:"id,attr"`
	Value int `xml:"value,attr"`
}

type CapsHostNUMACell struct {
	ID        int                    `xml:"id,attr"`
	Memory    CapsHostNUMAMemory     `xml:"memory"`
	PageInfo  []CapsHostNUMAPageInfo `xml:"pages"`
	Distances []CapsHostNUMADistance `xml:"distances>sibling"`
	CPUS      []CapsHostNUMACPU      `xml:"cpus>cpu"`
}

type CapsHostNUMATopology struct {
	Cells []CapsHostNUMACell `xml:"cells>cell"`
}

type CapsHostSecModelLabel struct {
	Type  string `xml:"type,attr"`
	Value string `xml:",chardata"`
}

type CapsHostSecModel struct {
	Name   string                  `xml:"model"`
	DOI    string                  `xml:"doi"`
	Labels []CapsHostSecModelLabel `xml:"baselabel"`
}

type CapsHost struct {
	UUID     string                `xml:"uuid"`
	CPU      *CapsHostCPU          `xml:"cpu"`
	NUMA     *CapsHostNUMATopology `xml:"topology"`
	SecModel []CapsHostSecModel    `xml:"secmodel"`
}

type CapsGuestMachine struct {
	Name      string  `xml:",chardata"`
	MaxCPUs   int     `xml:"maxCpus,attr"`
	Canonical *string `xml:"canonical,attr"`
}

type CapsGuestDomain struct {
	Type     string             `xml:"type,attr"`
	Emulator string             `xml:"emulator"`
	Machines []CapsGuestMachine `xml:"machine"`
}

type CapsGuestArch struct {
	Name     string             `xml:"name,attr"`
	WordSize string             `xml:"wordsize"`
	Emulator string             `xml:"emulator"`
	Machines []CapsGuestMachine `xml:"machine"`
	Domains  []CapsGuestDomain  `xml:"domain"`
}

type CapsGuestFeatures struct {
	CPUSelection *struct{} `xml:"cpuselection"`
	DeviceBoot   *struct{} `xml:"deviceboot"`
}

type CapsGuest struct {
	OSType   string             `xml:"os_type"`
	Arch     CapsGuestArch      `xml:"arch"`
	Features *CapsGuestFeatures `xml:"features"`
}

type Caps struct {
	XMLName xml.Name    `xml:"capabilities"`
	Host    CapsHost    `xml:"host"`
	Guests  []CapsGuest `xml:"guest"`
}

func (c *Caps) Unmarshal(doc string) error {
	return xml.Unmarshal([]byte(doc), c)
}

func (c *Caps) Marshal() (string, error) {
	doc, err := xml.MarshalIndent(c, "", "  ")
	if err != nil {
		return "", err
	}
	return string(doc), nil
}
<|endoftext|>


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

package walk

import (
	"syscall"
	"unsafe"
)

import (
	"github.com/lxn/win"
)

const (
	DlgCmdNone     = 0
	DlgCmdOK       = win.IDOK
	DlgCmdCancel   = win.IDCANCEL
	DlgCmdAbort    = win.IDABORT
	DlgCmdRetry    = win.IDRETRY
	DlgCmdIgnore   = win.IDIGNORE
	DlgCmdYes      = win.IDYES
	DlgCmdNo       = win.IDNO
	DlgCmdClose    = win.IDCLOSE
	DlgCmdHelp     = win.IDHELP
	DlgCmdTryAgain = win.IDTRYAGAIN
	DlgCmdContinue = win.IDCONTINUE
	DlgCmdTimeout  = win.IDTIMEOUT
)

const dialogWindowClass = `\o/ Walk_Dialog_Class \o/`

func init() {
	MustRegisterWindowClass(dialogWindowClass)
}

type dialogish interface {
	DefaultButton() *PushButton
	CancelButton() *PushButton
}

type Dialog struct {
	FormBase
	result               int
	defaultButton        *PushButton
	cancelButton         *PushButton
	centerInOwnerWhenRun bool
}

func NewDialog(owner Form) (*Dialog, error) {
	return newDialogWithStyle(owner, win.WS_THICKFRAME)
}

func NewDialogWithFixedSize(owner Form) (*Dialog, error) {
	return newDialogWithStyle(owner, 0)
}

func newDialogWithStyle(owner Form, style uint32) (*Dialog, error) {
	dlg := &Dialog{
		FormBase: FormBase{
			owner: owner,
		},
	}

	if err := InitWindow(
		dlg,
		owner,
		dialogWindowClass,
		win.WS_CAPTION|win.WS_SYSMENU|style,
		win.WS_EX_DLGMODALFRAME); err != nil {
		return nil, err
	}

	succeeded := false
	defer func() {
		if !succeeded {
			dlg.Dispose()
		}
	}()

	dlg.centerInOwnerWhenRun = owner != nil

	// This forces display of focus rectangles, as soon as the user starts to type.
	dlg.SendMessage(win.WM_CHANGEUISTATE, win.UIS_INITIALIZE, 0)

	dlg.result = DlgCmdNone

	succeeded = true

	return dlg, nil
}

func (dlg *Dialog) DefaultButton() *PushButton {
	return dlg.defaultButton
}

func (dlg *Dialog) SetDefaultButton(button *PushButton) error {
	if button != nil && !win.IsChild(dlg.hWnd, button.hWnd) {
		return newError("not a descendant of the dialog")
	}

	succeeded := false
	if dlg.defaultButton != nil {
		if err := dlg.defaultButton.setAndClearStyleBits(win.BS_PUSHBUTTON, win.BS_DEFPUSHBUTTON); err != nil {
			return err
		}
		defer func() {
			if !succeeded {
				dlg.defaultButton.setAndClearStyleBits(win.BS_DEFPUSHBUTTON, win.BS_PUSHBUTTON)
			}
		}()
	}

	if button != nil {
		if err := button.setAndClearStyleBits(win.BS_DEFPUSHBUTTON, win.BS_PUSHBUTTON); err != nil {
			return err
		}
	}

	dlg.defaultButton = button

	succeeded = true

	return nil
}

func (dlg *Dialog) CancelButton() *PushButton {
	return dlg.cancelButton
}

func (dlg *Dialog) SetCancelButton(button *PushButton) error {
	if button != nil && !win.IsChild(dlg.hWnd, button.hWnd) {
		return newError("not a descendant of the dialog")
	}

	dlg.cancelButton = button

	return nil
}

func (dlg *Dialog) Result() int {
	return dlg.result
}

func (dlg *Dialog) Accept() {
	dlg.Close(DlgCmdOK)
}

func (dlg *Dialog) Cancel() {
	dlg.Close(DlgCmdCancel)
}

func (dlg *Dialog) Close(result int) {
	dlg.result = result

	dlg.FormBase.Close()
}

func firstFocusableDescendantCallback(hwnd win.HWND, lParam uintptr) uintptr {
	widget := windowFromHandle(hwnd)

	if widget == nil || !widget.Visible() || !widget.Enabled() {
		return 1
	}

	style := uint(win.GetWindowLong(hwnd, win.GWL_STYLE))
	// FIXME: Ugly workaround for NumberEdit
	_, isTextSelectable := widget.(textSelectable)
	if style&win.WS_TABSTOP > 0 || isTextSelectable {
		hwndPtr := (*win.HWND)(unsafe.Pointer(lParam))
		*hwndPtr = hwnd
		return 0
	}

	return 1
}

var firstFocusableDescendantCallbackPtr = syscall.NewCallback(firstFocusableDescendantCallback)

func firstFocusableDescendant(container Container) Window {
	var hwnd win.HWND

	win.EnumChildWindows(container.Handle(), firstFocusableDescendantCallbackPtr, uintptr(unsafe.Pointer(&hwnd)))

	return windowFromHandle(hwnd)
}

type textSelectable interface {
	SetTextSelection(start, end int)
}

func (dlg *Dialog) focusFirstCandidateDescendant() {
	window := firstFocusableDescendant(dlg)
	if window == nil {
		return
	}

	if err := window.SetFocus(); err != nil {
		return
	}

	if textSel, ok := window.(textSelectable); ok {
		textSel.SetTextSelection(0, -1)
	}
}

func (dlg *Dialog) Show() {
	if dlg.owner != nil {
		var size Size
		if layout := dlg.Layout(); layout != nil {
			size = layout.MinSize()
			min := dlg.MinSize()
			size.Width = maxi(size.Width, min.Width)
			size.Height = maxi(size.Height, min.Height)
		} else {
			size = dlg.Size()
		}

		ob := dlg.owner.Bounds()

		if dlg.centerInOwnerWhenRun {
			dlg.SetBounds(Rectangle{
				ob.X + (ob.Width-size.Width)/2,
				ob.Y + (ob.Height-size.Height)/2,
				size.Width,
				size.Height,
			})
		}
	} else {
		dlg.SetBounds(dlg.Bounds())
	}

	dlg.FormBase.Show()

	dlg.focusFirstCandidateDescendant()
}

func (dlg *Dialog) Run() int {
	dlg.Show()

	if dlg.owner != nil {
		dlg.owner.SetEnabled(false)
	}

	dlg.FormBase.Run()

	return dlg.result
}
<commit_msg>Dialog: Remove WS_EX_DLGMODALFRAME to fix system menu for fixed size dialog<commit_after>// Copyright 2010 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package walk

import (
	"syscall"
	"unsafe"
)

import (
	"github.com/lxn/win"
)

const (
	DlgCmdNone     = 0
	DlgCmdOK       = win.IDOK
	DlgCmdCancel   = win.IDCANCEL
	DlgCmdAbort    = win.IDABORT
	DlgCmdRetry    = win.IDRETRY
	DlgCmdIgnore   = win.IDIGNORE
	DlgCmdYes      = win.IDYES
	DlgCmdNo       = win.IDNO
	DlgCmdClose    = win.IDCLOSE
	DlgCmdHelp     = win.IDHELP
	DlgCmdTryAgain = win.IDTRYAGAIN
	DlgCmdContinue = win.IDCONTINUE
	DlgCmdTimeout  = win.IDTIMEOUT
)

const dialogWindowClass = `\o/ Walk_Dialog_Class \o/`

func init() {
	MustRegisterWindowClass(dialogWindowClass)
}

type dialogish interface {
	DefaultButton() *PushButton
	CancelButton() *PushButton
}

type Dialog struct {
	FormBase
	result               int
	defaultButton        *PushButton
	cancelButton         *PushButton
	centerInOwnerWhenRun bool
}

func NewDialog(owner Form) (*Dialog, error) {
	return newDialogWithStyle(owner, win.WS_THICKFRAME)
}

func NewDialogWithFixedSize(owner Form) (*Dialog, error) {
	return newDialogWithStyle(owner, 0)
}

func newDialogWithStyle(owner Form, style uint32) (*Dialog, error) {
	dlg := &Dialog{
		FormBase: FormBase{
			owner: owner,
		},
	}

	if err := InitWindow(
		dlg,
		owner,
		dialogWindowClass,
		win.WS_CAPTION|win.WS_SYSMENU|style,
		0); err != nil {
		return nil, err
	}

	succeeded := false
	defer func() {
		if !succeeded {
			dlg.Dispose()
		}
	}()

	dlg.centerInOwnerWhenRun = owner != nil

	// This forces display of focus rectangles, as soon as the user starts to type.
	dlg.SendMessage(win.WM_CHANGEUISTATE, win.UIS_INITIALIZE, 0)

	dlg.result = DlgCmdNone

	succeeded = true

	return dlg, nil
}

func (dlg *Dialog) DefaultButton() *PushButton {
	return dlg.defaultButton
}

func (dlg *Dialog) SetDefaultButton(button *PushButton) error {
	if button != nil && !win.IsChild(dlg.hWnd, button.hWnd) {
		return newError("not a descendant of the dialog")
	}

	succeeded := false
	if dlg.defaultButton != nil {
		if err := dlg.defaultButton.setAndClearStyleBits(win.BS_PUSHBUTTON, win.BS_DEFPUSHBUTTON); err != nil {
			return err
		}
		defer func() {
			if !succeeded {
				dlg.defaultButton.setAndClearStyleBits(win.BS_DEFPUSHBUTTON, win.BS_PUSHBUTTON)
			}
		}()
	}

	if button != nil {
		if err := button.setAndClearStyleBits(win.BS_DEFPUSHBUTTON, win.BS_PUSHBUTTON); err != nil {
			return err
		}
	}

	dlg.defaultButton = button

	succeeded = true

	return nil
}

func (dlg *Dialog) CancelButton() *PushButton {
	return dlg.cancelButton
}

func (dlg *Dialog) SetCancelButton(button *PushButton) error {
	if button != nil && !win.IsChild(dlg.hWnd, button.hWnd) {
		return newError("not a descendant of the dialog")
	}

	dlg.cancelButton = button

	return nil
}

func (dlg *Dialog) Result() int {
	return dlg.result
}

func (dlg *Dialog) Accept() {
	dlg.Close(DlgCmdOK)
}

func (dlg *Dialog) Cancel() {
	dlg.Close(DlgCmdCancel)
}

func (dlg *Dialog) Close(result int) {
	dlg.result = result

	dlg.FormBase.Close()
}

func firstFocusableDescendantCallback(hwnd win.HWND, lParam uintptr) uintptr {
	widget := windowFromHandle(hwnd)

	if widget == nil || !widget.Visible() || !widget.Enabled() {
		return 1
	}

	style := uint(win.GetWindowLong(hwnd, win.GWL_STYLE))
	// FIXME: Ugly workaround for NumberEdit
	_, isTextSelectable := widget.(textSelectable)
	if style&win.WS_TABSTOP > 0 || isTextSelectable {
		hwndPtr := (*win.HWND)(unsafe.Pointer(lParam))
		*hwndPtr = hwnd
		return 0
	}

	return 1
}

var firstFocusableDescendantCallbackPtr = syscall.NewCallback(firstFocusableDescendantCallback)

func firstFocusableDescendant(container Container) Window {
	var hwnd win.HWND

	win.EnumChildWindows(container.Handle(), firstFocusableDescendantCallbackPtr, uintptr(unsafe.Pointer(&hwnd)))

	return windowFromHandle(hwnd)
}

type textSelectable interface {
	SetTextSelection(start, end int)
}

func (dlg *Dialog) focusFirstCandidateDescendant() {
	window := firstFocusableDescendant(dlg)
	if window == nil {
		return
	}

	if err := window.SetFocus(); err != nil {
		return
	}

	if textSel, ok := window.(textSelectable); ok {
		textSel.SetTextSelection(0, -1)
	}
}

func (dlg *Dialog) Show() {
	if dlg.owner != nil {
		var size Size
		if layout := dlg.Layout(); layout != nil {
			size = layout.MinSize()
			min := dlg.MinSize()
			size.Width = maxi(size.Width, min.Width)
			size.Height = maxi(size.Height, min.Height)
		} else {
			size = dlg.Size()
		}

		ob := dlg.owner.Bounds()

		if dlg.centerInOwnerWhenRun {
			dlg.SetBounds(Rectangle{
				ob.X + (ob.Width-size.Width)/2,
				ob.Y + (ob.Height-size.Height)/2,
				size.Width,
				size.Height,
			})
		}
	} else {
		dlg.SetBounds(dlg.Bounds())
	}

	dlg.FormBase.Show()

	dlg.focusFirstCandidateDescendant()
}

func (dlg *Dialog) Run() int {
	dlg.Show()

	if dlg.owner != nil {
		dlg.owner.SetEnabled(false)
	}

	dlg.FormBase.Run()

	return dlg.result
}
<|endoftext|>


<commit_before>// Copyright 2015-2018 HenryLee. 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 tp

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

	"github.com/henrylee2cn/teleport/quic"
)

// Dialer dial-up connection
type Dialer struct {
	network        string
	localAddr      net.Addr
	tlsConfig      *tls.Config
	dialTimeout    time.Duration
	redialInterval time.Duration
	redialTimes    int32
}

// NewDialer creates a dialer.
func NewDialer(localAddr net.Addr, tlsConfig *tls.Config,
	dialTimeout, redialInterval time.Duration, redialTimes int32,
) *Dialer {
	return &Dialer{
		network:        localAddr.Network(),
		localAddr:      localAddr,
		tlsConfig:      tlsConfig,
		dialTimeout:    dialTimeout,
		redialInterval: redialInterval,
		redialTimes:    redialTimes,
	}
}

// Network returns the network.
func (d *Dialer) Network() string {
	return d.network
}

// LocalAddr returns the local address.
func (d *Dialer) LocalAddr() net.Addr {
	return d.localAddr
}

// TLSConfig returns the TLS config.
func (d *Dialer) TLSConfig() *tls.Config {
	return d.tlsConfig
}

// DialTimeout returns the dial timeout.
func (d *Dialer) DialTimeout() time.Duration {
	return d.dialTimeout
}

// RedialInterval returns the redial interval.
func (d *Dialer) RedialInterval() time.Duration {
	return d.redialInterval
}

// RedialTimes returns the redial times.
func (d *Dialer) RedialTimes() int32 {
	return d.redialTimes
}

// Dial dials the connection, and try again if it fails.
func (d *Dialer) Dial(addr string) (net.Conn, error) {
	return d.dialWithRetry(addr, "")
}

// dialWithRetry dials the connection, and try again if it fails.
// NOTE:
//  sessID is not empty only when the disconnection is redialing
func (d *Dialer) dialWithRetry(addr, sessID string) (net.Conn, error) {
	conn, err := d.DialOne(addr)
	if err == nil {
		return conn, nil
	}
	redialTimes := d.NewRedialCounter()
	for redialTimes.Next() {
		time.Sleep(d.redialInterval)
		if sessID == "" {
			Debugf("trying to redial... (network:%s, addr:%s)", d.network, addr)
		} else {
			Debugf("trying to redial... (network:%s, addr:%s, id:%s)", d.network, addr, sessID)
		}
		conn, err = d.DialOne(addr)
		if err == nil {
			return conn, nil
		}
	}
	return nil, err
}

// DialOne dials the connection once.
func (d *Dialer) DialOne(addr string) (net.Conn, error) {
	if asQUIC(d.network) {
		ctx := context.Background()
		if d.dialTimeout > 0 {
			ctx, _ = context.WithTimeout(ctx, d.dialTimeout)
		}
		if d.tlsConfig == nil {
			return quic.DialAddrContext(ctx, addr, GenerateTLSConfigForClient(), nil)
		}
		return quic.DialAddrContext(ctx, addr, d.tlsConfig, nil)
	}
	dialer := &net.Dialer{
		LocalAddr: d.localAddr,
		Timeout:   d.dialTimeout,
	}
	if d.tlsConfig != nil {
		return tls.DialWithDialer(dialer, d.network, addr, d.tlsConfig)
	}
	return dialer.Dial(d.network, addr)
}

// NewRedialCounter creates a new redial counter.
func (d *Dialer) NewRedialCounter() *RedialCounter {
	r := RedialCounter(d.redialTimes)
	return &r
}

// RedialCounter redial counter
type RedialCounter int32

// Next returns whether there are still more redial times.
func (r *RedialCounter) Next() bool {
	t := *r
	if t == 0 {
		return false
	}
	if t > 0 {
		*r--
	}
	return true
}
<commit_msg>chore: Optimize dialer<commit_after>// Copyright 2015-2018 HenryLee. 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 tp

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

	"github.com/henrylee2cn/teleport/quic"
)

// Dialer dial-up connection
type Dialer struct {
	network        string
	localAddr      net.Addr
	tlsConfig      *tls.Config
	dialTimeout    time.Duration
	redialInterval time.Duration
	redialTimes    int32
}

// NewDialer creates a dialer.
func NewDialer(localAddr net.Addr, tlsConfig *tls.Config,
	dialTimeout, redialInterval time.Duration, redialTimes int32,
) *Dialer {
	return &Dialer{
		network:        localAddr.Network(),
		localAddr:      localAddr,
		tlsConfig:      tlsConfig,
		dialTimeout:    dialTimeout,
		redialInterval: redialInterval,
		redialTimes:    redialTimes,
	}
}

// Network returns the network.
func (d *Dialer) Network() string {
	return d.network
}

// LocalAddr returns the local address.
func (d *Dialer) LocalAddr() net.Addr {
	return d.localAddr
}

// TLSConfig returns the TLS config.
func (d *Dialer) TLSConfig() *tls.Config {
	return d.tlsConfig
}

// DialTimeout returns the dial timeout.
func (d *Dialer) DialTimeout() time.Duration {
	return d.dialTimeout
}

// RedialInterval returns the redial interval.
func (d *Dialer) RedialInterval() time.Duration {
	return d.redialInterval
}

// RedialTimes returns the redial times.
func (d *Dialer) RedialTimes() int32 {
	return d.redialTimes
}

// Dial dials the connection, and try again if it fails.
func (d *Dialer) Dial(addr string) (net.Conn, error) {
	return d.dialWithRetry(addr, "")
}

// dialWithRetry dials the connection, and try again if it fails.
// NOTE:
//  sessID is not empty only when the disconnection is redialing
func (d *Dialer) dialWithRetry(addr, sessID string) (net.Conn, error) {
	conn, err := d.dialOne(addr)
	if err == nil {
		return conn, nil
	}
	redialTimes := d.newRedialCounter()
	for redialTimes.Next() {
		time.Sleep(d.redialInterval)
		if sessID == "" {
			Debugf("trying to redial... (network:%s, addr:%s)", d.network, addr)
		} else {
			Debugf("trying to redial... (network:%s, addr:%s, id:%s)", d.network, addr, sessID)
		}
		conn, err = d.dialOne(addr)
		if err == nil {
			return conn, nil
		}
	}
	return nil, err
}

// dialOne dials the connection once.
func (d *Dialer) dialOne(addr string) (net.Conn, error) {
	if asQUIC(d.network) {
		ctx := context.Background()
		if d.dialTimeout > 0 {
			ctx, _ = context.WithTimeout(ctx, d.dialTimeout)
		}
		if d.tlsConfig == nil {
			return quic.DialAddrContext(ctx, addr, GenerateTLSConfigForClient(), nil)
		}
		return quic.DialAddrContext(ctx, addr, d.tlsConfig, nil)
	}
	dialer := &net.Dialer{
		LocalAddr: d.localAddr,
		Timeout:   d.dialTimeout,
	}
	if d.tlsConfig != nil {
		return tls.DialWithDialer(dialer, d.network, addr, d.tlsConfig)
	}
	return dialer.Dial(d.network, addr)
}

// newRedialCounter creates a new redial counter.
func (d *Dialer) newRedialCounter() *redialCounter {
	r := redialCounter(d.redialTimes)
	return &r
}

// redialCounter redial counter
type redialCounter int32

// Next returns whether there are still more redial times.
func (r *redialCounter) Next() bool {
	t := *r
	if t == 0 {
		return false
	}
	if t > 0 {
		*r--
	}
	return true
}
<|endoftext|>


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

// Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'cert.pem' and 'key.pem' and will overwrite existing files.

package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"net"
	"os"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
)

var (
	host       = "localhost"
	validFrom  = ""
	validFor   = 365 * 24 * time.Hour * 2 // 2 years
	isCA       = true
	rsaBits    = 2048
	ecdsaCurve = ""
)

func publicKey(priv interface{}) interface{} {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &k.PublicKey
	case *ecdsa.PrivateKey:
		return &k.PublicKey
	default:
		return nil
	}
}

func pemBlockForKey(priv interface{}) *pem.Block {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
	case *ecdsa.PrivateKey:
		b, err := x509.MarshalECPrivateKey(k)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
			os.Exit(2)
		}
		return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
	default:
		return nil
	}
}

func generateKey(ecdsaCurve string) (interface{}, error) {
	switch ecdsaCurve {
	case "":
		return rsa.GenerateKey(rand.Reader, rsaBits)
	case "P224":
		return ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
	case "P256":
		return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	case "P384":
		return ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
	case "P521":
		return ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
	default:
		return nil, fmt.Errorf("Unrecognized elliptic curve: %q", ecdsaCurve)
	}
}

func generateSingleCertificate(isCa bool) (*x509.Certificate, error) {
	var notBefore time.Time
	var err error
	if len(validFrom) == 0 {
		notBefore = time.Now()
	} else {
		notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom)
		if err != nil {
			return nil, fmt.Errorf("Failed to parse creation date: %s\n", err.Error())
		}
	}

	notAfter := notBefore.Add(validFor)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return nil, fmt.Errorf("failed to generate serial number: %s\n", err.Error())
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization:       []string{"Arduino LLC US"},
			Country:            []string{"US"},
			CommonName:         "localhost",
			OrganizationalUnit: []string{"IT"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	hosts := strings.Split(host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
		}
	}

	if isCA {
		template.IsCA = true
		template.KeyUsage |= x509.KeyUsageCertSign
	}

	return &template, nil
}

func generateCertificates() {

	// Create the key for the certification authority
	caKey, err := generateKey("")
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}

	keyOut, err := os.OpenFile("ca.key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}
	pem.Encode(keyOut, pemBlockForKey(caKey))
	keyOut.Close()
	log.Println("written ca.key.pem")

	// Create the certification authority
	caTemplate, err := generateSingleCertificate(true)

	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, publicKey(caKey), caKey)

	certOut, err := os.Create("ca.crt.pem")
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()
	log.Print("written ca.crt.pem")
}
<commit_msg>Create a signed certificate<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'cert.pem' and 'key.pem' and will overwrite existing files.

package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"net"
	"os"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
)

var (
	host       = "localhost"
	validFrom  = ""
	validFor   = 365 * 24 * time.Hour * 2 // 2 years
	isCA       = true
	rsaBits    = 2048
	ecdsaCurve = ""
)

func publicKey(priv interface{}) interface{} {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &k.PublicKey
	case *ecdsa.PrivateKey:
		return &k.PublicKey
	default:
		return nil
	}
}

func pemBlockForKey(priv interface{}) *pem.Block {
	switch k := priv.(type) {
	case *rsa.PrivateKey:
		return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
	case *ecdsa.PrivateKey:
		b, err := x509.MarshalECPrivateKey(k)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
			os.Exit(2)
		}
		return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
	default:
		return nil
	}
}

func generateKey(ecdsaCurve string) (interface{}, error) {
	switch ecdsaCurve {
	case "":
		return rsa.GenerateKey(rand.Reader, rsaBits)
	case "P224":
		return ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
	case "P256":
		return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	case "P384":
		return ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
	case "P521":
		return ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
	default:
		return nil, fmt.Errorf("Unrecognized elliptic curve: %q", ecdsaCurve)
	}
}

func generateSingleCertificate(isCa bool) (*x509.Certificate, error) {
	var notBefore time.Time
	var err error
	if len(validFrom) == 0 {
		notBefore = time.Now()
	} else {
		notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom)
		if err != nil {
			return nil, fmt.Errorf("Failed to parse creation date: %s\n", err.Error())
		}
	}

	notAfter := notBefore.Add(validFor)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return nil, fmt.Errorf("failed to generate serial number: %s\n", err.Error())
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization:       []string{"Arduino LLC US"},
			Country:            []string{"US"},
			CommonName:         "localhost",
			OrganizationalUnit: []string{"IT"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	hosts := strings.Split(host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
		}
	}

	if isCA {
		template.IsCA = true
		template.KeyUsage |= x509.KeyUsageCertSign
	}

	return &template, nil
}

func generateCertificates() {

	os.Remove("ca.cert.pem")
	os.Remove("ca.key.pem")
	os.Remove("cert.pem")
	os.Remove("key.pem")

	// Create the key for the certification authority
	caKey, err := generateKey("")
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}

	keyOut, err := os.OpenFile("ca.key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}
	pem.Encode(keyOut, pemBlockForKey(caKey))
	keyOut.Close()
	log.Println("written ca.key.pem")

	// Create the certification authority
	caTemplate, err := generateSingleCertificate(true)

	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, publicKey(caKey), caKey)

	certOut, err := os.Create("ca.cert.pem")
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()
	log.Print("written ca.cert.pem")

	// Create the key for the final certificate
	key, err := generateKey("")
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}

	keyOut, err = os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}
	pem.Encode(keyOut, pemBlockForKey(key))
	keyOut.Close()
	log.Println("written key.pem")

	// Create the final certificate
	template, err := generateSingleCertificate(false)

	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}

	derBytes, err = x509.CreateCertificate(rand.Reader, template, caTemplate, publicKey(key), key)

	certOut, err = os.Create("cert.pem")
	if err != nil {
		log.Error(err.Error())
		os.Exit(1)
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()
	log.Print("written cert.pem")
}
<|endoftext|>


<commit_before>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2016 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package core

import (
	"context"
	"strings"
	"sync"
	"time"

	"github.com/loadimpact/k6/core/local"
	"github.com/loadimpact/k6/lib"
	"github.com/loadimpact/k6/lib/metrics"
	"github.com/loadimpact/k6/stats"
	log "github.com/sirupsen/logrus"
	"gopkg.in/guregu/null.v3"
)

const (
	TickRate        = 1 * time.Millisecond
	MetricsRate     = 1 * time.Second
	CollectRate     = 10 * time.Millisecond
	ThresholdsRate  = 2 * time.Second
	ShutdownTimeout = 10 * time.Second

	BackoffAmount = 50 * time.Millisecond
	BackoffMax    = 10 * time.Second
)

// The Engine is the beating heart of K6.
type Engine struct {
	runLock sync.Mutex

	Executor  lib.Executor
	Options   lib.Options
	Collector lib.Collector

	logger *log.Logger

	Stages      []lib.Stage
	Metrics     map[string]*stats.Metric
	MetricsLock sync.RWMutex

	// Assigned to metrics upon first received sample.
	thresholds map[string]stats.Thresholds
	submetrics map[string][]stats.Submetric

	// Are thresholds tainted?
	thresholdsTainted bool
}

func NewEngine(ex lib.Executor, o lib.Options) (*Engine, error) {
	if ex == nil {
		ex = local.New(nil)
	}

	e := &Engine{
		Executor: ex,
		Options:  o,
		Metrics:  make(map[string]*stats.Metric),
	}
	e.SetLogger(log.StandardLogger())

	if err := ex.SetVUsMax(o.VUsMax.Int64); err != nil {
		return nil, err
	}
	if err := ex.SetVUs(o.VUs.Int64); err != nil {
		return nil, err
	}
	ex.SetPaused(o.Paused.Bool)

	// Use Stages if available, if not, construct a stage to fill the specified duration.
	// Special case: A valid duration of 0 = an infinite (invalid duration) stage.
	if o.Stages != nil {
		e.Stages = o.Stages
	} else if o.Duration.Valid && o.Duration.Duration > 0 {
		e.Stages = []lib.Stage{{Duration: o.Duration}}
	} else {
		e.Stages = []lib.Stage{{}}
	}

	ex.SetEndTime(SumStages(e.Stages))
	ex.SetEndIterations(o.Iterations)

	e.thresholds = o.Thresholds
	e.submetrics = make(map[string][]stats.Submetric)
	for name := range e.thresholds {
		if !strings.Contains(name, "{") {
			continue
		}

		parent, sm := stats.NewSubmetric(name)
		e.submetrics[parent] = append(e.submetrics[parent], sm)
	}

	return e, nil
}

func (e *Engine) Run(engctx context.Context) error {
	e.runLock.Lock()
	defer e.runLock.Unlock()

	engctx, engcancel := context.WithCancel(engctx)

	collectorwg := sync.WaitGroup{}
	collectorctx, collectorcancel := context.WithCancel(context.Background())
	if e.Collector != nil {
		collectorwg.Add(1)
		go func() {
			e.Collector.Run(collectorctx)
			collectorwg.Done()
		}()
	}

	subctx, subcancel := context.WithCancel(context.Background())
	subwg := sync.WaitGroup{}

	// Run metrics emission.
	subwg.Add(1)
	go func() {
		e.runMetricsEmission(subctx)
		subwg.Done()
	}()

	// Run thresholds.
	subwg.Add(1)
	go func() {
		e.runThresholds(subctx)
		subwg.Done()
	}()

	// Run the executor.
	out := make(chan []stats.Sample)
	subwg.Add(1)
	go func() {
		e.Executor.Run(subctx, out)
		engcancel()
		subwg.Done()
	}()

	defer func() {
		// Shut down subsystems.
		cutoff := time.Now()
		subcancel()

		// Process samples until the subsystems have shut down.
		// Filter out samples produced past the end of a test.
		go func() {
			subwg.Wait()
			close(out)
		}()
		for samples := range out {
			for _, sample := range samples {
				if !sample.Time.After(cutoff) {
					e.processSamples(sample)
				}
			}
		}

		// Emit final metrics.
		e.emitMetrics()

		// Process final thresholds.
		e.processThresholds()

		// Finally, shut down collector.
		collectorcancel()
		collectorwg.Wait()
	}()

	ticker := time.NewTicker(TickRate)
	for {
		select {
		case <-ticker.C:
			vus, keepRunning := ProcessStages(e.Stages, e.Executor.GetTime())
			if !keepRunning {
				e.logger.Debug("run: ProcessStages() returned false; exiting...")
				return nil
			}
			e.Executor.SetVUs(vus)
		case samples := <-out:
			e.processSamples(samples...)
		case <-engctx.Done():
			e.logger.Debug("run: context expired; exiting...")
			return nil
		}
	}
}

func (e *Engine) IsTainted() bool {
	return e.thresholdsTainted
}

func (e *Engine) SetLogger(l *log.Logger) {
	e.logger = l
	e.Executor.SetLogger(l)
}

func (e *Engine) GetLogger() *log.Logger {
	return e.logger
}

func (e *Engine) runMetricsEmission(ctx context.Context) {
	ticker := time.NewTicker(MetricsRate)
	for {
		select {
		case <-ticker.C:
			e.emitMetrics()
		case <-ctx.Done():
			return
		}
	}
}

func (e *Engine) emitMetrics() {
	t := time.Now()
	e.processSamples(
		stats.Sample{
			Time:   t,
			Metric: metrics.VUs,
			Value:  float64(e.Executor.GetVUs()),
		},
		stats.Sample{
			Time:   t,
			Metric: metrics.VUsMax,
			Value:  float64(e.Executor.GetVUsMax()),
		},
	)
}

func (e *Engine) runThresholds(ctx context.Context) {
	ticker := time.NewTicker(ThresholdsRate)
	for {
		select {
		case <-ticker.C:
			e.processThresholds()
		case <-ctx.Done():
			return
		}
	}
}

func (e *Engine) processThresholds() {
	e.MetricsLock.Lock()
	defer e.MetricsLock.Unlock()

	e.thresholdsTainted = false
	for _, m := range e.Metrics {
		if len(m.Thresholds.Thresholds) == 0 {
			continue
		}
		m.Tainted = null.BoolFrom(false)

		e.logger.WithField("m", m.Name).Debug("running thresholds")
		succ, err := m.Thresholds.Run(m.Sink)
		if err != nil {
			e.logger.WithField("m", m.Name).WithError(err).Error("Threshold error")
			continue
		}
		if !succ {
			e.logger.WithField("m", m.Name).Debug("Thresholds failed")
			m.Tainted = null.BoolFrom(true)
			e.thresholdsTainted = true
		}
	}
}

func (e *Engine) processSamples(samples ...stats.Sample) {
	if len(samples) == 0 {
		return
	}

	e.MetricsLock.Lock()
	defer e.MetricsLock.Unlock()

	for _, sample := range samples {
		m, ok := e.Metrics[sample.Metric.Name]
		if !ok {
			m = sample.Metric
			m.Thresholds = e.thresholds[m.Name]
			m.Submetrics = e.submetrics[m.Name]
			e.Metrics[m.Name] = m
		}
		m.Sink.Add(sample)

		for _, sm := range m.Submetrics {
			passing := true
			for k, v := range sm.Tags {
				if sample.Tags[k] != v {
					passing = false
					break
				}
			}
			if !passing {
				continue
			}

			if sm.Metric == nil {
				sm.Metric = stats.New(sm.Name, sample.Metric.Type, sample.Metric.Contains)
				sm.Metric.Thresholds = e.thresholds[sm.Name]
				e.Metrics[sm.Name] = sm.Metric
			}
			sm.Metric.Sink.Add(sample)
		}
	}

	if e.Collector != nil {
		e.Collector.Collect(samples)
	}
}
<commit_msg>Pass on executor errors properly<commit_after>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2016 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package core

import (
	"context"
	"strings"
	"sync"
	"time"

	"github.com/loadimpact/k6/core/local"
	"github.com/loadimpact/k6/lib"
	"github.com/loadimpact/k6/lib/metrics"
	"github.com/loadimpact/k6/stats"
	log "github.com/sirupsen/logrus"
	"gopkg.in/guregu/null.v3"
)

const (
	TickRate        = 1 * time.Millisecond
	MetricsRate     = 1 * time.Second
	CollectRate     = 10 * time.Millisecond
	ThresholdsRate  = 2 * time.Second
	ShutdownTimeout = 10 * time.Second

	BackoffAmount = 50 * time.Millisecond
	BackoffMax    = 10 * time.Second
)

// The Engine is the beating heart of K6.
type Engine struct {
	runLock sync.Mutex

	Executor  lib.Executor
	Options   lib.Options
	Collector lib.Collector

	logger *log.Logger

	Stages      []lib.Stage
	Metrics     map[string]*stats.Metric
	MetricsLock sync.RWMutex

	// Assigned to metrics upon first received sample.
	thresholds map[string]stats.Thresholds
	submetrics map[string][]stats.Submetric

	// Are thresholds tainted?
	thresholdsTainted bool
}

func NewEngine(ex lib.Executor, o lib.Options) (*Engine, error) {
	if ex == nil {
		ex = local.New(nil)
	}

	e := &Engine{
		Executor: ex,
		Options:  o,
		Metrics:  make(map[string]*stats.Metric),
	}
	e.SetLogger(log.StandardLogger())

	if err := ex.SetVUsMax(o.VUsMax.Int64); err != nil {
		return nil, err
	}
	if err := ex.SetVUs(o.VUs.Int64); err != nil {
		return nil, err
	}
	ex.SetPaused(o.Paused.Bool)

	// Use Stages if available, if not, construct a stage to fill the specified duration.
	// Special case: A valid duration of 0 = an infinite (invalid duration) stage.
	if o.Stages != nil {
		e.Stages = o.Stages
	} else if o.Duration.Valid && o.Duration.Duration > 0 {
		e.Stages = []lib.Stage{{Duration: o.Duration}}
	} else {
		e.Stages = []lib.Stage{{}}
	}

	ex.SetEndTime(SumStages(e.Stages))
	ex.SetEndIterations(o.Iterations)

	e.thresholds = o.Thresholds
	e.submetrics = make(map[string][]stats.Submetric)
	for name := range e.thresholds {
		if !strings.Contains(name, "{") {
			continue
		}

		parent, sm := stats.NewSubmetric(name)
		e.submetrics[parent] = append(e.submetrics[parent], sm)
	}

	return e, nil
}

func (e *Engine) Run(ctx context.Context) error {
	e.runLock.Lock()
	defer e.runLock.Unlock()

	collectorwg := sync.WaitGroup{}
	collectorctx, collectorcancel := context.WithCancel(context.Background())
	if e.Collector != nil {
		collectorwg.Add(1)
		go func() {
			e.Collector.Run(collectorctx)
			collectorwg.Done()
		}()
	}

	subctx, subcancel := context.WithCancel(context.Background())
	subwg := sync.WaitGroup{}

	// Run metrics emission.
	subwg.Add(1)
	go func() {
		e.runMetricsEmission(subctx)
		subwg.Done()
	}()

	// Run thresholds.
	subwg.Add(1)
	go func() {
		e.runThresholds(subctx)
		subwg.Done()
	}()

	// Run the executor.
	out := make(chan []stats.Sample)
	errC := make(chan error)
	subwg.Add(1)
	go func() {
		errC <- e.Executor.Run(subctx, out)
		subwg.Done()
	}()

	defer func() {
		// Shut down subsystems.
		cutoff := time.Now()
		subcancel()

		// Process samples until the subsystems have shut down.
		// Filter out samples produced past the end of a test.
		go func() {
			subwg.Wait()
			close(out)
		}()
		for samples := range out {
			for _, sample := range samples {
				if !sample.Time.After(cutoff) {
					e.processSamples(sample)
				}
			}
		}

		// Emit final metrics.
		e.emitMetrics()

		// Process final thresholds.
		e.processThresholds()

		// Finally, shut down collector.
		collectorcancel()
		collectorwg.Wait()
	}()

	ticker := time.NewTicker(TickRate)
	for {
		select {
		case <-ticker.C:
			vus, keepRunning := ProcessStages(e.Stages, e.Executor.GetTime())
			if !keepRunning {
				e.logger.Debug("run: ProcessStages() returned false; exiting...")
				return nil
			}
			e.Executor.SetVUs(vus)
		case samples := <-out:
			e.processSamples(samples...)
		case err := <-errC:
			if err != nil {
				e.logger.WithError(err).Debug("run: executor returned an error")
				return err
			}
			e.logger.Debug("run: executor terminated")
			return nil
		case <-ctx.Done():
			e.logger.Debug("run: context expired; exiting...")
			return nil
		}
	}
}

func (e *Engine) IsTainted() bool {
	return e.thresholdsTainted
}

func (e *Engine) SetLogger(l *log.Logger) {
	e.logger = l
	e.Executor.SetLogger(l)
}

func (e *Engine) GetLogger() *log.Logger {
	return e.logger
}

func (e *Engine) runMetricsEmission(ctx context.Context) {
	ticker := time.NewTicker(MetricsRate)
	for {
		select {
		case <-ticker.C:
			e.emitMetrics()
		case <-ctx.Done():
			return
		}
	}
}

func (e *Engine) emitMetrics() {
	t := time.Now()
	e.processSamples(
		stats.Sample{
			Time:   t,
			Metric: metrics.VUs,
			Value:  float64(e.Executor.GetVUs()),
		},
		stats.Sample{
			Time:   t,
			Metric: metrics.VUsMax,
			Value:  float64(e.Executor.GetVUsMax()),
		},
	)
}

func (e *Engine) runThresholds(ctx context.Context) {
	ticker := time.NewTicker(ThresholdsRate)
	for {
		select {
		case <-ticker.C:
			e.processThresholds()
		case <-ctx.Done():
			return
		}
	}
}

func (e *Engine) processThresholds() {
	e.MetricsLock.Lock()
	defer e.MetricsLock.Unlock()

	e.thresholdsTainted = false
	for _, m := range e.Metrics {
		if len(m.Thresholds.Thresholds) == 0 {
			continue
		}
		m.Tainted = null.BoolFrom(false)

		e.logger.WithField("m", m.Name).Debug("running thresholds")
		succ, err := m.Thresholds.Run(m.Sink)
		if err != nil {
			e.logger.WithField("m", m.Name).WithError(err).Error("Threshold error")
			continue
		}
		if !succ {
			e.logger.WithField("m", m.Name).Debug("Thresholds failed")
			m.Tainted = null.BoolFrom(true)
			e.thresholdsTainted = true
		}
	}
}

func (e *Engine) processSamples(samples ...stats.Sample) {
	if len(samples) == 0 {
		return
	}

	e.MetricsLock.Lock()
	defer e.MetricsLock.Unlock()

	for _, sample := range samples {
		m, ok := e.Metrics[sample.Metric.Name]
		if !ok {
			m = sample.Metric
			m.Thresholds = e.thresholds[m.Name]
			m.Submetrics = e.submetrics[m.Name]
			e.Metrics[m.Name] = m
		}
		m.Sink.Add(sample)

		for _, sm := range m.Submetrics {
			passing := true
			for k, v := range sm.Tags {
				if sample.Tags[k] != v {
					passing = false
					break
				}
			}
			if !passing {
				continue
			}

			if sm.Metric == nil {
				sm.Metric = stats.New(sm.Name, sample.Metric.Type, sample.Metric.Contains)
				sm.Metric.Thresholds = e.thresholds[sm.Name]
				e.Metrics[sm.Name] = sm.Metric
			}
			sm.Metric.Sink.Add(sample)
		}
	}

	if e.Collector != nil {
		e.Collector.Collect(samples)
	}
}
<|endoftext|>


<commit_before>package domino

import (
	"bytes"
	"fmt"
	"html"
	"sort"
	"strings"
)

// NSpaces can be adjusted to determine how many spaces are used in each
// indent.
var NSpaces = 4

// Attr is a shorthand for map[string]interface{}, used when declaring
// attributes for DomNodes.
type Attr map[string]interface{}

// Node is basically a stringer interface but with the ability to append
// to a buffer for performance reasons.
type Node interface {
	String() string
	IndentString() string
	StringBuild(*bytes.Buffer, bool, int)
}

// DomNode is a node in a dom tree. It has children nodes and attributes.
type DomNode struct {
	NodeName string
	Attrs    Attr
	Children []Node
}

// TextNode represents text in the dom tree. Text can not have child nodes or
// attributes.
type TextNode struct {
	Value string
}

// NewDomNode creates a new dom node with it's name (div, ul, html) and any
// number of arguments, these can be: children dom or text nodes, or Attr lists.
func NewDomNode(name string, args ...interface{}) *DomNode {
	n := &DomNode{
		NodeName: name,
		Attrs:    make(Attr, 0),
		Children: make([]Node, 0),
	}
	for _, arg := range args {
		switch a := arg.(type) {
		case *DomNode:
			n.Add(a)
		case *TextNode:
			n.Add(a)
		case string:
			n.Add(NewTextNode(a))
		case *Context:
			a.Add(n)
		case Attr:
			for k, v := range a {
				n.Attrs[k] = v
			}
		default:
			panic("wrong argument type")
		}
	}
	return n
}

// NewTextNode creates a new text node with the provided text.
func NewTextNode(value string) *TextNode {
	return &TextNode{Value: value}
}

// Add a new child node.
func (n *DomNode) Add(child Node) Node {
	n.Children = append(n.Children, child)
	return child
}

func (n *DomNode) setAttribute(k string, v interface{}) *DomNode {
	n.Attrs[k] = v
	return n
}

// String returns HTML for this node and all its ancestors
func (n *TextNode) String() string {
	return n.Value
}

// IndentString appends it's value to the provided buffer.
func (n *TextNode) IndentString() string {
	return n.Value
}

// StringBuild appends it's value to the provided buffer.
func (n *TextNode) StringBuild(b *bytes.Buffer, indent bool, depth int) {
	if indent && depth > 0 {
		indent := strings.Repeat(" ", NSpaces*depth)
		b.WriteString(indent)
		b.WriteString(strings.Replace(n.Value, "\n", "\n"+indent, -1))
		b.WriteByte('\n')
	} else {
		b.WriteString(n.Value)
	}
}

// String returns HTML for this node and all it's ancestors.
func (n *DomNode) String() string {
	b := &bytes.Buffer{}
	n.StringBuild(b, false, 0)
	return b.String()
}

// IndentString returns HTML for this node and all it's ancestors with
// indentation.
func (n *DomNode) IndentString() string {
	b := &bytes.Buffer{}
	n.StringBuild(b, true, 0)
	return b.String()
}

// StringBuild appends the html for this node and all it's ancestors to the
// provided buffer.
func (n *DomNode) StringBuild(b *bytes.Buffer, indent bool, depth int) {
	if indent && depth > 0 {
		b.WriteString(strings.Repeat(" ", NSpaces*depth))
	}

	b.WriteByte('<')
	b.WriteString(n.NodeName)

	keys := make([]string, 0, len(n.Attrs))
	for k, _ := range n.Attrs {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, k := range keys {
		v := n.Attrs[k]

		b.WriteByte(' ')
		if v == nil {
			fmt.Fprint(b, k)
			continue
		}

		vstr := html.EscapeString(fmt.Sprint(v))
		fmt.Fprintf(b, `%s="%s"`, k, vstr)
	}

	b.WriteByte('>')

	if _, ws := whiteSpaced[n.NodeName]; indent && !ws && len(n.Children) == 1 {
		if _, ok := n.Children[0].(*TextNode); ok {
			fmt.Fprintf(b, "%s</%s>\n", n.Children[0].String(), n.NodeName)
			return
		}
	}

	_, isVoid := voidElems[n.NodeName]

	if indent && (len(n.Children) > 0 || isVoid) {
		b.WriteByte('\n')
	}

	if isVoid {
		return
	}

	for _, child := range n.Children {
		child.StringBuild(b, indent, depth+1)
	}

	if indent && depth > 0 && len(n.Children) > 0 {
		b.WriteString(strings.Repeat(" ", depth*NSpaces))
	}

	b.WriteString("</")
	b.WriteString(n.NodeName)
	b.WriteByte('>')
	if indent {
		b.WriteByte('\n')
	}
}

// Text adds a text node with the provided text.
func (n *DomNode) Text(text string) *DomNode {
	n.Add(NewTextNode(text))
	return n
}

// Clear removes all children.
func (n *DomNode) Clear() *DomNode {
	n.Children = make([]Node, 0)
	return n
}

var voidElems = map[string]struct{}{
	"area":    struct{}{},
	"base":    struct{}{},
	"br":      struct{}{},
	"col":     struct{}{},
	"command": struct{}{},
	"embed":   struct{}{},
	"hr":      struct{}{},
	"img":     struct{}{},
	"input":   struct{}{},
	"keygen":  struct{}{},
	"link":    struct{}{},
	"meta":    struct{}{},
	"param":   struct{}{},
	"source":  struct{}{},
	"track":   struct{}{},
	"wbr":     struct{}{},
}

var whiteSpaced = map[string]struct{}{
	"style":    struct{}{},
	"script":   struct{}{},
	"textarea": struct{}{},
}
<commit_msg>Add is now variadic.<commit_after>package domino

import (
	"bytes"
	"fmt"
	"html"
	"sort"
	"strings"
)

// NSpaces can be adjusted to determine how many spaces are used in each
// indent.
var NSpaces = 4

// Attr is a shorthand for map[string]interface{}, used when declaring
// attributes for DomNodes.
type Attr map[string]interface{}

// Node is basically a stringer interface but with the ability to append
// to a buffer for performance reasons.
type Node interface {
	String() string
	IndentString() string
	StringBuild(*bytes.Buffer, bool, int)
}

// DomNode is a node in a dom tree. It has children nodes and attributes.
type DomNode struct {
	NodeName string
	Attrs    Attr
	Children []Node
}

// TextNode represents text in the dom tree. Text can not have child nodes or
// attributes.
type TextNode struct {
	Value string
}

// NewDomNode creates a new dom node with it's name (div, ul, html) and any
// number of arguments, these can be: children dom or text nodes, or Attr lists.
func NewDomNode(name string, args ...interface{}) *DomNode {
	n := &DomNode{
		NodeName: name,
		Attrs:    make(Attr, 0),
		Children: make([]Node, 0),
	}
	for _, arg := range args {
		switch a := arg.(type) {
		case *DomNode:
			n.Add(a)
		case *TextNode:
			n.Add(a)
		case string:
			n.Add(NewTextNode(a))
		case *Context:
			a.Add(n)
		case Attr:
			for k, v := range a {
				n.Attrs[k] = v
			}
		default:
			panic("wrong argument type")
		}
	}
	return n
}

// NewTextNode creates a new text node with the provided text.
func NewTextNode(value string) *TextNode {
	return &TextNode{Value: value}
}

// Add a new child node.
func (n *DomNode) Add(children ...Node) Node {
	n.Children = append(n.Children, children...)
	return children[len(children)-1]
}

func (n *DomNode) setAttribute(k string, v interface{}) *DomNode {
	n.Attrs[k] = v
	return n
}

// String returns HTML for this node and all its ancestors
func (n *TextNode) String() string {
	return n.Value
}

// IndentString appends it's value to the provided buffer.
func (n *TextNode) IndentString() string {
	return n.Value
}

// StringBuild appends it's value to the provided buffer.
func (n *TextNode) StringBuild(b *bytes.Buffer, indent bool, depth int) {
	if indent && depth > 0 {
		indent := strings.Repeat(" ", NSpaces*depth)
		b.WriteString(indent)
		b.WriteString(strings.Replace(n.Value, "\n", "\n"+indent, -1))
		b.WriteByte('\n')
	} else {
		b.WriteString(n.Value)
	}
}

// String returns HTML for this node and all it's ancestors.
func (n *DomNode) String() string {
	b := &bytes.Buffer{}
	n.StringBuild(b, false, 0)
	return b.String()
}

// IndentString returns HTML for this node and all it's ancestors with
// indentation.
func (n *DomNode) IndentString() string {
	b := &bytes.Buffer{}
	n.StringBuild(b, true, 0)
	return b.String()
}

// StringBuild appends the html for this node and all it's ancestors to the
// provided buffer.
func (n *DomNode) StringBuild(b *bytes.Buffer, indent bool, depth int) {
	if indent && depth > 0 {
		b.WriteString(strings.Repeat(" ", NSpaces*depth))
	}

	b.WriteByte('<')
	b.WriteString(n.NodeName)

	keys := make([]string, 0, len(n.Attrs))
	for k, _ := range n.Attrs {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, k := range keys {
		v := n.Attrs[k]

		b.WriteByte(' ')
		if v == nil {
			fmt.Fprint(b, k)
			continue
		}

		vstr := html.EscapeString(fmt.Sprint(v))
		fmt.Fprintf(b, `%s="%s"`, k, vstr)
	}

	b.WriteByte('>')

	if _, ws := whiteSpaced[n.NodeName]; indent && !ws && len(n.Children) == 1 {
		if _, ok := n.Children[0].(*TextNode); ok {
			fmt.Fprintf(b, "%s</%s>\n", n.Children[0].String(), n.NodeName)
			return
		}
	}

	_, isVoid := voidElems[n.NodeName]

	if indent && (len(n.Children) > 0 || isVoid) {
		b.WriteByte('\n')
	}

	if isVoid {
		return
	}

	for _, child := range n.Children {
		child.StringBuild(b, indent, depth+1)
	}

	if indent && depth > 0 && len(n.Children) > 0 {
		b.WriteString(strings.Repeat(" ", depth*NSpaces))
	}

	b.WriteString("</")
	b.WriteString(n.NodeName)
	b.WriteByte('>')
	if indent {
		b.WriteByte('\n')
	}
}

// Text adds a text node with the provided text.
func (n *DomNode) Text(text string) *DomNode {
	n.Add(NewTextNode(text))
	return n
}

// Clear removes all children.
func (n *DomNode) Clear() *DomNode {
	n.Children = make([]Node, 0)
	return n
}

var voidElems = map[string]struct{}{
	"area":    struct{}{},
	"base":    struct{}{},
	"br":      struct{}{},
	"col":     struct{}{},
	"command": struct{}{},
	"embed":   struct{}{},
	"hr":      struct{}{},
	"img":     struct{}{},
	"input":   struct{}{},
	"keygen":  struct{}{},
	"link":    struct{}{},
	"meta":    struct{}{},
	"param":   struct{}{},
	"source":  struct{}{},
	"track":   struct{}{},
	"wbr":     struct{}{},
}

var whiteSpaced = map[string]struct{}{
	"style":    struct{}{},
	"script":   struct{}{},
	"textarea": struct{}{},
}
<|endoftext|>


<commit_before>package moka

import (
	"errors"
	"fmt"
	"reflect"
)

// Double is the interface implemented by all Moka double types.
type Double interface {
	addInteraction(interaction interaction)
	Call(methodName string, args ...interface{}) ([]interface{}, error)
	verifyInteractions()
}

// StrictDouble is a strict implementation of the Double interface.
// Any invocation of the `Call` method that won't match any of the configured
// interactions will trigger a test failure and return an error.
type StrictDouble struct {
	interactions         []interaction
	interactionValidator interactionValidator
	failHandler          FailHandler
}

// NewStrictDouble instantiates a new `StrictDouble`, using the global fail
// handler and no validation on the configured interactions.
func NewStrictDouble() *StrictDouble {
	return &StrictDouble{
		interactions:         []interaction{},
		interactionValidator: newNullInteractionValidator(),
		failHandler:          globalFailHandler,
	}
}

// NewStrictDoubleWithTypeOf instantiates a new `StrictDouble`, using the
// global fail handler and validating that any configured interaction matches
// the specified type.
func NewStrictDoubleWithTypeOf(value interface{}) *StrictDouble {
	return &StrictDouble{
		interactions:         []interaction{},
		interactionValidator: newTypeInteractionValidator(reflect.TypeOf(value)),
		failHandler:          globalFailHandler,
	}
}

func newStrictDoubleWithInteractionValidatorAndFailHandler(interactionValidator interactionValidator, failHandler FailHandler) *StrictDouble {
	return &StrictDouble{
		interactions:         []interaction{},
		interactionValidator: interactionValidator,
		failHandler:          failHandler,
	}
}

// Call performs a method call on the double. If a matching interaction is
// found, its return values will be returned. If no configured interaction
// matches, an error will be returned.
func (d *StrictDouble) Call(methodName string, args ...interface{}) ([]interface{}, error) {
	for _, interaction := range d.interactions {
		interactionReturnValues, interactionMatches := interaction.call(methodName, args)
		if interactionMatches {
			return interactionReturnValues, nil
		}
	}

	errorMessage := fmt.Sprintf("Unexpected interaction: %s", formatMethodCall(methodName, args))
	d.failHandler(errorMessage)
	return nil, errors.New(errorMessage)
}

func (d *StrictDouble) addInteraction(interaction interaction) {
	validationError := d.interactionValidator.validate(interaction)

	if validationError != nil {
		d.failHandler(validationError.Error())
		return
	}

	d.interactions = append(d.interactions, interaction)
}

func (d *StrictDouble) verifyInteractions() {
	for _, interaction := range d.interactions {
		err := interaction.verify()
		if err != nil {
			d.failHandler(err.Error())
			return
		}
	}
}
<commit_msg>Panic when trying to instantiate a double with a nil fail handler<commit_after>package moka

import (
	"errors"
	"fmt"
	"reflect"
)

// Double is the interface implemented by all Moka double types.
type Double interface {
	addInteraction(interaction interaction)
	Call(methodName string, args ...interface{}) ([]interface{}, error)
	verifyInteractions()
}

// StrictDouble is a strict implementation of the Double interface.
// Any invocation of the `Call` method that won't match any of the configured
// interactions will trigger a test failure and return an error.
type StrictDouble struct {
	interactions         []interaction
	interactionValidator interactionValidator
	failHandler          FailHandler
}

// NewStrictDouble instantiates a new `StrictDouble`, using the global fail
// handler and no validation on the configured interactions.
func NewStrictDouble() *StrictDouble {
	return newStrictDoubleWithInteractionValidatorAndFailHandler(
		newNullInteractionValidator(),
		globalFailHandler,
	)
}

// NewStrictDoubleWithTypeOf instantiates a new `StrictDouble`, using the
// global fail handler and validating that any configured interaction matches
// the specified type.
func NewStrictDoubleWithTypeOf(value interface{}) *StrictDouble {
	return newStrictDoubleWithInteractionValidatorAndFailHandler(
		newTypeInteractionValidator(reflect.TypeOf(value)),
		globalFailHandler,
	)
}

func newStrictDoubleWithInteractionValidatorAndFailHandler(interactionValidator interactionValidator, failHandler FailHandler) *StrictDouble {
	if failHandler == nil {
		panic("You are trying to instantiate a double, but Moka's fail handler is nil.\n" +
			"If you're using Ginkgo, make sure you instantiate your doubles in a BeforeEach(), JustBeforeEach() or It() block.\n" +
			"Alternatively, you may have forgotten to register a fail handler with RegisterDoublesFailHandler().")
	}

	return &StrictDouble{
		interactions:         []interaction{},
		interactionValidator: interactionValidator,
		failHandler:          failHandler,
	}
}

// Call performs a method call on the double. If a matching interaction is
// found, its return values will be returned. If no configured interaction
// matches, an error will be returned.
func (d *StrictDouble) Call(methodName string, args ...interface{}) ([]interface{}, error) {
	for _, interaction := range d.interactions {
		interactionReturnValues, interactionMatches := interaction.call(methodName, args)
		if interactionMatches {
			return interactionReturnValues, nil
		}
	}

	errorMessage := fmt.Sprintf("Unexpected interaction: %s", formatMethodCall(methodName, args))
	d.failHandler(errorMessage)
	return nil, errors.New(errorMessage)
}

func (d *StrictDouble) addInteraction(interaction interaction) {
	validationError := d.interactionValidator.validate(interaction)

	if validationError != nil {
		d.failHandler(validationError.Error())
		return
	}

	d.interactions = append(d.interactions, interaction)
}

func (d *StrictDouble) verifyInteractions() {
	for _, interaction := range d.interactions {
		err := interaction.verify()
		if err != nil {
			d.failHandler(err.Error())
			return
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/model"

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

const (
	driverName = "com.ninjablocks.zwave"
)

var (
	log  = logger.GetLogger(driverName)
	info = ninja.LoadModuleInfo("./package.json")
)

type ZDriver struct {
	config    *Zconfig
	conn      *ninja.Connection
	sendEvent func(event string, payload interface{}) error
	debug     bool
	zwaveAPI  openzwave.API
	exit      chan int
}

type Zconfig struct {
}

func defaultConfig() *Zconfig {
	return &Zconfig{}
}

func (driver *ZDriver) ZWave() openzwave.API {
	return driver.zwaveAPI
}

func (driver *ZDriver) Ninja() ninja.Driver {
	return driver
}

func (driver *ZDriver) Connection() *ninja.Connection {
	return driver.conn
}

func newZWaveDriver(debug bool) (*ZDriver, error) {

	conn, err := ninja.Connect(driverName)

	if err != nil {
		log.Fatalf("Failed to create %s driver: %s", driverName, err)
	}

	driver := &ZDriver{
		config:    defaultConfig(),
		conn:      conn,
		sendEvent: nil,
		debug:     debug,
		zwaveAPI:  nil,
		exit:      make(chan int, 0),
	}

	err = conn.ExportDriver(driver)

	if err != nil {
		log.Fatalf("Failed to export %s driver: %s", driverName, err)
	}

	return driver, nil
}

func (d *ZDriver) Start(config *Zconfig) error {
	log.Infof("Driver %s starting with config %v", driverName, config)

	d.config = config

	zwaveDeviceFactory := func(api openzwave.API, node openzwave.Node) openzwave.Device {
		d.zwaveAPI = api
		return GetLibrary().GetDeviceFactory(*node.GetProductId())(d, node)
	}

	shuttingDown := false

	notificationCallback := func(api openzwave.API, nt openzwave.Notification) {
		switch nt.GetNotificationType().Code {
		case NT.NODE_REMOVED:
			//
			// Currently the RPC layer prevents us releasing the resources associated
			// with removed nodes. If the nodes come back (when, say, the zwave controller
			// is re-inserted), we can't build new device  wrappers for them because the
			// devices are already registered with the RPC layer.
			//
			// We could fix the RPC layer or we could attempt to work around the
			// problems with the RPC layer by using "patch" proxies for each ninja device
			// that allows us to change the actual zwave device.
			//
			// For now, it is simpler if we simply restart the driver process in the event of node
			// removal. This also avoids potential race conditions between
			// event dispatch and freeing of the resources associated with the
			// removed node.
			//
			if !shuttingDown {
				shuttingDown = true
				api.Logger().Infof("ZWave driver shutdown in response to node removed event.")
				api.Shutdown(openzwave.EXIT_NODE_REMOVED)
			}
		default:

		}
	}

	configurator := openzwave.
		BuildAPI("/usr/local/etc/openzwave", ".", "").
		SetLogger(log).
		SetNotificationCallback(notificationCallback).
		SetDeviceFactory(zwaveDeviceFactory)

	if d.debug {
		callback := func(api openzwave.API, notification openzwave.Notification) {
			api.Logger().Infof("%v\n", notification)
			notificationCallback(api, notification)
		}

		configurator.SetNotificationCallback(callback)
	}

	go func() {
		// slightly racy - we would like a guarantee we have replied to Start
		// before we start generating advice about new nodes.
		d.exit <- configurator.Run()
	}()

	d.sendEvent("config", config)

	return nil
}

func (d *ZDriver) Stop() error {
	log.Infof("Stop received - shutting down")
	d.zwaveAPI.Shutdown(0)
	return nil
}

// wait until the drivers are ready for us to shutdown.
func (d *ZDriver) wait() int {
	return <-d.exit
}

func (d *ZDriver) GetModuleInfo() *model.Module {
	return info
}

func (d *ZDriver) SetEventHandler(sendEvent func(event string, payload interface{}) error) {
	d.sendEvent = sendEvent
}
<commit_msg>Refactor driver-go-zwave to make use of DriverSupport.<commit_after>package main

import (
	"fmt"

	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/logger"
	"github.com/ninjasphere/go-ninja/support"

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

const (
	driverName = "com.ninjablocks.zwave"
)

var (
	info = ninja.LoadModuleInfo("./package.json")
)

type ZDriver struct {
	support.DriverSupport
	config   *Zconfig
	debug    bool
	zwaveAPI openzwave.API
	exit     chan int
}

type Zconfig struct {
}

func defaultConfig() *Zconfig {
	return &Zconfig{}
}

func (driver *ZDriver) ZWave() openzwave.API {
	return driver.zwaveAPI
}

func (driver *ZDriver) Ninja() ninja.Driver {
	return driver
}

func (driver *ZDriver) Connection() *ninja.Connection {
	return driver.Conn
}

func newZWaveDriver(debug bool) (*ZDriver, error) {

	driver := &ZDriver{
		config:   defaultConfig(),
		debug:    debug,
		zwaveAPI: nil,
		exit:     make(chan int, 0),
	}

	err := driver.Init(info)
	if err != nil {
		return nil, err
	}

	err = driver.Export(driver)
	if err != nil {
		return nil, err
	}

	return driver, nil
}

func (d *ZDriver) Start(config *Zconfig) error {
	d.Log.Infof("Driver %s starting with config %v", driverName, config)

	d.config = config

	zwaveDeviceFactory := func(api openzwave.API, node openzwave.Node) openzwave.Device {
		d.zwaveAPI = api
		return GetLibrary().GetDeviceFactory(*node.GetProductId())(d, node)
	}

	shuttingDown := false

	notificationCallback := func(api openzwave.API, nt openzwave.Notification) {
		switch nt.GetNotificationType().Code {
		case NT.NODE_REMOVED:
			//
			// Currently the RPC layer prevents us releasing the resources associated
			// with removed nodes. If the nodes come back (when, say, the zwave controller
			// is re-inserted), we can't build new device  wrappers for them because the
			// devices are already registered with the RPC layer.
			//
			// We could fix the RPC layer or we could attempt to work around the
			// problems with the RPC layer by using "patch" proxies for each ninja device
			// that allows us to change the actual zwave device.
			//
			// For now, it is simpler if we simply restart the driver process in the event of node
			// removal. This also avoids potential race conditions between
			// event dispatch and freeing of the resources associated with the
			// removed node.
			//
			if !shuttingDown {
				shuttingDown = true
				api.Logger().Infof("ZWave driver shutdown in response to node removed event.")
				api.Shutdown(openzwave.EXIT_NODE_REMOVED)
			}
		default:

		}
	}

	configurator := openzwave.
		BuildAPI("/usr/local/etc/openzwave", ".", "").
		SetLogger(logger.GetLogger(fmt.Sprintf("%s.backend", d.Info.ID))).
		SetNotificationCallback(notificationCallback).
		SetDeviceFactory(zwaveDeviceFactory)

	if d.debug {
		callback := func(api openzwave.API, notification openzwave.Notification) {
			api.Logger().Infof("%v\n", notification)
			notificationCallback(api, notification)
		}

		configurator.SetNotificationCallback(callback)
	}

	go func() {
		// slightly racy - we would like a guarantee we have replied to Start
		// before we start generating advice about new nodes.
		d.exit <- configurator.Run()
	}()

	d.SendEvent("config", config)

	return nil
}

func (d *ZDriver) Stop() error {
	d.Log.Infof("Stop received - shutting down")
	d.zwaveAPI.Shutdown(0)
	return nil
}

// wait until the drivers are ready for us to shutdown.
func (d *ZDriver) wait() int {
	return <-d.exit
}
<|endoftext|>


<commit_before>package core
import  "strings"
import "strconv"
import "fmt"
//import "encoding/json"

/*questa funzione controlla se immagine appartiene a tvl o no */
/*func IsOfSite(url string) int {
    if strings.Contains(url, "tvl.lotrek.it") {
        return 1
    } else {
        return 0
    }
}*/

/* questa funzione spezzetta il parametro in url passato */

func Parser (name string) (uint,uint,uint,error) { //return integer, integer , integer, error

    /*ci separiamo la stringa passata per il carattere */
    stringSlice := strings.Split(name, "/")
    /*ora in posizoione 0 della stringslide, avremo dimensione e qualita*/
    var dimqual string = stringSlice[0]
    /* se togliamo dalla stringa originale con un replace il dimqual, ecco che abbiamo la urla*/
    //var url = strings.Replace(name, dimqual+"/", "", -1)

    dimQualityArray := strings.Split(dimqual, "_")
    fmt.Println(dimQualityArray)
    arrayOfInt := make([]uint, 3)
    var err error=nil

    var tmpr int
    arrayOfInt[2] = 100
    arrayOfInt[0] = 0
    arrayOfInt[1] = 0
    for i := 0; i <len(dimQualityArray); i++ {
        tmpr,err=strconv.Atoi(dimQualityArray[i])
        arrayOfInt[i]=uint(tmpr)
        fmt.Println(arrayOfInt[i])
        if err != nil { fmt.Println(err) }
    }
    if err != nil {
        fmt.Println(err)
    }
    return arrayOfInt[0],arrayOfInt[1],arrayOfInt[2],nil
}

<commit_msg>Removed commented check on url domain<commit_after>package core
import  "strings"
import "strconv"
import "fmt"
//import "encoding/json"

/* questa funzione spezzetta il parametro in url passato */
func Parser (name string) (uint,uint,uint,error) { //return integer, integer , integer, error

    /*ci separiamo la stringa passata per il carattere */
    stringSlice := strings.Split(name, "/")
    /*ora in posizoione 0 della stringslide, avremo dimensione e qualita*/
    var dimqual string = stringSlice[0]
    /* se togliamo dalla stringa originale con un replace il dimqual, ecco che abbiamo la urla*/
    //var url = strings.Replace(name, dimqual+"/", "", -1)

    dimQualityArray := strings.Split(dimqual, "_")
    fmt.Println(dimQualityArray)
    arrayOfInt := make([]uint, 3)
    var err error=nil

    var tmpr int
    arrayOfInt[2] = 100
    arrayOfInt[0] = 0
    arrayOfInt[1] = 0
    for i := 0; i <len(dimQualityArray); i++ {
        tmpr,err=strconv.Atoi(dimQualityArray[i])
        arrayOfInt[i]=uint(tmpr)
        fmt.Println(arrayOfInt[i])
        if err != nil { fmt.Println(err) }
    }
    if err != nil {
        fmt.Println(err)
    }
    return arrayOfInt[0],arrayOfInt[1],arrayOfInt[2],nil
}

<|endoftext|>