<commit_before>package nosqlorm

type Mantle interface{
        Connect()
        Get(key interface{}) interface{}
        Set(key interface{}, value interface{}) bool
        MGet(key ...interface{}) map[interface{}]interface{}
        MSet(k_v_map map[interface{}]interface{}) bool
        Expire(keys ...interface{}) bool
}

/*

func main(){
        driver := Mantle{Redis{host:"localhost", port:"6379"}}
        connection = driver.Connect()
        connection.Get("key") //returns value
        connection.Set("key", "value") //returns true or false
        connection.MGet(["key1", "key2", "key3"]) // returns map of k v
        connection.MSet(["key"]"value") //returns true or false
}

*/
<commit_msg>interface mantle<commit_after>package mantle

import (
        "string"
        "./backends/redis"
        "./backends/memcache"
)

type Mantle interface{
        Connect()
        Get(key interface{}) interface{}
        Set(key interface{}, value interface{}) bool
        MGet(key ...interface{}) map[interface{}]interface{}
        MSet(k_v_map map[interface{}]interface{}) bool
        Expire(keys ...interface{}) bool
}

type Orm struct{
        driver string
        host string
        port string
}

func (o *Orm) Get() interface{}{
        if o.driver == "memcache" {
                return &Mantle{&Memcache{o.host, o.port}}
        }else{
                return &Mantle{&Redis{o.host, o.port}}
        }
}

func main(){
        driver := &Orm{}
        driver.Get()
        /*
        connection = driver.Connect()
        connection.Get("key") //returns value
        connection.Set("key", "value") //returns true or false
        connection.MGet(["key1", "key2", "key3"]) // returns map of k v
        connection.MSet(["key"]"value") //returns true or false
        */
}

<|endoftext|>


<commit_before>package linalg

import (
	"errors"
	"strconv"
)

type Matrix struct {
	row, col int
	Mij      []complex128
}

func (M *Matrix) String() string {
	ret := ""
	for i := 0; i < M.row; i++ {
		for j := 0; j < M.col; j++ {
			ret += strconv.FormatFloat(real(M.Elem(i, j)), 'g', -1, 64)
			if j < M.col-1 {
				ret += " "
			}
		}
		ret += "\n"
	}
	return ret
}

/* Access Functions */
func (M *Matrix) Elem(row, col int) complex128 {
	return M.Mij[row+col*M.row]
}

func (M *Matrix) Set_elem(row, col int, val complex128) {
	M.Mij[row+col*M.row] = val
}

func (M *Matrix) Set_int(row, col, val int) {
	M.Set_elem(row, col, complex(float64(val), 0))
}

func (M *Matrix) Set_float(row, col int, val float64) {
	M.Set_elem(row, col, complex(val, 0))
}

/* Creation Functions */
func Ident(dim int) *Matrix {
	var mat = new(Matrix)
	mat.row = dim
	mat.col = dim
	mat.Mij = make([]complex128, dim*dim)
	for i := 0; i < dim; i++ {
		mat.Set_elem(i, i, 1)
	}

	return mat
}

func Zero(row, col int) *Matrix {
	var M = new(Matrix)
	M.row = row
	M.col = col
	M.Mij = make([]complex128, row*col)
	return M
}

func (M *Matrix) Copy() *Matrix {
	var N = Zero(M.col, M.row)
	for i := 0; i < N.col; i++ {
		for j := 0; j < N.row; j++ {
			N.Set_elem(i, j, M.Elem(i, j))
		}
	}

	return N
}

func Init(row, col int, data []complex128) *Matrix {
	var M = Zero(row, col)
	M.Mij = data
	return M
}

/* Math Functions */
func (M *Matrix) Eq(N *Matrix) bool {
	if (M.row != N.row) || (M.col != N.col) {
		return false
	}
	for i := 0; i < M.col; i++ {
		for j := 0; j < M.row; j++ {
			if M.Elem(i, j) != N.Elem(i, j) {
				return false
			}
		}
	}
	return true
}

func Mul(A, B, C *Matrix) error {
	if A.col != B.row || A.row != C.row || B.col != C.col {
		return errors.New("Matrix Multiplication size mismatch")
	}

	for i := 0; i < C.row; i++ {
		for j := 0; j < C.col; j++ {
			var accum complex128
			for k := 0; k < A.col; k++ {
				accum += A.Elem(i, k) * B.Elem(k, j)
			}
			C.Set_elem(i, j, accum)
		}
	}
	return nil
}
<commit_msg>Adds scalar multiplication<commit_after>package linalg

import (
	"errors"
	"strconv"
)

type Matrix struct {
	row, col int
	Mij      []complex128
}

func (M *Matrix) String() string {
	ret := ""
	for i := 0; i < M.row; i++ {
		for j := 0; j < M.col; j++ {
			ret += strconv.FormatFloat(real(M.Elem(i, j)), 'g', -1, 64)
			if j < M.col-1 {
				ret += " "
			}
		}
		ret += "\n"
	}
	return ret
}

/* Access Functions */
func (M *Matrix) Elem(row, col int) complex128 {
	return M.Mij[row+col*M.row]
}

func (M *Matrix) Set_elem(row, col int, val complex128) {
	M.Mij[row+col*M.row] = val
}

func (M *Matrix) Set_int(row, col, val int) {
	M.Set_elem(row, col, complex(float64(val), 0))
}

func (M *Matrix) Set_float(row, col int, val float64) {
	M.Set_elem(row, col, complex(val, 0))
}

/* Creation Functions */
func Ident(dim int) *Matrix {
	var mat = new(Matrix)
	mat.row = dim
	mat.col = dim
	mat.Mij = make([]complex128, dim*dim)
	for i := 0; i < dim; i++ {
		mat.Set_elem(i, i, 1)
	}

	return mat
}

func Zero(row, col int) *Matrix {
	var M = new(Matrix)
	M.row = row
	M.col = col
	M.Mij = make([]complex128, row*col)
	return M
}

func (M *Matrix) Copy() *Matrix {
	var N = Zero(M.col, M.row)
	copy(N.Mij, M.Mij)

	return N
}

func Init(row, col int, data []complex128) *Matrix {
	var M = Zero(row, col)
	M.Mij = data
	return M
}

/* Math Functions */
func (M *Matrix) Eq(N *Matrix) bool {
	if (M.row != N.row) || (M.col != N.col) {
		return false
	}
	for i := 0; i < M.col; i++ {
		for j := 0; j < M.row; j++ {
			if M.Elem(i, j) != N.Elem(i, j) {
				return false
			}
		}
	}
	return true
}

func Mul(A, B, C *Matrix) error {
	if A.col != B.row || A.row != C.row || B.col != C.col {
		return errors.New("Matrix Multiplication size mismatch")
	}

	for i := 0; i < C.row; i++ {
		for j := 0; j < C.col; j++ {
			var accum complex128
			for k := 0; k < A.col; k++ {
				accum += A.Elem(i, k) * B.Elem(k, j)
			}
			C.Set_elem(i, j, accum)
		}
	}
	return nil
}

