<commit_before>package emil

import (
	"errors"
	"fmt"
	"time"
)

var errNowNewAnalysis = errors.New("errNowNewAnalysis")

type analysis struct {
	analysisDone bool
	dtm          int // Depth to mate

	board *Board
	move  *Move
}

// EndGameDb to query for mate in 1,2, etc.
type EndGameDb struct {
	positionDb map[string]*analysis

	dtmDb []map[string]bool

	searchedPositions int
}

func (db *EndGameDb) Find(board *Board) (bestMove *Move) {
	if DEBUG {
		fmt.Printf("Find:\n%s\n", board.String())
	}
	a := db.positionDb[board.String()]
	if DEBUG {
		fmt.Printf("Found: positionDb with dtm %d\n", a.dtm)
	}
	return a.move
}
func (db *EndGameDb) FindMates() (boards []*Board) {
	for str := range db.dtmDb[0] {
		a := db.positionDb[str]
		boards = append(boards, a.board)
	}
	return boards
}

func (db *EndGameDb) FindMate(piece, square int) (boards []*Board) {
	for str := range db.dtmDb[0] {
		a := db.positionDb[str]
		if a.board.squares[square] == piece {
			boards = append(boards, a.board)
		}
	}
	return boards
}

func (db *EndGameDb) addPosition(board *Board) {
	db.addAnalysis(board, -1, nil)
}

func (db *EndGameDb) addAnalysis(board *Board, dtm int, move *Move) {
	a := &analysis{
		dtm:   dtm,
		board: board}
	if move != nil {
		a.move = move.reverse()
	}
	done := dtm >= 0
	if done {
		db.dtmDb[dtm][a.board.String()] = true
	}
	a.analysisDone = done

	db.positionDb[a.board.String()] = a
}

func (db *EndGameDb) positions() int {
	return len(db.positionDb)
}

// find positions where black is checkmate
func (db *EndGameDb) retrogradeAnalysisStep1() {
	db.dtmDb = append(db.dtmDb, make(map[string]bool))

	start := time.Now()

	player := BLACK
	for boardStr, a := range db.positionDb {
		// mate only on border square
		blackKingSquare := BoardSquares[a.board.blackKing]
		if !blackKingSquare.isBorder {
			continue
		}
		// mate only with help from king
		if squaresDistances[a.board.blackKing][a.board.whiteKing] > 2 {
			continue
		}

		p := NewPosition(a.board, player)

		move := Search(p)
		db.searchedPositions++
		if move == nil {
			if isKingInCheck(p) {
				a.dtm = 0
				db.addAnalysis(a.board, 0, nil)
				if DEBUG {
					fmt.Printf("mate:\n%s\n", boardStr)
				}
			}
		}
	}
	end := time.Now()
	if DEBUG {
		fmt.Printf("searchedPositions %d\n", db.searchedPositions)
		fmt.Printf("db.dtmDb[0] %d\n", len(db.dtmDb[0]))
		fmt.Printf("duration %v\n\n\n", end.Sub(start))
	}
}
func playerForStepN(dtm int) (player int) {
	if dtm%2 == 0 {
		player = BLACK
		if DEBUG {
			fmt.Printf("retrogradeAnalysis BLACK %d\n", dtm)
		}
	} else {
		player = WHITE
		if DEBUG {
			fmt.Printf("retrogradeAnalysis WHITE %d\n", dtm)
		}
	}
	return player
}

func (db *EndGameDb) retrogradeAnalysisStepN(dtm int) (noError error) {
	start := time.Now()
	db.dtmDb = append(db.dtmDb, make(map[string]bool))

	player := playerForStepN(dtm)

	if player == WHITE {
		if DEBUG {
			fmt.Printf("WHITE Start positions %d\n", len(db.dtmDb[dtm-1]))
		}
		for str := range db.dtmDb[dtm-1] {
			a := db.positionDb[str]
			p := NewPosition(a.board, player)
			list := generateMoves(p)
			moves := filterKingCaptures(p, list)
			moves = filterKingCaptures(NewPosition(a.board, otherPlayer(player)), list)
			for _, m := range moves {
				newBoard := a.board.doMove(m)
				newAnalysis, ok := db.positionDb[newBoard.String()]
				if ok && !newAnalysis.analysisDone {
					db.addAnalysis(newBoard, dtm, m)
				}
			}
		}
	} else {
		// Suche alle Stellungen, bei denen Schwarz am Zug ist und
		// **jeder** Zug von ihm zu einer Stellung unter 2. führt.
		// Schwarz kann hier Matt in einem Zug nicht verhindern.
		// Markiere diese Stellungen in der Datei.
		if DEBUG {
			fmt.Printf("BLACK Start positions %d\n", len(db.positionDb))
		}
		for _, a := range db.positionDb {
			p := NewPosition(a.board, player)
			list := generateMoves(p)
			moves := filterKingCaptures(p, list)
			moves = filterKingCaptures(NewPosition(a.board, otherPlayer(player)), list)

			found := 0
			for _, m := range moves {
				newBoard := a.board.doMove(m)
				_, ok := db.dtmDb[dtm-1][newBoard.String()]
				if ok {
					found++
				}
			}
			if found == len(moves) {
				for _, m := range moves {
					newBoard := a.board.doMove(m)
					db.addAnalysis(newBoard, dtm, m)
				}
			}
		}
	}
	end := time.Now()

	if DEBUG {
		fmt.Printf("db.dtmDb[%d] %d\n", dtm, len(db.dtmDb[dtm]))
		fmt.Printf("duration %v\n\n\n", end.Sub(start))
	}

	if len(db.dtmDb[dtm]) == 0 {
		return errNowNewAnalysis
	}
	return noError
}

func (db *EndGameDb) retrogradeAnalysis() {
	// find positions where black is checkmate
	db.retrogradeAnalysisStep1()
	dtm := 1
	for {
		err := db.retrogradeAnalysisStepN(dtm)
		if err != nil {
			break
		}
		dtm++
	}
}

func generateMoves(p *position) (list []*Move) {
	for src, piece := range p.board.squares {
		if isOwnPiece(p.player, piece) {
			switch abs(piece) {
			case kingValue:
				for _, dst := range kingDestinationsFrom(src) {
					capture := p.board.squares[dst]
					if isOtherKing(p.player, capture) {
						continue
					}
					if capture == Empty {
						list = append(list, newSilentMove(p.player, piece, src, dst))
					} else if !isOwnPiece(p.player, capture) {
						list = append(list, newCaptureMove(p.player, piece, capture, src, dst))
					}
				}
			case rockValue:
				for _, dsts := range rockDestinationsFrom(src) {
					for _, dst := range dsts {
						capture := p.board.squares[dst]
						if isOtherKing(p.player, capture) {
							break
						}
						if capture == Empty {
							list = append(list, newSilentMove(p.player, piece, src, dst))
						} else if !isOwnPiece(p.player, capture) {
							list = append(list, newCaptureMove(p.player, piece, capture, src, dst))
							break
						} else {
							break // onOwnPiece
						}
					}
				}
			}
		}
	}
	return list
}

// NewEndGameDb generates an end game DB for KRK
func NewEndGameDb() *EndGameDb {
	var err error
	start := time.Now()

	endGames := &EndGameDb{
		positionDb: make(map[string]*analysis),
		dtmDb:      make([]map[string]bool, 0)}

	for wk := A1; wk <= H8; wk++ {
		//for wk := E3; wk <= E3; wk++ {
		if DEBUG {
			fmt.Printf("White king on %s\n", BoardSquares[wk])
		}
		for wr := A1; wr <= H8; wr++ {
			for bk := A1; bk <= H8; bk++ {

				board := NewBoard()

				err = board.Setup(WhiteKing, wk)
				if err != nil {
					continue
				}

				err = board.Setup(WhiteRock, wr)
				if err != nil {
					continue
				}

				err = board.Setup(BlackKing, bk)
				if err != nil {
					continue
				}

				err = board.kingsToClose()
				if err != nil {
					continue
				}

				endGames.addPosition(board)
			}
		}
	}
	end := time.Now()
	if DEBUG {
		fmt.Printf("all positions %d\n", 64*63*62)
		fmt.Printf("endGames.positions() %d\n", endGames.positions())
		fmt.Printf("difference %d\n", 64*63*62-endGames.positions())
		fmt.Printf("duration %v\n", end.Sub(start))
	}
	endGames.retrogradeAnalysis()

	return endGames
}
<commit_msg>isMateForBlack<commit_after>package emil

import (
	"errors"
	"fmt"
	"time"
)

var errNowNewAnalysis = errors.New("errNowNewAnalysis")

type analysis struct {
	analysisDone bool
	dtm          int // Depth to mate

	board *Board
	move  *Move
}

// EndGameDb to query for mate in 1,2, etc.
type EndGameDb struct {
	positionDb map[string]*analysis

	dtmDb []map[string]bool

	searchedPositions int
}

func (db *EndGameDb) Find(board *Board) (bestMove *Move) {
	if DEBUG {
		fmt.Printf("Find:\n%s\n", board.String())
	}
	a := db.positionDb[board.String()]
	if DEBUG {
		fmt.Printf("Found: positionDb with dtm %d\n", a.dtm)
	}
	return a.move
}
func (db *EndGameDb) FindMates() (boards []*Board) {
	for str := range db.dtmDb[0] {
		a := db.positionDb[str]
		boards = append(boards, a.board)
	}
	return boards
}

func (db *EndGameDb) FindMate(piece, square int) (boards []*Board) {
	for str := range db.dtmDb[0] {
		a := db.positionDb[str]
		if a.board.squares[square] == piece {
			boards = append(boards, a.board)
		}
	}
	return boards
}

func (db *EndGameDb) addPosition(board *Board) {
	db.addAnalysis(board, -1, nil)
}

func (db *EndGameDb) addAnalysis(board *Board, dtm int, move *Move) {
	a := &analysis{
		dtm:   dtm,
		board: board}
	if move != nil {
		a.move = move.reverse()
	}
	done := dtm >= 0
	if done {
		db.dtmDb[dtm][a.board.String()] = true
	}
	a.analysisDone = done

	db.positionDb[a.board.String()] = a
}

func (db *EndGameDb) positions() int {
	return len(db.positionDb)
}

// find positions where black is checkmate
func (db *EndGameDb) retrogradeAnalysisStep1() {
	db.dtmDb = append(db.dtmDb, make(map[string]bool))

	start := time.Now()

	player := BLACK
	for boardStr, a := range db.positionDb {
		// mate only on border square
		blackKingSquare := BoardSquares[a.board.blackKing]
		if !blackKingSquare.isBorder {
			continue
		}
		// mate only with help from king
		if squaresDistances[a.board.blackKing][a.board.whiteKing] > 2 {
			continue
		}

		p := NewPosition(a.board, player)

		move := Search(p)
		db.searchedPositions++
		if move == nil {
			if isKingInCheck(p) {
				a.dtm = 0
				db.addAnalysis(a.board, 0, nil)
				if DEBUG {
					fmt.Printf("mate:\n%s\n", boardStr)
				}
			}
		}
	}
	end := time.Now()
	if DEBUG {
		fmt.Printf("searchedPositions %d\n", db.searchedPositions)
		fmt.Printf("db.dtmDb[0] %d\n", len(db.dtmDb[0]))
		fmt.Printf("duration %v\n\n\n", end.Sub(start))
	}
}
func playerForStepN(dtm int) (player int) {
	if dtm%2 == 0 {
		player = BLACK
		if DEBUG {
			fmt.Printf("retrogradeAnalysis BLACK %d\n", dtm)
		}
	} else {
		player = WHITE
		if DEBUG {
			fmt.Printf("retrogradeAnalysis WHITE %d\n", dtm)
		}
	}
	return player
}