func (M *Matrix) Scale(scalar complex128) {
	for i := 0; i < M.col * M.row; i++ {
		M.Mij[i] *= scalar
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/rand"
	"flag"
	"fmt"
	"log"
	"math"
	"math/big"
	"strconv"
)

var (
	startingCards = flag.Int("starting_cards", 5, "Number of cards each player should start with.")
	numGames      = flag.Int("num_games", 1000, "Number of games that will be played.")
	numTests      = flag.Int("num_tests", 100, "Number of tests to be performed.")
	playerAI      = flag.String("player_ai", "randomAI", "AI to be used by the main player.")
	opponentAI    = flag.String("opponent_ai", "onlyFirstAI", "AI to be used by the opponent player.")
	randomStart   = flag.Bool("random_start", true, "Defines who starts randomly. If false, the first player always starts.")
	debug         = flag.Bool("debug", false, "Print debug information")
)

func main() {
	flag.Parse()
	var results []int
	total := 0
	for i := 0; i < *numTests; i++ {
		res := runGame()
		results = append(results, res)
		total += res
	}
	avg := float64(total) / float64(*numTests)
	variance := 0.0
	for _, res := range results {
		term := float64(res) - avg
		variance += term * term
	}
	variance /= float64(*numTests)
	fmt.Printf("%v+-%v\n", avg, math.Sqrt(variance))
}

func runGame() int {
	w := 0
	for i := 0; i < *numGames; i++ {
		g := newGame()
		if g.play() == 0 {
			w++
		}
	}
	return w
}

type game struct {
	players []*player
	playing int
	deck    *deck
	top     *card
	asked   suit
	order   int
	garbage []*card
}

func newGame() *game {
	g := &game{}
	if *randomStart {
		if *debug {
			fmt.Println("random_start")
		}
		g.playing = randInt(2)
	}
	g.deck = newDeck()
	var pa, oa ai
	for _, a := range ais {
		switch a.name() {
		case *playerAI:
			pa = a
			fallthrough
		case *opponentAI:
			oa = a
		}
	}
	g.players = []*player{newPlayer(pa), newPlayer(oa)}
	for nc := 0; nc < *startingCards; nc++ {
		g.players[0].addCard(g.getCard())
		g.players[1].addCard(g.getCard())
	}
	g.top = g.getCard()
	g.order = 1
	return g
}

func (g *game) play() int {
	for {
		top, asked := g.player().play(g.top, g.asked, g.deck)
		if *debug {
			fmt.Println(g, top, asked)
		}
		if top == nil {
			g.addCard()
			g.next()
			continue
		}
		isPlayValid(top, asked, g.top, g.asked)
		if g.end() {
			return g.playing
		}
		g.garbage = append(g.garbage, g.top)
		g.top, g.asked = top, asked
		switch g.top.n {
		case 1:
		case 12:
			if len(g.players) == 2 {
				g.next()
			} else {
				g.order *= -1
			}
		case 7:
			g.next()
			g.addCard()
			g.addCard()
		}
		g.next()
	}
}

func (g *game) player() *player {
	return g.players[g.playing]
}

func (g *game) next() {
	g.playing = (g.playing + g.order + len(g.players)) % len(g.players)
}

func (g *game) getCard() *card {
	c := g.deck.getCard()
	if c != nil {
		return c
	}
	if g.garbage == nil {
		log.Fatal("empty garbage")
	}
	g.deck.cs = g.garbage
	g.deck.shuffle()
	g.garbage = nil
	return g.deck.getCard()
}

func (g *game) addCard() {
	g.player().addCard(g.getCard())
}

func (g *game) end() bool {
	return g.player().end()
}

func (g *game) String() string {
	var b bytes.Buffer
	b.WriteString(fmt.Sprintf("-> %v %v %v %v %v %v ", len(g.deck.cs), len(g.garbage), g.playing, g.top, g.asked, g.order))
	for _, p := range g.players {
		b.WriteString(p.String())
		b.WriteString(" ")
	}
	return b.String()
}

type deck struct {
	cs []*card
}

func newDeck() *deck {
	d := &deck{}
	for n := 1; n <= 13; n++ {
		for s := spades; s <= clubs; s++ {
			d.cs = append(d.cs, &card{n, s})
		}
	}
	d.shuffle()
	return d
}

func (d *deck) shuffle() {
	l := len(d.cs)
	s := make([]*card, l)
	for i, c := range d.cs {
		r := randInt(i + 1)
		s[i] = s[r]
		s[r] = c
	}
	d.cs = s
}

func (d *deck) getCard() *card {
	if len(d.cs) == 0 {
		return nil
	}
	c := d.cs[0]
	d.cs = d.cs[1:]
	return c
}

type card struct {
	n int
	s suit
}

func (c *card) String() string {
	return strconv.Itoa(c.n) + "/" + strconv.Itoa(int(c.s))
}

type suit int

const (
	noSuit suit = iota
	spades
	hearts
	diamonds
	clubs
)

type player struct {
	cs []*card
	ai ai
}

func newPlayer(a ai) *player {
	return &player{nil, a}
}

func (p *player) addCard(c *card) {
	p.cs = append(p.cs, c)
}

func (p *player) play(top *card, asked suit, d *deck) (*card, suit) {
	i, s := p.ai.play(p.cs, top, asked, d)
	if i == -1 {
		return nil, noSuit
	}
	c := p.cs[i]
	p.cs = append(p.cs[:i], p.cs[i+1:]...)
	if c.n != 11 {
		return c, noSuit
	}
	return c, s
}

func (p *player) end() bool {
	return len(p.cs) == 0
}

func (p *player) String() string {
	return fmt.Sprintf("%v", p.cs)
}

type ai interface {
	// play returns the index of the card in cs that should be played, -1 if
	// there's no card to play, and suit if the card is a 11.
	play(cs []*card, top *card, asked suit, d *deck) (int, suit)
	name() string
}

var ais = []ai{randomAI{}, onlyFirstAI{}, onlyBuyAI{}}

// randomAI plays a random card between the valid cards to play.
type randomAI struct{}

func (randomAI) play(cs []*card, top *card, asked suit, d *deck) (int, suit) {
	is := validIndexes(cs, top, asked)
	if len(is) == 0 {
		return -1, noSuit
	}
	return is[randInt(len(is))], suit(randInt(4) + 1)
}

func (randomAI) name() string {
	return "randomAI"
}

type onlyFirstAI struct{}

func (onlyFirstAI) play(cs []*card, top *card, asked suit, d *deck) (int, suit) {
	if cs[0].n == 11 {
		return 0, spades
	}
	if asked != noSuit {
		if cs[0].s == asked {
			return 0, noSuit
		}
		return -1, noSuit
	}
	if cs[0].n == top.n || cs[0].s == top.s {
		return 0, noSuit
	}
	return -1, noSuit
}

func (onlyFirstAI) name() string {
	return "onlyFirstAI"
}

type onlyBuyAI struct{}

func (onlyBuyAI) play(cs []*card, top *card, asked suit, d *deck) (int, suit) {
	return -1, noSuit
}

func (onlyBuyAI) name() string {
	return "onlyBuyAI"
}

func validIndexes(cs []*card, top *card, asked suit) []int {
	var is []int
	for i, c := range cs {
		if c.n == 11 {
			is = append(is, i)
			continue
		}
		if asked != noSuit {
			if c.s == asked {
				is = append(is, i)
			}
			continue
		}
		if c.s == top.s || c.n == top.n {
			is = append(is, i)
		}
	}
	return is
}

func isPlayValid(newc *card, newa suit, oldc *card, olda suit) {
	if newc.n == 11 {
		if newa == noSuit {
			log.Fatal("newc.n = 11, newa = noSuit")
		}
		return
	}
	if newa != noSuit {
		log.Fatalf("newc.n = %v, newa = %v", newc.n, newa)
	}
	if olda != noSuit {
		if newc.s != olda {
			log.Fatalf("newc.s = %v, olda = %v", newc.s, olda)
		}
		return
	}
	if newc.n != oldc.n && newc.s != newc.s {
		log.Fatalf("newc = %v, oldc = %v", newc, oldc)
	}
}

// randInt returns a random number from 0 to max - 1.
func randInt(max int) int {
	b, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
	if err != nil {
		log.Fatal(err)
	}
	return int(b.Int64())
}
<commit_msg>ai=functions<commit_after>package main

import (
	"bytes"
	"crypto/rand"
	"flag"
	"fmt"
	"log"
	"math"
	"math/big"
	"strconv"
)

var (
	startingCards = flag.Int("starting_cards", 5, "Number of cards each player should start with.")
	numGames      = flag.Int("num_games", 1000, "Number of games that will be played.")
	numTests      = flag.Int("num_tests", 100, "Number of tests to be performed.")
	playerAI      = flag.String("player_ai", "randomAI", "AI to be used by the main player.")
	opponentAI    = flag.String("opponent_ai", "onlyFirstAI", "AI to be used by the opponent player.")
	randomStart   = flag.Bool("random_start", true, "Defines who starts randomly. If false, the first player always starts.")
	debug         = flag.Bool("debug", false, "Print debug information")
)

func main() {
	flag.Parse()
	var results []int
	total := 0
	for i := 0; i < *numTests; i++ {
		res := runGame()
		results = append(results, res)
		total += res
	}
	avg := float64(total) / float64(*numTests)
	variance := 0.0
	for _, res := range results {
		term := float64(res) - avg
		variance += term * term
	}
	variance /= float64(*numTests)
	fmt.Printf("%v+-%v\n", avg, math.Sqrt(variance))
}

func runGame() int {
	w := 0
	for i := 0; i < *numGames; i++ {
		g := newGame()
		if g.play() == 0 {
			w++
		}
	}
	return w
}

type game struct {
	players []*player
	playing int
	deck    *deck
	top     *card
	asked   suit
	order   int
	garbage []*card
}

func newGame() *game {
	g := &game{}
	if *randomStart {
		if *debug {
			fmt.Println("random_start")
		}
		g.playing = randInt(2)
	}
	g.deck = newDeck()
	g.players = []*player{newPlayer(*playerAI), newPlayer(*opponentAI)}
	for nc := 0; nc < *startingCards; nc++ {
		g.players[0].addCard(g.getCard())
		g.players[1].addCard(g.getCard())
	}
	g.top = g.getCard()
	g.order = 1
	return g
}

func (g *game) play() int {
	for {
		top, asked := g.player().play(g.top, g.asked, g.deck)
		if *debug {
			fmt.Println(g, top, asked)
		}
		if top == nil {
			g.addCard()
			g.next()
			continue
		}
		isPlayValid(top, asked, g.top, g.asked)
		if g.end() {
			return g.playing
		}
		g.garbage = append(g.garbage, g.top)
		g.top, g.asked = top, asked
		switch g.top.n {
		case 1:
		case 12:
			if len(g.players) == 2 {
				g.next()
			} else {
				g.order *= -1
			}
		case 7:
			g.next()
			g.addCard()
			g.addCard()
		}
		g.next()
	}
}

func (g *game) player() *player {
	return g.players[g.playing]
}

func (g *game) next() {
	g.playing = (g.playing + g.order + len(g.players)) % len(g.players)
}

func (g *game) getCard() *card {
	c := g.deck.getCard()
	if c != nil {
		return c
	}
	if g.garbage == nil {
		log.Fatal("empty garbage")
	}
	g.deck.cs = g.garbage
	g.deck.shuffle()
	g.garbage = nil
	return g.deck.getCard()
}

func (g *game) addCard() {
	g.player().addCard(g.getCard())
}

func (g *game) end() bool {
	return g.player().end()
}

func (g *game) String() string {
	var b bytes.Buffer
	b.WriteString(fmt.Sprintf("-> %v %v %v %v %v %v ", len(g.deck.cs), len(g.garbage), g.playing, g.top, g.asked, g.order))
	for _, p := range g.players {
		b.WriteString(p.String())
		b.WriteString(" ")
	}
	return b.String()
}

type deck struct {
	cs []*card
}

func newDeck() *deck {
	d := &deck{}
	for n := 1; n <= 13; n++ {
		for s := spades; s <= clubs; s++ {
			d.cs = append(d.cs, &card{n, s})
		}
	}
	d.shuffle()
	return d
}

func (d *deck) shuffle() {
	l := len(d.cs)
	s := make([]*card, l)
	for i, c := range d.cs {
		r := randInt(i + 1)
		s[i] = s[r]
		s[r] = c
	}
	d.cs = s
}

func (d *deck) getCard() *card {
	if len(d.cs) == 0 {
		return nil
	}
	c := d.cs[0]
	d.cs = d.cs[1:]
	return c
}

type card struct {
	n int
	s suit
}

func (c *card) String() string {
	return strconv.Itoa(c.n) + "/" + strconv.Itoa(int(c.s))
}

type suit int

const (
	noSuit suit = iota
	spades
	hearts
	diamonds
	clubs
)

type player struct {
	cs []*card
	ai ai
}

func newPlayer(aiName string) *player {
	return &player{nil, ais[aiName]}
}

func (p *player) addCard(c *card) {
	p.cs = append(p.cs, c)
}

func (p *player) play(top *card, asked suit, d *deck) (*card, suit) {
	i, s := p.ai(p.cs, top, asked, d)
	if i == -1 {
		return nil, noSuit
	}
	c := p.cs[i]
	p.cs = append(p.cs[:i], p.cs[i+1:]...)
	if c.n != 11 {
		return c, noSuit
	}
	return c, s
}

func (p *player) end() bool {
	return len(p.cs) == 0
}

func (p *player) String() string {
	return fmt.Sprintf("%v", p.cs)
}

// ai returns the index of the card in cs that should be played, -1 if there's
// no card to play, and suit if the card is a 11.
type ai func(cs []*card, top *card, asked suit, d *deck) (int, suit)

var ais = map[string]ai{
	"randomAI": randomAI,
	"onlyFirstAI": onlyFirstAI,
	"onlyBuyAI": onlyBuyAI,
}

func randomAI(cs []*card, top *card, asked suit, d *deck) (int, suit) {
	is := validIndexes(cs, top, asked)
	if len(is) == 0 {
		return -1, noSuit
	}
	return is[randInt(len(is))], suit(randInt(4) + 1)
}

func onlyFirstAI(cs []*card, top *card, asked suit, d *deck) (int, suit) {
	if cs[0].n == 11 {
		return 0, spades
	}
	if asked != noSuit {
		if cs[0].s == asked {
			return 0, noSuit
		}
		return -1, noSuit
	}
	if cs[0].n == top.n || cs[0].s == top.s {
		return 0, noSuit
	}
	return -1, noSuit
}

func onlyBuyAI(cs []*card, top *card, asked suit, d *deck) (int, suit) {
	return -1, noSuit
}

func validIndexes(cs []*card, top *card, asked suit) []int {
	var is []int
	for i, c := range cs {
		if c.n == 11 {
			is = append(is, i)
			continue
		}
		if asked != noSuit {
			if c.s == asked {
				is = append(is, i)
			}
			continue
		}
		if c.s == top.s || c.n == top.n {
			is = append(is, i)
		}
	}
	return is
}

func isPlayValid(newc *card, newa suit, oldc *card, olda suit) {
	if newc.n == 11 {
		if newa == noSuit {
			log.Fatal("newc.n = 11, newa = noSuit")
		}
		return
	}
	if newa != noSuit {
		log.Fatalf("newc.n = %v, newa = %v", newc.n, newa)
	}
	if olda != noSuit {
		if newc.s != olda {
			log.Fatalf("newc.s = %v, olda = %v", newc.s, olda)
		}
		return
	}
	if newc.n != oldc.n && newc.s != newc.s {
		log.Fatalf("newc = %v, oldc = %v", newc, oldc)
	}
}

// randInt returns a random number from 0 to max - 1.
func randInt(max int) int {
	b, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
	if err != nil {
		log.Fatal(err)
	}
	return int(b.Int64())
}
<|endoftext|>


<commit_before>package model_loader

import (
	"encoding/json"
	"fmt"
	valid "github.com/asaskevich/govalidator"
	"github.com/centurylinkcloud/clc-go-cli/parser"
	"reflect"
	"time"
)

const (
	timeFormat = "2006-01-02 15:04:05"
)

func LoadModel(parsedArgs map[string]interface{}, inputModel interface{}) error {
	metaModel := reflect.ValueOf(inputModel)
	if metaModel.Kind() != reflect.Ptr {
		return fmt.Errorf("Input model must be passed by pointer.")
	}
	for k, v := range parsedArgs {
		field, err := getFieldByName(metaModel, k)
		if err != nil {
			return err
		}
		err = loadValue(k, v, field)
		if err != nil {
			return err
		}
	}
	return nil
}

func loadValue(key string, arg interface{}, field reflect.Value) error {
	if arg == nil {
		return nil
	}
	switch field.Interface().(type) {
	case int64:
		var argInt int64
		var mismatch = true
		if reflect.ValueOf(arg).Kind() == reflect.Int {
			argInt = arg.(int64)
			mismatch = false
		} else if reflect.ValueOf(arg).Kind() == reflect.Float64 {
			if valid.IsWhole(arg.(float64)) {
				argInt = int64(arg.(float64))
				mismatch = false
			}
		} else if reflect.ValueOf(arg).Kind() == reflect.String {
			if valid.IsInt(arg.(string)) {
				argInt, _ = valid.ToInt(arg.(string))
				mismatch = false
			}
		}
		if mismatch {
			return fmt.Errorf("Type mismatch: %s value must be integer.", key)
		} else {
			field.SetInt(argInt)
			return nil
		}
	case float64:
		var argFloat64 float64
		var mismatch = true
		if reflect.ValueOf(arg).Kind() == reflect.Float64 {
			argFloat64 = arg.(float64)
			mismatch = false
		} else if reflect.ValueOf(arg).Kind() == reflect.String {
			if valid.IsFloat(arg.(string)) {
				argFloat64, _ = valid.ToFloat(arg.(string))
				mismatch = false
			}
		}
		if mismatch {
			return fmt.Errorf("Type mismatch: %s value must be float.", key)
		} else {
			field.SetFloat(argFloat64)
			return nil
		}
	case time.Time:
		var argTime time.Time
		var err error
		var mismatch = true
		if reflect.ValueOf(arg).Kind() == reflect.String {
			if argTime, err = time.Parse(timeFormat, arg.(string)); err == nil {
				mismatch = false
			}
		}
		if mismatch {
			return fmt.Errorf("Type mismatch: %s value must be datetime in `YYYY-MM-DD hh:mm:ss` format.", key)
		} else {
			field.Set(reflect.ValueOf(argTime))
			return nil
		}
	case bool:
		var argBool bool
		var mismatch = true
		if reflect.ValueOf(arg).Kind() == reflect.Bool {
			argBool = arg.(bool)
			mismatch = false
		} else if reflect.ValueOf(arg).Kind() == reflect.String {
			if arg == "true" {
				argBool = true
				mismatch = false
			} else if arg == "false" {
				argBool = false
				mismatch = false
			}
		}
		if mismatch {
			return fmt.Errorf("Type mismatch: %s value must be either true or false.", key)
		} else {
			field.SetBool(argBool)
		}
		return nil
	case string:
		if reflect.ValueOf(arg).Kind() != reflect.String {
			return fmt.Errorf("Type mismatch: %s value must be string.", key)
		}
		field.SetString(arg.(string))
		return nil
	}
	if isStruct(field) {
		argStruct, err := parseStruct(arg)
		if err != nil {
			return err
		}
		for k, v := range argStruct {
			nestedField, err := getFieldByName(field.Addr(), k)
			if err != nil {
				return err
			}
			err = loadValue(k, v, nestedField)
			if err != nil {
				return err
			}
		}
		return nil
	} else if isSlice(field) {
		argSlice, err := parseSlice(arg)
		if err != nil {
			return err
		}
		for _, v := range argSlice {
			elementPtr := getEmplySliceType(field)
			err = loadValue(key, v, elementPtr.Elem())
			if err != nil {
				return err
			}
			field.Set(reflect.Append(field, elementPtr.Elem()))
		}
		return nil
	}
	return fmt.Errorf("Unsupported field type %s", field.Kind())
}

func getFieldByName(model reflect.Value, name string) (reflect.Value, error) {
	field := model.Elem().FieldByName(name)
	if !field.IsValid() {
		return reflect.ValueOf(nil), fmt.Errorf("Field `%s` does not exist.", name)
	}
	return field, nil
}

func isStruct(model reflect.Value) bool {
	return model.Kind() == reflect.Struct
}

func isSlice(model reflect.Value) bool {
	return model.Kind() == reflect.Slice
}

// Parses an object of type map[string]interface{} either from JSON or from a=b,c=d,.. notation.
// Also, calls NormalizeKeys with the parsed object.
// If arg is already of type map[string]interface{} returns it as is.
func parseStruct(arg interface{}) (map[string]interface{}, error) {
	if argMap, isMap := arg.(map[string]interface{}); isMap {
		return argMap, nil
	}
	parsed := make(map[string]interface{}, 0)
	if err := json.Unmarshal([]byte(arg.(string)), &parsed); err == nil {
		parser.NormalizeKeys(parsed)
		return parsed, nil
	}
	if parsed, err := parser.ParseObject(arg.(string)); err == nil {
		return parsed, nil
	}
	return nil, fmt.Errorf("`%s` is neither in JSON nor in key=value,.. format.", arg.(string))
}

// Parses an object of type []interface{} either from JSON.
// Also, calls NormalizeKeys with the parsed object.
// If arg is already of type []interface{} returns it as is.
func parseSlice(arg interface{}) ([]interface{}, error) {
	if argSlice, isSlice := arg.([]interface{}); isSlice {
		return argSlice, nil
	}
	parsed := make([]interface{}, 0)
	if err := json.Unmarshal([]byte(arg.(string)), &parsed); err == nil {
		parser.NormalizeKeys(parsed)
		return parsed, nil
	}
	return nil, fmt.Errorf("`%s` is neither in JSON nor in key=value,.. format.", arg.(string))
}

func getEmplySliceType(slice reflect.Value) reflect.Value {
	return reflect.New(slice.Type().Elem())
}
<commit_msg>Ignore nil input in LoadModel.<commit_after>package model_loader

import (
	"encoding/json"
	"fmt"
	valid "github.com/asaskevich/govalidator"
	"github.com/centurylinkcloud/clc-go-cli/parser"
	"reflect"
	"time"
)

const (
	timeFormat = "2006-01-02 15:04:05"
)

func LoadModel(parsedArgs map[string]interface{}, inputModel interface{}) error {
	metaModel := reflect.ValueOf(inputModel)
	if !metaModel.IsValid() {
		return nil
	}
	if metaModel.Kind() != reflect.Ptr {
		return fmt.Errorf("Input model must be passed by pointer.")
	}
	for k, v := range parsedArgs {
		field, err := getFieldByName(metaModel, k)
		if err != nil {
			return err
		}
		err = loadValue(k, v, field)
		if err != nil {
			return err
		}
	}
	return nil
}

func loadValue(key string, arg interface{}, field reflect.Value) error {
	if arg == nil {
		return nil
	}
	switch field.Interface().(type) {
	case int64:
		var argInt int64
		var mismatch = true
		if reflect.ValueOf(arg).Kind() == reflect.Int {
			argInt = arg.(int64)
			mismatch = false
		} else if reflect.ValueOf(arg).Kind() == reflect.Float64 {
			if valid.IsWhole(arg.(float64)) {
				argInt = int64(arg.(float64))
				mismatch = false
			}
		} else if reflect.ValueOf(arg).Kind() == reflect.String {
			if valid.IsInt(arg.(string)) {
				argInt, _ = valid.ToInt(arg.(string))
				mismatch = false
			}
		}
		if mismatch {
			return fmt.Errorf("Type mismatch: %s value must be integer.", key)
		} else {
			field.SetInt(argInt)
			return nil
		}
	case float64:
		var argFloat64 float64
		var mismatch = true
		if reflect.ValueOf(arg).Kind() == reflect.Float64 {
			argFloat64 = arg.(float64)
			mismatch = false
		} else if reflect.ValueOf(arg).Kind() == reflect.String {
			if valid.IsFloat(arg.(string)) {
				argFloat64, _ = valid.ToFloat(arg.(string))
				mismatch = false
			}
		}
		if mismatch {
			return fmt.Errorf("Type mismatch: %s value must be float.", key)
		} else {
			field.SetFloat(argFloat64)
			return nil
		}
	case time.Time:
		var argTime time.Time
		var err error
		var mismatch = true
		if reflect.ValueOf(arg).Kind() == reflect.String {
			if argTime, err = time.Parse(timeFormat, arg.(string)); err == nil {
				mismatch = false
			}
		}
		if mismatch {
			return fmt.Errorf("Type mismatch: %s value must be datetime in `YYYY-MM-DD hh:mm:ss` format.", key)
		} else {
			field.Set(reflect.ValueOf(argTime))
			return nil
		}
	case bool:
		var argBool bool
		var mismatch = true
		if reflect.ValueOf(arg).Kind() == reflect.Bool {
			argBool = arg.(bool)
			mismatch = false
		} else if reflect.ValueOf(arg).Kind() == reflect.String {
			if arg == "true" {
				argBool = true
				mismatch = false
			} else if arg == "false" {
				argBool = false
				mismatch = false
			}
		}
		if mismatch {
			return fmt.Errorf("Type mismatch: %s value must be either true or false.", key)
		} else {
			field.SetBool(argBool)
		}
		return nil
	case string:
		if reflect.ValueOf(arg).Kind() != reflect.String {
			return fmt.Errorf("Type mismatch: %s value must be string.", key)
		}
		field.SetString(arg.(string))
		return nil
	}
	if isStruct(field) {
		argStruct, err := parseStruct(arg)
		if err != nil {
			return err
		}
		for k, v := range argStruct {
			nestedField, err := getFieldByName(field.Addr(), k)
			if err != nil {
				return err
			}
			err = loadValue(k, v, nestedField)
			if err != nil {
				return err
			}
		}
		return nil
	} else if isSlice(field) {
		argSlice, err := parseSlice(arg)
		if err != nil {
			return err
		}
		for _, v := range argSlice {
			elementPtr := getEmplySliceType(field)
			err = loadValue(key, v, elementPtr.Elem())
			if err != nil {
				return err
			}
			field.Set(reflect.Append(field, elementPtr.Elem()))
		}
		return nil
	}
	return fmt.Errorf("Unsupported field type %s", field.Kind())
}

func getFieldByName(model reflect.Value, name string) (reflect.Value, error) {
	field := model.Elem().FieldByName(name)
	if !field.IsValid() {
		return reflect.ValueOf(nil), fmt.Errorf("Field `%s` does not exist.", name)
	}
	return field, nil
}

func isStruct(model reflect.Value) bool {
	return model.Kind() == reflect.Struct
}

func isSlice(model reflect.Value) bool {
	return model.Kind() == reflect.Slice
}

// Parses an object of type map[string]interface{} either from JSON or from a=b,c=d,.. notation.
// Also, calls NormalizeKeys with the parsed object.
// If arg is already of type map[string]interface{} returns it as is.
func parseStruct(arg interface{}) (map[string]interface{}, error) {
	if argMap, isMap := arg.(map[string]interface{}); isMap {
		return argMap, nil
	}
	parsed := make(map[string]interface{}, 0)
	if err := json.Unmarshal([]byte(arg.(string)), &parsed); err == nil {
		parser.NormalizeKeys(parsed)
		return parsed, nil
	}
	if parsed, err := parser.ParseObject(arg.(string)); err == nil {
		return parsed, nil
	}
	return nil, fmt.Errorf("`%s` is neither in JSON nor in key=value,.. format.", arg.(string))
}

// Parses an object of type []interface{} either from JSON.
// Also, calls NormalizeKeys with the parsed object.
// If arg is already of type []interface{} returns it as is.
func parseSlice(arg interface{}) ([]interface{}, error) {
	if argSlice, isSlice := arg.([]interface{}); isSlice {
		return argSlice, nil
	}
	parsed := make([]interface{}, 0)
	if err := json.Unmarshal([]byte(arg.(string)), &parsed); err == nil {
		parser.NormalizeKeys(parsed)
		return parsed, nil
	}
	return nil, fmt.Errorf("`%s` is neither in JSON nor in key=value,.. format.", arg.(string))
}

func getEmplySliceType(slice reflect.Value) reflect.Value {
	return reflect.New(slice.Type().Elem())
}
<|endoftext|>


<commit_before>/*

The html transform package implements a html css selector and transformer.

An html doc can be inspected and queried using css selectors as well as
transformed.

	doc := NewDoc(str)
	t := NewTransform(doc)
	t.Apply(CopyAnd(myModifiers...), "li.menuitem")
	t.Apply(Replace(Text("my new text"), "a")
	newDoc := t.Doc()
*/
package transform

// TODO(jwall): Documentation...
import (
	. "code.google.com/p/go-html-transform/h5"
	"log"
	"reflect"
)

// The TransformFunc type is the type of a Node transformation function.
type TransformFunc func(*Node)

// Transformer encapsulates a document under transformation.
type Transformer struct {
	doc *Node
}

// Constructor for a Transformer. It makes a copy of the document
// and transforms that instead of the original.
func NewTransform(d *Node) *Transformer {
	return &Transformer{doc: d.Clone()}
}

// The Doc method returns the document under transformation.
func (t *Transformer) Doc() *Node {
	return t.doc
}

func (t *Transformer) String() string {
	return t.doc.String()
}

// TODO(jwall): TransformApplication type that we can process the doc in one
// pass.
// The Apply method applies a TransformFunc to the nodes returned from
// the Selector query
func (t *Transformer) Apply(f TransformFunc, sel ...string) *Transformer {
	// TODO come up with a way to walk tree once?
	sq := NewSelectorQuery(sel...)
	nodes := sq.Apply(t.doc)
	for _, n := range nodes {
		f(n)
	}
	return t
}

// Compose a set of TransformFuncs into a single TransformFunc
func Compose(fs ...TransformFunc) TransformFunc {
	return func(n *Node) {
		for _, f := range fs {
			f(n)
		}
	}
}

// AppendChildren creates a TransformFunc that appends the Children passed in.
func AppendChildren(cs ...*Node) TransformFunc {
	return func(n *Node) {
		sz := len(n.Children)
		newChild := make([]*Node, sz+len(cs))
		copy(newChild, n.Children)
		copy(newChild[sz:], cs)
		n.Children = newChild
	}
}

// PrependChildren creates a TransformFunc that prepends the Children passed in.
func PrependChildren(cs ...*Node) TransformFunc {
	return func(n *Node) {
		sz := len(n.Children)
		sz2 := len(cs)
		newChild := make([]*Node, sz+len(cs))
		copy(newChild[sz2:], n.Children)
		copy(newChild[0:sz2], cs)
		n.Children = newChild
	}
}

// RemoveChildren creates a TransformFunc that removes the Children of the node
// it operates on.
func RemoveChildren() TransformFunc {
	return func(n *Node) {
		n.Children = make([]*Node, 0)
	}
}

// ReplaceChildren creates a TransformFunc that replaces the Children of the
// node it operates on with the Children passed in.
func ReplaceChildren(ns ...*Node) TransformFunc {
	return func(n *Node) {
		n.Children = ns
	}
}

func Replace(ns ...*Node) TransformFunc {
	return func(n *Node) {
		p := n.Parent
		switch p {
		case nil:
			n.Children = ns
		default:
			for i, c := range p.Children {
				if reflect.DeepEqual(c, n) {
					pre := append(p.Children[:i], ns...)
					p.Children = append(pre, p.Children[i+1:]...)
				}
			}
		}
	}
}

// ModifyAttrb creates a TransformFunc that modifies the attributes
// of the node it operates on.
func ModifyAttrib(key string, val string) TransformFunc {
	return func(n *Node) {
		found := false
		for i, attr := range n.Attr {
			if attr.Name == key {
				n.Attr[i].Value = val
				found = true
			}
		}
		if !found {
			newAttr := make([]*Attribute, len(n.Attr)+1)
			newAttr[len(n.Attr)] = &Attribute{Name: key, Value: val}
			n.Attr = newAttr
		}
	}
}

func TransformAttrib(key string, f func(string) string) TransformFunc {
	return func(n *Node) {
		for i, attr := range n.Attr {
			if attr.Name == key {
				n.Attr[i].Value = f(n.Attr[i].Value)
			}
		}
	}
}

func DoAll(fs ...TransformFunc) TransformFunc {
	return func(n *Node) {
		for _, f := range fs {
			f(n)
		}
	}
}

// ForEach takes a function and a list of Nodes and performs that
// function for each node in the list.
// The function should be of a type either func(...*Node) TransformFunc
// or func(*Node) TransformFunc. Any other type will panic.
// Returns a TransformFunc.
func ForEach(f interface{}, ns ...*Node) TransformFunc {
	switch t := f.(type) {
	case func(...*Node) TransformFunc:
		return func(n *Node) {
			for _, n2 := range ns {
				f1 := f.(func(...*Node) TransformFunc)
				f2 := f1(n2)
				f2(n)
			}
		}
	case func(*Node) TransformFunc:
		return func(n *Node) {
			for _, n2 := range ns {
				f1 := f.(func(*Node) TransformFunc)
				f2 := f1(n2)
				f2(n)
			}
		}
	default:
		log.Panicf("Wrong function type passed to ForEach %s", t)
	}
	return nil
}

// CopyAnd will construct a TransformFunc that will
// make a copy of the node for each passed in TransformFunc
// And replace the passed in node with the resulting transformed
// Nodes.
// Returns a TransformFunc
func CopyAnd(fns ...TransformFunc) TransformFunc {
	return func(n *Node) {
		newNodes := make([]*Node, len(fns))
		for i, fn := range fns {
			node := n.Clone()
			fn(node)
			newNodes[i] = node
		}
		replaceFn := Replace(newNodes...)
		replaceFn(n)
	}
}
// Copyright 2010 Jeremy Wall (jeremy@marzhillstudios.com)
// Use of this source code is governed by the Artistic License 2.0.
// That License is included in the LICENSE file.
<commit_msg>Add a clone and an apply all method to a transformer.<commit_after>/*

The html transform package implements a html css selector and transformer.

An html doc can be inspected and queried using css selectors as well as
transformed.

	doc := NewDoc(str)
	t := NewTransform(doc)
	t.Apply(CopyAnd(myModifiers...), "li.menuitem")
	t.Apply(Replace(Text("my new text"), "a")
	newDoc := t.Doc()
*/
package transform

// TODO(jwall): Documentation...
import (
	. "code.google.com/p/go-html-transform/h5"
	"log"
	"reflect"
)

// The TransformFunc type is the type of a Node transformation function.
type TransformFunc func(*Node)

// Transformer encapsulates a document under transformation.
type Transformer struct {
	doc *Node
}

// Constructor for a Transformer. It makes a copy of the document
// and transforms that instead of the original.
func NewTransform(d *Node) *Transformer {
	return &Transformer{doc: d.Clone()}
}

// The Doc method returns the document under transformation.
func (t *Transformer) Doc() *Node {
	return t.doc
}

func (t *Transformer) String() string {
	return t.doc.String()
}

func (t *Transformer) Clone() *Transformer {
	return NewTransform(t.Doc())
}

// TODO(jwall): TransformApplication type that we can process the doc in one
// pass.
// The Apply method applies a TransformFunc to the nodes returned from
// the Selector query
func (t *Transformer) Apply(f TransformFunc, sel ...string) *Transformer {
	// TODO come up with a way to walk tree once?
	sq := NewSelectorQuery(sel...)
	nodes := sq.Apply(t.doc)
	for _, n := range nodes {
		f(n)
	}
	return t
}

type Transform struct {
	q []string
	f TransformFunc
}

// Spec creates a Transform that you can apply using ApplyAll.
func Trans(f TransformFunc, sel1 string, sel ...string) Transform {
	return Transform{f:f, q:append([]string{sel1}, sel...)}
}

// ApplyAll applies a series of Transforms to a document.
//     t.ApplyAll(Trans(f, sel1, sel2), Trans(f2, sel3, sel4))
func (t *Transformer) ApplyAll(ts ...Transform) *Transformer {
	for _, spec := range ts {
		t.Apply(spec.f, spec.q...)
	}
	return t
}

// Compose a set of TransformFuncs into a single TransformFunc
func Compose(fs ...TransformFunc) TransformFunc {
	return func(n *Node) {
		for _, f := range fs {
			f(n)
		}
	}
}

// AppendChildren creates a TransformFunc that appends the Children passed in.
func AppendChildren(cs ...*Node) TransformFunc {
	return func(n *Node) {
		sz := len(n.Children)
		newChild := make([]*Node, sz+len(cs))
		copy(newChild, n.Children)
		copy(newChild[sz:], cs)
		n.Children = newChild
	}
}

// PrependChildren creates a TransformFunc that prepends the Children passed in.
func PrependChildren(cs ...*Node) TransformFunc {
	return func(n *Node) {
		sz := len(n.Children)
		sz2 := len(cs)
		newChild := make([]*Node, sz+len(cs))
		copy(newChild[sz2:], n.Children)
		copy(newChild[0:sz2], cs)
		n.Children = newChild
	}
}

// RemoveChildren creates a TransformFunc that removes the Children of the node
// it operates on.
func RemoveChildren() TransformFunc {
	return func(n *Node) {
		n.Children = make([]*Node, 0)
	}
}

// ReplaceChildren creates a TransformFunc that replaces the Children of the
// node it operates on with the Children passed in.
func ReplaceChildren(ns ...*Node) TransformFunc {
	return func(n *Node) {
		n.Children = ns
	}
}

func Replace(ns ...*Node) TransformFunc {
	return func(n *Node) {
		p := n.Parent
		switch p {
		case nil:
			n.Children = ns
		default:
			for i, c := range p.Children {
				if reflect.DeepEqual(c, n) {
					pre := append(p.Children[:i], ns...)
					p.Children = append(pre, p.Children[i+1:]...)
				}
			}
		}
	}
}

// ModifyAttrb creates a TransformFunc that modifies the attributes
// of the node it operates on.
func ModifyAttrib(key string, val string) TransformFunc {
	return func(n *Node) {
		found := false
		for i, attr := range n.Attr {
			if attr.Name == key {
				n.Attr[i].Value = val
				found = true
			}
		}
		if !found {
			newAttr := make([]*Attribute, len(n.Attr)+1)
			newAttr[len(n.Attr)] = &Attribute{Name: key, Value: val}
			n.Attr = newAttr
		}
	}
}

func TransformAttrib(key string, f func(string) string) TransformFunc {
	return func(n *Node) {
		for i, attr := range n.Attr {
			if attr.Name == key {
				n.Attr[i].Value = f(n.Attr[i].Value)
			}
		}
	}
}

func DoAll(fs ...TransformFunc) TransformFunc {
	return func(n *Node) {
		for _, f := range fs {
			f(n)
		}
	}
}

// ForEach takes a function and a list of Nodes and performs that
// function for each node in the list.
// The function should be of a type either func(...*Node) TransformFunc
// or func(*Node) TransformFunc. Any other type will panic.
// Returns a TransformFunc.
func ForEach(f interface{}, ns ...*Node) TransformFunc {
	switch t := f.(type) {
	case func(...*Node) TransformFunc:
		return func(n *Node) {
			for _, n2 := range ns {
				f1 := f.(func(...*Node) TransformFunc)
				f2 := f1(n2)
				f2(n)
			}
		}
	case func(*Node) TransformFunc:
		return func(n *Node) {
			for _, n2 := range ns {
				f1 := f.(func(*Node) TransformFunc)
				f2 := f1(n2)
				f2(n)
			}
		}
	default:
		log.Panicf("Wrong function type passed to ForEach %s", t)
	}
	return nil
}

// CopyAnd will construct a TransformFunc that will
// make a copy of the node for each passed in TransformFunc
// And replace the passed in node with the resulting transformed
// Nodes.
// Returns a TransformFunc
func CopyAnd(fns ...TransformFunc) TransformFunc {
	return func(n *Node) {
		newNodes := make([]*Node, len(fns))
		for i, fn := range fns {
			node := n.Clone()
			fn(node)
			newNodes[i] = node
		}
		replaceFn := Replace(newNodes...)
		replaceFn(n)
	}
}
// Copyright 2010 Jeremy Wall (jeremy@marzhillstudios.com)
// Use of this source code is governed by the Artistic License 2.0.
// That License is included in the LICENSE file.
<|endoftext|>


<commit_before>package uic

import (
	"encoding/base64"
	"github.com/Cepave/fe/g"
	"github.com/Cepave/fe/http/base"
	. "github.com/Cepave/fe/model/uic"
	"github.com/Cepave/fe/utils"
	"github.com/toolkits/str"
	"net/url"
	"strings"
	"time"
)

type AuthController struct {
	base.BaseController
}

func (this *AuthController) Logout() {
	u := this.Ctx.Input.GetData("CurrentUser").(*User)
	RemoveSessionByUid(u.Id)
	this.Ctx.SetCookie("sig", "", 0, "/")
	this.Ctx.SetCookie("sig", "", 0, "/", ".owlemon.com")
	this.Redirect("/auth/login", 302)
}

func (this *AuthController) LoginGet() {
	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")

	cookieSig := this.Ctx.GetCookie("sig")
	if cookieSig == "" {
		this.renderLoginPage(appSig, callback)
		return
	}

	sessionObj := ReadSessionBySig(cookieSig)
	if sessionObj == nil {
		this.renderLoginPage(appSig, callback)
		return
	}

	if int64(sessionObj.Expired) < time.Now().Unix() {
		RemoveSessionByUid(sessionObj.Uid)
		this.renderLoginPage(appSig, callback)
		return
	}

	if appSig != "" && callback != "" {
		this.Redirect(callback, 302)
	} else {
		this.Redirect("/me/info", 302)
	}
}

func (this *AuthController) LoginPost() {
	name := this.GetString("name", "")
	password := this.GetString("password", "")

	if name == "" || password == "" {
		this.ServeErrJson("name or password is blank")
		return
	}

	var u *User

	ldapEnabled := this.MustGetBool("ldap", false)

	if ldapEnabled {
		sucess, err := utils.LdapBind(g.Config().Ldap.Addr, name, password)
		if err != nil {
			this.ServeErrJson(err.Error())
			return
		}

		if !sucess {
			this.ServeErrJson("name or password error")
			return
		}

		arr := strings.Split(name, "@")
		var userName, userEmail string
		if len(arr) == 2 {
			userName = arr[0]
			userEmail = name
		} else {
			userName = name
			userEmail = ""
		}

		u = ReadUserByName(userName)
		if u == nil {
			// 说明用户不存在
			u = &User{
				Name:   userName,
				Passwd: "",
				Email:  userEmail,
			}
			_, err = u.Save()
			if err != nil {
				this.ServeErrJson("insert user fail " + err.Error())
				return
			}
		}
	} else {
		u = ReadUserByName(name)
		if u == nil {
			this.ServeErrJson("no such user")
			return
		}

		if u.Passwd != str.Md5Encode(g.Config().Salt+password) {
			this.ServeErrJson("password error")
			return
		}
	}

	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")
	if appSig != "" && callback != "" {
		SaveSessionAttrs(u.Id, appSig, int(time.Now().Unix())+3600*24*30)
	} else {
		this.CreateSession(u.Id, 3600*24*30)
	}

	this.ServeDataJson(callback)
}

func (this *AuthController) renderLoginPage(sig, callback string) {
	this.Data["CanRegister"] = g.Config().CanRegister
	this.Data["LdapEnabled"] = g.Config().Ldap.Enabled
	this.Data["Sig"] = sig
	this.Data["Callback"] = callback
	this.Data["Shortcut"] = g.Config().Shortcut
	this.TplNames = "auth/login.html"
}

func (this *AuthController) RegisterGet() {
	this.Data["CanRegister"] = g.Config().CanRegister
	this.Data["Shortcut"] = g.Config().Shortcut
	this.TplNames = "auth/register.html"
}

func (this *AuthController) RegisterPost() {
	if !g.Config().CanRegister {
		this.ServeErrJson("registration system is not open")
		return
	}

	name := strings.TrimSpace(this.GetString("name", ""))
	password := strings.TrimSpace(this.GetString("password", ""))
	repeatPassword := strings.TrimSpace(this.GetString("repeat_password", ""))

	if password != repeatPassword {
		this.ServeErrJson("password not equal the repeart one")
		return
	}

	if !utils.IsUsernameValid(name) {
		this.ServeErrJson("name pattern is invalid")
		return
	}

	if ReadUserIdByName(name) > 0 {
		this.ServeErrJson("name is already existent")
		return
	}

	lastId, err := InsertRegisterUser(name, str.Md5Encode(g.Config().Salt+password))
	if err != nil {
		this.ServeErrJson("insert user fail " + err.Error())
		return
	}

	this.CreateSession(lastId, 3600*24*30)

	this.ServeOKJson()
}

func (this *AuthController) CreateSession(uid int64, maxAge int) int {
	sig := utils.GenerateUUID()
	expired := int(time.Now().Unix()) + maxAge
	SaveSessionAttrs(uid, sig, expired)
	this.Ctx.SetCookie("sig", sig, maxAge, "/")
	this.Ctx.SetCookie("sig", sig, maxAge, "/", ".owlemon.com")
	return expired
}

/**
 * @function name:   func (this *AuthController) LoginThirdParty()
 * @description:     This function returns third party login URL.
 * @related issues:  OWL-206
 * @param:           void
 * @return:          void
 * @author:          Don Hsieh
 * @since:           12/17/2015
 * @last modified:   12/17/2015
 * @called by:       beego.Router("/auth/third-party", &AuthController{}, "post:LoginThirdParty")
 *                    in fe/http/uic/uic_routes.go
 */
func (this *AuthController) LoginThirdParty() {
	s := g.Config().Api.Redirect
	s = base64.StdEncoding.EncodeToString([]byte(s))
	strEncoded := url.QueryEscape(s)
	loginUrl := g.Config().Api.Login + "/" + strEncoded
	this.ServeDataJson(loginUrl)
}
<commit_msg>[OWL-186] add func getRequest(url string)<commit_after>package uic

import (
	"encoding/base64"
	"github.com/Cepave/fe/g"
	"github.com/Cepave/fe/http/base"
	. "github.com/Cepave/fe/model/uic"
	"github.com/Cepave/fe/utils"
	"github.com/toolkits/str"
	"net/url"
	"strings"
	"time"
)

type AuthController struct {
	base.BaseController
}

func (this *AuthController) Logout() {
	u := this.Ctx.Input.GetData("CurrentUser").(*User)
	RemoveSessionByUid(u.Id)
	this.Ctx.SetCookie("sig", "", 0, "/")
	this.Ctx.SetCookie("sig", "", 0, "/", ".owlemon.com")
	this.Redirect("/auth/login", 302)
}

func (this *AuthController) LoginGet() {
	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")

	cookieSig := this.Ctx.GetCookie("sig")
	if cookieSig == "" {
		this.renderLoginPage(appSig, callback)
		return
	}

	sessionObj := ReadSessionBySig(cookieSig)
	if sessionObj == nil {
		this.renderLoginPage(appSig, callback)
		return
	}

	if int64(sessionObj.Expired) < time.Now().Unix() {
		RemoveSessionByUid(sessionObj.Uid)
		this.renderLoginPage(appSig, callback)
		return
	}

	if appSig != "" && callback != "" {
		this.Redirect(callback, 302)
	} else {
		this.Redirect("/me/info", 302)
	}
}

func (this *AuthController) LoginPost() {
	name := this.GetString("name", "")
	password := this.GetString("password", "")

	if name == "" || password == "" {
		this.ServeErrJson("name or password is blank")
		return
	}

	var u *User

	ldapEnabled := this.MustGetBool("ldap", false)

	if ldapEnabled {
		sucess, err := utils.LdapBind(g.Config().Ldap.Addr, name, password)
		if err != nil {
			this.ServeErrJson(err.Error())
			return
		}

		if !sucess {
			this.ServeErrJson("name or password error")
			return
		}

		arr := strings.Split(name, "@")
		var userName, userEmail string
		if len(arr) == 2 {
			userName = arr[0]
			userEmail = name
		} else {
			userName = name
			userEmail = ""
		}

		u = ReadUserByName(userName)
		if u == nil {
			// 说明用户不存在
			u = &User{
				Name:   userName,
				Passwd: "",
				Email:  userEmail,
			}
			_, err = u.Save()
			if err != nil {
				this.ServeErrJson("insert user fail " + err.Error())
				return
			}
		}
	} else {
		u = ReadUserByName(name)
		if u == nil {
			this.ServeErrJson("no such user")
			return
		}

		if u.Passwd != str.Md5Encode(g.Config().Salt+password) {
			this.ServeErrJson("password error")
			return
		}
	}

	appSig := this.GetString("sig", "")
	callback := this.GetString("callback", "")
	if appSig != "" && callback != "" {
		SaveSessionAttrs(u.Id, appSig, int(time.Now().Unix())+3600*24*30)
	} else {
		this.CreateSession(u.Id, 3600*24*30)
	}

	this.ServeDataJson(callback)
}

func (this *AuthController) renderLoginPage(sig, callback string) {
	this.Data["CanRegister"] = g.Config().CanRegister
	this.Data["LdapEnabled"] = g.Config().Ldap.Enabled
	this.Data["Sig"] = sig
	this.Data["Callback"] = callback
	this.Data["Shortcut"] = g.Config().Shortcut
	this.TplNames = "auth/login.html"
}

func (this *AuthController) RegisterGet() {
	this.Data["CanRegister"] = g.Config().CanRegister
	this.Data["Shortcut"] = g.Config().Shortcut
	this.TplNames = "auth/register.html"
}

func (this *AuthController) RegisterPost() {
	if !g.Config().CanRegister {
		this.ServeErrJson("registration system is not open")
		return
	}

	name := strings.TrimSpace(this.GetString("name", ""))
	password := strings.TrimSpace(this.GetString("password", ""))
	repeatPassword := strings.TrimSpace(this.GetString("repeat_password", ""))

	if password != repeatPassword {
		this.ServeErrJson("password not equal the repeart one")
		return
	}

	if !utils.IsUsernameValid(name) {
		this.ServeErrJson("name pattern is invalid")
		return
	}

	if ReadUserIdByName(name) > 0 {
		this.ServeErrJson("name is already existent")
		return
	}

	lastId, err := InsertRegisterUser(name, str.Md5Encode(g.Config().Salt+password))
	if err != nil {
		this.ServeErrJson("insert user fail " + err.Error())
		return
	}

	this.CreateSession(lastId, 3600*24*30)

	this.ServeOKJson()
}

func (this *AuthController) CreateSession(uid int64, maxAge int) int {
	sig := utils.GenerateUUID()
	expired := int(time.Now().Unix()) + maxAge
	SaveSessionAttrs(uid, sig, expired)
	this.Ctx.SetCookie("sig", sig, maxAge, "/")
	this.Ctx.SetCookie("sig", sig, maxAge, "/", ".owlemon.com")
	return expired
}

/**
 * @function name:   func (this *AuthController) LoginThirdParty()
 * @description:     This function returns third party login URL.
 * @related issues:  OWL-206
 * @param:           void
 * @return:          void
 * @author:          Don Hsieh
 * @since:           12/17/2015
 * @last modified:   12/17/2015
 * @called by:       beego.Router("/auth/third-party", &AuthController{}, "post:LoginThirdParty")
 *                    in fe/http/uic/uic_routes.go
 */
func (this *AuthController) LoginThirdParty() {
	s := g.Config().Api.Redirect
	s = base64.StdEncoding.EncodeToString([]byte(s))
	strEncoded := url.QueryEscape(s)
	loginUrl := g.Config().Api.Login + "/" + strEncoded
	this.ServeDataJson(loginUrl)
}

/**
 * @function name:   func getRequest(url string) map[string]interface{}
 * @description:     This function sends GET request to given URL.
 * @related issues:  OWL-206, OWL-159
 * @param:           url string
 * @return:          map[string]interface{}
 * @author:          Don Hsieh
 * @since:           12/17/2015
 * @last modified:   12/17/2015
 * @called by:       func (this *AuthController) LoginWithToken()
 *                    in fe/http/uic/auth_controller.go
 */
func getRequest(url string) map[string]interface{} {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Println("Error =", err.Error())
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Println("Error =", err.Error())
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	var nodes = make(map[string]interface{})
	if err := json.Unmarshal(body, &nodes); err != nil {
		log.Println("Error =", err.Error())
	}
	return nodes
}
<|endoftext|>


<commit_before>package manager

import (
	"bytes"
	"crypto/rand"
	"errors"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"
	"time"

	"github.com/Symantec/Dominator/lib/fsutil"
	"github.com/Symantec/Dominator/lib/json"
	"github.com/Symantec/Dominator/lib/log/prefixlogger"
	"github.com/Symantec/Dominator/lib/meminfo"
	"github.com/Symantec/Dominator/lib/objectserver/cachingreader"
	"github.com/Symantec/Dominator/lib/rpcclientpool"
	proto "github.com/Symantec/Dominator/proto/hypervisor"
	"github.com/Symantec/tricorder/go/tricorder/messages"
	trimsg "github.com/Symantec/tricorder/go/tricorder/messages"
)

const (
	dirPerms = syscall.S_IRWXU | syscall.S_IRGRP | syscall.S_IXGRP |
		syscall.S_IROTH | syscall.S_IXOTH
	privateFilePerms  = syscall.S_IRUSR | syscall.S_IWUSR
	publicFilePerms   = privateFilePerms | syscall.S_IRGRP | syscall.S_IROTH
	productSerialFile = "/sys/class/dmi/id/product_serial"
)

func newManager(startOptions StartOptions) (*Manager, error) {
	memInfo, err := meminfo.GetMemInfo()
	if err != nil {
		return nil, err
	}
	rootCookie := make([]byte, 32)
	if _, err := rand.Read(rootCookie); err != nil {
		return nil, err
	}
	err = fsutil.CopyToFile(filepath.Join(startOptions.StateDir,
		"root-cookie"), privateFilePerms, bytes.NewReader(rootCookie), 0)
	if err != nil {
		return nil, err
	}
	manager := &Manager{
		StartOptions:      startOptions,
		rootCookie:        rootCookie,
		memTotalInMiB:     memInfo.Total >> 20,
		notifiers:         make(map[<-chan proto.Update]chan<- proto.Update),
		numCPU:            runtime.NumCPU(),
		serialNumber:      readProductSerial(),
		vms:               make(map[string]*vmInfoType),
		volumeDirectories: startOptions.VolumeDirectories,
	}
	if err := manager.loadSubnets(); err != nil {
		return nil, err
	}
	if err := manager.loadAddressPool(); err != nil {
		return nil, err
	}
	dirname := filepath.Join(manager.StateDir, "VMs")
	dir, err := os.Open(dirname)
	if err != nil {
		if os.IsNotExist(err) {
			if err := os.Mkdir(dirname, dirPerms); err != nil {
				return nil, errors.New(
					"error making: " + dirname + ": " + err.Error())
			}
			dir, err = os.Open(dirname)
		}
	}
	if err != nil {
		return nil, err
	}
	defer dir.Close()
	names, err := dir.Readdirnames(-1)
	if err != nil {
		return nil, errors.New(
			"error reading directory: " + dirname + ": " + err.Error())
	}
	for _, ipAddr := range names {
		vmDirname := filepath.Join(dirname, ipAddr)
		filename := filepath.Join(vmDirname, "info.json")
		var vmInfo vmInfoType
		if err := json.ReadFromFile(filename, &vmInfo); err != nil {
			return nil, err
		}
		vmInfo.Address.Shrink()
		vmInfo.manager = manager
		vmInfo.dirname = vmDirname
		vmInfo.ipAddress = ipAddr
		vmInfo.ownerUsers = make(map[string]struct{}, len(vmInfo.OwnerUsers))
		for _, username := range vmInfo.OwnerUsers {
			vmInfo.ownerUsers[username] = struct{}{}
		}
		vmInfo.logger = prefixlogger.New(ipAddr+": ", manager.Logger)
		vmInfo.metadataChannels = make(map[chan<- string]struct{})
		manager.vms[ipAddr] = &vmInfo
		if _, err := vmInfo.startManaging(0, false); err != nil {
			manager.Logger.Println(err)
			if ipAddr == "0.0.0.0" {
				delete(manager.vms, ipAddr)
				vmInfo.destroy()
			}
		}
	}
	// Check address pool for used addresses with no VM.
	freeIPs := make(map[string]struct{}, len(manager.addressPool.Free))
	for _, addr := range manager.addressPool.Free {
		freeIPs[addr.IpAddress.String()] = struct{}{}
	}
	for _, addr := range manager.addressPool.Registered {
		ipAddr := addr.IpAddress.String()
		if _, ok := freeIPs[ipAddr]; ok {
			continue
		}
		if _, ok := manager.vms[ipAddr]; !ok {
			manager.Logger.Printf("%s shown as used but no corresponding VM\n",
				ipAddr)
		}
	}
	if len(manager.volumeDirectories) < 1 {
		manager.volumeDirectories, err = getVolumeDirectories()
		if err != nil {
			return nil, err
		}
	}
	if len(manager.volumeDirectories) < 1 {
		return nil, errors.New("no volume directories available")
	}
	for _, volumeDirectory := range manager.volumeDirectories {
		if err := os.MkdirAll(volumeDirectory, dirPerms); err != nil {
			return nil, err
		}
	}
	if startOptions.ObjectCacheBytes >= 1<<20 {
		dirname := filepath.Join(filepath.Dir(manager.volumeDirectories[0]),
			"objectcache")
		if err := os.MkdirAll(dirname, dirPerms); err != nil {
			return nil, err
		}
		objSrv, err := cachingreader.NewObjectServer(dirname,
			startOptions.ObjectCacheBytes, startOptions.ImageServerAddress,
			startOptions.Logger)
		if err != nil {
			return nil, err
		}
		manager.objectCache = objSrv
	}
	go manager.loopCheckHealthStatus()
	return manager, nil
}

func readProductSerial() string {
	if file, err := os.Open(productSerialFile); err != nil {
		return ""
	} else {
		defer file.Close()
		buffer := make([]byte, 256)
		if nRead, err := file.Read(buffer); err != nil {
			return ""
		} else if nRead < 1 {
			return ""
		} else {
			serial := strings.TrimSpace(string(buffer[:nRead]))
			if serial == "System Serial Number" {
				serial = ""
			}
			return serial
		}
	}
}

func (m *Manager) loopCheckHealthStatus() {
	cr := rpcclientpool.New("tcp", ":6910", true, "")
	for ; ; time.Sleep(time.Second * 10) {
		healthStatus := m.checkHealthStatus(cr)
		m.mutex.Lock()
		if m.healthStatus != healthStatus {
			m.healthStatus = healthStatus
			m.sendUpdateWithLock(proto.Update{})
		}
		m.mutex.Unlock()
	}
}

func (m *Manager) checkHealthStatus(cr *rpcclientpool.ClientResource) string {
	client, err := cr.Get(nil)
	if err != nil {
		m.Logger.Printf("error getting health-agent client: %s", err)
		return "bad health-agent"
	}
	defer client.Put()
	var metric messages.Metric
	err = client.Call("MetricsServer.GetMetric", "/sys/storage/health", &metric)
	if err != nil {
		if strings.Contains(err.Error(), trimsg.ErrMetricNotFound.Error()) {
			return ""
		}
		m.Logger.Printf("error getting health-agent metrics: %s", err)
		client.Close()
		return "failed getting health metrics"
	}
	if healthStatus, ok := metric.Value.(string); !ok {
		m.Logger.Println("list metric is not string")
		return "bad health metric type"
	} else if healthStatus == "good" {
		return "healthy"
	} else {
		return healthStatus
	}
}
<commit_msg>Hypervisor: do not complain about used secondary IPs.<commit_after>package manager

import (
	"bytes"
	"crypto/rand"
	"errors"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"syscall"
	"time"

	"github.com/Symantec/Dominator/lib/fsutil"
	"github.com/Symantec/Dominator/lib/json"
	"github.com/Symantec/Dominator/lib/log/prefixlogger"
	"github.com/Symantec/Dominator/lib/meminfo"
	"github.com/Symantec/Dominator/lib/objectserver/cachingreader"
	"github.com/Symantec/Dominator/lib/rpcclientpool"
	proto "github.com/Symantec/Dominator/proto/hypervisor"
	"github.com/Symantec/tricorder/go/tricorder/messages"
	trimsg "github.com/Symantec/tricorder/go/tricorder/messages"
)

const (
	dirPerms = syscall.S_IRWXU | syscall.S_IRGRP | syscall.S_IXGRP |
		syscall.S_IROTH | syscall.S_IXOTH
	privateFilePerms  = syscall.S_IRUSR | syscall.S_IWUSR
	publicFilePerms   = privateFilePerms | syscall.S_IRGRP | syscall.S_IROTH
	productSerialFile = "/sys/class/dmi/id/product_serial"
)

func newManager(startOptions StartOptions) (*Manager, error) {
	memInfo, err := meminfo.GetMemInfo()
	if err != nil {
		return nil, err
	}
	rootCookie := make([]byte, 32)
	if _, err := rand.Read(rootCookie); err != nil {
		return nil, err
	}
	err = fsutil.CopyToFile(filepath.Join(startOptions.StateDir,
		"root-cookie"), privateFilePerms, bytes.NewReader(rootCookie), 0)
	if err != nil {
		return nil, err
	}
	manager := &Manager{
		StartOptions:      startOptions,
		rootCookie:        rootCookie,
		memTotalInMiB:     memInfo.Total >> 20,
		notifiers:         make(map[<-chan proto.Update]chan<- proto.Update),
		numCPU:            runtime.NumCPU(),
		serialNumber:      readProductSerial(),
		vms:               make(map[string]*vmInfoType),
		volumeDirectories: startOptions.VolumeDirectories,
	}
	if err := manager.loadSubnets(); err != nil {
		return nil, err
	}
	if err := manager.loadAddressPool(); err != nil {
		return nil, err
	}
	dirname := filepath.Join(manager.StateDir, "VMs")
	dir, err := os.Open(dirname)
	if err != nil {
		if os.IsNotExist(err) {
			if err := os.Mkdir(dirname, dirPerms); err != nil {
				return nil, errors.New(
					"error making: " + dirname + ": " + err.Error())
			}
			dir, err = os.Open(dirname)
		}
	}
	if err != nil {
		return nil, err
	}
	defer dir.Close()
	names, err := dir.Readdirnames(-1)
	if err != nil {
		return nil, errors.New(
			"error reading directory: " + dirname + ": " + err.Error())
	}
	for _, ipAddr := range names {
		vmDirname := filepath.Join(dirname, ipAddr)
		filename := filepath.Join(vmDirname, "info.json")
		var vmInfo vmInfoType
		if err := json.ReadFromFile(filename, &vmInfo); err != nil {
			return nil, err
		}
		vmInfo.Address.Shrink()
		vmInfo.manager = manager
		vmInfo.dirname = vmDirname
		vmInfo.ipAddress = ipAddr
		vmInfo.ownerUsers = make(map[string]struct{}, len(vmInfo.OwnerUsers))
		for _, username := range vmInfo.OwnerUsers {
			vmInfo.ownerUsers[username] = struct{}{}
		}
		vmInfo.logger = prefixlogger.New(ipAddr+": ", manager.Logger)
		vmInfo.metadataChannels = make(map[chan<- string]struct{})
		manager.vms[ipAddr] = &vmInfo
		if _, err := vmInfo.startManaging(0, false); err != nil {
			manager.Logger.Println(err)
			if ipAddr == "0.0.0.0" {
				delete(manager.vms, ipAddr)
				vmInfo.destroy()
			}
		}
	}
	// Check address pool for used addresses with no VM.
	freeIPs := make(map[string]struct{}, len(manager.addressPool.Free))
	for _, addr := range manager.addressPool.Free {
		freeIPs[addr.IpAddress.String()] = struct{}{}
	}
	secondaryIPs := make(map[string]struct{})
	for _, vm := range manager.vms {
		for _, addr := range vm.SecondaryAddresses {
			secondaryIPs[addr.IpAddress.String()] = struct{}{}
		}
	}
	for _, addr := range manager.addressPool.Registered {
		ipAddr := addr.IpAddress.String()
		if _, ok := freeIPs[ipAddr]; ok {
			continue
		}
		if _, ok := manager.vms[ipAddr]; ok {
			continue
		}
		if _, ok := secondaryIPs[ipAddr]; ok {
			continue
		}
		manager.Logger.Printf("%s shown as used but no corresponding VM\n",
			ipAddr)
	}
	if len(manager.volumeDirectories) < 1 {
		manager.volumeDirectories, err = getVolumeDirectories()
		if err != nil {
			return nil, err
		}
	}
	if len(manager.volumeDirectories) < 1 {
		return nil, errors.New("no volume directories available")
	}
	for _, volumeDirectory := range manager.volumeDirectories {
		if err := os.MkdirAll(volumeDirectory, dirPerms); err != nil {
			return nil, err
		}
	}
	if startOptions.ObjectCacheBytes >= 1<<20 {
		dirname := filepath.Join(filepath.Dir(manager.volumeDirectories[0]),
			"objectcache")
		if err := os.MkdirAll(dirname, dirPerms); err != nil {
			return nil, err
		}
		objSrv, err := cachingreader.NewObjectServer(dirname,
			startOptions.ObjectCacheBytes, startOptions.ImageServerAddress,
			startOptions.Logger)
		if err != nil {
			return nil, err
		}
		manager.objectCache = objSrv
	}
	go manager.loopCheckHealthStatus()
	return manager, nil
}

func readProductSerial() string {
	if file, err := os.Open(productSerialFile); err != nil {
		return ""
	} else {
		defer file.Close()
		buffer := make([]byte, 256)
		if nRead, err := file.Read(buffer); err != nil {
			return ""
		} else if nRead < 1 {
			return ""
		} else {
			serial := strings.TrimSpace(string(buffer[:nRead]))
			if serial == "System Serial Number" {
				serial = ""
			}
			return serial
		}
	}
}

func (m *Manager) loopCheckHealthStatus() {
	cr := rpcclientpool.New("tcp", ":6910", true, "")
	for ; ; time.Sleep(time.Second * 10) {
		healthStatus := m.checkHealthStatus(cr)
		m.mutex.Lock()
		if m.healthStatus != healthStatus {
			m.healthStatus = healthStatus
			m.sendUpdateWithLock(proto.Update{})
		}
		m.mutex.Unlock()
	}
}

func (m *Manager) checkHealthStatus(cr *rpcclientpool.ClientResource) string {
	client, err := cr.Get(nil)
	if err != nil {
		m.Logger.Printf("error getting health-agent client: %s", err)
		return "bad health-agent"
	}
	defer client.Put()
	var metric messages.Metric
	err = client.Call("MetricsServer.GetMetric", "/sys/storage/health", &metric)
	if err != nil {
		if strings.Contains(err.Error(), trimsg.ErrMetricNotFound.Error()) {
			return ""
		}
		m.Logger.Printf("error getting health-agent metrics: %s", err)
		client.Close()
		return "failed getting health metrics"
	}
	if healthStatus, ok := metric.Value.(string); !ok {
		m.Logger.Println("list metric is not string")
		return "bad health metric type"
	} else if healthStatus == "good" {
		return "healthy"
	} else {
		return healthStatus
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"
)

func TestExec(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && sleep 100")
	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
		t.Fatal(out, err)
	}

	execCmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/tmp/file")
	out, _, err := runCommandWithOutput(execCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	out = strings.Trim(out, "\r\n")

	if expected := "test"; out != expected {
		t.Errorf("container exec should've printed %q but printed %q", expected, out)
	}

	deleteAllContainers()

	logDone("exec - basic test")
}

func TestExecInteractiveStdinClose(t *testing.T) {
	defer deleteAllContainers()
	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "busybox", "/bin/cat"))
	if err != nil {
		t.Fatal(err)
	}

	contId := strings.TrimSpace(out)

	returnchan := make(chan struct{})

	go func() {
		var err error
		cmd := exec.Command(dockerBinary, "exec", "-i", contId, "/bin/ls", "/")
		cmd.Stdin = os.Stdin
		if err != nil {
			t.Fatal(err)
		}

		out, err := cmd.CombinedOutput()
		if err != nil {
			t.Fatal(err, out)
		}

		if string(out) == "" {
			t.Fatalf("Output was empty, likely blocked by standard input")
		}

		returnchan <- struct{}{}
	}()

	select {
	case <-returnchan:
	case <-time.After(10 * time.Second):
		t.Fatal("timed out running docker exec")
	}

	logDone("exec - interactive mode closes stdin after execution")
}