func (db *EndGameDb) retrogradeAnalysisStepN(dtm int) (noError error) {
	start := time.Now()
	db.dtmDb = append(db.dtmDb, make(map[string]bool))

	player := playerForStepN(dtm)

	if player == WHITE {
		if DEBUG {
			fmt.Printf("WHITE Start positions %d\n", len(db.dtmDb[dtm-1]))
		}
		for str := range db.dtmDb[dtm-1] {
			a := db.positionDb[str]
			p := NewPosition(a.board, player)
			list := generateMoves(p)
			moves := filterKingCaptures(p, list)
			moves = filterKingCaptures(NewPosition(a.board, otherPlayer(player)), list)
			for _, m := range moves {
				newBoard := a.board.doMove(m)
				newAnalysis, ok := db.positionDb[newBoard.String()]
				if ok && !newAnalysis.analysisDone {
					db.addAnalysis(newBoard, dtm, m)
				}
			}
		}
	} else {
		// Suche alle Stellungen, bei denen Schwarz am Zug ist und
		// **jeder** Zug von ihm zu einer Stellung unter 2. führt.
		// Schwarz kann hier Matt in einem Zug nicht verhindern.
		// Markiere diese Stellungen in der Datei.
		if DEBUG {
			fmt.Printf("BLACK Start positions %d\n", len(db.positionDb))
		}
		for _, a := range db.positionDb {
			p := NewPosition(a.board, player)
			list := generateMoves(p)
			moves := filterKingCaptures(p, list)
			moves = filterKingCaptures(NewPosition(a.board, otherPlayer(player)), list)

			found := 0
			for _, m := range moves {
				newBoard := a.board.doMove(m)
				if db.isMateForBlack(newBoard, dtm) {
					found++
				}
			}
			if found == len(moves) {
				for _, m := range moves {
					newBoard := a.board.doMove(m)
					db.addAnalysis(newBoard, dtm, m)
				}
			}
		}
	}
	end := time.Now()

	if DEBUG {
		fmt.Printf("db.dtmDb[%d] %d\n", dtm, len(db.dtmDb[dtm]))
		fmt.Printf("duration %v\n\n\n", end.Sub(start))
	}

	if len(db.dtmDb[dtm]) == 0 {
		return errNowNewAnalysis
	}
	return noError
}
func (db *EndGameDb) isMateForBlack(board *Board, maxDtm int) bool {
	for dtm := 0; dtm < maxDtm; dtm += 2 {
		_, ok := db.dtmDb[dtm][board.String()]
		if ok {
			return true
		}
	}
	return false
}

func (db *EndGameDb) retrogradeAnalysis() {
	// find positions where black is checkmate
	db.retrogradeAnalysisStep1()
	dtm := 1
	for {
		err := db.retrogradeAnalysisStepN(dtm)
		if err != nil {
			break
		}
		dtm++
	}
}

func generateMoves(p *position) (list []*Move) {
	for src, piece := range p.board.squares {
		if isOwnPiece(p.player, piece) {
			switch abs(piece) {
			case kingValue:
				for _, dst := range kingDestinationsFrom(src) {
					capture := p.board.squares[dst]
					if isOtherKing(p.player, capture) {
						continue
					}
					if capture == Empty {
						list = append(list, newSilentMove(p.player, piece, src, dst))
					} else if !isOwnPiece(p.player, capture) {
						list = append(list, newCaptureMove(p.player, piece, capture, src, dst))
					}
				}
			case rockValue:
				for _, dsts := range rockDestinationsFrom(src) {
					for _, dst := range dsts {
						capture := p.board.squares[dst]
						if isOtherKing(p.player, capture) {
							break
						}
						if capture == Empty {
							list = append(list, newSilentMove(p.player, piece, src, dst))
						} else if !isOwnPiece(p.player, capture) {
							list = append(list, newCaptureMove(p.player, piece, capture, src, dst))
							break
						} else {
							break // onOwnPiece
						}
					}
				}
			}
		}
	}
	return list
}

// NewEndGameDb generates an end game DB for KRK
func NewEndGameDb() *EndGameDb {
	var err error
	start := time.Now()

	endGames := &EndGameDb{
		positionDb: make(map[string]*analysis),
		dtmDb:      make([]map[string]bool, 0)}

	for wk := A1; wk <= H8; wk++ {
		//for wk := E3; wk <= E3; wk++ {
		if DEBUG {
			fmt.Printf("White king on %s\n", BoardSquares[wk])
		}
		for wr := A1; wr <= H8; wr++ {
			for bk := A1; bk <= H8; bk++ {

				board := NewBoard()

				err = board.Setup(WhiteKing, wk)
				if err != nil {
					continue
				}

				err = board.Setup(WhiteRock, wr)
				if err != nil {
					continue
				}

				err = board.Setup(BlackKing, bk)
				if err != nil {
					continue
				}

				err = board.kingsToClose()
				if err != nil {
					continue
				}

				endGames.addPosition(board)
			}
		}
	}
	end := time.Now()
	if DEBUG {
		fmt.Printf("all positions %d\n", 64*63*62)
		fmt.Printf("endGames.positions() %d\n", endGames.positions())
		fmt.Printf("difference %d\n", 64*63*62-endGames.positions())
		fmt.Printf("duration %v\n", end.Sub(start))
	}
	endGames.retrogradeAnalysis()

	return endGames
}
<|endoftext|>


<commit_before>package fileutils

import (
	"io"
	"os"
)

// CopyFile copies the file at source to dest
func CopyFile(source string, dest string) error {
	sf, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sf.Close()

	df, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer df.Close()

	_, err = io.Copy(df, sf)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Add support for handling symlinks and device files<commit_after>package fileutils

import (
	"fmt"
	"io"
	"os"
	"syscall"
)

// CopyFile copies the file at source to dest
func CopyFile(source string, dest string) error {
	si, err := os.Lstat(source)
	if err != nil {
		return err
	}

	// Handle symlinks
	if si.Mode()&os.ModeSymlink != 0 {
		target, err := os.Readlink(source)
		if err != nil {
			return err
		}
		if err := os.Symlink(target, dest); err != nil {
			return err
		}
		return nil
	}

	// Handle device files
	st, ok := si.Sys().(*syscall.Stat_t)
	if !ok {
		return fmt.Errorf("could not convert to syscall.Stat_t")
	}

	if st.Mode&syscall.S_IFBLK != 0 || st.Mode&syscall.S_IFCHR != 0 {
		devMajor := int64(major(uint64(st.Rdev)))
		devMinor := int64(minor(uint64(st.Rdev)))
		mode := uint32(si.Mode() & 07777)
		if st.Mode&syscall.S_IFBLK != 0 {
			fmt.Printf("BLOCK")
			mode |= syscall.S_IFBLK
		}
		if st.Mode&syscall.S_IFCHR != 0 {
			fmt.Printf("CHAR")
			mode |= syscall.S_IFCHR
		}
		if err := syscall.Mknod(dest, mode, int(mkdev(devMajor, devMinor))); err != nil {
			return err
		}
		return nil
	}

	// Handle regular files
	if si.Mode().IsRegular() {
		sf, err := os.Open(source)
		if err != nil {
			return err
		}
		defer sf.Close()

		df, err := os.Create(dest)
		if err != nil {
			return err
		}
		defer df.Close()

		_, err = io.Copy(df, sf)
		if err != nil {
			return err
		}
	}

	return nil
}

func major(device uint64) uint64 {
	return (device >> 8) & 0xfff
}

func minor(device uint64) uint64 {
	return (device & 0xff) | ((device >> 12) & 0xfff00)
}

func mkdev(major int64, minor int64) uint32 {
	return uint32(((minor & 0xfff00) << 12) | ((major & 0xfff) << 8) | (minor & 0xff))
}
<|endoftext|>


<commit_before>// Copyright ©2011-2013 The bíogo 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 dp

import (
	"github.com/biogo/biogo/align/pals/filter"
	"github.com/biogo/biogo/alphabet"
	"github.com/biogo/biogo/seq/linear"
)

// A kernel handles the actual dp alignment process.
type kernel struct {
	target, query *linear.Seq

	minLen  int
	maxDiff float64

	valueToCode alphabet.Index

	Costs

	lowEnd     Hit
	highEnd    Hit
	vectors    [2][]int
	trapezoids []*filter.Trapezoid
	covered    []bool
	slot       int
	result     chan Hit
}

// An offset slice seems to be the easiest way to implement the C idiom used in PALS to implement
// an offset (by o) view (v) on an array (a):
//
//  int *v, o;
//  int [n]a;
//  v = a - o;
//
// now v[i] is a view on a[i-o]
type offsetSlice struct {
	offset int
	slice  []int
}

func (o *offsetSlice) at(i int) int {
	i -= o.offset
	if i == -1 || i == len(o.slice) {
		return 0
	}
	return o.slice[i]
}
func (o *offsetSlice) set(i, v int) { o.slice[i-o.offset] = v }

var vecBuffering int = 100000

// Handle the recursive search for alignable segments.
func (k *kernel) alignRecursion(t *filter.Trapezoid) {
	mid := (t.Bottom + t.Top) / 2

	k.traceForward(mid, mid-t.Right, mid-t.Left)

	for x := 1; x == 1 || k.highEnd.Bbpos > mid+x*k.MaxIGap && k.highEnd.Score < k.lowEnd.Score; x++ {
		k.traceReverse(k.lowEnd.Bepos, k.lowEnd.Aepos, k.lowEnd.Aepos, mid+k.MaxIGap, k.BlockCost+2*x*k.DiffCost)
	}

	k.highEnd.Aepos, k.highEnd.Bepos = k.lowEnd.Aepos, k.lowEnd.Bepos

	lowTrap, highTrap := *t, *t
	lowTrap.Top = k.highEnd.Bbpos - k.MaxIGap
	highTrap.Bottom = k.highEnd.Bepos + k.MaxIGap

	if k.highEnd.Bepos-k.highEnd.Bbpos >= k.minLen && k.highEnd.Aepos-k.highEnd.Abpos >= k.minLen {
		indel := (k.highEnd.Abpos - k.highEnd.Bbpos) - (k.highEnd.Aepos - k.highEnd.Bepos)
		if indel < 0 {
			if indel == -indel {
				panic("dp: weird number overflow")
			}
			indel = -indel
		}
		identity := ((1 / k.RMatchCost) - float64(k.highEnd.Score-indel)/(k.RMatchCost*float64(k.highEnd.Bepos-k.highEnd.Bbpos)))

		if identity <= k.maxDiff {
			k.highEnd.Error = identity

			for i, trap := range k.trapezoids[k.slot+1:] {
				var trapAProjection, trapBProjection, coverageA, coverageB int

				if trap.Bottom >= k.highEnd.Bepos {
					break
				}

				trapBProjection = trap.Top - trap.Bottom + 1
				trapAProjection = trap.Right - trap.Left + 1
				if trap.Left < k.highEnd.LowDiagonal {
					coverageA = k.highEnd.LowDiagonal
				} else {
					coverageA = trap.Left
				}
				if trap.Right > k.highEnd.HighDiagonal {
					coverageB = k.highEnd.HighDiagonal
				} else {
					coverageB = trap.Right
				}

				if coverageA > coverageB {
					continue
				}

				coverageA = coverageB - coverageA + 1
				if trap.Top > k.highEnd.Bepos {
					coverageB = k.highEnd.Bepos - trap.Bottom + 1
				} else {
					coverageB = trapBProjection
				}

				if (float64(coverageA)/float64(trapAProjection))*(float64(coverageB)/float64(trapBProjection)) > 0.99 {
					k.covered[i] = true
				}
			}

			// Diagonals to this point are query-target, not target-query.
			k.highEnd.LowDiagonal, k.highEnd.HighDiagonal = -k.highEnd.HighDiagonal, -k.highEnd.LowDiagonal

			k.result <- k.highEnd
		}
	}

	if lowTrap.Top-lowTrap.Bottom > k.minLen && lowTrap.Top < t.Top-k.MaxIGap {
		k.alignRecursion(&lowTrap)
	}
	if highTrap.Top-highTrap.Bottom > k.minLen {
		k.alignRecursion(&highTrap)
	}
}

func (k *kernel) allocateVectors(required int) {
	vecMax := required + required>>2 + vecBuffering
	k.vectors[0] = make([]int, vecMax)
	k.vectors[1] = make([]int, vecMax)
}

// Forward and Reverse D.P. Extension Routines
// Called at the mid-point of trapezoid -- mid X [low,high], the extension
// is computed to an end point and the lowest and highest diagonals
// are recorded. These are returned in a partially filled DPHit
// record, that will be merged with that returned for extension in the
// opposite direction.
func (k *kernel) traceForward(mid, low, high int) {
	odd := false
	var (
		maxScore          int
		maxLeft, maxRight int
		maxI, maxJ        int
		i, j              int
	)

	// Set basis from (mid,low) .. (mid,high).
	if low < 0 {
		low = 0
	}
	if high > k.target.Len() {
		high = k.target.Len()
	}

	if required := (high - low) + k.MaxIGap; required >= len(k.vectors[0]) {
		k.allocateVectors(required)
	}

	thisVector := &offsetSlice{
		slice:  k.vectors[0],
		offset: low,
	}

	for j = low; j <= high; j++ {
		thisVector.set(j, 0)
	}

	high += k.MaxIGap
	if high > k.target.Len() {
		high = k.target.Len()
	}

	for ; j <= high; j++ {
		thisVector.set(j, thisVector.at(j-1)-k.DiffCost)
	}

	maxScore = 0
	maxRight = mid - low
	maxLeft = mid - high
	maxI = mid
	maxJ = low

	// Advance to next row.
	thatVector := &offsetSlice{}
	for i = mid; low <= high && i < k.query.Len(); i++ {
		var cost, score int

		*thatVector = *thisVector
		if !odd {
			thisVector.slice = k.vectors[1]
		} else {
			thisVector.slice = k.vectors[0]
		}
		thisVector.offset = low
		odd = !odd

		score = thatVector.at(low)
		thisVector.set(low, score-k.DiffCost)
		cost = thisVector.at(low)

		for j = low + 1; j <= high; j++ {
			var ratchet, temp int

			temp = cost
			cost = score
			score = thatVector.at(j)
			if k.query.Seq[i] == k.target.Seq[j-1] && k.valueToCode[k.query.Seq[i]] >= 0 {
				cost += k.MatchCost
			}

			ratchet = cost
			if score > ratchet {
				ratchet = score
			}
			if temp > ratchet {
				ratchet = temp
			}

			cost = ratchet - k.DiffCost
			thisVector.set(j, cost)
			if cost >= maxScore {
				maxScore = cost
				maxI = i + 1
				maxJ = j
			}
		}

		if j <= k.target.Len() {
			var ratchet int

			if k.query.Seq[i] == k.target.Seq[j-1] && k.valueToCode[k.query.Seq[i]] >= 0 {
				score += k.MatchCost
			}

			ratchet = score
			if cost > ratchet {
				ratchet = cost
			}

			score = ratchet - k.DiffCost
			thisVector.set(j, score)
			if score > maxScore {
				maxScore = score
				maxI = i + 1
				maxJ = j
			}

			for j++; j <= k.target.Len(); j++ {
				score -= k.DiffCost
				if score < maxScore-k.BlockCost {
					break
				}
				thisVector.set(j, score)
			}
		}

		high = j - 1

		for low <= high && thisVector.at(low) < maxScore-k.BlockCost {
			low++
		}
		for low <= high && thisVector.at(high) < maxScore-k.BlockCost {
			high--
		}

		if required := (high - low) + 2; required > len(k.vectors[0]) {
			k.allocateVectors(required)
		}

		if (i+1)-low > maxRight {
			maxRight = (i + 1) - low
		}
		if (i+1)-high < maxLeft {
			maxLeft = (i + 1) - high
		}
	}

	k.lowEnd.Aepos = maxJ
	k.lowEnd.Bepos = maxI
	k.lowEnd.LowDiagonal = maxLeft
	k.lowEnd.HighDiagonal = maxRight
	k.lowEnd.Score = maxScore
}

func (k *kernel) traceReverse(top, low, high, bottom, xfactor int) {
	odd := false
	var (
		maxScore          int
		maxLeft, maxRight int
		maxI, maxJ        int
		i, j              int
	)

	// Set basis from (top,low) .. (top,high).
	if low < 0 {
		low = 0
	}
	if high > k.target.Len() {
		high = k.target.Len()
	}

	if required := (high - low) + k.MaxIGap; required >= len(k.vectors[0]) {
		k.allocateVectors(required)
	}

	thisVector := &offsetSlice{
		slice:  k.vectors[0],
		offset: high - (len(k.vectors[0]) - 1),
	}
	for j = high; j >= low; j-- {
		thisVector.set(j, 0)
	}

	low -= k.MaxIGap
	if low < 0 {
		low = 0
	}

	for ; j >= low; j-- {
		thisVector.set(j, thisVector.at(j+1)-k.DiffCost)
	}

	maxScore = 0
	maxRight = top - low
	maxLeft = top - high
	maxI = top
	maxJ = low

	// Advance to next row.
	if top-1 <= bottom {
		xfactor = k.BlockCost
	}

	thatVector := &offsetSlice{}
	for i = top - 1; low <= high && i >= 0; i-- {
		var cost, score int

		*thatVector = *thisVector
		if !odd {
			thisVector.slice = k.vectors[1]
		} else {
			thisVector.slice = k.vectors[0]
		}
		thisVector.offset = high - (len(k.vectors[0]) - 1)
		odd = !odd

		score = thatVector.at(high)
		thisVector.set(high, score-k.DiffCost)
		cost = thisVector.at(high)

		for j = high - 1; j >= low; j-- {
			var ratchet, temp int

			temp = cost
			cost = score
			score = thatVector.at(j)
			if k.query.Seq[i] == k.target.Seq[j] && k.valueToCode[k.query.Seq[i]] >= 0 {
				cost += k.MatchCost
			}

			ratchet = cost
			if score > ratchet {
				ratchet = score
			}
			if temp > ratchet {
				ratchet = temp
			}

			cost = ratchet - k.DiffCost
			thisVector.set(j, cost)
			if cost >= maxScore {
				maxScore = cost
				maxI = i
				maxJ = j
			}
		}

		if j >= 0 {
			var ratchet int

			if k.query.Seq[i] == k.target.Seq[j] && k.valueToCode[k.query.Seq[i]] >= 0 {
				score += k.MatchCost
			}

			ratchet = score
			if cost > ratchet {
				ratchet = cost
			}

			score = ratchet - k.DiffCost
			thisVector.set(j, score)
			if score > maxScore {
				maxScore = score
				maxI = i
				maxJ = j
			}

			for j--; j >= 0; j-- {
				score -= k.DiffCost
				if score < maxScore-xfactor {
					break
				}
				thisVector.set(j, score)
			}
		}

		low = j + 1

		for low <= high && thisVector.at(low) < maxScore-xfactor {
			low++
		}
		for low <= high && thisVector.at(high) < maxScore-xfactor {
			high--
		}

		if i == bottom {
			xfactor = k.BlockCost
		}

		if required := (high - low) + 2; required > len(k.vectors[0]) {
			k.allocateVectors(required)
		}

		if i-low > maxRight {
			maxRight = i - low
		}
		if i-high < maxLeft {
			maxLeft = i - high
		}
	}

	k.highEnd.Abpos = maxJ
	k.highEnd.Bbpos = maxI
	k.highEnd.LowDiagonal = maxLeft
	k.highEnd.HighDiagonal = maxRight
	k.highEnd.Score = maxScore
}
<commit_msg>Fix pals dp indexing fault<commit_after>// Copyright ©2011-2013 The bíogo 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 dp

import (
	"github.com/biogo/biogo/align/pals/filter"
	"github.com/biogo/biogo/alphabet"
	"github.com/biogo/biogo/seq/linear"
)

// A kernel handles the actual dp alignment process.
type kernel struct {
	target, query *linear.Seq

	minLen  int
	maxDiff float64

	valueToCode alphabet.Index

	Costs

	lowEnd     Hit
	highEnd    Hit
	vectors    [2][]int
	trapezoids []*filter.Trapezoid
	covered    []bool
	slot       int
	result     chan Hit
}

// An offset slice seems to be the easiest way to implement the C idiom used in PALS to implement
// an offset (by o) view (v) on an array (a):
//
//  int *v, o;
//  int [n]a;
//  v = a - o;
//
// now v[i] is a view on a[i-o]
type offsetSlice struct {
	offset int
	slice  []int
}

func (o *offsetSlice) at(i int) int { return o.slice[i-o.offset] }
func (o *offsetSlice) set(i, v int) { o.slice[i-o.offset] = v }

var vecBuffering int = 100000

// Handle the recursive search for alignable segments.
func (k *kernel) alignRecursion(t *filter.Trapezoid) {
	mid := (t.Bottom + t.Top) / 2

	k.traceForward(mid, mid-t.Right, mid-t.Left)

	for x := 1; x == 1 || k.highEnd.Bbpos > mid+x*k.MaxIGap && k.highEnd.Score < k.lowEnd.Score; x++ {
		k.traceReverse(k.lowEnd.Bepos, k.lowEnd.Aepos, k.lowEnd.Aepos, mid+k.MaxIGap, k.BlockCost+2*x*k.DiffCost)
	}

	k.highEnd.Aepos, k.highEnd.Bepos = k.lowEnd.Aepos, k.lowEnd.Bepos

	lowTrap, highTrap := *t, *t
	lowTrap.Top = k.highEnd.Bbpos - k.MaxIGap
	highTrap.Bottom = k.highEnd.Bepos + k.MaxIGap

	if k.highEnd.Bepos-k.highEnd.Bbpos >= k.minLen && k.highEnd.Aepos-k.highEnd.Abpos >= k.minLen {
		indel := (k.highEnd.Abpos - k.highEnd.Bbpos) - (k.highEnd.Aepos - k.highEnd.Bepos)
		if indel < 0 {
			if indel == -indel {
				panic("dp: weird number overflow")
			}
			indel = -indel
		}
		identity := ((1 / k.RMatchCost) - float64(k.highEnd.Score-indel)/(k.RMatchCost*float64(k.highEnd.Bepos-k.highEnd.Bbpos)))

		if identity <= k.maxDiff {
			k.highEnd.Error = identity

			for i, trap := range k.trapezoids[k.slot+1:] {
				var trapAProjection, trapBProjection, coverageA, coverageB int

				if trap.Bottom >= k.highEnd.Bepos {
					break
				}

				trapBProjection = trap.Top - trap.Bottom + 1
				trapAProjection = trap.Right - trap.Left + 1
				if trap.Left < k.highEnd.LowDiagonal {
					coverageA = k.highEnd.LowDiagonal
				} else {
					coverageA = trap.Left
				}
				if trap.Right > k.highEnd.HighDiagonal {
					coverageB = k.highEnd.HighDiagonal
				} else {
					coverageB = trap.Right
				}

				if coverageA > coverageB {
					continue
				}

				coverageA = coverageB - coverageA + 1
				if trap.Top > k.highEnd.Bepos {
					coverageB = k.highEnd.Bepos - trap.Bottom + 1
				} else {
					coverageB = trapBProjection
				}

				if (float64(coverageA)/float64(trapAProjection))*(float64(coverageB)/float64(trapBProjection)) > 0.99 {
					k.covered[i] = true
				}
			}

			// Diagonals to this point are query-target, not target-query.
			k.highEnd.LowDiagonal, k.highEnd.HighDiagonal = -k.highEnd.HighDiagonal, -k.highEnd.LowDiagonal

			k.result <- k.highEnd
		}
	}

	if lowTrap.Top-lowTrap.Bottom > k.minLen && lowTrap.Top < t.Top-k.MaxIGap {
		k.alignRecursion(&lowTrap)
	}
	if highTrap.Top-highTrap.Bottom > k.minLen {
		k.alignRecursion(&highTrap)
	}
}

func (k *kernel) allocateVectors(required int) {
	vecMax := required + required>>2 + vecBuffering
	k.vectors[0] = make([]int, vecMax)
	k.vectors[1] = make([]int, vecMax)
}

// Forward and Reverse D.P. Extension Routines
// Called at the mid-point of trapezoid -- mid X [low,high], the extension
// is computed to an end point and the lowest and highest diagonals
// are recorded. These are returned in a partially filled DPHit
// record, that will be merged with that returned for extension in the
// opposite direction.
func (k *kernel) traceForward(mid, low, high int) {
	odd := false
	var (
		maxScore          int
		maxLeft, maxRight int
		maxI, maxJ        int
		i, j              int
	)

	// Set basis from (mid,low) .. (mid,high).
	if low < 0 {
		low = 0
	}
	if high > k.target.Len() {
		high = k.target.Len()
	}
	if high < low {
		high = low
	}

	if required := (high - low) + k.MaxIGap; required >= len(k.vectors[0]) {
		k.allocateVectors(required)
	}

	thisVector := &offsetSlice{
		slice:  k.vectors[0],
		offset: low,
	}

	for j = low; j <= high; j++ {
		thisVector.set(j, 0)
	}

	high += k.MaxIGap
	if high > k.target.Len() {
		high = k.target.Len()
	}

	for ; j <= high; j++ {
		thisVector.set(j, thisVector.at(j-1)-k.DiffCost)
	}

	maxScore = 0
	maxRight = mid - low
	maxLeft = mid - high
	maxI = mid
	maxJ = low

	// Advance to next row.
	thatVector := &offsetSlice{}
	for i = mid; low <= high && i < k.query.Len(); i++ {
		var cost, score int

		*thatVector = *thisVector
		if !odd {
			thisVector.slice = k.vectors[1]
		} else {
			thisVector.slice = k.vectors[0]
		}
		thisVector.offset = low
		odd = !odd

		score = thatVector.at(low)
		thisVector.set(low, score-k.DiffCost)
		cost = thisVector.at(low)

		for j = low + 1; j <= high; j++ {
			var ratchet, temp int

			temp = cost
			cost = score
			score = thatVector.at(j)
			if k.query.Seq[i] == k.target.Seq[j-1] && k.valueToCode[k.query.Seq[i]] >= 0 {
				cost += k.MatchCost
			}

			ratchet = cost
			if score > ratchet {
				ratchet = score
			}
			if temp > ratchet {
				ratchet = temp
			}

			cost = ratchet - k.DiffCost
			thisVector.set(j, cost)
			if cost >= maxScore {
				maxScore = cost
				maxI = i + 1
				maxJ = j
			}
		}

		if j <= k.target.Len() {
			var ratchet int

			if k.query.Seq[i] == k.target.Seq[j-1] && k.valueToCode[k.query.Seq[i]] >= 0 {
				score += k.MatchCost
			}

			ratchet = score
			if cost > ratchet {
				ratchet = cost
			}

			score = ratchet - k.DiffCost
			thisVector.set(j, score)
			if score > maxScore {
				maxScore = score
				maxI = i + 1
				maxJ = j
			}

			for j++; j <= k.target.Len(); j++ {
				score -= k.DiffCost
				if score < maxScore-k.BlockCost {
					break
				}
				thisVector.set(j, score)
			}
		}

		high = j - 1

		for low <= high && thisVector.at(low) < maxScore-k.BlockCost {
			low++
		}
		for low <= high && thisVector.at(high) < maxScore-k.BlockCost {
			high--
		}

		if required := (high - low) + 2; required > len(k.vectors[0]) {
			k.allocateVectors(required)
		}

		if (i+1)-low > maxRight {
			maxRight = (i + 1) - low
		}
		if (i+1)-high < maxLeft {
			maxLeft = (i + 1) - high
		}
	}

	k.lowEnd.Aepos = maxJ
	k.lowEnd.Bepos = maxI
	k.lowEnd.LowDiagonal = maxLeft
	k.lowEnd.HighDiagonal = maxRight
	k.lowEnd.Score = maxScore
}

func (k *kernel) traceReverse(top, low, high, bottom, xfactor int) {
	odd := false
	var (
		maxScore          int
		maxLeft, maxRight int
		maxI, maxJ        int
		i, j              int
	)

	// Set basis from (top,low) .. (top,high).
	if low < 0 {
		low = 0
	}
	if high > k.target.Len() {
		high = k.target.Len()
	}
	if high < low {
		high = low
	}

	if required := (high - low) + k.MaxIGap; required >= len(k.vectors[0]) {
		k.allocateVectors(required)
	}

	thisVector := &offsetSlice{
		slice:  k.vectors[0],
		offset: high - (len(k.vectors[0]) - 1),
	}
	for j = high; j >= low; j-- {
		thisVector.set(j, 0)
	}

	low -= k.MaxIGap
	if low < 0 {
		low = 0
	}

	for ; j >= low; j-- {
		thisVector.set(j, thisVector.at(j+1)-k.DiffCost)
	}

	maxScore = 0
	maxRight = top - low
	maxLeft = top - high
	maxI = top
	maxJ = low

	// Advance to next row.
	if top-1 <= bottom {
		xfactor = k.BlockCost
	}

	thatVector := &offsetSlice{}
	for i = top - 1; low <= high && i >= 0; i-- {
		var cost, score int

		*thatVector = *thisVector
		if !odd {
			thisVector.slice = k.vectors[1]
		} else {
			thisVector.slice = k.vectors[0]
		}
		thisVector.offset = high - (len(k.vectors[0]) - 1)
		odd = !odd

		score = thatVector.at(high)
		thisVector.set(high, score-k.DiffCost)
		cost = thisVector.at(high)

		for j = high - 1; j >= low; j-- {
			var ratchet, temp int

			temp = cost
			cost = score
			score = thatVector.at(j)
			if k.query.Seq[i] == k.target.Seq[j] && k.valueToCode[k.query.Seq[i]] >= 0 {
				cost += k.MatchCost
			}

			ratchet = cost
			if score > ratchet {
				ratchet = score
			}
			if temp > ratchet {
				ratchet = temp
			}

			cost = ratchet - k.DiffCost
			thisVector.set(j, cost)
			if cost >= maxScore {
				maxScore = cost
				maxI = i
				maxJ = j
			}
		}

		if j >= 0 {
			var ratchet int

			if k.query.Seq[i] == k.target.Seq[j] && k.valueToCode[k.query.Seq[i]] >= 0 {
				score += k.MatchCost
			}

			ratchet = score
			if cost > ratchet {
				ratchet = cost
			}

			score = ratchet - k.DiffCost
			thisVector.set(j, score)
			if score > maxScore {
				maxScore = score
				maxI = i
				maxJ = j
			}

			for j--; j >= 0; j-- {
				score -= k.DiffCost
				if score < maxScore-xfactor {
					break
				}
				thisVector.set(j, score)
			}
		}

		low = j + 1

		for low <= high && thisVector.at(low) < maxScore-xfactor {
			low++
		}
		for low <= high && thisVector.at(high) < maxScore-xfactor {
			high--
		}

		if i == bottom {
			xfactor = k.BlockCost
		}

		if required := (high - low) + 2; required > len(k.vectors[0]) {
			k.allocateVectors(required)
		}

		if i-low > maxRight {
			maxRight = i - low
		}
		if i-high < maxLeft {
			maxLeft = i - high
		}
	}

	k.highEnd.Abpos = maxJ
	k.highEnd.Bbpos = maxI
	k.highEnd.LowDiagonal = maxLeft
	k.highEnd.HighDiagonal = maxRight
	k.highEnd.Score = maxScore
}
<|endoftext|>


<commit_before>package single_node

import (
	"context"
	"strings"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	v1 "github.com/openshift/api/config/v1"
	exutil "github.com/openshift/origin/test/extended/util"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	e2e "k8s.io/kubernetes/test/e2e/framework"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
)

func getOpenshiftNamespaces(f *e2e.Framework) []corev1.Namespace {
	list, err := f.ClientSet.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
	Expect(err).NotTo(HaveOccurred())

	var openshiftNamespaces []corev1.Namespace
	for _, namespace := range list.Items {
		if strings.HasPrefix(namespace.Name, "openshift-") {
			openshiftNamespaces = append(openshiftNamespaces, namespace)
		}
	}

	return openshiftNamespaces
}

func getNamespaceDeployments(f *e2e.Framework, namespace corev1.Namespace) []appsv1.Deployment {
	list, err := f.ClientSet.AppsV1().Deployments(namespace.Name).List(context.Background(), metav1.ListOptions{})
	Expect(err).NotTo(HaveOccurred())

	return list.Items
}

func getTopologies(f *e2e.Framework) (controlPlaneTopology, infraTopology v1.TopologyMode) {
	oc := exutil.NewCLIWithFramework(f)
	infra, err := oc.AdminConfigClient().ConfigV1().Infrastructures().Get(context.Background(),
		"cluster", metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())

	return infra.Status.ControlPlaneTopology, infra.Status.InfrastructureTopology
}

func isInfrastructureDeployment(deployment appsv1.Deployment) bool {
	infrastructureNamespaces := map[string][]string{
		"openshift-ingress": {
			"router-default",
		},
	}

	namespaceInfraDeployments, ok := infrastructureNamespaces[deployment.Namespace]

	if !ok {
		return false
	}

	for _, infraDeploymentName := range namespaceInfraDeployments {
		if deployment.Name == infraDeploymentName {
			return true
		}
	}

	return false
}

func validateReplicas(deployment appsv1.Deployment,
	controlPlaneTopology, infraTopology v1.TopologyMode, failureAllowed bool) {
	if isInfrastructureDeployment(deployment) {
		if infraTopology != v1.SingleReplicaTopologyMode {
			return
		}
	} else if controlPlaneTopology != v1.SingleReplicaTopologyMode {
		return
	}

	Expect(deployment.Spec.Replicas).ToNot(BeNil())

	replicas := int(*deployment.Spec.Replicas)

	if !failureAllowed {
		Expect(replicas).To(Equal(1),
			"%s in %s namespace has wrong number of replicas", deployment.Name, deployment.Namespace)
	} else {
		if replicas == 1 {
			t := GinkgoT()
			t.Logf("Deployment %s in namespace %s has one replica, consider taking it off the topology allow-list",
				deployment.Name, deployment.Namespace)
		}
	}
}

func isAllowedToFail(deployment appsv1.Deployment) bool {
	// allowedToFail is a list of deployments that currently have 2 replicas even in single-replica
	// topology deployments, because their operator has yet to be made aware of the new API.
	// We will slowly remove deployments from this list once their operators have been made
	// aware until this list is empty and this function will be removed.
	allowedToFail := map[string][]string{
		"openshift-authentication": {
			"oauth-openshift",
		},
		"openshift-image-registry": {
			"image-registry",
		},
		"openshift-monitoring": {
			"prometheus-adapter",
			"thanos-querier",
		},
		"openshift-operator-lifecycle-manager": {
			"packageserver",
		},
	}

	namespaceAllowedToFailDeployments, ok := allowedToFail[deployment.Namespace]

	if !ok {
		return false
	}

	for _, allowedToFailDeploymentName := range namespaceAllowedToFailDeployments {
		if deployment.Name == allowedToFailDeploymentName {
			return true
		}
	}

	return false
}

var _ = Describe("[sig-arch] Cluster topology single node tests", func() {
	f := e2e.NewDefaultFramework("single-node")

	It("Verify that OpenShift components deploy one replica in SingleReplica topology mode", func() {
		controlPlaneTopology, infraTopology := getTopologies(f)

		if controlPlaneTopology != v1.SingleReplicaTopologyMode && infraTopology != v1.SingleReplicaTopologyMode {
			e2eskipper.Skipf("Test is only relevant for single replica topologies")
		}

		for _, namespace := range getOpenshiftNamespaces(f) {
			for _, deployment := range getNamespaceDeployments(f, namespace) {
				validateReplicas(deployment, controlPlaneTopology, infraTopology, isAllowedToFail(deployment))
			}
		}
	})
})
<commit_msg>test/extended/single_node: update for monitoring components<commit_after>package single_node

import (
	"context"
	"strings"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	v1 "github.com/openshift/api/config/v1"
	exutil "github.com/openshift/origin/test/extended/util"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	e2e "k8s.io/kubernetes/test/e2e/framework"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
)

func getOpenshiftNamespaces(f *e2e.Framework) []corev1.Namespace {
	list, err := f.ClientSet.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
	Expect(err).NotTo(HaveOccurred())

	var openshiftNamespaces []corev1.Namespace
	for _, namespace := range list.Items {
		if strings.HasPrefix(namespace.Name, "openshift-") {
			openshiftNamespaces = append(openshiftNamespaces, namespace)
		}
	}

	return openshiftNamespaces
}

func getNamespaceDeployments(f *e2e.Framework, namespace corev1.Namespace) []appsv1.Deployment {
	list, err := f.ClientSet.AppsV1().Deployments(namespace.Name).List(context.Background(), metav1.ListOptions{})
	Expect(err).NotTo(HaveOccurred())

	return list.Items
}

func getTopologies(f *e2e.Framework) (controlPlaneTopology, infraTopology v1.TopologyMode) {
	oc := exutil.NewCLIWithFramework(f)
	infra, err := oc.AdminConfigClient().ConfigV1().Infrastructures().Get(context.Background(),
		"cluster", metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())

	return infra.Status.ControlPlaneTopology, infra.Status.InfrastructureTopology
}

func isInfrastructureDeployment(deployment appsv1.Deployment) bool {
	infrastructureNamespaces := map[string][]string{
		"openshift-ingress": {
			"router-default",
		},
	}

	namespaceInfraDeployments, ok := infrastructureNamespaces[deployment.Namespace]

	if !ok {
		return false
	}

	for _, infraDeploymentName := range namespaceInfraDeployments {
		if deployment.Name == infraDeploymentName {
			return true
		}
	}

	return false
}

func validateReplicas(deployment appsv1.Deployment,
	controlPlaneTopology, infraTopology v1.TopologyMode, failureAllowed bool) {
	if isInfrastructureDeployment(deployment) {
		if infraTopology != v1.SingleReplicaTopologyMode {
			return
		}
	} else if controlPlaneTopology != v1.SingleReplicaTopologyMode {
		return
	}

	Expect(deployment.Spec.Replicas).ToNot(BeNil())

	replicas := int(*deployment.Spec.Replicas)

	if !failureAllowed {
		Expect(replicas).To(Equal(1),
			"%s in %s namespace has wrong number of replicas", deployment.Name, deployment.Namespace)
	} else {
		if replicas == 1 {
			t := GinkgoT()
			t.Logf("Deployment %s in namespace %s has one replica, consider taking it off the topology allow-list",
				deployment.Name, deployment.Namespace)
		}
	}
}

func isAllowedToFail(deployment appsv1.Deployment) bool {
	// allowedToFail is a list of deployments that currently have 2 replicas even in single-replica
	// topology deployments, because their operator has yet to be made aware of the new API.
	// We will slowly remove deployments from this list once their operators have been made
	// aware until this list is empty and this function will be removed.
	allowedToFail := map[string][]string{
		"openshift-authentication": {
			"oauth-openshift",
		},
		"openshift-image-registry": {
			"image-registry",
		},
		"openshift-operator-lifecycle-manager": {
			"packageserver",
		},
	}

	namespaceAllowedToFailDeployments, ok := allowedToFail[deployment.Namespace]

	if !ok {
		return false
	}

	for _, allowedToFailDeploymentName := range namespaceAllowedToFailDeployments {
		if deployment.Name == allowedToFailDeploymentName {
			return true
		}
	}

	return false
}

var _ = Describe("[sig-arch] Cluster topology single node tests", func() {
	f := e2e.NewDefaultFramework("single-node")

	It("Verify that OpenShift components deploy one replica in SingleReplica topology mode", func() {
		controlPlaneTopology, infraTopology := getTopologies(f)

		if controlPlaneTopology != v1.SingleReplicaTopologyMode && infraTopology != v1.SingleReplicaTopologyMode {
			e2eskipper.Skipf("Test is only relevant for single replica topologies")
		}

		for _, namespace := range getOpenshiftNamespaces(f) {
			for _, deployment := range getNamespaceDeployments(f, namespace) {
				validateReplicas(deployment, controlPlaneTopology, infraTopology, isAllowedToFail(deployment))
			}
		}
	})
})
<|endoftext|>


<commit_before>package api

// RootResponse object which will be formatted to json and sent back to google and onto the user.
type RootResponse struct {
	ConversationToken  *string         `json:"conversation_token"`
	ExpectUserResponse bool            `json:"expect_user_response"`
	ExpectedInputs     []ExpectedInput `json:"expected_inputs,omitempty"`
	FinalResponse_     FinalResponse   `json:"final_response"`
}

type ExpectedInput struct {
	PossibleIntents []ExpectedIntent `json:"possible_intents"`
	InputPrompt_    InputPrompt      `json:"input_prompt"`
}

type ExpectedIntent struct {
	Intent          string         `json:"intent"`
	InputValueSpec_ InputValueSpec `json:"input_value_spec"`
}

type FinalResponse struct {
	SpeechResponse_ SpeechResponse `json:"speech_response"`
}

type InputValueSpec struct {
	PermissionValueSpec_ PermissionValueSpec `json:"permission_value_spec"`
}

type PermissionValueSpec struct {
	OptContext  *string  `json:"opt_context"`
	Permissions []string `json:"permissions"`
}

type SpeechResponse struct {
	TextToSpeech *string `json:"text_to_speech"`
	SSML         *string `json:"ssml"`
}

type InputPrompt struct {
	InitialPrompts []SpeechResponse `json:"initial_prompts"`
	NoInputPrompts []SpeechResponse `json:"no_input_prompts"`
}
<commit_msg>either SSML or text to speech can be defined, not both<commit_after>package api

// RootResponse object which will be formatted to json and sent back to google and onto the user.
type RootResponse struct {
	ConversationToken  *string         `json:"conversation_token"`
	ExpectUserResponse bool            `json:"expect_user_response"`
	ExpectedInputs     []ExpectedInput `json:"expected_inputs,omitempty"`
	FinalResponse_     FinalResponse   `json:"final_response"`
}

type ExpectedInput struct {
	PossibleIntents []ExpectedIntent `json:"possible_intents"`
	InputPrompt_    InputPrompt      `json:"input_prompt"`
}

type ExpectedIntent struct {
	Intent          string         `json:"intent"`
	InputValueSpec_ InputValueSpec `json:"input_value_spec"`
}

type FinalResponse struct {
	SpeechResponse_ SpeechResponse `json:"speech_response"`
}

type InputValueSpec struct {
	PermissionValueSpec_ PermissionValueSpec `json:"permission_value_spec"`
}

type PermissionValueSpec struct {
	OptContext  *string  `json:"opt_context"`
	Permissions []string `json:"permissions"`
}

type SpeechResponse struct {
	TextToSpeech *string `json:"text_to_speech,omitempty"`
	SSML         *string `json:"ssml,omitempty"`
}

type InputPrompt struct {
	InitialPrompts []SpeechResponse `json:"initial_prompts"`
	NoInputPrompts []SpeechResponse `json:"no_input_prompts"`
}
<|endoftext|>


<commit_before>package jsonmap

import (
	"encoding/json"
	"fmt"
	"reflect"
)

type ValidationError struct {
	reason string
}

func NewValidationError(reason string, a ...interface{}) *ValidationError {
	return &ValidationError{
		reason: fmt.Sprintf(reason, a...),
	}
}

func (e *ValidationError) Error() string {
	return e.reason
}

type Validator interface {
	Validate(interface{}) (interface{}, error)
}

type Encoder interface {
	Unmarshal(partial interface{}, dstValue reflect.Value) error
	Marshal(reflect.Value) (json.Marshaler, error)
}

type MappedField struct {
	StructFieldName string
	JSONFieldName   string
	Contains        Encoder
	Validator       Validator
	Optional        bool
}

type TypeMap struct {
	UnderlyingType interface{}
	Fields         []MappedField
}

type russellRawMessage struct {
	Data []byte
}

func (rm russellRawMessage) MarshalJSON() ([]byte, error) {
	return rm.Data, nil
}

func (tm TypeMap) Unmarshal(partial interface{}, dstValue reflect.Value) error {
	data, ok := partial.(map[string]interface{})
	if !ok {
		return NewValidationError("expected a JSON object")
	}

	for _, field := range tm.Fields {
		dstField := dstValue.FieldByName(field.StructFieldName)
		if !dstField.IsValid() {
			panic("No such underlying field: " + field.StructFieldName)
		}

		val, ok := data[field.JSONFieldName]
		if !ok {
			if field.Optional {
				continue
			} else {
				return NewValidationError("missing required field: %s", field.JSONFieldName)
			}
		}

		if field.Contains != nil {
			return field.Contains.Unmarshal(val, dstField)
		} else {
			val, err := field.Validator.Validate(val)
			if err != nil {
				if ve, ok := err.(*ValidationError); ok {
					return NewValidationError("error validating field '%s': %s", field.JSONFieldName, ve.Error())
				} else {
					return err
				}
			}

			dstField.Set(reflect.ValueOf(val))
		}
	}

	return nil
}

func (tm TypeMap) Marshal(src reflect.Value) (json.Marshaler, error) {
	if src.Kind() == reflect.Ptr {
		src = src.Elem()
	}
	result := map[string]interface{}{}

	for _, field := range tm.Fields {
		srcField := src.FieldByName(field.StructFieldName)
		if !srcField.IsValid() {
			panic("No such underlying field: " + field.StructFieldName)
		}

		if field.Contains != nil {
			val, err := field.Contains.Marshal(srcField)
			if err != nil {
				return nil, err
			}
			result[field.JSONFieldName] = val
		} else {
			result[field.JSONFieldName] = srcField.Interface()
		}

	}

	data, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}

	return russellRawMessage{data}, nil
}