func TestExecInteractive(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && sleep 100")
	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
		t.Fatal(out, err)
	}

	execCmd := exec.Command(dockerBinary, "exec", "-i", "testing", "sh")
	stdin, err := execCmd.StdinPipe()
	if err != nil {
		t.Fatal(err)
	}
	stdout, err := execCmd.StdoutPipe()
	if err != nil {
		t.Fatal(err)
	}

	if err := execCmd.Start(); err != nil {
		t.Fatal(err)
	}
	if _, err := stdin.Write([]byte("cat /tmp/file\n")); err != nil {
		t.Fatal(err)
	}

	r := bufio.NewReader(stdout)
	line, err := r.ReadString('\n')
	if err != nil {
		t.Fatal(err)
	}
	line = strings.TrimSpace(line)
	if line != "test" {
		t.Fatalf("Output should be 'test', got '%q'", line)
	}
	if err := stdin.Close(); err != nil {
		t.Fatal(err)
	}
	finish := make(chan struct{})
	go func() {
		if err := execCmd.Wait(); err != nil {
			t.Fatal(err)
		}
		close(finish)
	}()
	select {
	case <-finish:
	case <-time.After(1 * time.Second):
		t.Fatal("docker exec failed to exit on stdin close")
	}

	deleteAllContainers()

	logDone("exec - Interactive test")
}

func TestExecAfterContainerRestart(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "exec", cleanedContainerID, "echo", "hello")
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	outStr := strings.TrimSpace(out)
	if outStr != "hello" {
		t.Errorf("container should've printed hello, instead printed %q", outStr)
	}

	deleteAllContainers()

	logDone("exec - exec running container after container restart")
}

func TestExecAfterDaemonRestart(t *testing.T) {
	d := NewDaemon(t)
	if err := d.StartWithBusybox(); err != nil {
		t.Fatalf("Could not start daemon with busybox: %v", err)
	}
	defer d.Stop()

	if out, err := d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil {
		t.Fatalf("Could not run top: err=%v\n%s", err, out)
	}

	if err := d.Restart(); err != nil {
		t.Fatalf("Could not restart daemon: %v", err)
	}

	if out, err := d.Cmd("start", "top"); err != nil {
		t.Fatalf("Could not start top after daemon restart: err=%v\n%s", err, out)
	}

	out, err := d.Cmd("exec", "top", "echo", "hello")
	if err != nil {
		t.Fatalf("Could not exec on container top: err=%v\n%s", err, out)
	}

	outStr := strings.TrimSpace(string(out))
	if outStr != "hello" {
		t.Errorf("container should've printed hello, instead printed %q", outStr)
	}

	logDone("exec - exec running container after daemon restart")
}