type TypeMapper struct {
	typeMaps map[reflect.Type]TypeMap
}

func NewTypeMapper(maps ...TypeMap) *TypeMapper {
	t := &TypeMapper{
		typeMaps: make(map[reflect.Type]TypeMap),
	}
	for _, m := range maps {
		t.typeMaps[reflect.TypeOf(m.UnderlyingType)] = m
	}
	return t
}

func (tm *TypeMapper) getTypeMap(obj interface{}) TypeMap {
	if reflect.TypeOf(obj).Kind() != reflect.Ptr {
		panic("dst is not a pointer")
	}

	t := reflect.TypeOf(obj).Elem()
	m, ok := tm.typeMaps[t]

	if !ok {
		panic("no TypeMap registered for type: " + t.String())
	}

	return m
}

func (tm *TypeMapper) Unmarshal(data []byte, dest interface{}) error {
	m := tm.getTypeMap(dest)
	partial := map[string]interface{}{}

	err := json.Unmarshal(data, &partial)
	if err != nil {
		return err
	}

	return m.Unmarshal(partial, reflect.ValueOf(dest).Elem())
}

func (tm *TypeMapper) Marshal(src interface{}) ([]byte, error) {
	m := tm.getTypeMap(src)
	data, err := m.Marshal(reflect.ValueOf(src))
	if err != nil {
		return nil, err
	}
	return data.MarshalJSON()
}
<commit_msg>Fix a bug that prevented marshaling of fields listed after a nested struct<commit_after>package jsonmap