// Regresssion test for #9155, #9044
func TestExecEnv(t *testing.T) {
	defer deleteAllContainers()

	runCmd := exec.Command(dockerBinary, "run",
		"-e", "LALA=value1",
		"-e", "LALA=value2",
		"-d", "--name", "testing", "busybox", "top")
	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
		t.Fatal(out, err)
	}

	execCmd := exec.Command(dockerBinary, "exec", "testing", "env")
	out, _, err := runCommandWithOutput(execCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if strings.Contains(out, "LALA=value1") ||
		!strings.Contains(out, "LALA=value2") ||
		!strings.Contains(out, "HOME=/root") {
		t.Errorf("exec env(%q), expect %q, %q", out, "LALA=value2", "HOME=/root")
	}

	logDone("exec - exec inherits correct env")
}

func TestExecExitStatus(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "top", "busybox", "top")
	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
		t.Fatal(out, err)
	}

	// Test normal (non-detached) case first
	cmd := exec.Command(dockerBinary, "exec", "top", "sh", "-c", "exit 23")
	ec, _ := runCommand(cmd)

	if ec != 23 {
		t.Fatalf("Should have had an ExitCode of 23, not: %d", ec)
	}

	logDone("exec - exec non-zero ExitStatus")
}

func TestExecPausedContainer(t *testing.T) {

	defer deleteAllContainers()
	defer unpauseAllContainers()

	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	ContainerID := stripTrailingCharacters(out)

	pausedCmd := exec.Command(dockerBinary, "pause", "testing")
	out, _, _, err = runCommandWithStdoutStderr(pausedCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	execCmd := exec.Command(dockerBinary, "exec", "-i", "-t", ContainerID, "echo", "hello")
	out, _, err = runCommandWithOutput(execCmd)
	if err == nil {
		t.Fatal("container should fail to exec new command if it is paused")
	}

	expected := ContainerID + " is paused, unpause the container before exec"
	if !strings.Contains(out, expected) {
		t.Fatal("container should not exec new command if it is paused")
	}

	logDone("exec - exec should not exec a pause container")
}
<commit_msg>Add test for exec tty stdin close<commit_after>package main

import (
	"bufio"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"
)

func TestExec(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && sleep 100")
	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
		t.Fatal(out, err)
	}

	execCmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/tmp/file")
	out, _, err := runCommandWithOutput(execCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	out = strings.Trim(out, "\r\n")

	if expected := "test"; out != expected {
		t.Errorf("container exec should've printed %q but printed %q", expected, out)
	}

	deleteAllContainers()

	logDone("exec - basic test")
}

func TestExecInteractiveStdinClose(t *testing.T) {
	defer deleteAllContainers()
	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "busybox", "/bin/cat"))
	if err != nil {
		t.Fatal(err)
	}

	contId := strings.TrimSpace(out)

	returnchan := make(chan struct{})

	go func() {
		var err error
		cmd := exec.Command(dockerBinary, "exec", "-i", contId, "/bin/ls", "/")
		cmd.Stdin = os.Stdin
		if err != nil {
			t.Fatal(err)
		}

		out, err := cmd.CombinedOutput()
		if err != nil {
			t.Fatal(err, out)
		}

		if string(out) == "" {
			t.Fatalf("Output was empty, likely blocked by standard input")
		}

		returnchan <- struct{}{}
	}()

	select {
	case <-returnchan:
	case <-time.After(10 * time.Second):
		t.Fatal("timed out running docker exec")
	}

	logDone("exec - interactive mode closes stdin after execution")
}