import (
	"encoding/json"
	"fmt"
	"reflect"
)

type ValidationError struct {
	reason string
}

func NewValidationError(reason string, a ...interface{}) *ValidationError {
	return &ValidationError{
		reason: fmt.Sprintf(reason, a...),
	}
}

func (e *ValidationError) Error() string {
	return e.reason
}

type Validator interface {
	Validate(interface{}) (interface{}, error)
}

type Encoder interface {
	Unmarshal(partial interface{}, dstValue reflect.Value) error
	Marshal(reflect.Value) (json.Marshaler, error)
}

type MappedField struct {
	StructFieldName string
	JSONFieldName   string
	Contains        Encoder
	Validator       Validator
	Optional        bool
}

type TypeMap struct {
	UnderlyingType interface{}
	Fields         []MappedField
}

type russellRawMessage struct {
	Data []byte
}

func (rm russellRawMessage) MarshalJSON() ([]byte, error) {
	return rm.Data, nil
}

func (tm TypeMap) Unmarshal(partial interface{}, dstValue reflect.Value) error {
	data, ok := partial.(map[string]interface{})
	if !ok {
		return NewValidationError("expected a JSON object")
	}

	for _, field := range tm.Fields {
		dstField := dstValue.FieldByName(field.StructFieldName)
		if !dstField.IsValid() {
			panic("No such underlying field: " + field.StructFieldName)
		}

		val, ok := data[field.JSONFieldName]
		if !ok {
			if field.Optional {
				continue
			} else {
				return NewValidationError("missing required field: %s", field.JSONFieldName)
			}
		}

		var err error

		if field.Contains != nil {
			err = field.Contains.Unmarshal(val, dstField)
		} else {
			val, err = field.Validator.Validate(val)
			if err == nil {
				dstField.Set(reflect.ValueOf(val))
			}
		}

		if err != nil {
			if ve, ok := err.(*ValidationError); ok {
				return NewValidationError("error validating field '%s': %s", field.JSONFieldName, ve.Error())
			} else {
				return err
			}
		}
	}

	return nil
}

func (tm TypeMap) Marshal(src reflect.Value) (json.Marshaler, error) {
	if src.Kind() == reflect.Ptr {
		src = src.Elem()
	}
	result := map[string]interface{}{}

	for _, field := range tm.Fields {
		srcField := src.FieldByName(field.StructFieldName)
		if !srcField.IsValid() {
			panic("No such underlying field: " + field.StructFieldName)
		}

		if field.Contains != nil {
			val, err := field.Contains.Marshal(srcField)
			if err != nil {
				return nil, err
			}
			result[field.JSONFieldName] = val
		} else {
			result[field.JSONFieldName] = srcField.Interface()
		}

	}

	data, err := json.Marshal(result)
	if err != nil {
		return nil, err
	}

	return russellRawMessage{data}, nil
}

type TypeMapper struct {
	typeMaps map[reflect.Type]TypeMap
}

func NewTypeMapper(maps ...TypeMap) *TypeMapper {
	t := &TypeMapper{
		typeMaps: make(map[reflect.Type]TypeMap),
	}
	for _, m := range maps {
		t.typeMaps[reflect.TypeOf(m.UnderlyingType)] = m
	}
	return t
}

func (tm *TypeMapper) getTypeMap(obj interface{}) TypeMap {
	if reflect.TypeOf(obj).Kind() != reflect.Ptr {
		panic("dst is not a pointer")
	}

	t := reflect.TypeOf(obj).Elem()
	m, ok := tm.typeMaps[t]

	if !ok {
		panic("no TypeMap registered for type: " + t.String())
	}

	return m
}

func (tm *TypeMapper) Unmarshal(data []byte, dest interface{}) error {
	m := tm.getTypeMap(dest)
	partial := map[string]interface{}{}

	err := json.Unmarshal(data, &partial)
	if err != nil {
		return err
	}

	return m.Unmarshal(partial, reflect.ValueOf(dest).Elem())
}

func (tm *TypeMapper) Marshal(src interface{}) ([]byte, error) {
	m := tm.getTypeMap(src)
	data, err := m.Marshal(reflect.ValueOf(src))
	if err != nil {
		return nil, err
	}
	return data.MarshalJSON()
}
<|endoftext|>


<commit_before>package ethchain

import (
	"bytes"
	"github.com/ethereum/eth-go/ethutil"
	"log"
	"math"
	"math/big"
)

type BlockChain struct {
	// The famous, the fabulous Mister GENESIIIIIIS (block)
	genesisBlock *Block
	// Last known total difficulty
	TD *big.Int

	LastBlockNumber uint64

	CurrentBlock  *Block
	LastBlockHash []byte
}

func NewBlockChain() *BlockChain {
	bc := &BlockChain{}
	bc.genesisBlock = NewBlockFromData(ethutil.Encode(Genesis))

	bc.setLastBlock()

	return bc
}

func (bc *BlockChain) Genesis() *Block {
	return bc.genesisBlock
}