func TestExecInteractive(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && sleep 100")
	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
		t.Fatal(out, err)
	}

	execCmd := exec.Command(dockerBinary, "exec", "-i", "testing", "sh")
	stdin, err := execCmd.StdinPipe()
	if err != nil {
		t.Fatal(err)
	}
	stdout, err := execCmd.StdoutPipe()
	if err != nil {
		t.Fatal(err)
	}

	if err := execCmd.Start(); err != nil {
		t.Fatal(err)
	}
	if _, err := stdin.Write([]byte("cat /tmp/file\n")); err != nil {
		t.Fatal(err)
	}

	r := bufio.NewReader(stdout)
	line, err := r.ReadString('\n')
	if err != nil {
		t.Fatal(err)
	}
	line = strings.TrimSpace(line)
	if line != "test" {
		t.Fatalf("Output should be 'test', got '%q'", line)
	}
	if err := stdin.Close(); err != nil {
		t.Fatal(err)
	}
	finish := make(chan struct{})
	go func() {
		if err := execCmd.Wait(); err != nil {
			t.Fatal(err)
		}
		close(finish)
	}()
	select {
	case <-finish:
	case <-time.After(1 * time.Second):
		t.Fatal("docker exec failed to exit on stdin close")
	}

	deleteAllContainers()

	logDone("exec - Interactive test")
}

func TestExecAfterContainerRestart(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	cleanedContainerID := stripTrailingCharacters(out)

	runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
	if out, _, err = runCommandWithOutput(runCmd); err != nil {
		t.Fatal(out, err)
	}

	runCmd = exec.Command(dockerBinary, "exec", cleanedContainerID, "echo", "hello")
	out, _, err = runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	outStr := strings.TrimSpace(out)
	if outStr != "hello" {
		t.Errorf("container should've printed hello, instead printed %q", outStr)
	}

	deleteAllContainers()

	logDone("exec - exec running container after container restart")
}

func TestExecAfterDaemonRestart(t *testing.T) {
	d := NewDaemon(t)
	if err := d.StartWithBusybox(); err != nil {
		t.Fatalf("Could not start daemon with busybox: %v", err)
	}
	defer d.Stop()

	if out, err := d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil {
		t.Fatalf("Could not run top: err=%v\n%s", err, out)
	}

	if err := d.Restart(); err != nil {
		t.Fatalf("Could not restart daemon: %v", err)
	}

	if out, err := d.Cmd("start", "top"); err != nil {
		t.Fatalf("Could not start top after daemon restart: err=%v\n%s", err, out)
	}

	out, err := d.Cmd("exec", "top", "echo", "hello")
	if err != nil {
		t.Fatalf("Could not exec on container top: err=%v\n%s", err, out)
	}

	outStr := strings.TrimSpace(string(out))
	if outStr != "hello" {
		t.Errorf("container should've printed hello, instead printed %q", outStr)
	}

	logDone("exec - exec running container after daemon restart")
}

// Regresssion test for #9155, #9044
func TestExecEnv(t *testing.T) {
	defer deleteAllContainers()

	runCmd := exec.Command(dockerBinary, "run",
		"-e", "LALA=value1",
		"-e", "LALA=value2",
		"-d", "--name", "testing", "busybox", "top")
	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
		t.Fatal(out, err)
	}

	execCmd := exec.Command(dockerBinary, "exec", "testing", "env")
	out, _, err := runCommandWithOutput(execCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	if strings.Contains(out, "LALA=value1") ||
		!strings.Contains(out, "LALA=value2") ||
		!strings.Contains(out, "HOME=/root") {
		t.Errorf("exec env(%q), expect %q, %q", out, "LALA=value2", "HOME=/root")
	}

	logDone("exec - exec inherits correct env")
}

func TestExecExitStatus(t *testing.T) {
	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "top", "busybox", "top")
	if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
		t.Fatal(out, err)
	}

	// Test normal (non-detached) case first
	cmd := exec.Command(dockerBinary, "exec", "top", "sh", "-c", "exit 23")
	ec, _ := runCommand(cmd)

	if ec != 23 {
		t.Fatalf("Should have had an ExitCode of 23, not: %d", ec)
	}

	logDone("exec - exec non-zero ExitStatus")
}

func TestExecPausedContainer(t *testing.T) {

	defer deleteAllContainers()
	defer unpauseAllContainers()

	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	ContainerID := stripTrailingCharacters(out)

	pausedCmd := exec.Command(dockerBinary, "pause", "testing")
	out, _, _, err = runCommandWithStdoutStderr(pausedCmd)
	if err != nil {
		t.Fatal(out, err)
	}

	execCmd := exec.Command(dockerBinary, "exec", "-i", "-t", ContainerID, "echo", "hello")
	out, _, err = runCommandWithOutput(execCmd)
	if err == nil {
		t.Fatal("container should fail to exec new command if it is paused")
	}

	expected := ContainerID + " is paused, unpause the container before exec"
	if !strings.Contains(out, expected) {
		t.Fatal("container should not exec new command if it is paused")
	}

	logDone("exec - exec should not exec a pause container")
}