func (bc *BlockChain) NewBlock(coinbase []byte, txs []*Transaction) *Block {
	var root interface{}
	var lastBlockTime int64
	hash := ZeroHash256

	if bc.CurrentBlock != nil {
		root = bc.CurrentBlock.State().Root
		hash = bc.LastBlockHash
		lastBlockTime = bc.CurrentBlock.Time
	}

	block := CreateBlock(
		root,
		hash,
		coinbase,
		ethutil.BigPow(2, 32),
		nil,
		"",
		txs)

	if bc.CurrentBlock != nil {
		var mul *big.Int
		if block.Time < lastBlockTime+42 {
			mul = big.NewInt(1)
		} else {
			mul = big.NewInt(-1)
		}

		diff := new(big.Int)
		diff.Add(diff, bc.CurrentBlock.Difficulty)
		diff.Div(diff, big.NewInt(1024))
		diff.Mul(diff, mul)
		diff.Add(diff, bc.CurrentBlock.Difficulty)
		block.Difficulty = diff
	}

	return block
}

func (bc *BlockChain) HasBlock(hash []byte) bool {
	data, _ := ethutil.Config.Db.Get(hash)
	return len(data) != 0
}

func (bc *BlockChain) GenesisBlock() *Block {
	return bc.genesisBlock
}

// Get chain return blocks from hash up to max in RLP format
func (bc *BlockChain) GetChainFromHash(hash []byte, max uint64) []interface{} {
	var chain []interface{}
	// Get the current hash to start with
	currentHash := bc.CurrentBlock.Hash()
	// Get the last number on the block chain
	lastNumber := bc.BlockInfo(bc.CurrentBlock).Number
	// Get the parents number
	parentNumber := bc.BlockInfoByHash(hash).Number
	// Get the min amount. We might not have max amount of blocks
	count := uint64(math.Min(float64(lastNumber-parentNumber), float64(max)))
	startNumber := parentNumber + count

	num := lastNumber
	for ; num > startNumber; currentHash = bc.GetBlock(currentHash).PrevHash {
		num--
	}
	for i := uint64(0); bytes.Compare(currentHash, hash) != 0 && num >= parentNumber && i < count; i++ {
		// Get the block of the chain
		block := bc.GetBlock(currentHash)
		currentHash = block.PrevHash

		chain = append(chain, block.Value().Val)

		num--
	}

	return chain
}

func (bc *BlockChain) setLastBlock() {
	data, _ := ethutil.Config.Db.Get([]byte("LastBlock"))
	if len(data) != 0 {
		block := NewBlockFromBytes(data)
		info := bc.BlockInfo(block)
		bc.CurrentBlock = block
		bc.LastBlockHash = block.Hash()
		bc.LastBlockNumber = info.Number

		log.Printf("[CHAIN] Last known block height #%d\n", bc.LastBlockNumber)
	}

	// Set the last know difficulty (might be 0x0 as initial value, Genesis)
	bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
}

func (bc *BlockChain) SetTotalDifficulty(td *big.Int) {
	ethutil.Config.Db.Put([]byte("LastKnownTotalDifficulty"), td.Bytes())
	bc.TD = td
}

// Add a block to the chain and record addition information
func (bc *BlockChain) Add(block *Block) {
	bc.writeBlockInfo(block)

	// Prepare the genesis block
	bc.CurrentBlock = block
	bc.LastBlockHash = block.Hash()

	encodedBlock := block.RlpEncode()
	ethutil.Config.Db.Put(block.Hash(), encodedBlock)
	ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock)
}

func (bc *BlockChain) GetBlock(hash []byte) *Block {
	data, _ := ethutil.Config.Db.Get(hash)

	return NewBlockFromData(data)
}

func (bc *BlockChain) BlockInfoByHash(hash []byte) BlockInfo {
	bi := BlockInfo{}
	data, _ := ethutil.Config.Db.Get(append(hash, []byte("Info")...))
	bi.RlpDecode(data)

	return bi
}

func (bc *BlockChain) BlockInfo(block *Block) BlockInfo {
	bi := BlockInfo{}
	data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...))
	bi.RlpDecode(data)

	return bi
}

// Unexported method for writing extra non-essential block info to the db
func (bc *BlockChain) writeBlockInfo(block *Block) {
	bc.LastBlockNumber++
	bi := BlockInfo{Number: bc.LastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash}

	// For now we use the block hash with the words "info" appended as key
	ethutil.Config.Db.Put(append(block.Hash(), []byte("Info")...), bi.RlpEncode())
}

func (bc *BlockChain) Stop() {
	if bc.CurrentBlock != nil {
		log.Println("[CHAIN] Stopped")
	}
}
<commit_msg>Get a chain of blocks made simple<commit_after>package ethchain

import (
	"bytes"
	"fmt"
	"github.com/ethereum/eth-go/ethutil"
	"log"
	"math"
	"math/big"
)

type BlockChain struct {
	// The famous, the fabulous Mister GENESIIIIIIS (block)
	genesisBlock *Block
	// Last known total difficulty
	TD *big.Int

	LastBlockNumber uint64

	CurrentBlock  *Block
	LastBlockHash []byte
}

func NewBlockChain() *BlockChain {
	bc := &BlockChain{}
	bc.genesisBlock = NewBlockFromData(ethutil.Encode(Genesis))

	bc.setLastBlock()

	return bc
}

func (bc *BlockChain) Genesis() *Block {
	return bc.genesisBlock
}

func (bc *BlockChain) NewBlock(coinbase []byte, txs []*Transaction) *Block {
	var root interface{}
	var lastBlockTime int64
	hash := ZeroHash256

	if bc.CurrentBlock != nil {
		root = bc.CurrentBlock.State().Root
		hash = bc.LastBlockHash
		lastBlockTime = bc.CurrentBlock.Time
	}

	block := CreateBlock(
		root,
		hash,
		coinbase,
		ethutil.BigPow(2, 32),
		nil,
		"",
		txs)

	if bc.CurrentBlock != nil {
		var mul *big.Int
		if block.Time < lastBlockTime+42 {
			mul = big.NewInt(1)
		} else {
			mul = big.NewInt(-1)
		}

		diff := new(big.Int)
		diff.Add(diff, bc.CurrentBlock.Difficulty)
		diff.Div(diff, big.NewInt(1024))
		diff.Mul(diff, mul)
		diff.Add(diff, bc.CurrentBlock.Difficulty)
		block.Difficulty = diff
	}

	return block
}

func (bc *BlockChain) HasBlock(hash []byte) bool {
	data, _ := ethutil.Config.Db.Get(hash)
	return len(data) != 0
}

func (bc *BlockChain) GenesisBlock() *Block {
	return bc.genesisBlock
}

// Get chain return blocks from hash up to max in RLP format
func (bc *BlockChain) GetChainFromHash(hash []byte, max uint64) []interface{} {
	var chain []interface{}
	// Get the current hash to start with
	currentHash := bc.CurrentBlock.Hash()
	// Get the last number on the block chain
	lastNumber := bc.BlockInfo(bc.CurrentBlock).Number
	// Get the parents number
	parentNumber := bc.BlockInfoByHash(hash).Number
	// Get the min amount. We might not have max amount of blocks
	count := uint64(math.Min(float64(lastNumber-parentNumber), float64(max)))
	startNumber := parentNumber + count

	num := lastNumber
	for ; num > startNumber; currentHash = bc.GetBlock(currentHash).PrevHash {
		num--
	}
	for i := uint64(0); bytes.Compare(currentHash, hash) != 0 && num >= parentNumber && i < count; i++ {
		// Get the block of the chain
		block := bc.GetBlock(currentHash)
		currentHash = block.PrevHash

		chain = append(chain, block.Value().Val)

		num--
	}

	return chain
}

func (bc *BlockChain) GetChain(hash []byte, amount int) []*Block {
	genHash := bc.genesisBlock.Hash()

	block := bc.GetBlock(hash)
	var blocks []*Block

	for i := 0; i < amount && block != nil; block = bc.GetBlock(block.PrevHash) {
		fmt.Println(block)
		blocks = append([]*Block{block}, blocks...)

		if bytes.Compare(genHash, block.Hash()) == 0 {
			break
		}
		i++
	}

	return blocks
}

func (bc *BlockChain) setLastBlock() {
	data, _ := ethutil.Config.Db.Get([]byte("LastBlock"))
	if len(data) != 0 {
		block := NewBlockFromBytes(data)
		info := bc.BlockInfo(block)
		bc.CurrentBlock = block
		bc.LastBlockHash = block.Hash()
		bc.LastBlockNumber = info.Number

		log.Printf("[CHAIN] Last known block height #%d\n", bc.LastBlockNumber)
	}

	// Set the last know difficulty (might be 0x0 as initial value, Genesis)
	bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
}

func (bc *BlockChain) SetTotalDifficulty(td *big.Int) {
	ethutil.Config.Db.Put([]byte("LastKnownTotalDifficulty"), td.Bytes())
	bc.TD = td
}

// Add a block to the chain and record addition information
func (bc *BlockChain) Add(block *Block) {
	bc.writeBlockInfo(block)

	// Prepare the genesis block
	bc.CurrentBlock = block
	bc.LastBlockHash = block.Hash()

	encodedBlock := block.RlpEncode()
	ethutil.Config.Db.Put(block.Hash(), encodedBlock)
	ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock)
}

func (bc *BlockChain) GetBlock(hash []byte) *Block {
	data, _ := ethutil.Config.Db.Get(hash)
	if len(data) == 0 {
		return nil
	}

	return NewBlockFromData(data)
}

func (bc *BlockChain) BlockInfoByHash(hash []byte) BlockInfo {
	bi := BlockInfo{}
	data, _ := ethutil.Config.Db.Get(append(hash, []byte("Info")...))
	bi.RlpDecode(data)

	return bi
}

func (bc *BlockChain) BlockInfo(block *Block) BlockInfo {
	bi := BlockInfo{}
	data, _ := ethutil.Config.Db.Get(append(block.Hash(), []byte("Info")...))
	bi.RlpDecode(data)

	return bi
}

// Unexported method for writing extra non-essential block info to the db
func (bc *BlockChain) writeBlockInfo(block *Block) {
	bc.LastBlockNumber++
	bi := BlockInfo{Number: bc.LastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash}

	// For now we use the block hash with the words "info" appended as key
	ethutil.Config.Db.Put(append(block.Hash(), []byte("Info")...), bi.RlpEncode())
}

func (bc *BlockChain) Stop() {
	if bc.CurrentBlock != nil {
		log.Println("[CHAIN] Stopped")
	}
}
<|endoftext|>


<commit_before>// 22-24 august 2012
package main

import (
	"fmt"
	"strings"
	"sort"

	// for drawing the progress bar
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"encoding/base64"
	"bytes"
)

type SortOrder int
const (
	SortByRegion SortOrder = iota
	SortByBoxState
	SortByMediaState
)

type GameScan struct {
	Name		string
	HasNoScans	bool			// for whole games
	Region		string
	BoxState		ScanState
	MediaState	ScanState
	Error			error
}

type ScanSet []*GameScan

func getMediaState(scan Scan) ScanState {
	if scan.Cart == "" && scan.Disc == "" {
		return Missing
	}
	if scan.Cart != "" && scan.Disc == "" {
		return scan.CartScanState()
	}
	if scan.Cart == "" && scan.Disc != "" {
		return scan.DiscScanState()
	}
	return scan.CartScanState().Join(scan.DiscScanState())	// else
}

func GetConsoleScans(console string) (ScanSet, error) {
	var gameScans ScanSet

	games, err := GetGameList(console)
	if err != nil {
		return nil, fmt.Errorf("error getting %s game list: %v", console, err)
	}
	for _, game := range games {
//fmt.Println(game)
		if strings.HasPrefix(game, "List of " + console + " games") {	// omit list from report
			continue
		}
		scans, err := GetScans(game, console)
		if err == ErrGameNoScans {		// omit games for this console that will not have scans
			continue
		}
		if err != nil {
			gameScans = append(gameScans, &GameScan{
				Name:	game,
				Error:	err,
			})
			continue
		}
		if len(scans) == 0 {				// there are no scans at all
			gameScans = append(gameScans, &GameScan{
				Name:		game,
				HasNoScans:	true,
			})
			continue
		}
		nScans := 0
		for _, scan := range scans {
			var mediaState ScanState

			if scan.Console != console {	// omit scans from other consoles
				continue
			}
			nScans++
			boxState := scan.BoxScanState()
			mediaState = getMediaState(scan)
			gameScans = append(gameScans, &GameScan{
				Name:		game,
				Region:		scan.Region,
				BoxState:		boxState,
				MediaState:	mediaState,
			})
		}
		if nScans == 0 {					// there are no scans for the specified console
			gameScans = append(gameScans, &GameScan{
				Name:		game,
				HasNoScans:	true,
			})
			continue
		}
	}
	return gameScans, nil
}

type sorter struct {
	scans		ScanSet
	sortOrder		SortOrder
}

// for sort.Interface
func (s sorter) Len() int {
	return len(s.scans)
}

func (s sorter) Less(i, j int) bool {
	scans := s.scans
	// the sort orders make no sense if there is either an error or no scans for a game, so handle those cases first
	if scans[i].Error != nil && scans[j].Error != nil {		// errors go first
		return scans[i].Name < scans[j].Name		// by title if they both error
	}
	if scans[i].Error != nil {
		return true
	}
	if scans[j].Error != nil {
		return false
	}
	if scans[i].HasNoScans && scans[j].HasNoScans {	// then lack of scans
		return scans[i].Name < scans[j].Name		// by title if they both lack scans
	}
	if scans[i].HasNoScans {
		return true
	}
	if scans[j].HasNoScans {
		return false
	}
	switch s.sortOrder {
	case SortByRegion:		// sort by region, then by name
		if scans[i].Region == scans[j].Region {			// then if they have the same region, alphabetically
			return scans[i].Name < scans[j].Name
		}
		return scans[i].Region < scans[j].Region			// finally
	case SortByBoxState:
		if scans[i].BoxState == scans[j].BoxState {			// then if they have the same region, alphabetically
			return scans[i].Name < scans[j].Name
		}
		return scans[i].BoxState < scans[j].BoxState		// finally
	case SortByMediaState:
		if scans[i].MediaState == scans[j].MediaState {		// then if they have the same region, alphabetically
			return scans[i].Name < scans[j].Name
		}
		return scans[i].MediaState < scans[j].MediaState	// finally
	}
	panic(fmt.Sprintf("invalid sort order %d", int(s.sortOrder)))
}

func (s sorter) Swap(i, j int) {
	s.scans[i], s.scans[j] = s.scans[j], s.scans[i]
}

func (scans ScanSet) Sort(so SortOrder) {
	sort.Sort(sorter{
		scans:		scans,
		sortOrder:		so,
	})
}

type Stats struct {
	nBoxScans		int
	nBoxHave			int
	nBoxGood		int
	nBoxBad			int
	pBoxHave			float64
	pBoxGood		float64
	pBoxGoodAll		float64
	pBoxBad			float64
	pBoxBadAll		float64
	nMediaScans		int
	nMediaHave		int
	nMediaGood		int
	nMediaBad		int
	pMediaHave		float64
	pMediaGood		float64
	pMediaGoodAll		float64
	pMediaBad		float64
	pMediaBadAll		float64
}

func pcnt(_a, _b int) float64 {
	if _a != 0 && _b == 0 {	// sanity check
		panic("we somehow have scans where none are expected")
	}
	if _b == 0 {
		return 0.0
	}
	a, b := float64(_a), float64(_b)
	return (a / b) * 100.0
}

func (scans ScanSet) GetStats(filterRegion string) (stats Stats) {
	for _, scan := range scans {
		if scan.Error != nil || scan.HasNoScans {		// TODO really skip entries without scans?
			continue
		}
		if filterRegion != "" &&
			!strings.HasPrefix(scan.Region, filterRegion) {
			continue
		}
		stats.nBoxScans++
		switch scan.BoxState {
		case Good:
			stats.nBoxGood++
			stats.nBoxHave++
		case Bad:
			stats.nBoxBad++
			fallthrough
		case Incomplete:
			stats.nBoxHave++
		}
		stats.nMediaScans++
		switch scan.MediaState {
		case Good:
			stats.nMediaGood++
			stats.nMediaHave++
		case Bad:
			stats.nMediaBad++
			fallthrough
		case Incomplete:
			stats.nMediaHave++
		}
	}
	stats.pBoxHave = pcnt(stats.nBoxHave, stats.nBoxScans)
	stats.pBoxGood = pcnt(stats.nBoxGood, stats.nBoxHave)
	stats.pBoxGoodAll = pcnt(stats.nBoxGood, stats.nBoxScans)
	stats.pBoxBad = pcnt(stats.nBoxBad, stats.nBoxHave)
	stats.pBoxBadAll = pcnt(stats.nBoxBad, stats.nBoxScans)
	stats.pMediaHave = pcnt(stats.nMediaHave, stats.nMediaScans)
	stats.pMediaGood = pcnt(stats.nMediaGood, stats.nMediaHave)
	stats.pMediaGoodAll = pcnt(stats.nMediaGood, stats.nMediaScans)
	stats.pMediaBad = pcnt(stats.nMediaBad, stats.nMediaHave)
	stats.pMediaBadAll = pcnt(stats.nMediaBad, stats.nMediaScans)
	return
}

const pbarWidth = 300
const pbarHeight = 20
const pbarPercentFactor = 3
const pbarBorderThickness = 2

var (
	black = image.NewUniform(color.Black)
	white = image.NewUniform(color.White)
	red = image.NewUniform(color.RGBA{255, 0, 0, 255})
	green = image.NewUniform(color.RGBA{0, 255, 0, 255})
)

func progressbar(pGoodAll float64, pBadAll float64) string {
	pbar := image.NewRGBA(image.Rect(0, 0,
		pbarWidth + (pbarBorderThickness * 2),
		pbarHeight + (pbarBorderThickness * 2)))
	// 1) fill black for border
	draw.Draw(pbar, pbar.Rect, black, image.ZP, draw.Src)
	// 2) draw white for what we have
	draw.Draw(pbar, image.Rect(
		pbarBorderThickness, pbarBorderThickness,
		pbarBorderThickness + pbarWidth,
		pbarBorderThickness + pbarHeight), white, image.ZP, draw.Src)
	// 3) figure out the rectanges for good and bad
	goodWid := int(pGoodAll + 0.5) * pbarPercentFactor
	badWid := int(pBadAll + 0.5) * pbarPercentFactor
	goodRect := image.Rect(
		pbarBorderThickness, pbarBorderThickness,
		pbarBorderThickness + goodWid,
		pbarBorderThickness + pbarHeight)
	badRect := image.Rect(
		pbarBorderThickness + goodWid, pbarBorderThickness,
		pbarBorderThickness + goodWid + badWid,
		pbarBorderThickness + pbarHeight)
	// 4) draw good and bad
	draw.Draw(pbar, goodRect, green, image.ZP, draw.Src)
	draw.Draw(pbar, badRect, red, image.ZP, draw.Src)
	// 5) convert to base64 and return
	_pngDat := new(bytes.Buffer)
	pngDat := base64.NewEncoder(base64.StdEncoding, _pngDat)
	defer pngDat.Close()
	err := png.Encode(pngDat, pbar)
	if err != nil {
		panic(fmt.Errorf("error producing progress bar PNG: %v\n", err))
	}
	return _pngDat.String()
}

func (s Stats) BoxProgressBar() string {
	return progressbar(s.pBoxGoodAll, s.pBoxBadAll)
}

func (s Stats) MediaProgressBar() string {
	return progressbar(s.pMediaGoodAll, s.pMediaBadAll)
}
<commit_msg>Split out statistics percentage calculation and added an Add() function for combining multiple statistics. This will be used for an "overal status" feature on the front page.<commit_after>// 22-24 august 2012
package main

import (
	"fmt"
	"strings"
	"sort"

	// for drawing the progress bar
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"encoding/base64"
	"bytes"
)

type SortOrder int
const (
	SortByRegion SortOrder = iota
	SortByBoxState
	SortByMediaState
)

type GameScan struct {
	Name		string
	HasNoScans	bool			// for whole games
	Region		string
	BoxState		ScanState
	MediaState	ScanState
	Error			error
}

type ScanSet []*GameScan

func getMediaState(scan Scan) ScanState {
	if scan.Cart == "" && scan.Disc == "" {
		return Missing
	}
	if scan.Cart != "" && scan.Disc == "" {
		return scan.CartScanState()
	}
	if scan.Cart == "" && scan.Disc != "" {
		return scan.DiscScanState()
	}
	return scan.CartScanState().Join(scan.DiscScanState())	// else
}

func GetConsoleScans(console string) (ScanSet, error) {
	var gameScans ScanSet

	games, err := GetGameList(console)
	if err != nil {
		return nil, fmt.Errorf("error getting %s game list: %v", console, err)
	}
	for _, game := range games {
//fmt.Println(game)
		if strings.HasPrefix(game, "List of " + console + " games") {	// omit list from report
			continue
		}
		scans, err := GetScans(game, console)
		if err == ErrGameNoScans {		// omit games for this console that will not have scans
			continue
		}
		if err != nil {
			gameScans = append(gameScans, &GameScan{
				Name:	game,
				Error:	err,
			})
			continue
		}
		if len(scans) == 0 {				// there are no scans at all
			gameScans = append(gameScans, &GameScan{
				Name:		game,
				HasNoScans:	true,
			})
			continue
		}
		nScans := 0
		for _, scan := range scans {
			var mediaState ScanState

			if scan.Console != console {	// omit scans from other consoles
				continue
			}
			nScans++
			boxState := scan.BoxScanState()
			mediaState = getMediaState(scan)
			gameScans = append(gameScans, &GameScan{
				Name:		game,
				Region:		scan.Region,
				BoxState:		boxState,
				MediaState:	mediaState,
			})
		}
		if nScans == 0 {					// there are no scans for the specified console
			gameScans = append(gameScans, &GameScan{
				Name:		game,
				HasNoScans:	true,
			})
			continue
		}
	}
	return gameScans, nil
}

type sorter struct {
	scans		ScanSet
	sortOrder		SortOrder
}

// for sort.Interface
func (s sorter) Len() int {
	return len(s.scans)
}

func (s sorter) Less(i, j int) bool {
	scans := s.scans
	// the sort orders make no sense if there is either an error or no scans for a game, so handle those cases first
	if scans[i].Error != nil && scans[j].Error != nil {		// errors go first
		return scans[i].Name < scans[j].Name		// by title if they both error
	}
	if scans[i].Error != nil {
		return true
	}
	if scans[j].Error != nil {
		return false
	}
	if scans[i].HasNoScans && scans[j].HasNoScans {	// then lack of scans
		return scans[i].Name < scans[j].Name		// by title if they both lack scans
	}
	if scans[i].HasNoScans {
		return true
	}
	if scans[j].HasNoScans {
		return false
	}
	switch s.sortOrder {
	case SortByRegion:		// sort by region, then by name
		if scans[i].Region == scans[j].Region {			// then if they have the same region, alphabetically
			return scans[i].Name < scans[j].Name
		}
		return scans[i].Region < scans[j].Region			// finally
	case SortByBoxState:
		if scans[i].BoxState == scans[j].BoxState {			// then if they have the same region, alphabetically
			return scans[i].Name < scans[j].Name
		}
		return scans[i].BoxState < scans[j].BoxState		// finally
	case SortByMediaState:
		if scans[i].MediaState == scans[j].MediaState {		// then if they have the same region, alphabetically
			return scans[i].Name < scans[j].Name
		}
		return scans[i].MediaState < scans[j].MediaState	// finally
	}
	panic(fmt.Sprintf("invalid sort order %d", int(s.sortOrder)))
}

func (s sorter) Swap(i, j int) {
	s.scans[i], s.scans[j] = s.scans[j], s.scans[i]
}

func (scans ScanSet) Sort(so SortOrder) {
	sort.Sort(sorter{
		scans:		scans,
		sortOrder:		so,
	})
}

type Stats struct {
	nBoxScans		int
	nBoxHave			int
	nBoxGood		int
	nBoxBad			int
	pBoxHave			float64
	pBoxGood		float64
	pBoxGoodAll		float64
	pBoxBad			float64
	pBoxBadAll		float64
	nMediaScans		int
	nMediaHave		int
	nMediaGood		int
	nMediaBad		int
	pMediaHave		float64
	pMediaGood		float64
	pMediaGoodAll		float64
	pMediaBad		float64
	pMediaBadAll		float64
}

func pcnt(_a, _b int) float64 {
	if _a != 0 && _b == 0 {	// sanity check
		panic("we somehow have scans where none are expected")
	}
	if _b == 0 {
		return 0.0
	}
	a, b := float64(_a), float64(_b)
	return (a / b) * 100.0
}

func (scans ScanSet) GetStats(filterRegion string) (stats Stats) {
	for _, scan := range scans {
		if scan.Error != nil || scan.HasNoScans {		// TODO really skip entries without scans?
			continue
		}
		if filterRegion != "" &&
			!strings.HasPrefix(scan.Region, filterRegion) {
			continue
		}
		stats.nBoxScans++
		switch scan.BoxState {
		case Good:
			stats.nBoxGood++
			stats.nBoxHave++
		case Bad:
			stats.nBoxBad++
			fallthrough
		case Incomplete:
			stats.nBoxHave++
		}
		stats.nMediaScans++
		switch scan.MediaState {
		case Good:
			stats.nMediaGood++
			stats.nMediaHave++
		case Bad:
			stats.nMediaBad++
			fallthrough
		case Incomplete:
			stats.nMediaHave++
		}
	}
	stats.CalculatePercents()
	return
}