// regression test for #9476
func TestExecTtyCloseStdin(t *testing.T) {
	defer deleteAllContainers()

	cmd := exec.Command(dockerBinary, "run", "-d", "-it", "--name", "exec_tty_stdin", "busybox")
	if out, _, err := runCommandWithOutput(cmd); err != nil {
		t.Fatal(out, err)
	}

	cmd = exec.Command(dockerBinary, "exec", "-it", "exec_tty_stdin", "cat")
	stdinRw, err := cmd.StdinPipe()
	if err != nil {
		t.Fatal(err)
	}

	stdinRw.Write([]byte("test"))
	stdinRw.Close()

	if out, _, err := runCommandWithOutput(cmd); err != nil {
		t.Fatal(out, err)
	}

	cmd = exec.Command(dockerBinary, "top", "exec_tty_stdin")
	out, _, err := runCommandWithOutput(cmd)
	if err != nil {
		t.Fatal(out, err)
	}

	outArr := strings.Split(out, "\n")
	if len(outArr) > 3 || strings.Contains(out, "nsenter-exec") {
		// This is the really bad part
		if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rm", "-f", "exec_tty_stdin")); err != nil {
			t.Fatal(out, err)
		}

		t.Fatalf("exec process left running\n\t %s", out)
	}

	logDone("exec - stdin is closed properly with tty enabled")
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type IdenticalToTest struct {
}

func init() { RegisterTestSuite(&IdenticalToTest{}) }

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *IdenticalToTest) TypesNotIdentical() {
	var m Matcher
	var err error

	type intAlias int

	// Type alias expected value
	m = IdenticalTo(intAlias(17))
	err = m.Matches(int(17))
	ExpectThat(err, Error(Equals("which is of type int")))

	// Type alias candidate
	m = IdenticalTo(int(17))
	err = m.Matches(intAlias(17))
	ExpectThat(err, Error(Equals("which is of type intAlias")))

	// int and uint
	m = IdenticalTo(int(17))
	err = m.Matches(uint(17))
	ExpectThat(err, Error(Equals("which is of type uint")))
}

func (t *IdenticalToTest) InvalidTypeExpectedValue() {
	f := func() { IdenticalTo(nil) }
	ExpectThat(f, Panics(AllOf(HasSubstr("IdenticalTo"), HasSubstr("invalid"))))
}

func (t *IdenticalToTest) InvalidTypeCandidate() {
	var m Matcher
	var err error

	// Nil chan expected value
	m = IdenticalTo((chan int)(nil))
	err = m.Matches(nil)
	ExpectThat(err, Error(Equals("which is of type <nil>")))

	// Non-nil chan expected value
	m = IdenticalTo(make(chan int))
	err = m.Matches(nil)
	ExpectThat(err, Error(Equals("which is of type <nil>")))
}

func (t *IdenticalToTest) Slices() {
	var m Matcher
	var err error

	// Nil expected value
	m = IdenticalTo(([]int)(nil))

	err = m.Matches(([]int)(nil))
	ExpectEq(nil, err)

	err = m.Matches([]int{})
	ExpectThat(err, Equals("which is not an identical reference"))

	// Non-nil expected value
	o1 := []int{}
	o2 := []int{}
	m = IdenticalTo(o1)

	err = m.Matches(o1)
	ExpectEq(nil, err)

	err = m.Matches(o2)
	ExpectThat(err, Equals("which is not an identical reference"))
}

func (t *IdenticalToTest) Maps() {
	var m Matcher
	var err error

	// Nil expected value
	m = IdenticalTo((map[int]int)(nil))

	err = m.Matches((map[int]int)(nil))
	ExpectEq(nil, err)

	err = m.Matches(map[int]int{})
	ExpectThat(err, Equals("which is not an identical reference"))

	// Non-nil expected value
	o1 := map[int]int{}
	o2 := map[int]int{}
	m = IdenticalTo(o1)

	err = m.Matches(o1)
	ExpectEq(nil, err)

	err = m.Matches(o2)
	ExpectThat(err, Equals("which is not an identical reference"))
}

func (t *IdenticalToTest) Functions() {
	var m Matcher
	var err error

	// Nil expected value
	m = IdenticalTo((func())(nil))

	err = m.Matches((func())(nil))
	ExpectEq(nil, err)

	err = m.Matches(func(){})
	ExpectThat(err, Equals("which is not an identical reference"))

	// Non-nil expected value
	o1 := func() {}
	o2 := func() {}
	m = IdenticalTo(o1)

	err = m.Matches(o1)
	ExpectEq(nil, err)

	err = m.Matches(o2)
	ExpectThat(err, Equals("which is not an identical reference"))
}

func (t *IdenticalToTest) Channels() {
	var m Matcher
	var err error

	// Nil expected value
	m = IdenticalTo((chan int)(nil))

	err = m.Matches((chan int)(nil))
	ExpectEq(nil, err)

	err = m.Matches(make(chan int))
	ExpectThat(err, Equals("which is not an identical reference"))

	// Non-nil expected value
	o1 := make(chan int)
	o2 := make(chan int)
	m = IdenticalTo(o1)

	err = m.Matches(o1)
	ExpectEq(nil, err)

	err = m.Matches(o2)
	ExpectThat(err, Equals("which is not an identical reference"))
}

func (t *IdenticalToTest) Bools() {
}

func (t *IdenticalToTest) Ints() {
}

func (t *IdenticalToTest) Int8s() {
}

func (t *IdenticalToTest) Int16s() {
}

func (t *IdenticalToTest) Int32s() {
}

func (t *IdenticalToTest) Int64s() {
}

func (t *IdenticalToTest) Uints() {
}

func (t *IdenticalToTest) Uint8s() {
}

func (t *IdenticalToTest) Uint16s() {
}

func (t *IdenticalToTest) Uint32s() {
}

func (t *IdenticalToTest) Uint64s() {
}

func (t *IdenticalToTest) Float32s() {
}

func (t *IdenticalToTest) Float64s() {
}

func (t *IdenticalToTest) Complex64s() {
}

func (t *IdenticalToTest) Complex128s() {
}

func (t *IdenticalToTest) ComparableArrays() {
}

func (t *IdenticalToTest) NonComparableArrays() {
}

func (t *IdenticalToTest) ComparableInterfaces() {
}

func (t *IdenticalToTest) NonComparableInterfaces() {
}

func (t *IdenticalToTest) Pointers() {
}

func (t *IdenticalToTest) Strings() {
}

func (t *IdenticalToTest) ComparableStructs() {
}

func (t *IdenticalToTest) NonComparableStructs() {
}

func (t *IdenticalToTest) UnsafePointers() {
}

func (t *IdenticalToTest) IntAlias() {
}
<commit_msg>IdenticalToTest.Bools<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type IdenticalToTest struct {
}

func init() { RegisterTestSuite(&IdenticalToTest{}) }

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *IdenticalToTest) TypesNotIdentical() {
	var m Matcher
	var err error

	type intAlias int

	// Type alias expected value
	m = IdenticalTo(intAlias(17))
	err = m.Matches(int(17))
	ExpectThat(err, Error(Equals("which is of type int")))

	// Type alias candidate
	m = IdenticalTo(int(17))
	err = m.Matches(intAlias(17))
	ExpectThat(err, Error(Equals("which is of type intAlias")))

	// int and uint
	m = IdenticalTo(int(17))
	err = m.Matches(uint(17))
	ExpectThat(err, Error(Equals("which is of type uint")))
}

func (t *IdenticalToTest) InvalidTypeExpectedValue() {
	f := func() { IdenticalTo(nil) }
	ExpectThat(f, Panics(AllOf(HasSubstr("IdenticalTo"), HasSubstr("invalid"))))
}

func (t *IdenticalToTest) InvalidTypeCandidate() {
	var m Matcher
	var err error

	// Nil chan expected value
	m = IdenticalTo((chan int)(nil))
	err = m.Matches(nil)
	ExpectThat(err, Error(Equals("which is of type <nil>")))

	// Non-nil chan expected value
	m = IdenticalTo(make(chan int))
	err = m.Matches(nil)
	ExpectThat(err, Error(Equals("which is of type <nil>")))
}

func (t *IdenticalToTest) Slices() {
	var m Matcher
	var err error

	// Nil expected value
	m = IdenticalTo(([]int)(nil))

	err = m.Matches(([]int)(nil))
	ExpectEq(nil, err)

	err = m.Matches([]int{})
	ExpectThat(err, Equals("which is not an identical reference"))

	// Non-nil expected value
	o1 := []int{}
	o2 := []int{}
	m = IdenticalTo(o1)

	err = m.Matches(o1)
	ExpectEq(nil, err)

	err = m.Matches(o2)
	ExpectThat(err, Equals("which is not an identical reference"))
}

func (t *IdenticalToTest) Maps() {
	var m Matcher
	var err error

	// Nil expected value
	m = IdenticalTo((map[int]int)(nil))

	err = m.Matches((map[int]int)(nil))
	ExpectEq(nil, err)

	err = m.Matches(map[int]int{})
	ExpectThat(err, Equals("which is not an identical reference"))

	// Non-nil expected value
	o1 := map[int]int{}
	o2 := map[int]int{}
	m = IdenticalTo(o1)

	err = m.Matches(o1)
	ExpectEq(nil, err)

	err = m.Matches(o2)
	ExpectThat(err, Equals("which is not an identical reference"))
}

func (t *IdenticalToTest) Functions() {
	var m Matcher
	var err error

	// Nil expected value
	m = IdenticalTo((func())(nil))

	err = m.Matches((func())(nil))
	ExpectEq(nil, err)

	err = m.Matches(func(){})
	ExpectThat(err, Equals("which is not an identical reference"))

	// Non-nil expected value
	o1 := func() {}
	o2 := func() {}
	m = IdenticalTo(o1)

	err = m.Matches(o1)
	ExpectEq(nil, err)

	err = m.Matches(o2)
	ExpectThat(err, Equals("which is not an identical reference"))
}

func (t *IdenticalToTest) Channels() {
	var m Matcher
	var err error

	// Nil expected value
	m = IdenticalTo((chan int)(nil))

	err = m.Matches((chan int)(nil))
	ExpectEq(nil, err)

	err = m.Matches(make(chan int))
	ExpectThat(err, Equals("which is not an identical reference"))

	// Non-nil expected value
	o1 := make(chan int)
	o2 := make(chan int)
	m = IdenticalTo(o1)

	err = m.Matches(o1)
	ExpectEq(nil, err)

	err = m.Matches(o2)
	ExpectThat(err, Equals("which is not an identical reference"))
}

func (t *IdenticalToTest) Bools() {
	var m Matcher
	var err error

	// false
	m = IdenticalTo(false)

	err = m.Matches(false)
	ExpectEq(nil, err)

	err = m.Matches(true)
	ExpectThat(err, Error(Equals("")))

	// true
	m = IdenticalTo(true)

	err = m.Matches(false)
	ExpectThat(err, Error(Equals("")))

	err = m.Matches(true)
	ExpectEq(nil, err)
}

func (t *IdenticalToTest) Ints() {
}

func (t *IdenticalToTest) Int8s() {
}

func (t *IdenticalToTest) Int16s() {
}

func (t *IdenticalToTest) Int32s() {
}

func (t *IdenticalToTest) Int64s() {
}

func (t *IdenticalToTest) Uints() {
}

func (t *IdenticalToTest) Uint8s() {
}

func (t *IdenticalToTest) Uint16s() {
}

func (t *IdenticalToTest) Uint32s() {
}

func (t *IdenticalToTest) Uint64s() {
}

func (t *IdenticalToTest) Float32s() {
}

func (t *IdenticalToTest) Float64s() {
}

func (t *IdenticalToTest) Complex64s() {
}

func (t *IdenticalToTest) Complex128s() {
}

func (t *IdenticalToTest) ComparableArrays() {
}

func (t *IdenticalToTest) NonComparableArrays() {
}

func (t *IdenticalToTest) ComparableInterfaces() {
}

func (t *IdenticalToTest) NonComparableInterfaces() {
}

func (t *IdenticalToTest) Pointers() {
}

func (t *IdenticalToTest) Strings() {
}

func (t *IdenticalToTest) ComparableStructs() {
}

func (t *IdenticalToTest) NonComparableStructs() {
}

func (t *IdenticalToTest) UnsafePointers() {
}

func (t *IdenticalToTest) IntAlias() {
}
<|endoftext|>