func (stats *Stats) Add(stats2 Stats) {
	stats.nBoxScans += stats2.nBoxScans
	stats.nBoxHave += stats2.nBoxHave
	stats.nBoxGood += stats2.nBoxGood
	stats.nBoxBad += stats2.nBoxBad
	stats.nMediaScans += stats2.nMediaScans
	stats.nMediaHave += stats2.nMediaHave
	stats.nMediaGood += stats2.nMediaGood
	stats.nMediaBad += stats2.nMediaBad
	stats.CalculatePercents()		// TODO move out for optimization?
}

func (stats *Stats) CalculatePercents() {
	stats.pBoxHave = pcnt(stats.nBoxHave, stats.nBoxScans)
	stats.pBoxGood = pcnt(stats.nBoxGood, stats.nBoxHave)
	stats.pBoxGoodAll = pcnt(stats.nBoxGood, stats.nBoxScans)
	stats.pBoxBad = pcnt(stats.nBoxBad, stats.nBoxHave)
	stats.pBoxBadAll = pcnt(stats.nBoxBad, stats.nBoxScans)
	stats.pMediaHave = pcnt(stats.nMediaHave, stats.nMediaScans)
	stats.pMediaGood = pcnt(stats.nMediaGood, stats.nMediaHave)
	stats.pMediaGoodAll = pcnt(stats.nMediaGood, stats.nMediaScans)
	stats.pMediaBad = pcnt(stats.nMediaBad, stats.nMediaHave)
	stats.pMediaBadAll = pcnt(stats.nMediaBad, stats.nMediaScans)
}

const pbarWidth = 300
const pbarHeight = 20
const pbarPercentFactor = 3
const pbarBorderThickness = 2

var (
	black = image.NewUniform(color.Black)
	white = image.NewUniform(color.White)
	red = image.NewUniform(color.RGBA{255, 0, 0, 255})
	green = image.NewUniform(color.RGBA{0, 255, 0, 255})
)

func progressbar(pGoodAll float64, pBadAll float64) string {
	pbar := image.NewRGBA(image.Rect(0, 0,
		pbarWidth + (pbarBorderThickness * 2),
		pbarHeight + (pbarBorderThickness * 2)))
	// 1) fill black for border
	draw.Draw(pbar, pbar.Rect, black, image.ZP, draw.Src)
	// 2) draw white for what we have
	draw.Draw(pbar, image.Rect(
		pbarBorderThickness, pbarBorderThickness,
		pbarBorderThickness + pbarWidth,
		pbarBorderThickness + pbarHeight), white, image.ZP, draw.Src)
	// 3) figure out the rectanges for good and bad
	goodWid := int(pGoodAll + 0.5) * pbarPercentFactor
	badWid := int(pBadAll + 0.5) * pbarPercentFactor
	goodRect := image.Rect(
		pbarBorderThickness, pbarBorderThickness,
		pbarBorderThickness + goodWid,
		pbarBorderThickness + pbarHeight)
	badRect := image.Rect(
		pbarBorderThickness + goodWid, pbarBorderThickness,
		pbarBorderThickness + goodWid + badWid,
		pbarBorderThickness + pbarHeight)
	// 4) draw good and bad
	draw.Draw(pbar, goodRect, green, image.ZP, draw.Src)
	draw.Draw(pbar, badRect, red, image.ZP, draw.Src)
	// 5) convert to base64 and return
	_pngDat := new(bytes.Buffer)
	pngDat := base64.NewEncoder(base64.StdEncoding, _pngDat)
	defer pngDat.Close()
	err := png.Encode(pngDat, pbar)
	if err != nil {
		panic(fmt.Errorf("error producing progress bar PNG: %v\n", err))
	}
	return _pngDat.String()
}

func (s Stats) BoxProgressBar() string {
	return progressbar(s.pBoxGoodAll, s.pBoxBadAll)
}

func (s Stats) MediaProgressBar() string {
	return progressbar(s.pMediaGoodAll, s.pMediaBadAll)
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

// This file tests types.Check by using it to
// typecheck the standard library and tests.

package types

import (
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"
)

var verbose = flag.Bool("types.v", false, "verbose mode")

var (
	pkgCount int // number of packages processed
	start    = time.Now()
)

func TestStdlib(t *testing.T) {
	walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg"))
	if *verbose {
		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
	}
}

// firstComment returns the contents of the first comment in
// the given file, assuming there's one within the first KB.
func firstComment(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		return ""
	}
	defer f.Close()

	var src [1 << 10]byte // read at most 1KB
	n, _ := f.Read(src[:])

	var s scanner.Scanner
	s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil, scanner.ScanComments)
	for {
		_, tok, lit := s.Scan()
		switch tok {
		case token.COMMENT:
			// remove trailing */ of multi-line comment
			if lit[1] == '*' {
				lit = lit[:len(lit)-2]
			}
			return strings.TrimSpace(lit[2:])
		case token.EOF:
			return ""
		}
	}
}

func testTestDir(t *testing.T, path string, ignore ...string) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		t.Fatal(err)
	}

	excluded := make(map[string]bool)
	for _, filename := range ignore {
		excluded[filename] = true
	}

	fset := token.NewFileSet()
	for _, f := range files {
		// filter directory contents
		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
			continue
		}

		// get per-file instructions
		expectErrors := false
		filename := filepath.Join(path, f.Name())
		if cmd := firstComment(filename); cmd != "" {
			switch cmd {
			case "skip", "compiledir":
				continue // ignore this file
			case "errorcheck":
				expectErrors = true
			}
		}

		// parse and type-check file
		file, err := parser.ParseFile(fset, filename, nil, 0)
		if err == nil {
			_, err = Check(filename, fset, []*ast.File{file})
		}

		if expectErrors {
			if err == nil {
				t.Errorf("expected errors but found none in %s", filename)
			}
		} else {
			if err != nil {
				t.Error(err)
			}
		}
	}
}

func TestStdtest(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
		"cmplxdivide.go",          // also needs file cmplxdivide1.go - ignore
		"mapnan.go", "sigchld.go", // don't work on Windows; testTestDir should consult build tags
	)
}

func TestStdfixed(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
		"bug165.go",                           // TODO(gri) isComparable not working for incomplete struct type
		"bug223.go", "bug413.go", "bug459.go", // TODO(gri) complete initialization checks
		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
		"issue3924.go", // TODO(gri) && and || produce bool result (not untyped bool)
		"issue4847.go", // TODO(gri) initialization cycle error not found
	)
}

func TestStdken(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken"))
}

// Package paths of excluded packages.
var excluded = map[string]bool{
	"builtin": true,
}

// typecheck typechecks the given package files.
func typecheck(t *testing.T, path string, filenames []string) {
	fset := token.NewFileSet()

	// parse package files
	var files []*ast.File
	for _, filename := range filenames {
		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
		if err != nil {
			// the parser error may be a list of individual errors; report them all
			if list, ok := err.(scanner.ErrorList); ok {
				for _, err := range list {
					t.Error(err)
				}
				return
			}
			t.Error(err)
			return
		}

		if *verbose {
			if len(files) == 0 {
				fmt.Println("package", file.Name.Name)
			}
			fmt.Println("\t", filename)
		}

		files = append(files, file)
	}

	// typecheck package files
	var conf Config
	conf.Error = func(err error) { t.Error(err) }
	conf.Check(path, fset, files, nil)
	pkgCount++
}

// pkgfiles returns the list of package files for the given directory.
func pkgfiles(t *testing.T, dir string) []string {
	ctxt := build.Default
	ctxt.CgoEnabled = false
	pkg, err := ctxt.ImportDir(dir, 0)
	if err != nil {
		if _, nogo := err.(*build.NoGoError); !nogo {
			t.Error(err)
		}
		return nil
	}
	if excluded[pkg.ImportPath] {
		return nil
	}
	var filenames []string
	for _, name := range pkg.GoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	for _, name := range pkg.TestGoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	return filenames
}

// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
//       necessarily be shorter or clearer after adding the code to
//       terminate early for -short tests.

func walkDirs(t *testing.T, dir string) {
	// limit run time for short tests
	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
		return
	}

	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Error(err)
		return
	}

	// typecheck package in directory
	if files := pkgfiles(t, dir); files != nil {
		typecheck(t, dir, files)
	}

	// traverse subdirectories, but don't walk into testdata
	for _, fi := range fis {
		if fi.IsDir() && fi.Name() != "testdata" {
			walkDirs(t, filepath.Join(dir, fi.Name()))
		}
	}
}
<commit_msg>go.tools/go/types: enable std lib test of map key types<commit_after>// Copyright 2013 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.

// This file tests types.Check by using it to
// typecheck the standard library and tests.

package types

import (
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"
)

var verbose = flag.Bool("types.v", false, "verbose mode")

var (
	pkgCount int // number of packages processed
	start    = time.Now()
)

func TestStdlib(t *testing.T) {
	walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg"))
	if *verbose {
		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
	}
}

// firstComment returns the contents of the first comment in
// the given file, assuming there's one within the first KB.
func firstComment(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		return ""
	}
	defer f.Close()

	var src [1 << 10]byte // read at most 1KB
	n, _ := f.Read(src[:])

	var s scanner.Scanner
	s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil, scanner.ScanComments)
	for {
		_, tok, lit := s.Scan()
		switch tok {
		case token.COMMENT:
			// remove trailing */ of multi-line comment
			if lit[1] == '*' {
				lit = lit[:len(lit)-2]
			}
			return strings.TrimSpace(lit[2:])
		case token.EOF:
			return ""
		}
	}
}

func testTestDir(t *testing.T, path string, ignore ...string) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		t.Fatal(err)
	}

	excluded := make(map[string]bool)
	for _, filename := range ignore {
		excluded[filename] = true
	}

	fset := token.NewFileSet()
	for _, f := range files {
		// filter directory contents
		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
			continue
		}

		// get per-file instructions
		expectErrors := false
		filename := filepath.Join(path, f.Name())
		if cmd := firstComment(filename); cmd != "" {
			switch cmd {
			case "skip", "compiledir":
				continue // ignore this file
			case "errorcheck":
				expectErrors = true
			}
		}

		// parse and type-check file
		file, err := parser.ParseFile(fset, filename, nil, 0)
		if err == nil {
			_, err = Check(filename, fset, []*ast.File{file})
		}

		if expectErrors {
			if err == nil {
				t.Errorf("expected errors but found none in %s", filename)
			}
		} else {
			if err != nil {
				t.Error(err)
			}
		}
	}
}

func TestStdtest(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
		"cmplxdivide.go",          // also needs file cmplxdivide1.go - ignore
		"mapnan.go", "sigchld.go", // don't work on Windows; testTestDir should consult build tags
	)
}

func TestStdfixed(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
		"bug223.go", "bug413.go", "bug459.go", // TODO(gri) complete initialization checks
		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
		"issue3924.go", // TODO(gri) && and || produce bool result (not untyped bool)
		"issue4847.go", // TODO(gri) initialization cycle error not found
	)
}

func TestStdken(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken"))
}

// Package paths of excluded packages.
var excluded = map[string]bool{
	"builtin": true,
}

// typecheck typechecks the given package files.
func typecheck(t *testing.T, path string, filenames []string) {
	fset := token.NewFileSet()

	// parse package files
	var files []*ast.File
	for _, filename := range filenames {
		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
		if err != nil {
			// the parser error may be a list of individual errors; report them all
			if list, ok := err.(scanner.ErrorList); ok {
				for _, err := range list {
					t.Error(err)
				}
				return
			}
			t.Error(err)
			return
		}

		if *verbose {
			if len(files) == 0 {
				fmt.Println("package", file.Name.Name)
			}
			fmt.Println("\t", filename)
		}

		files = append(files, file)
	}

	// typecheck package files
	var conf Config
	conf.Error = func(err error) { t.Error(err) }
	conf.Check(path, fset, files, nil)
	pkgCount++
}

// pkgfiles returns the list of package files for the given directory.
func pkgfiles(t *testing.T, dir string) []string {
	ctxt := build.Default
	ctxt.CgoEnabled = false
	pkg, err := ctxt.ImportDir(dir, 0)
	if err != nil {
		if _, nogo := err.(*build.NoGoError); !nogo {
			t.Error(err)
		}
		return nil
	}
	if excluded[pkg.ImportPath] {
		return nil
	}
	var filenames []string
	for _, name := range pkg.GoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	for _, name := range pkg.TestGoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	return filenames
}

// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
//       necessarily be shorter or clearer after adding the code to
//       terminate early for -short tests.

func walkDirs(t *testing.T, dir string) {
	// limit run time for short tests
	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
		return
	}

	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Error(err)
		return
	}

	// typecheck package in directory
	if files := pkgfiles(t, dir); files != nil {
		typecheck(t, dir, files)
	}

	// traverse subdirectories, but don't walk into testdata
	for _, fi := range fis {
		if fi.IsDir() && fi.Name() != "testdata" {
			walkDirs(t, filepath.Join(dir, fi.Name()))
		}
	}
}
<|endoftext|>