<commit_before>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

package parse

import (
	"code.google.com/p/go.text/unicode/norm"
	"github.com/demizer/go-elog"
	"strings"
	"unicode"
	"unicode/utf8"
)

type Id int

func (i Id) IdNumber() Id { return i }

// The line number of an item in the input string
type Line int

func (l Line) LineNumber() Line { return l }

// The begining location of an item in the input.
type StartPosition int

func (s StartPosition) Position() StartPosition { return s }

// itemElement are the types that are emitted by the lexer.
type itemElement int

const (
	itemEOF itemElement = iota
	itemError
	itemTitle
	itemSectionAdornment
	itemParagraph
	itemBlockquote
	itemLiteralBlock
	itemSystemMessage
	itemSpace
	itemBlankLine
)

var elements = [...]string{
	"itemEOF",
	"itemError",
	"itemTitle",
	"itemSectionAdornment",
	"itemParagraph",
	"itemBlockquote",
	"itemLiteralBlock",
	"itemSystemMessage",
	"itemSpace",
	"itemBlankLine",
}

// String implements the Stringer interface for printing itemElement types.
func (t itemElement) String() string { return elements[t] }

func (t *itemElement) UnmarshalJSON(data []byte) error {
	for num, elm := range elements {
		if elm == string(data[1:len(data)-1]) {
			*t = itemElement(num)
		}
	}
	return nil
}

// Valid section adornment runes
var sectionAdornments = []rune{'!', '"', '#', '$', '\'', '%', '&', '(', ')', '*',
	'+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\',
	']', '^', '_', '`', '{', '|', '}', '~'}

// Emitted by the lexer on End of File
const eof rune = -1

// Function prototype for scanner functions
type stateFn func(*lexer) stateFn

// Struct for tokens emitted by the scanning process
type item struct {
	Id            `json:"id"`
	Type          itemElement `json:"type"`
	Text          interface{} `json:"text"`
	Line          `json:"line"`
	StartPosition `json:"startPosition"`
	Length        int `json:"length"`
}

// The lexer struct tracks the state of the lexer
type lexer struct {
	name             string    // The name of the current lexer
	input            string    // The input text
	state            stateFn   // The current state of the lexer
	index            int       // Position in input
	start            int       // The start of the current token
	width            int       // The width of the current position
	items            chan item // The channel items are emitted to
	lastItem         *item     // The last item emitted to the channel
	lastItemPosition StartPosition
	id               int // Unique id for each item emitted
}

// lex is the entry point of the lexer
func lex(name, input string) *lexer {
	log.Debugln("Start")
	if !norm.NFC.IsNormalString(input) {
		input = norm.NFC.String(input)
	}
	l := &lexer{
		name:  name,
		input: input,
		items: make(chan item),
	}
	go l.run()
	log.Debugln("End")
	return l
}

// run is the engine of the lexing process.
func (l *lexer) run() {
	log.Debugln("Start")
	for l.state = lexStart; l.state != nil; {
		l.state = l.state(l)
	}
	log.Debugln("End")
}

// emit passes an item back to the client.
func (l *lexer) emit(t itemElement) {
	if l.start == l.index && int(l.index) < len(l.input) {
		l.index += 1
	}
	log.Infof("#### %s: %q start: %d pos: %d line: %d\n", t,
		l.input[l.start:l.index], l.start, l.index, l.lineNumber())
	l.id++
	length := utf8.RuneCountInString(l.input[l.start:l.index])
	nItem := item{
		Id:            Id(l.id),
		Type:          t,
		Text:          l.input[l.start:l.index],
		Line:          Line(l.lineNumber()),
		StartPosition: StartPosition(l.start + 1),
		Length:        length,
	}
	l.items <- nItem
	l.lastItem = &nItem
	l.start = l.index
}

// backup backs up the lexer by one position using the width of the last rune retrieved from the
// input.
func (l *lexer) backup() {
	l.index -= l.width
}

// current returns the rune at the current position in the input.
func (l *lexer) current() rune {
	r, _ := utf8.DecodeRuneInString(l.input[l.index:])
	return r
}

// peek looks ahead in the input by one position and returns the rune.
func (l *lexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}

// advance fast forwards the lexer to the next rune in the input specified by "to".
func (l *lexer) advance(to rune) {
	for {
		if l.next() == eof || to == l.current() {
			break
		}
	}
}

// next advances the position of the lexer by one rune and returns that rune.
func (l *lexer) next() rune {
	if int(l.index) >= len(l.input) {
		log.Debugln("Reached eof!")
		l.width = 0
		return eof
	}
	r, w := utf8.DecodeRuneInString(l.input[l.index:])
	l.width = w
	l.index += l.width
	if unicode.In(r, unicode.Diacritic) {
		log.Debugf("DIACRITIC char found: %#U width: %d\n", r, w)
	}
	log.Debugf("cur: %q start: %d pos: %d\n", r, l.start, l.index)
	return r
}

// nextItem returns the next item from the input.
func (l *lexer) nextItem() *item {
	item := <-l.items
	l.lastItemPosition = item.StartPosition
	return &item

}

func (l *lexer) lineNumber() int {
	return strings.Count(l.input[:l.index-1], "\n") + 1
}

// isSpace reports whether r is a space character.
func isSpace(r rune) bool {
	return r == ' ' || r == '\t' || r == '\n' || r == '\r'
}

// isEndOfLine reports whether r is an end-of-line character.
func isEndOfLine(r rune) bool {
	return r == '\r' || r == '\n'
}

// isSection compares a number of positions (skipping whitespace) to
// determine if the runes are sectionAdornments and returns a true if the
// positions match each other. Rune comparison begins at the current lexer
// position. isSection returns false if there is a blank line between the
// positions or if there is a rune mismatch between positions.
func isSection(l *lexer) bool {
	log.Debugln("Start")
	var lookPositions = 2
	var lastAdornment rune
	var newLineNum int
	var runePositions []rune
	var matchCount int
	cPos := l.index

	exit := func(value bool) bool {
		l.index = cPos
		log.Debugln("Returning", value)
		return value
	}

	log.Debugln("Looking ahead", lookPositions, "position(s) for sectionAdornments...")

	// Check two runes to see if they are section adornments, if not, we will check the next
	// line (after whitespace).
	if isSectionAdornment(l.current()) && isSectionAdornment(l.peek()) &&
		l.current() == l.peek() {
		return true
	}

	// Advance to the end of the line
	l.advance('\n')
	if l.current() == eof {
		log.Debugln("Found eof, returning false.")
		return false
	}

	for j := 0; j < lookPositions; j++ {
		for isSpace(l.current()) {
			if isEndOfLine(l.current()) {
				if newLineNum == 1 {
					log.Debugln("Too many newlines!")
					return exit(false)
				}
				newLineNum += 1
				log.Debugln("newLineNum:", newLineNum)
			}
			if l.next() == eof {
				return exit(false)
			}
		}
		if isSectionAdornment(l.current()) {
			log.Debugf("Found adornment: \"%s\" pos: %d\n", string(l.current()), l.index)
			if lastAdornment != 0 && l.current() != lastAdornment {
				log.Debugf("Adornment mismatch, last: %s current: %s\n",
					string(lastAdornment), string(l.current()))
				return exit(false)
			}
			runePositions = append(runePositions, l.current())
			lastAdornment = l.current()
			matchCount += 1
		}
		if l.next() == eof {
			return exit(false)
		}
	}

	if len(runePositions) == 0 || matchCount != lookPositions {
		return exit(false)
	}

	return exit(true)
}

// isSectionAdornment returns true if r matches a section adornment.
func isSectionAdornment(r rune) bool {
	for _, a := range sectionAdornments {
		if a == r {
			return true
		}
	}
	return false
}

// lexStart is the first stateFn called by run(). From here other stateFn's are called depending on
// the input. When this function returns nil, the lexing is finished and run() will exit.
func lexStart(l *lexer) stateFn {
	log.Debugln("Start")
	for {
		var tokenLength = l.index - l.start
		r := l.current()
		if tokenLength == l.width && !isEndOfLine(r) {
			log.Debugln("Start of new token")
			if isSpace(r) {
				return lexSpace
			} else if isSection(l) {
				return lexSection
			} else if isEndOfLine(r) {
				l.emit(itemBlankLine)
				l.start += 1
			}
		} else if isEndOfLine(r) {
			log.Debugln("isEndOfLine == true")
			if l.index > l.start {
				l.emit(itemParagraph)
				l.start += 1 // Skip the new line
			} else if l.start == l.index {
				l.emit(itemBlankLine)
			}
		}
		if l.next() == eof {
			break
		}
	}

	// Correctly reached eof.
	if l.index > l.start {
		l.emit(itemParagraph)
	}

	l.emit(itemEOF)
	log.Debugln("End")
	return nil
}

// lexSpace consumes space characters (space and tab) in the input and emits a itemSpace token.
func lexSpace(l *lexer) stateFn {
	log.Debugln("Start")
	for isSpace(l.current()) {
		l.next()
	}
	if l.start < l.index {
		l.emit(itemSpace)
		l.next()
	}
	log.Debugln("End")
	return lexStart
}

// lexSection is used after isSection() has determined that the next runes of input are section.
// From here, the lexTitle() and lexSectionAdornment() are called based on the input.
func lexSection(l *lexer) stateFn {
	log.Debugln("Start")
	// The order of the case statement matter here
	switch r := l.next(); {
	case isSectionAdornment(r):
		if l.lastItem.Type != itemTitle {
			return lexSectionAdornment
		}
		lexSectionAdornment(l)
	case isSpace(r):
		return lexSpace
	case unicode.IsPrint(r):
		return lexTitle
	case isEndOfLine(r):
		l.start += 1
	}
	log.Debugln("Exit")
	return lexStart
}

// lexTitle consumes input until newline and emits an itemTitle token. Once the token is emitted,
// control is returned to lexSection().
func lexTitle(l *lexer) stateFn {
	log.Debugln("Start")
	for {
		l.next()
		if l.peek() == '\n' {
			l.emit(itemTitle)
			l.start += 1
			l.index += 1
			break
		}
	}
	log.Debugln("End")
	return lexSection
}

// lexSectionAdornment advances the lexer until a newline is encountered and emits a
// itemSectionAdornment token. Control is returned to lexSection() on completion.
func lexSectionAdornment(l *lexer) stateFn {
	log.Debugln("Start")
	for {
		//TODO: Add adornment rune check
		l.next()
		if l.peek() == '\n' {
			l.emit(itemSectionAdornment)
			l.start += 1
			l.index += 1
			break
		}
	}
	log.Debugln("End")
	return lexSection
}
<commit_msg>lex.go: Add isStartOfLine()<commit_after>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

package parse

import (
	"code.google.com/p/go.text/unicode/norm"
	"github.com/demizer/go-elog"
	"strings"
	"unicode"
	"unicode/utf8"
)

type Id int

func (i Id) IdNumber() Id { return i }

// The line number of an item in the input string
type Line int

func (l Line) LineNumber() Line { return l }

// The begining location of an item in the input.
type StartPosition int

func (s StartPosition) Position() StartPosition { return s }

// itemElement are the types that are emitted by the lexer.
type itemElement int

const (
	itemEOF itemElement = iota
	itemError
	itemTitle
	itemSectionAdornment
	itemParagraph
	itemBlockquote
	itemLiteralBlock
	itemSystemMessage
	itemSpace
	itemBlankLine
)

var elements = [...]string{
	"itemEOF",
	"itemError",
	"itemTitle",
	"itemSectionAdornment",
	"itemParagraph",
	"itemBlockquote",
	"itemLiteralBlock",
	"itemSystemMessage",
	"itemSpace",
	"itemBlankLine",
}

// String implements the Stringer interface for printing itemElement types.
func (t itemElement) String() string { return elements[t] }

func (t *itemElement) UnmarshalJSON(data []byte) error {
	for num, elm := range elements {
		if elm == string(data[1:len(data)-1]) {
			*t = itemElement(num)
		}
	}
	return nil
}

// Valid section adornment runes
var sectionAdornments = []rune{'!', '"', '#', '$', '\'', '%', '&', '(', ')', '*',
	'+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\',
	']', '^', '_', '`', '{', '|', '}', '~'}

// Emitted by the lexer on End of File
const eof rune = -1

// Function prototype for scanner functions
type stateFn func(*lexer) stateFn

// Struct for tokens emitted by the scanning process
type item struct {
	Id            `json:"id"`
	Type          itemElement `json:"type"`
	Text          interface{} `json:"text"`
	Line          `json:"line"`
	StartPosition `json:"startPosition"`
	Length        int `json:"length"`
}

// The lexer struct tracks the state of the lexer
type lexer struct {
	name             string    // The name of the current lexer
	input            string    // The input text
	state            stateFn   // The current state of the lexer
	index            int       // Position in input
	start            int       // The start of the current token
	width            int       // The width of the current position
	items            chan item // The channel items are emitted to
	lastItem         *item     // The last item emitted to the channel
	lastItemPosition StartPosition
	id               int // Unique id for each item emitted
}

// lex is the entry point of the lexer
func lex(name, input string) *lexer {
	log.Debugln("Start")
	if !norm.NFC.IsNormalString(input) {
		input = norm.NFC.String(input)
	}
	l := &lexer{
		name:  name,
		input: input,
		items: make(chan item),
	}
	go l.run()
	log.Debugln("End")
	return l
}

// run is the engine of the lexing process.
func (l *lexer) run() {
	log.Debugln("Start")
	for l.state = lexStart; l.state != nil; {
		l.state = l.state(l)
	}
	log.Debugln("End")
}

// emit passes an item back to the client.
func (l *lexer) emit(t itemElement) {
	if l.start == l.index && int(l.index) < len(l.input) {
		l.index += 1
	}
	log.Infof("#### %s: %q start: %d pos: %d line: %d\n", t,
		l.input[l.start:l.index], l.start, l.index, l.lineNumber())
	l.id++
	length := utf8.RuneCountInString(l.input[l.start:l.index])
	nItem := item{
		Id:            Id(l.id),
		Type:          t,
		Text:          l.input[l.start:l.index],
		Line:          Line(l.lineNumber()),
		StartPosition: StartPosition(l.start + 1),
		Length:        length,
	}
	l.items <- nItem
	l.lastItem = &nItem
	l.start = l.index
}

// backup backs up the lexer by one position using the width of the last rune retrieved from the
// input.
func (l *lexer) backup() {
	l.index -= l.width
}

// current returns the rune at the current position in the input.
func (l *lexer) current() rune {
	r, _ := utf8.DecodeRuneInString(l.input[l.index:])
	return r
}

// peek looks ahead in the input by one position and returns the rune.
func (l *lexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}

// advance fast forwards the lexer to the next rune in the input specified by "to".
func (l *lexer) advance(to rune) {
	for {
		if l.next() == eof || to == l.current() {
			break
		}
	}
}

// next advances the position of the lexer by one rune and returns that rune.
func (l *lexer) next() rune {
	if int(l.index) >= len(l.input) {
		log.Debugln("Reached eof!")
		l.width = 0
		return eof
	}
	r, w := utf8.DecodeRuneInString(l.input[l.index:])
	l.width = w
	l.index += l.width
	if unicode.In(r, unicode.Diacritic) {
		log.Debugf("DIACRITIC char found: %#U width: %d\n", r, w)
	}
	log.Debugf("cur: %q start: %d pos: %d\n", r, l.start, l.index)
	return r
}

// nextItem returns the next item from the input.
func (l *lexer) nextItem() *item {
	item := <-l.items
	l.lastItemPosition = item.StartPosition
	return &item

}

func (l *lexer) lineNumber() int {
	return strings.Count(l.input[:l.index-1], "\n") + 1
}

func (l *lexer) isStartOfLine() bool {
	return (l.index - l.start - l.width) == 1
}

// isSpace reports whether r is a space character.
func isSpace(r rune) bool {
	return r == ' ' || r == '\t' || r == '\n' || r == '\r'
}

// isEndOfLine reports whether r is an end-of-line character.
func isEndOfLine(r rune) bool {
	return r == '\r' || r == '\n'
}

// isSection compares a number of positions (skipping whitespace) to
// determine if the runes are sectionAdornments and returns a true if the
// positions match each other. Rune comparison begins at the current lexer
// position. isSection returns false if there is a blank line between the
// positions or if there is a rune mismatch between positions.
func isSection(l *lexer) bool {
	log.Debugln("Start")
	var lookPositions = 2
	var lastAdornment rune
	var newLineNum int
	var runePositions []rune
	var matchCount int
	cPos := l.index

	exit := func(value bool) bool {
		l.index = cPos
		log.Debugln("Returning", value)
		return value
	}

	log.Debugln("Looking ahead", lookPositions, "position(s) for sectionAdornments...")

	// Check two runes to see if they are section adornments, if not, we will check the next
	// line (after whitespace).
	if isSectionAdornment(l.current()) && isSectionAdornment(l.peek()) &&
		l.current() == l.peek() {
		return true
	}

	// Advance to the end of the line
	l.advance('\n')
	if l.current() == eof {
		log.Debugln("Found eof, returning false.")
		return false
	}

	for j := 0; j < lookPositions; j++ {
		for isSpace(l.current()) {
			if isEndOfLine(l.current()) {
				if newLineNum == 1 {
					log.Debugln("Too many newlines!")
					return exit(false)
				}
				newLineNum += 1
				log.Debugln("newLineNum:", newLineNum)
			}
			if l.next() == eof {
				return exit(false)
			}
		}
		if isSectionAdornment(l.current()) {
			log.Debugf("Found adornment: \"%s\" pos: %d\n", string(l.current()), l.index)
			if lastAdornment != 0 && l.current() != lastAdornment {
				log.Debugf("Adornment mismatch, last: %s current: %s\n",
					string(lastAdornment), string(l.current()))
				return exit(false)
			}
			runePositions = append(runePositions, l.current())
			lastAdornment = l.current()
			matchCount += 1
		}
		if l.next() == eof {
			return exit(false)
		}
	}

	if len(runePositions) == 0 || matchCount != lookPositions {
		return exit(false)
	}

	return exit(true)
}

// isSectionAdornment returns true if r matches a section adornment.
func isSectionAdornment(r rune) bool {
	for _, a := range sectionAdornments {
		if a == r {
			return true
		}
	}
	return false
}

// lexStart is the first stateFn called by run(). From here other stateFn's are called depending on
// the input. When this function returns nil, the lexing is finished and run() will exit.
func lexStart(l *lexer) stateFn {
	log.Debugln("Start")
	for {
		var tokenLength = l.index - l.start
		r := l.current()
		if tokenLength == l.width && !isEndOfLine(r) {
			log.Debugln("Start of new token")
			if isSpace(r) {
				return lexSpace
			} else if isSection(l) {
				return lexSection
			} else if isEndOfLine(r) {
				l.emit(itemBlankLine)
				l.start += 1
			}
		} else if isEndOfLine(r) {
			log.Debugln("isEndOfLine == true")
			if l.index > l.start {
				l.emit(itemParagraph)
				l.start += 1 // Skip the new line
			} else if l.start == l.index {
				l.emit(itemBlankLine)
			}
		}
		if l.next() == eof {
			break
		}
	}

	// Correctly reached eof.
	if l.index > l.start {
		l.emit(itemParagraph)
	}

	l.emit(itemEOF)
	log.Debugln("End")
	return nil
}

// lexSpace consumes space characters (space and tab) in the input and emits a itemSpace token.
func lexSpace(l *lexer) stateFn {
	log.Debugln("Start")
	for isSpace(l.current()) {
		l.next()
	}
	if l.start < l.index {
		l.emit(itemSpace)
		l.next()
	}
	log.Debugln("End")
	return lexStart
}

// lexSection is used after isSection() has determined that the next runes of input are section.
// From here, the lexTitle() and lexSectionAdornment() are called based on the input.
func lexSection(l *lexer) stateFn {
	log.Debugln("Start")
	// The order of the case statement matter here
	switch r := l.next(); {
	case isSectionAdornment(r):
		if l.lastItem.Type != itemTitle {
			return lexSectionAdornment
		}
		lexSectionAdornment(l)
	case isSpace(r):
		return lexSpace
	case unicode.IsPrint(r):
		return lexTitle
	case isEndOfLine(r):
		l.start += 1
	}
	log.Debugln("Exit")
	return lexStart
}

// lexTitle consumes input until newline and emits an itemTitle token. Once the token is emitted,
// control is returned to lexSection().
func lexTitle(l *lexer) stateFn {
	log.Debugln("Start")
	for {
		if isSpace(l.current()) && l.isStartOfLine() {
			return lexSpace
		}
		l.next()
		if l.peek() == '\n' {
			l.emit(itemTitle)
			l.start += 1
			l.index += 1
			break
		}
	}
	log.Debugln("End")
	return lexSection
}

// lexSectionAdornment advances the lexer until a newline is encountered and emits a
// itemSectionAdornment token. Control is returned to lexSection() on completion.
func lexSectionAdornment(l *lexer) stateFn {
	log.Debugln("Start")
	for {
		//TODO: Add adornment rune check
		l.next()
		if l.peek() == '\n' {
			l.emit(itemSectionAdornment)
			l.start += 1
			l.index += 1
			break
		}
	}
	log.Debugln("End")
	return lexSection
}
<|endoftext|>


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

import (
	"github.com/Comcast/webpa-common/health"
	"github.com/Comcast/webpa-common/webhook"
	"github.com/go-kit/kit/metrics"
	"github.com/stretchr/testify/mock"
	"net/http"
	"time"
)

// mockHandler only needs to mock the `HandleRequest` method
type mockHandler struct {
	mock.Mock
}

func (m *mockHandler) HandleRequest(workerID int, inRequest CaduceusRequest) {
	m.Called(workerID, inRequest)
}

// mockHealthTracker needs to mock things from both the `HealthTracker`
// interface as well as the `health.Monitor` interface
type mockHealthTracker struct {
	mock.Mock
}

func (m *mockHealthTracker) SendEvent(healthFunc health.HealthFunc) {
	m.Called(healthFunc)
}

func (m *mockHealthTracker) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	m.Called(response, request)
}

func (m *mockHealthTracker) IncrementBucket(inSize int) {
	m.Called(inSize)
}

// mockOutboundSender needs to mock things that the `OutboundSender` does
type mockOutboundSender struct {
	mock.Mock
}

func (m *mockOutboundSender) Extend(until time.Time) {
	m.Called(until)
}

func (m *mockOutboundSender) Shutdown(gentle bool) {
	m.Called(gentle)
}

func (m *mockOutboundSender) RetiredSince() time.Time {
	arguments := m.Called()
	return arguments.Get(0).(time.Time)
}

func (m *mockOutboundSender) QueueJSON(req CaduceusRequest, eventType, deviceID, transID string) {
	m.Called(req, eventType, deviceID, transID)
}

func (m *mockOutboundSender) QueueWrp(req CaduceusRequest, metaData map[string]string, eventType, deviceID, transID string) {
	m.Called(req, metaData, eventType, deviceID, transID)
}

// mockSenderWrapper needs to mock things that the `SenderWrapper` does
type mockSenderWrapper struct {
	mock.Mock
}

func (m *mockSenderWrapper) Update(list []webhook.W) {
	m.Called(list)
}

func (m *mockSenderWrapper) Queue(req CaduceusRequest) {
	m.Called(req)
}

func (m *mockSenderWrapper) Shutdown(gentle bool) {
	m.Called(gentle)
}

// mockServerProfiler needs to mock things that the `ServerProfiler` does
type mockServerProfiler struct {
	mock.Mock
}

func (m *mockServerProfiler) Send(inData interface{}) error {
	arguments := m.Called(inData)
	return arguments.Error(0)
}

func (m *mockServerProfiler) Report() (values []interface{}) {
	arguments := m.Called()
	if arguments.Get(0) == nil {
		return nil
	}

	return arguments.Get(0).([]interface{})
}

func (m *mockServerProfiler) Close() {
	m.Called()
}

// mockCounter provides the mock implementation of the metrics.Counter object
type mockCounter struct {
	mock.Mock
}

func (m *mockCounter) Add(delta float64) {
	m.Called(delta)
}

func (m *mockCounter) With(labelValues ...string) metrics.Counter {
	args := m.Called(labelValues)
	return args.Get(0).(metrics.Counter)
}

// mockGauge provides the mock implementation of the metrics.Counter object
type mockGauge struct {
	mock.Mock
}

func (m *mockGauge) Add(delta float64) {
	m.Called(delta)
}

func (m *mockGauge) Set(value float64) {
	m.Called(value)
}

func (m *mockGauge) With(labelValues ...string) metrics.Gauge {
	args := m.Called(labelValues)
	return args.Get(0).(metrics.Gauge)
}

// mockCaduceusMetricsRegistry provides the mock implementation of the
// CaduceusMetricsRegistry  object
type mockCaduceusMetricsRegistry struct {
	mock.Mock
}

func (m *mockCaduceusMetricsRegistry) NewCounter(name string) metrics.Counter {
	args := m.Called(name)
	return args.Get(0).(metrics.Counter)
}

func (m *mockCaduceusMetricsRegistry) NewGauge(name string) metrics.Gauge {
	args := m.Called(name)
	return args.Get(0).(metrics.Gauge)
}
<commit_msg>Remove some dead test code.<commit_after>/**
 * Copyright 2017 Comcast Cable Communications Management, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package main

import (
	"github.com/Comcast/webpa-common/health"
	"github.com/Comcast/webpa-common/webhook"
	"github.com/go-kit/kit/metrics"
	"github.com/stretchr/testify/mock"
	"net/http"
	"time"
)

// mockHandler only needs to mock the `HandleRequest` method
type mockHandler struct {
	mock.Mock
}

func (m *mockHandler) HandleRequest(workerID int, inRequest CaduceusRequest) {
	m.Called(workerID, inRequest)
}

// mockHealthTracker needs to mock things from both the `HealthTracker`
// interface as well as the `health.Monitor` interface
type mockHealthTracker struct {
	mock.Mock
}

func (m *mockHealthTracker) SendEvent(healthFunc health.HealthFunc) {
	m.Called(healthFunc)
}

func (m *mockHealthTracker) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	m.Called(response, request)
}

func (m *mockHealthTracker) IncrementBucket(inSize int) {
	m.Called(inSize)
}

// mockOutboundSender needs to mock things that the `OutboundSender` does
type mockOutboundSender struct {
	mock.Mock
}

func (m *mockOutboundSender) Extend(until time.Time) {
	m.Called(until)
}

func (m *mockOutboundSender) Shutdown(gentle bool) {
	m.Called(gentle)
}

func (m *mockOutboundSender) RetiredSince() time.Time {
	arguments := m.Called()
	return arguments.Get(0).(time.Time)
}

func (m *mockOutboundSender) QueueJSON(req CaduceusRequest, eventType, deviceID, transID string) {
	m.Called(req, eventType, deviceID, transID)
}

func (m *mockOutboundSender) QueueWrp(req CaduceusRequest, metaData map[string]string, eventType, deviceID, transID string) {
	m.Called(req, metaData, eventType, deviceID, transID)
}

// mockSenderWrapper needs to mock things that the `SenderWrapper` does
type mockSenderWrapper struct {
	mock.Mock
}

func (m *mockSenderWrapper) Update(list []webhook.W) {
	m.Called(list)
}

func (m *mockSenderWrapper) Queue(req CaduceusRequest) {
	m.Called(req)
}

func (m *mockSenderWrapper) Shutdown(gentle bool) {
	m.Called(gentle)
}

// mockCounter provides the mock implementation of the metrics.Counter object
type mockCounter struct {
	mock.Mock
}

func (m *mockCounter) Add(delta float64) {
	m.Called(delta)
}

func (m *mockCounter) With(labelValues ...string) metrics.Counter {
	args := m.Called(labelValues)
	return args.Get(0).(metrics.Counter)
}

// mockGauge provides the mock implementation of the metrics.Counter object
type mockGauge struct {
	mock.Mock
}

func (m *mockGauge) Add(delta float64) {
	m.Called(delta)
}

func (m *mockGauge) Set(value float64) {
	m.Called(value)
}

func (m *mockGauge) With(labelValues ...string) metrics.Gauge {
	args := m.Called(labelValues)
	return args.Get(0).(metrics.Gauge)
}

// mockCaduceusMetricsRegistry provides the mock implementation of the
// CaduceusMetricsRegistry  object
type mockCaduceusMetricsRegistry struct {
	mock.Mock
}

func (m *mockCaduceusMetricsRegistry) NewCounter(name string) metrics.Counter {
	args := m.Called(name)
	return args.Get(0).(metrics.Counter)
}

func (m *mockCaduceusMetricsRegistry) NewGauge(name string) metrics.Gauge {
	args := m.Called(name)
	return args.Get(0).(metrics.Gauge)
}
<|endoftext|>


<commit_before>package app

import (
	"encoding/xml"
	"fmt"
	stdlog "log"
	"math"
	"net/http"
	"sync"

	"github.com/go-martini/martini"
	"github.com/orofarne/hmetrics2"

	"program_version"
	"servicestatus"
)

type xmlstatusLogger struct {
}

func (self *xmlstatusLogger) Write(p []byte) (n int, err error) {
	log.Debug("%s", p)
	return len(p), nil
}

func CreateXMLStatusHandler() http.Handler {
	m := martini.Classic()

	var mu sync.Mutex
	var data = make(map[string]float64)
	hmetrics2.AddHook(func(newData map[string]float64) {
		mu.Lock()
		defer mu.Unlock()
		data = make(map[string]float64)
		for k, v := range newData {
			if !math.IsNaN(v) && !math.IsInf(v, 0) {
				data[k] = v
			}
		}
	})

	var logger xmlstatusLogger
	m.Map(stdlog.New(&logger, "[martini] ", stdlog.LstdFlags))

	m.Get("/mon", func() string {
		return servicestatus.GetString()
	})

	m.Get("/version", func() string {
		return program_version.GetVersion()
	})

	m.Get("/config", func(w http.ResponseWriter) {
		w.Header().Add("Content-type", "application/json")
		w.Write([]byte(App.Config()))
	})

	m.Get("/stat", func(w http.ResponseWriter) {
		mu.Lock()
		defer mu.Unlock()
		w.Header().Add("Content-type", "text/xml")
		w.Write([]byte(xml.Header))
		w.Write([]byte("<stat>\n"))
		for k, v := range data {
			w.Write([]byte(fmt.Sprintf("    <%s>%v</%s>\n", k, v, k)))
		}
		w.Write([]byte("</stat>\n"))
	})

	return m
}
<commit_msg>xmlstatus: correct /stat<commit_after>package app

import (
	"encoding/xml"
	"fmt"
	stdlog "log"
	"math"
	"net/http"
	"os"
	"sync"
	"time"

	"github.com/go-martini/martini"
	"github.com/orofarne/hmetrics2"

	"program_version"
	"servicestatus"
)

var startTime time.Time

type xmlstatusLogger struct {
}

func init() {
	startTime = time.Now()
}

func (self *xmlstatusLogger) Write(p []byte) (n int, err error) {
	log.Debug("%s", p)
	return len(p), nil
}

func CreateXMLStatusHandler() http.Handler {
	m := martini.Classic()

	var mu sync.Mutex
	var data = make(map[string]float64)
	hmetrics2.AddHook(func(newData map[string]float64) {
		mu.Lock()
		defer mu.Unlock()
		data = make(map[string]float64)
		for k, v := range newData {
			if !math.IsNaN(v) && !math.IsInf(v, 0) {
				data[k] = v
			}
		}
	})

	var logger xmlstatusLogger
	m.Map(stdlog.New(&logger, "[martini] ", stdlog.LstdFlags))

	m.Get("/mon", func() string {
		return servicestatus.GetString()
	})

	m.Get("/version", func() string {
		return program_version.GetVersion()
	})

	m.Get("/config", func(w http.ResponseWriter) {
		w.Header().Add("Content-type", "application/json")
		w.Write([]byte(App.Config()))
	})

	m.Get("/stat", func(w http.ResponseWriter) {
		mu.Lock()
		defer mu.Unlock()
		w.Header().Add("Content-type", "application/xml")
		w.Write([]byte(xml.Header))
		w.Write([]byte(fmt.Sprintf("<stat:document xmlns:stat=\"http://xml.sputnik.ru/stat\" name=\"%v\" version=\"%v\">\n", os.Args[0], program_version.GetVersion())))
		w.Write([]byte(fmt.Sprintf("  <stat>\n    <start_time>%v</start_time>\n  </stat>\n", startTime)))
		w.Write([]byte("  <user>\n"))
		for k, v := range data {
			w.Write([]byte(fmt.Sprintf("    <%s>%v</%s>\n", k, v, k)))
		}
		w.Write([]byte("  </user>\n"))
		w.Write([]byte("</stat:document>\n"))
	})

	return m
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"reflect"
	"strings"
	"text/template"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/radeksimko/terraform-gen/schemagen"

	api "k8s.io/kubernetes/pkg/api/v1"
)

type schemaGen struct {
	Obj          interface{}
	Filename     string
	VariableName string
}

func main() {
	pkgName := "kubernetes"
	schemas := []schemaGen{
		{
			Obj:          &api.VolumeSource{},
			Filename:     "volume_source_schema.go",
			VariableName: "volumeSourceSchema",
		},
		{
			Obj:          &api.PodSpec{},
			Filename:     "pod_spec_schema.go",
			VariableName: "podSpecSchema",
		},
		// resources
		{
			Obj:          &api.Pod{},
			Filename:     "pod_schema.go",
			VariableName: "podSchema",
		},
		{
			Obj:          &api.Service{},
			Filename:     "service_schema.go",
			VariableName: "serviceSchema",
		},
		{
			Obj:          &api.ReplicationController{},
			Filename:     "replication_controller_schema.go",
			VariableName: "replicationControllerSchema",
		},
		{
			Obj:          &api.Namespace{},
			Filename:     "namespace_schema.go",
			VariableName: "namespaceSchema",
		},
	}

	for _, s := range schemas {
		log.Printf("Generating %q...\n", s.Filename)
		f, err := os.Create(s.Filename)
		defer f.Close()
		if err != nil {
			log.Fatal(err)
		}

		sg := &schemagen.SchemaGenerator{DocsFunc: docsFunc, FilterFunc: filterFunc}
		fields := sg.FromStruct(s.Obj)

		err = podTemplate.Execute(f, struct {
			PkgName      string
			VariableName string
			Fields       map[string]string
		}{
			PkgName:      pkgName,
			VariableName: s.VariableName,
			Fields:       fields,
		})
		if err != nil {
			log.Fatal(err)
		}
	}
}

func docsFunc(iface interface{}, sf *reflect.StructField) string {
	tag := sf.Tag
	jsonTag := strings.Split(tag.Get("json"), ",")
	jsonName := jsonTag[0]

	docs, err := getSwaggerDocs(iface, sf, jsonName)
	if err != nil {
		log.Printf("Docs not found: %s", err)
	}
	return docs
}

func filterFunc(iface interface{}, sf *reflect.StructField, s *schema.Schema) bool {
	tag := sf.Tag
	jsonTag := strings.Split(tag.Get("json"), ",")
	jsonName := jsonTag[0]

	if jsonName == "-" {
		return false
	}

	t := reflect.TypeOf(iface)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	if t.String() == "v1.Time" {
		log.Printf("Ignoring time field - %q\n", sf.Name)
		return false
	}

	// Pod
	if (t.String() == "v1.Pod" && sf.Name == "Status") ||
		(t.String() == "v1.Pod" && sf.Name == "PodSpec") ||
		(t.String() == "v1.Volume" && sf.Name == "VolumeSource") {
		log.Printf("Ignoring %q -> %q (will be implemented as data source)", t.String(), sf.Name)
		return false
	}
	// Service
	if t.String() == "v1.Service" && sf.Name == "Status" {
		log.Printf("Ignoring %q -> %q (will be implemented as data source)", t.String(), sf.Name)
		return false
	}
	// ReplicationController
	if (t.String() == "v1.PodTemplateSpec" && sf.Name == "Spec") ||
		(t.String() == "v1.ReplicationController" && sf.Name == "Status") {
		log.Printf("Ignoring %q -> %q (will be implemented as data source)", t.String(), sf.Name)
		return false
	}

	docs, err := getSwaggerDocs(iface, sf, jsonName)
	if err != nil {
		return true
	}

	if strings.Contains(docs, "Deprecated:") {
		log.Printf("Ignoring %q (deprecated)\n", sf.Name)
		return false
	}
	if strings.Contains(docs, "NOT YET IMPLEMENTED.") {
		log.Printf("Ignoring %q (not implemented)\n", sf.Name)
		return false
	}

	if strings.Contains(docs, "Read-only.") {
		s.Computed = true
	} else {
		if strings.Contains(docs, "Required.") {
			s.Required = true
		} else {
			s.Optional = true
		}
	}

	if strings.Contains(docs, "Cannot be updated.") {
		s.ForceNew = true
	}

	return true
}

func getSwaggerDocs(iface interface{}, sf *reflect.StructField, jsonName string) (string, error) {
	structType := reflect.TypeOf(iface)
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}

	val := reflect.New(structType).Elem()
	method := val.MethodByName("SwaggerDoc")
	if method.IsValid() {
		out := method.Call([]reflect.Value{})
		m := out[0]
		docs := m.MapIndex(reflect.ValueOf(jsonName))
		if !docs.IsValid() {
			docs = m.MapIndex(reflect.ValueOf(""))
		}
		return docs.String(), nil
	}
	return "", fmt.Errorf("Docs not found for %q (%s)", sf.Name, sf.Type.String())
}

var podTemplate = template.Must(template.New("pod").Parse(`package {{.PkgName}}

import (
	"github.com/hashicorp/terraform/helper/schema"
)

var {{.VariableName}} = map[string]*schema.Schema{
{{range $name, $schema := .Fields}}
	"{{ $name }}": {{ $schema }},{{end}}
}
`))
<commit_msg>example: Improve k8s example<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"reflect"
	"strings"
	"text/template"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/radeksimko/terraform-gen/schemagen"

	api "k8s.io/kubernetes/pkg/api/v1"
)

type schemaGen struct {
	Obj          interface{}
	Filename     string
	VariableName string
}

func main() {
	pkgName := "kubernetes"
	schemas := []schemaGen{
		{
			Obj:          &api.PodSpec{},
			Filename:     "pod_spec_schema.go",
			VariableName: "podSpecSchema",
		},
	}

	for _, s := range schemas {
		log.Printf("Generating %q...\n", s.Filename)
		f, err := os.Create(s.Filename)
		defer f.Close()
		if err != nil {
			log.Fatal(err)
		}

		sg := &schemagen.SchemaGenerator{DocsFunc: docsFunc, FilterFunc: filterFunc}
		fields := sg.FromStruct(s.Obj)

		err = podTemplate.Execute(f, struct {
			PkgName      string
			VariableName string
			Fields       map[string]string
		}{
			PkgName:      pkgName,
			VariableName: s.VariableName,
			Fields:       fields,
		})
		if err != nil {
			log.Fatal(err)
		}
	}
}

func docsFunc(iface interface{}, sf *reflect.StructField) string {
	tag := sf.Tag
	jsonTag := strings.Split(tag.Get("json"), ",")
	jsonName := jsonTag[0]

	docs, err := getSwaggerDocs(iface, sf, jsonName)
	if err != nil {
		log.Printf("Docs not found: %s", err)
	}
	return docs
}

func filterFunc(iface interface{}, sf *reflect.StructField, kind reflect.Kind, s *schema.Schema) (reflect.Kind, bool) {
	tag := sf.Tag
	jsonTag := strings.Split(tag.Get("json"), ",")
	jsonName := jsonTag[0]

	if jsonName == "-" {
		return kind, false
	}

	t := reflect.TypeOf(iface)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	if sf.Type.String() == "v1.Time" {
		log.Printf("Converting %s field to TypeString - %q\n", sf.Type.String(), sf.Name)
		return reflect.String, true
	}

	if sf.Type.String() == "resource.Quantity" {
		log.Printf("Converting %s field to TypeInt - %q\n", sf.Type.String(), sf.Name)
		return reflect.Int, true
	}

	if sf.Type.String() == "intstr.IntOrString" {
		log.Printf("Converting %s field to TypeInt - %q\n", sf.Type.String(), sf.Name)
		return reflect.Int, true
	}

	// Pod
	if (t.String() == "v1.Pod" && sf.Name == "Status") ||
		(t.String() == "v1.Pod" && sf.Name == "PodSpec") ||
		(t.String() == "v1.Volume" && sf.Name == "VolumeSource") {
		log.Printf("Ignoring %q -> %q (will be implemented as data source)", t.String(), sf.Name)
		return kind, false
	}
	// Service
	if t.String() == "v1.Service" && sf.Name == "Status" {
		log.Printf("Ignoring %q -> %q (will be implemented as data source)", t.String(), sf.Name)
		return kind, false
	}
	// ReplicationController
	if (t.String() == "v1.PodTemplateSpec" && sf.Name == "Spec") ||
		(t.String() == "v1.ReplicationController" && sf.Name == "Status") {
		log.Printf("Ignoring %q -> %q (will be implemented as data source)", t.String(), sf.Name)
		return kind, false
	}

	docs, err := getSwaggerDocs(iface, sf, jsonName)
	if err != nil {
		return kind, true
	}

	if strings.Contains(docs, "Deprecated:") {
		log.Printf("Ignoring %q (deprecated)\n", sf.Name)
		return kind, false
	}
	if strings.Contains(docs, "NOT YET IMPLEMENTED.") {
		log.Printf("Ignoring %q (not implemented)\n", sf.Name)
		return kind, false
	}

	if strings.Contains(docs, "Read-only.") {
		s.Computed = true
	} else {
		if strings.Contains(docs, "Required.") || strings.Contains(docs, "Required:") {
			s.Required = true
		} else {
			s.Optional = true
		}
	}

	if strings.Contains(docs, "Cannot be updated.") {
		s.ForceNew = true
	}

	return kind, true
}

func getSwaggerDocs(iface interface{}, sf *reflect.StructField, jsonName string) (string, error) {
	structType := reflect.TypeOf(iface)
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}

	val := reflect.New(structType).Elem()
	method := val.MethodByName("SwaggerDoc")
	if method.IsValid() {
		out := method.Call([]reflect.Value{})
		m := out[0]
		docs := m.MapIndex(reflect.ValueOf(jsonName))
		if !docs.IsValid() {
			docs = m.MapIndex(reflect.ValueOf(""))
		}
		return docs.String(), nil
	}
	return "", fmt.Errorf("Docs not found for %s -> %s (%s)", structType.Name(), sf.Name, sf.Type.String())
}

var podTemplate = template.Must(template.New("pod").Parse(`package {{.PkgName}}

import (
	"github.com/hashicorp/terraform/helper/schema"
)

var {{.VariableName}} = map[string]*schema.Schema{
{{range $name, $schema := .Fields}}
	"{{ $name }}": {{ $schema }},{{end}}
}
`))
<|endoftext|>


<commit_before>package babble

import (
	"fmt"
	"os"
	"time"

	"github.com/mosaicnetworks/babble/src/config"
	"github.com/mosaicnetworks/babble/src/crypto/keys"
	h "github.com/mosaicnetworks/babble/src/hashgraph"
	"github.com/mosaicnetworks/babble/src/net"
	"github.com/mosaicnetworks/babble/src/net/signal/wamp"
	"github.com/mosaicnetworks/babble/src/node"
	"github.com/mosaicnetworks/babble/src/peers"
	"github.com/mosaicnetworks/babble/src/service"
	"github.com/sirupsen/logrus"
)

// Babble is a struct containing the key parts of a babble node
type Babble struct {
	Config       *config.Config
	Node         *node.Node
	Transport    net.Transport
	Store        h.Store
	Peers        *peers.PeerSet
	GenesisPeers *peers.PeerSet
	Service      *service.Service
	logger       *logrus.Entry
}

// NewBabble is a factory method to produce
// a Babble instance.
func NewBabble(c *config.Config) *Babble {
	engine := &Babble{
		Config: c,
		logger: c.Logger(),
	}

	return engine
}

// Init initialises the babble engine
func (b *Babble) Init() error {

	b.logger.Debug("validateConfig")
	if err := b.validateConfig(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() validateConfig")
	}

	b.logger.Debug("initKey")
	if err := b.initKey(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initKey")
		return err
	}

	b.logger.Debug("initPeers")
	if err := b.initPeers(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initPeers")
		return err
	}

	b.logger.Debug("initStore")
	if err := b.initStore(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initStore")
		return err
	}

	b.logger.Debug("initTransport")
	if err := b.initTransport(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initTransport")
		return err
	}

	b.logger.Debug("initNode")
	if err := b.initNode(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initNode")
		return err
	}

	b.logger.Debug("initService")
	if err := b.initService(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initService")
		return err
	}

	return nil
}

// Run starts the Babble Node running
func (b *Babble) Run() {
	if b.Service != nil && b.Config.ServiceAddr != "" {
		go b.Service.Serve()
	}

	b.Node.Run(true)
}

func (b *Babble) validateConfig() error {
	// If --datadir was explicitely set, but not --db, the following line will
	// update the default database dir to be inside the new datadir
	b.Config.SetDataDir(b.Config.DataDir)

	logFields := logrus.Fields{
		"babble.DataDir":          b.Config.DataDir,
		"babble.BindAddr":         b.Config.BindAddr,
		"babble.AdvertiseAddr":    b.Config.AdvertiseAddr,
		"babble.ServiceAddr":      b.Config.ServiceAddr,
		"babble.NoService":        b.Config.NoService,
		"babble.MaxPool":          b.Config.MaxPool,
		"babble.Store":            b.Config.Store,
		"babble.LoadPeers":        b.Config.LoadPeers,
		"babble.LogLevel":         b.Config.LogLevel,
		"babble.Moniker":          b.Config.Moniker,
		"babble.HeartbeatTimeout": b.Config.HeartbeatTimeout,
		"babble.TCPTimeout":       b.Config.TCPTimeout,
		"babble.JoinTimeout":      b.Config.JoinTimeout,
		"babble.CacheSize":        b.Config.CacheSize,
		"babble.SyncLimit":        b.Config.SyncLimit,
		"babble.EnableFastSync":   b.Config.EnableFastSync,
		"babble.MaintenanceMode":  b.Config.MaintenanceMode,
		"babble.SuspendLimit":     b.Config.SuspendLimit,
	}

	// Maintenance-mode only works with bootstrap
	if b.Config.MaintenanceMode {
		b.logger.Debug("Config --maintenance-mode => --bootstrap")
		b.Config.Bootstrap = true
	}

	// Bootstrap only works with store
	if b.Config.Bootstrap {
		b.logger.Debug("Config --boostrap => --store")
		b.Config.Store = true
	}

	if b.Config.Store {
		logFields["babble.DatabaseDir"] = b.Config.DatabaseDir
		logFields["babble.Bootstrap"] = b.Config.Bootstrap
	}

	// SlowHeartbeat cannot be less than Heartbeat
	if b.Config.SlowHeartbeatTimeout < b.Config.HeartbeatTimeout {
		b.logger.Debugf("SlowHeartbeatTimeout (%v) cannot be less than Heartbeat (%v)",
			b.Config.SlowHeartbeatTimeout,
			b.Config.HeartbeatTimeout)
		b.Config.SlowHeartbeatTimeout = b.Config.HeartbeatTimeout
	}
	logFields["babble.SlowHeartbeatTimeout"] = b.Config.SlowHeartbeatTimeout

	b.logger.WithFields(logFields).Debug("Config")

	return nil
}

func (b *Babble) initTransport() error {
	// XXX
	if b.Config.WebRTC {
		fmt.Println("XXX init webrtc, with signal addr ", b.Config.SignalAddr)
		signal, err := wamp.NewClient(
			b.Config.SignalAddr,
			"office", // XXX
			keys.PublicKeyHex(&b.Config.Key.PublicKey)) //XXX

		if err != nil {
			fmt.Println("XXX wtf")
			return err
		}

		webRTCTransport, err := net.NewWebRTCTransport(
			signal,
			1,
			time.Second,
			2*time.Second,
			b.logger.WithField("component", "signal_client"))

		if err != nil {
			return err
		}

		b.Transport = webRTCTransport
	} else {
		tcpTransport, err := net.NewTCPTransport(
			b.Config.BindAddr,
			b.Config.AdvertiseAddr,
			b.Config.MaxPool,
			b.Config.TCPTimeout,
			b.Config.JoinTimeout,
			b.Config.Logger(),
		)

		if err != nil {
			return err
		}

		b.Transport = tcpTransport
	}

	return nil
}

func (b *Babble) initPeers() error {
	if !b.Config.LoadPeers {
		if b.Peers == nil {
			return fmt.Errorf("LoadPeers false, but babble.Peers is nil")
		}

		if b.GenesisPeers == nil {
			return fmt.Errorf("LoadPeers false, but babble.GenesisPeers is nil")
		}

		b.logger.Debug("LoadPeers is false. Skipped loading peers.")
		return nil
	}

	peerStore := peers.NewJSONPeerSet(b.Config.DataDir, true)

	participants, err := peerStore.PeerSet()
	if err != nil {
		return err
	}

	b.Peers = participants

	b.logger.Debug("Loaded Peers")
	//	b.logger.WithField("*participants", *participants).Info("Created Peers")

	// Set Genesis Peer Set from peers.genesis.json
	genesisPeerStore := peers.NewJSONPeerSet(b.Config.DataDir, false)

	genesisParticipants, err := genesisPeerStore.PeerSet()
	if err != nil { // If there is any error, the current peer set is used as the genesis peer set
		b.logger.Debugf("could not read peers.genesis.json: %v", err)
		b.GenesisPeers = participants
	} else {
		b.GenesisPeers = genesisParticipants
	}

	return nil
}

func (b *Babble) initStore() error {
	if !b.Config.Store {
		b.logger.Debug("Creating InmemStore")
		b.Store = h.NewInmemStore(b.Config.CacheSize)
	} else {
		dbPath := b.Config.DatabaseDir

		b.logger.WithField("path", dbPath).Debug("Creating BadgerStore")

		if !b.Config.Bootstrap {
			b.logger.Debug("No Bootstrap")

			backup := backupFileName(dbPath)

			err := os.Rename(dbPath, backup)

			if err != nil {
				if !os.IsNotExist(err) {
					return err
				}
				b.logger.Debug("Nothing to backup")
			} else {
				b.logger.WithField("path", backup).Debug("Created backup")
			}
		}

		b.logger.WithField("path", dbPath).Debug("Opening BadgerStore")

		dbStore, err := h.NewBadgerStore(
			b.Config.CacheSize,
			dbPath,
			b.Config.MaintenanceMode,
			b.logger)
		if err != nil {
			return err
		}

		b.Store = dbStore
	}

	return nil
}

func (b *Babble) initKey() error {
	if b.Config.Key == nil {
		simpleKeyfile := keys.NewSimpleKeyfile(b.Config.Keyfile())

		privKey, err := simpleKeyfile.ReadKey()
		if err != nil {
			b.logger.Errorf("Error reading private key from file: %v", err)
		}

		b.Config.Key = privKey
	}
	return nil
}

func (b *Babble) initNode() error {

	validator := node.NewValidator(b.Config.Key, b.Config.Moniker)

	p, ok := b.Peers.ByID[validator.ID()]
	if ok {
		if p.Moniker != validator.Moniker {
			b.logger.WithFields(logrus.Fields{
				"json_moniker": p.Moniker,
				"cli_moniker":  validator.Moniker,
			}).Debugf("Using moniker from peers.json file")
			validator.Moniker = p.Moniker
		}
	}

	b.Config.Logger().WithFields(logrus.Fields{
		"genesis_peers": len(b.GenesisPeers.Peers),
		"peers":         len(b.Peers.Peers),
		"id":            validator.ID(),
		"moniker":       validator.Moniker,
	}).Debug("PARTICIPANTS")

	b.Node = node.NewNode(
		b.Config,
		validator,
		b.Peers,
		b.GenesisPeers,
		b.Store,
		b.Transport,
		b.Config.Proxy,
	)

	return b.Node.Init()
}

func (b *Babble) initService() error {
	if !b.Config.NoService {
		b.Service = service.NewService(b.Config.ServiceAddr, b.Node, b.Config.Logger())
	}
	return nil
}

// backupFileName implements the naming convention for database backups:
// badger_db--UTC--<created_at UTC ISO8601>
func backupFileName(base string) string {
	ts := time.Now().UTC()
	return fmt.Sprintf("%s--UTC--%s", base, toISO8601(ts))
}

func toISO8601(t time.Time) string {
	var tz string
	name, offset := t.Zone()
	if name == "UTC" {
		tz = "Z"
	} else {
		tz = fmt.Sprintf("%03d00", offset/3600)
	}
	return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s",
		t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz)
}
<commit_msg>Temporary hardcoded timeouts for webrtc transport<commit_after>package babble

import (
	"fmt"
	"os"
	"time"

	"github.com/mosaicnetworks/babble/src/config"
	"github.com/mosaicnetworks/babble/src/crypto/keys"
	h "github.com/mosaicnetworks/babble/src/hashgraph"
	"github.com/mosaicnetworks/babble/src/net"
	"github.com/mosaicnetworks/babble/src/net/signal/wamp"
	"github.com/mosaicnetworks/babble/src/node"
	"github.com/mosaicnetworks/babble/src/peers"
	"github.com/mosaicnetworks/babble/src/service"
	"github.com/sirupsen/logrus"
)

// Babble is a struct containing the key parts of a babble node
type Babble struct {
	Config       *config.Config
	Node         *node.Node
	Transport    net.Transport
	Store        h.Store
	Peers        *peers.PeerSet
	GenesisPeers *peers.PeerSet
	Service      *service.Service
	logger       *logrus.Entry
}

// NewBabble is a factory method to produce
// a Babble instance.
func NewBabble(c *config.Config) *Babble {
	engine := &Babble{
		Config: c,
		logger: c.Logger(),
	}

	return engine
}

// Init initialises the babble engine
func (b *Babble) Init() error {

	b.logger.Debug("validateConfig")
	if err := b.validateConfig(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() validateConfig")
	}

	b.logger.Debug("initKey")
	if err := b.initKey(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initKey")
		return err
	}

	b.logger.Debug("initPeers")
	if err := b.initPeers(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initPeers")
		return err
	}

	b.logger.Debug("initStore")
	if err := b.initStore(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initStore")
		return err
	}

	b.logger.Debug("initTransport")
	if err := b.initTransport(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initTransport")
		return err
	}

	b.logger.Debug("initNode")
	if err := b.initNode(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initNode")
		return err
	}

	b.logger.Debug("initService")
	if err := b.initService(); err != nil {
		b.logger.WithError(err).Error("babble.go:Init() initService")
		return err
	}

	return nil
}

// Run starts the Babble Node running
func (b *Babble) Run() {
	if b.Service != nil && b.Config.ServiceAddr != "" {
		go b.Service.Serve()
	}

	b.Node.Run(true)
}

func (b *Babble) validateConfig() error {
	// If --datadir was explicitely set, but not --db, the following line will
	// update the default database dir to be inside the new datadir
	b.Config.SetDataDir(b.Config.DataDir)

	logFields := logrus.Fields{
		"babble.DataDir":          b.Config.DataDir,
		"babble.BindAddr":         b.Config.BindAddr,
		"babble.AdvertiseAddr":    b.Config.AdvertiseAddr,
		"babble.ServiceAddr":      b.Config.ServiceAddr,
		"babble.NoService":        b.Config.NoService,
		"babble.MaxPool":          b.Config.MaxPool,
		"babble.Store":            b.Config.Store,
		"babble.LoadPeers":        b.Config.LoadPeers,
		"babble.LogLevel":         b.Config.LogLevel,
		"babble.Moniker":          b.Config.Moniker,
		"babble.HeartbeatTimeout": b.Config.HeartbeatTimeout,
		"babble.TCPTimeout":       b.Config.TCPTimeout,
		"babble.JoinTimeout":      b.Config.JoinTimeout,
		"babble.CacheSize":        b.Config.CacheSize,
		"babble.SyncLimit":        b.Config.SyncLimit,
		"babble.EnableFastSync":   b.Config.EnableFastSync,
		"babble.MaintenanceMode":  b.Config.MaintenanceMode,
		"babble.SuspendLimit":     b.Config.SuspendLimit,
	}

	// Maintenance-mode only works with bootstrap
	if b.Config.MaintenanceMode {
		b.logger.Debug("Config --maintenance-mode => --bootstrap")
		b.Config.Bootstrap = true
	}

	// Bootstrap only works with store
	if b.Config.Bootstrap {
		b.logger.Debug("Config --boostrap => --store")
		b.Config.Store = true
	}

	if b.Config.Store {
		logFields["babble.DatabaseDir"] = b.Config.DatabaseDir
		logFields["babble.Bootstrap"] = b.Config.Bootstrap
	}

	// SlowHeartbeat cannot be less than Heartbeat
	if b.Config.SlowHeartbeatTimeout < b.Config.HeartbeatTimeout {
		b.logger.Debugf("SlowHeartbeatTimeout (%v) cannot be less than Heartbeat (%v)",
			b.Config.SlowHeartbeatTimeout,
			b.Config.HeartbeatTimeout)
		b.Config.SlowHeartbeatTimeout = b.Config.HeartbeatTimeout
	}
	logFields["babble.SlowHeartbeatTimeout"] = b.Config.SlowHeartbeatTimeout

	b.logger.WithFields(logFields).Debug("Config")

	return nil
}

func (b *Babble) initTransport() error {
	// XXX
	if b.Config.WebRTC {
		fmt.Println("XXX init webrtc, with signal addr ", b.Config.SignalAddr)
		signal, err := wamp.NewClient(
			b.Config.SignalAddr,
			"office", // XXX
			keys.PublicKeyHex(&b.Config.Key.PublicKey)) //XXX

		if err != nil {
			fmt.Println("XXX wtf")
			return err
		}

		// XXX
		webRTCTransport, err := net.NewWebRTCTransport(
			signal,
			10,
			20*time.Second,
			20*time.Second,
			b.logger.WithField("component", "signal_client"))

		if err != nil {
			return err
		}

		b.Transport = webRTCTransport
	} else {
		tcpTransport, err := net.NewTCPTransport(
			b.Config.BindAddr,
			b.Config.AdvertiseAddr,
			b.Config.MaxPool,
			b.Config.TCPTimeout,
			b.Config.JoinTimeout,
			b.Config.Logger(),
		)

		if err != nil {
			return err
		}

		b.Transport = tcpTransport
	}

	return nil
}

func (b *Babble) initPeers() error {
	if !b.Config.LoadPeers {
		if b.Peers == nil {
			return fmt.Errorf("LoadPeers false, but babble.Peers is nil")
		}

		if b.GenesisPeers == nil {
			return fmt.Errorf("LoadPeers false, but babble.GenesisPeers is nil")
		}

		b.logger.Debug("LoadPeers is false. Skipped loading peers.")
		return nil
	}

	peerStore := peers.NewJSONPeerSet(b.Config.DataDir, true)

	participants, err := peerStore.PeerSet()
	if err != nil {
		return err
	}

	b.Peers = participants

	b.logger.Debug("Loaded Peers")
	//	b.logger.WithField("*participants", *participants).Info("Created Peers")

	// Set Genesis Peer Set from peers.genesis.json
	genesisPeerStore := peers.NewJSONPeerSet(b.Config.DataDir, false)

	genesisParticipants, err := genesisPeerStore.PeerSet()
	if err != nil { // If there is any error, the current peer set is used as the genesis peer set
		b.logger.Debugf("could not read peers.genesis.json: %v", err)
		b.GenesisPeers = participants
	} else {
		b.GenesisPeers = genesisParticipants
	}

	return nil
}

func (b *Babble) initStore() error {
	if !b.Config.Store {
		b.logger.Debug("Creating InmemStore")
		b.Store = h.NewInmemStore(b.Config.CacheSize)
	} else {
		dbPath := b.Config.DatabaseDir

		b.logger.WithField("path", dbPath).Debug("Creating BadgerStore")

		if !b.Config.Bootstrap {
			b.logger.Debug("No Bootstrap")

			backup := backupFileName(dbPath)

			err := os.Rename(dbPath, backup)

			if err != nil {
				if !os.IsNotExist(err) {
					return err
				}
				b.logger.Debug("Nothing to backup")
			} else {
				b.logger.WithField("path", backup).Debug("Created backup")
			}
		}

		b.logger.WithField("path", dbPath).Debug("Opening BadgerStore")

		dbStore, err := h.NewBadgerStore(
			b.Config.CacheSize,
			dbPath,
			b.Config.MaintenanceMode,
			b.logger)
		if err != nil {
			return err
		}

		b.Store = dbStore
	}

	return nil
}

func (b *Babble) initKey() error {
	if b.Config.Key == nil {
		simpleKeyfile := keys.NewSimpleKeyfile(b.Config.Keyfile())

		privKey, err := simpleKeyfile.ReadKey()
		if err != nil {
			b.logger.Errorf("Error reading private key from file: %v", err)
		}

		b.Config.Key = privKey
	}
	return nil
}

func (b *Babble) initNode() error {

	validator := node.NewValidator(b.Config.Key, b.Config.Moniker)

	p, ok := b.Peers.ByID[validator.ID()]
	if ok {
		if p.Moniker != validator.Moniker {
			b.logger.WithFields(logrus.Fields{
				"json_moniker": p.Moniker,
				"cli_moniker":  validator.Moniker,
			}).Debugf("Using moniker from peers.json file")
			validator.Moniker = p.Moniker
		}
	}

	b.Config.Logger().WithFields(logrus.Fields{
		"genesis_peers": len(b.GenesisPeers.Peers),
		"peers":         len(b.Peers.Peers),
		"id":            validator.ID(),
		"moniker":       validator.Moniker,
	}).Debug("PARTICIPANTS")

	b.Node = node.NewNode(
		b.Config,
		validator,
		b.Peers,
		b.GenesisPeers,
		b.Store,
		b.Transport,
		b.Config.Proxy,
	)

	return b.Node.Init()
}

func (b *Babble) initService() error {
	if !b.Config.NoService {
		b.Service = service.NewService(b.Config.ServiceAddr, b.Node, b.Config.Logger())
	}
	return nil
}

// backupFileName implements the naming convention for database backups:
// badger_db--UTC--<created_at UTC ISO8601>
func backupFileName(base string) string {
	ts := time.Now().UTC()
	return fmt.Sprintf("%s--UTC--%s", base, toISO8601(ts))
}

func toISO8601(t time.Time) string {
	var tz string
	name, offset := t.Zone()
	if name == "UTC" {
		tz = "Z"
	} else {
		tz = fmt.Sprintf("%03d00", offset/3600)
	}
	return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s",
		t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz)
}
<|endoftext|>


<commit_before>package main

import "testing"
//import "runtime"
import "strconv"
import "barista"
//import "os"
import "time"
import "fmt"
import "math/rand"
import "git.apache.org/thrift.git/lib/go/thrift"
import "handler"

var BINARY_PORTS = []string {":9021", ":9022", ":9023", ":9024", ":9025"}
var ADDRS = []string {"128.52.161.243", "128.52.161.243", "128.52.161.243", "128.52.161.243", "128.52.161.243"}
var ADDRS_WITH_PORTS = []string {"128.52.161.243:9021", "128.52.161.243:9022", "128.52.161.243:9023",
  "128.52.161.243:9024", "128.52.161.243:9025"}
var PG_PORTS = []string {"5434", "5435", "5436", "5437", "5438"}
var SP_PORTS = []string {":9011", ":9012", ":9013", ":9014", ":9015"}

func StartServer(me int) {
  binary_protocol_factory := thrift.NewTBinaryProtocolFactoryDefault()
  transport_factory := thrift.NewTTransportFactory()

  binary_transport, err := thrift.NewTServerSocket(ADDRS[me] + BINARY_PORTS[me])

  if err != nil {
    fmt.Println("Error opening socket: ", err)
    return
  }

  handler := handler.NewBaristaHandler(ADDRS, me, PG_PORTS, SP_PORTS)
  processor := barista.NewBaristaProcessor(handler)
  binary_server := thrift.NewTSimpleServer4(processor, binary_transport, transport_factory, binary_protocol_factory)

  fmt.Println("Starting the Barista server (Binary Mode) on ", ADDRS[me] + BINARY_PORTS[me])
  go binary_server.Serve()
}

func TestBasic(t *testing.T) {
  const nservers = 5

  // store the addresses of the servers
  var kvh []string = make([]string, nservers)
  // initialize the addresses

  //var kva []*TSimpleServer = make([]*TSimpleServer, nservers)

  for i := 0; i < nservers; i++ {
  	// start servers on the various machines
    StartServer(i)
  }

  ck := MakeClerk()
  var cka [nservers]*Clerk
  for i := 0; i < nservers; i++ {
    cka[i] = MakeClerk() // this no longer stores all the servers
  }

  fmt.Printf("Test: Basic open/execute/close ...\n")

  con, err := ck.OpenConnection(ADDRS_WITH_PORTS)
  if err != nil {
  	t.Fatalf("Error opening connection:", err)
  } else if con == nil {
  	t.Fatalf("Error nil connection returned by open:", err)
  }

  _, err = ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
      "CREATE TABLE IF NOT EXISTS sqlpaxos_test (key text, value text)", nil)
  if err != nil {
    t.Fatalf("Error creating table:", err)
    return
  }

  // count number of rows in the table
  res, err := ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
  	"select count(*) from sqlpaxos_test", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  for _, tuple := range *(res.Tuples) {
    for _, cell := range *(tuple.Cells) {
      if "0" != string(cell[:]) {
      	t.Fatalf("Table should be empty: %s", cell)
      }
    }
  }

  // insert item into table
  key := "a"
  val := "100"
  res, err = ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
  	"INSERT INTO sqlpaxos_test VALUES ('"+ key +"', '" +
  		val +"')", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  // retrieve old item from table
  res, err = ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
  	"select value from sqlpaxos_test where key='" + key +
  	"'", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  Print_result_set(res)

  if res != nil && res.Tuples != nil {
    for _, tuple := range *(res.Tuples) {
      for _, cell := range *(tuple.Cells) {
        if val != string(cell[:]) {
          t.Fatalf("Table should be empty: %s", cell)
        }
      }
    }
  }

  err = ck.CloseConnection(ADDRS_WITH_PORTS, con)
	if err != nil {
  	t.Fatalf("Error closing connection:", err)
  }

  fmt.Printf("  ... Passed\n")
  return

  fmt.Printf("Test: Concurrent clients ...\n")

  for iters := 0; iters < 20; iters++ {
    const npara = 15
    var ca [npara]chan bool
    for nth := 0; nth < npara; nth++ {
      ca[nth] = make(chan bool)
      go func(me int) {
        defer func() { ca[me] <- true }()
        ci := (rand.Int() % nservers)
        myck := MakeClerk()
        con, err := ck.OpenConnection(ADDRS_WITH_PORTS)
    		if err != nil {
    		  t.Fatalf("Error opening connection:", err)
    		} else if con == nil {
    		  t.Fatalf("Error nil connection returned by open:", err)
    		}
        if (rand.Int() % 1000) < 500 {
          // insert
          res, err := ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
  			  "insert into sqlpaxos_test values ('"+ key + "', '" +
  		    strconv.Itoa(rand.Int()) +"')", nil)
    		  if err != nil || res == nil {
    		  	t.Fatalf("Error querying table:", err)
    		  }
  		  } else {
          // retrieve old item from table
    		  res, err = ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
    		  	"select value from sqlpaxos_test where key='" + key +
    		  	  "'", nil)
    		  if err != nil || res == nil {
    		  	t.Fatalf("Error querying table:", err)
    		  }
        }
        err = ck.CloseConnection(ADDRS_WITH_PORTS, con)
    		if err != nil {
    		  t.Fatalf("Error closing connection:", err)
    		}
      }(nth)
    }

    for nth := 0; nth < npara; nth++ {
      <- ca[nth]
    }

    var va [nservers]string
    for i := 0; i < nservers; i++ {
	  res, err := ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
	  	"select value from sqlpaxos_test where key='" + key +
	  	  "'", nil)
	  if err != nil || res == nil {
	  	t.Fatalf("Error querying table:", err)
	  }
	  for _, tuple := range *(res.Tuples) {
        for _, cell := range *(tuple.Cells) {
          va[i] = string(cell[:])
    	}
      }

      if va[i] != va[0] {
        t.Fatalf("mismatch")
      }
    }
  }

  fmt.Printf("  ... Passed\n")

  time.Sleep(1 * time.Second)
}

<commit_msg>test fixes<commit_after>package main

import "testing"
//import "runtime"
import "strconv"
import "barista"
//import "os"
import "time"
import "fmt"
import "math/rand"
import "git.apache.org/thrift.git/lib/go/thrift"
import "handler"

var BINARY_PORTS = []string {":9021", ":9022", ":9023", ":9024", ":9025"}
var ADDRS = []string {"128.52.161.243", "128.52.161.243", "128.52.161.243", "128.52.161.243", "128.52.161.243"}
var ADDRS_WITH_PORTS = []string {"128.52.161.243:9021", "128.52.161.243:9022", "128.52.161.243:9023",
  "128.52.161.243:9024", "128.52.161.243:9025"}
var PG_PORTS = []string {"5434", "5435", "5436", "5437", "5438"}
var SP_PORTS = []string {":9011", ":9012", ":9013", ":9014", ":9015"}

func StartServer(me int) {
  binary_protocol_factory := thrift.NewTBinaryProtocolFactoryDefault()
  transport_factory := thrift.NewTTransportFactory()

  binary_transport, err := thrift.NewTServerSocket(ADDRS[me] + BINARY_PORTS[me])

  if err != nil {
    fmt.Println("Error opening socket: ", err)
    return
  }

  handler := handler.NewBaristaHandler(ADDRS, me, PG_PORTS, SP_PORTS)
  processor := barista.NewBaristaProcessor(handler)
  binary_server := thrift.NewTSimpleServer4(processor, binary_transport, transport_factory, binary_protocol_factory)

  fmt.Println("Starting the Barista server (Binary Mode) on ", ADDRS[me] + BINARY_PORTS[me])
  go binary_server.Serve()
}

func TestBasic(t *testing.T) {
  const nservers = 5

  // store the addresses of the servers
  //var kvh []string = make([]string, nservers)
  // initialize the addresses

  //var kva []*TSimpleServer = make([]*TSimpleServer, nservers)

  for i := 0; i < nservers; i++ {
  	// start servers on the various machines
    StartServer(i)
  }

  ck := MakeClerk()
  var cka [nservers]*Clerk
  for i := 0; i < nservers; i++ {
    cka[i] = MakeClerk() // this no longer stores all the servers
  }

  fmt.Printf("Test: Basic open/execute/close ...\n")

  con, err := ck.OpenConnection(ADDRS_WITH_PORTS)
  if err != nil {
  	t.Fatalf("Error opening connection:", err)
  } else if con == nil {
  	t.Fatalf("Error nil connection returned by open:", err)
  }

  _, err = ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
      "CREATE TABLE IF NOT EXISTS sqlpaxos_test (key text, value text)", nil)
  if err != nil {
    t.Fatalf("Error creating table:", err)
    return
  }

  // count number of rows in the table
  res, err := ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
  	"select count(*) from sqlpaxos_test", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  for _, tuple := range *(res.Tuples) {
    for _, cell := range *(tuple.Cells) {
      if "0" != string(cell[:]) {
      	t.Fatalf("Table should be empty: %s", cell)
      }
    }
  }

  // insert item into table
  key := "a"
  val := "100"
  res, err = ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
  	"INSERT INTO sqlpaxos_test VALUES ('"+ key +"', '" +
  		val +"')", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  // retrieve old item from table
  res, err = ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
  	"select value from sqlpaxos_test where key='" + key +
  	"'", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  Print_result_set(res)

  if res != nil && res.Tuples != nil {
    for _, tuple := range *(res.Tuples) {
      for _, cell := range *(tuple.Cells) {
        if val != string(cell[:]) {
          t.Fatalf("Table should be empty: %s", cell)
        }
      }
    }
  }

  err = ck.CloseConnection(ADDRS_WITH_PORTS, con)
	if err != nil {
  	t.Fatalf("Error closing connection:", err)
  }

  fmt.Printf("  ... Passed\n")
  return

  fmt.Printf("Test: Concurrent clients ...\n")

  for iters := 0; iters < 20; iters++ {
    const npara = 15
    var ca [npara]chan bool
    for nth := 0; nth < npara; nth++ {
      ca[nth] = make(chan bool)
      go func(me int) {
        defer func() { ca[me] <- true }()
        //ci := (rand.Int() % nservers)
        //myck := MakeClerk()
        con, err := ck.OpenConnection(ADDRS_WITH_PORTS)
    		if err != nil {
    		  t.Fatalf("Error opening connection:", err)
    		} else if con == nil {
    		  t.Fatalf("Error nil connection returned by open:", err)
    		}
        if (rand.Int() % 1000) < 500 {
          // insert
          res, err := ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
  			  "insert into sqlpaxos_test values ('"+ key + "', '" +
  		    strconv.Itoa(rand.Int()) +"')", nil)
    		  if err != nil || res == nil {
    		  	t.Fatalf("Error querying table:", err)
    		  }
  		  } else {
          // retrieve old item from table
    		  res, err = ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
    		  	"select value from sqlpaxos_test where key='" + key +
    		  	  "'", nil)
    		  if err != nil || res == nil {
    		  	t.Fatalf("Error querying table:", err)
    		  }
        }
        err = ck.CloseConnection(ADDRS_WITH_PORTS, con)
    		if err != nil {
    		  t.Fatalf("Error closing connection:", err)
    		}
      }(nth)
    }

    for nth := 0; nth < npara; nth++ {
      <- ca[nth]
    }

    var va [nservers]string
    for i := 0; i < nservers; i++ {
	  res, err := ck.ExecuteSQL(ADDRS_WITH_PORTS, con,
	  	"select value from sqlpaxos_test where key='" + key +
	  	  "'", nil)
	  if err != nil || res == nil {
	  	t.Fatalf("Error querying table:", err)
	  }
	  for _, tuple := range *(res.Tuples) {
        for _, cell := range *(tuple.Cells) {
          va[i] = string(cell[:])
    	}
      }

      if va[i] != va[0] {
        t.Fatalf("mismatch")
      }
    }
  }

  fmt.Printf("  ... Passed\n")

  time.Sleep(1 * time.Second)
}

<|endoftext|>


<commit_before>/*
   Copyright 2014 Outbrain Inc.

   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 os

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"

	"vitess.io/vitess/go/vt/orchestrator/config"
	"vitess.io/vitess/go/vt/orchestrator/external/golib/log"
)

var EmptyEnv = []string{}

// CommandRun executes some text as a command. This is assumed to be
// text that will be run by a shell so we need to write out the
// command to a temporary file and then ask the shell to execute
// it, after which the temporary file is removed.
func CommandRun(commandText string, env []string, arguments ...string) error {
	// show the actual command we have been asked to run
	log.Infof("CommandRun(%v,%+v)", commandText, arguments)

	cmd, shellScript, err := generateShellScript(commandText, env, arguments...)
	defer os.Remove(shellScript)
	if err != nil {
		return log.Errore(err)
	}

	var waitStatus syscall.WaitStatus

	log.Infof("CommandRun/running: %s", strings.Join(cmd.Args, " "))
	cmdOutput, err := cmd.CombinedOutput()
	log.Infof("CommandRun: %s\n", string(cmdOutput))
	if err != nil {
		// Did the command fail because of an unsuccessful exit code
		if exitError, ok := err.(*exec.ExitError); ok {
			waitStatus = exitError.Sys().(syscall.WaitStatus)
			log.Errorf("CommandRun: failed. exit status %d", waitStatus.ExitStatus())
		}

		return log.Errore(fmt.Errorf("(%s) %s", err.Error(), cmdOutput))
	}

	// Command was successful
	waitStatus = cmd.ProcessState.Sys().(syscall.WaitStatus)
	log.Infof("CommandRun successful. exit status %d", waitStatus.ExitStatus())

	return nil
}

// generateShellScript generates a temporary shell script based on
// the given command to be executed, writes the command to a temporary
// file and returns the exec.Command which can be executed together
// with the script name that was created.
func generateShellScript(commandText string, env []string, arguments ...string) (*exec.Cmd, string, error) {
	shell := config.Config.ProcessesShellCommand

	commandBytes := []byte(commandText)
	tmpFile, err := os.CreateTemp("", "orchestrator-process-cmd-")
	if err != nil {
		return nil, "", log.Errorf("generateShellScript() failed to create TempFile: %v", err.Error())
	}
	// write commandText to temporary file
	os.WriteFile(tmpFile.Name(), commandBytes, 0640)
	shellArguments := append([]string{}, tmpFile.Name())
	shellArguments = append(shellArguments, arguments...)

	cmd := exec.Command(shell, shellArguments...)
	cmd.Env = env

	return cmd, tmpFile.Name(), nil
}
<commit_msg>refactor: fix lint issues in os package<commit_after>/*
   Copyright 2014 Outbrain Inc.

   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 os

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"

	"vitess.io/vitess/go/vt/orchestrator/config"
	"vitess.io/vitess/go/vt/orchestrator/external/golib/log"
)

var EmptyEnv []string

// CommandRun executes some text as a command. This is assumed to be
// text that will be run by a shell so we need to write out the
// command to a temporary file and then ask the shell to execute
// it, after which the temporary file is removed.
func CommandRun(commandText string, env []string, arguments ...string) error {
	// show the actual command we have been asked to run
	log.Infof("CommandRun(%v,%+v)", commandText, arguments)

	cmd, shellScript, err := generateShellScript(commandText, env, arguments...)
	defer os.Remove(shellScript)
	if err != nil {
		return log.Errore(err)
	}

	var waitStatus syscall.WaitStatus

	log.Infof("CommandRun/running: %s", strings.Join(cmd.Args, " "))
	cmdOutput, err := cmd.CombinedOutput()
	log.Infof("CommandRun: %s\n", string(cmdOutput))
	if err != nil {
		// Did the command fail because of an unsuccessful exit code
		if exitError, ok := err.(*exec.ExitError); ok {
			waitStatus = exitError.Sys().(syscall.WaitStatus)
			log.Errorf("CommandRun: failed. exit status %d", waitStatus.ExitStatus())
		}

		return log.Errore(fmt.Errorf("(%s) %s", err.Error(), cmdOutput))
	}

	// Command was successful
	waitStatus = cmd.ProcessState.Sys().(syscall.WaitStatus)
	log.Infof("CommandRun successful. exit status %d", waitStatus.ExitStatus())

	return nil
}

// generateShellScript generates a temporary shell script based on
// the given command to be executed, writes the command to a temporary
// file and returns the exec.Command which can be executed together
// with the script name that was created.
func generateShellScript(commandText string, env []string, arguments ...string) (*exec.Cmd, string, error) {
	shell := config.Config.ProcessesShellCommand

	commandBytes := []byte(commandText)
	tmpFile, err := os.CreateTemp("", "orchestrator-process-cmd-")
	if err != nil {
		return nil, "", log.Errorf("generateShellScript() failed to create TempFile: %v", err.Error())
	}
	// write commandText to temporary file
	os.WriteFile(tmpFile.Name(), commandBytes, 0640)
	shellArguments := append([]string{}, tmpFile.Name())
	shellArguments = append(shellArguments, arguments...)

	cmd := exec.Command(shell, shellArguments...)
	cmd.Env = env

	return cmd, tmpFile.Name(), nil
}
<|endoftext|>


<commit_before>package main_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/fgrosse/goldi/goldigen"
)

var _ = Describe("TypeDefinition", func() {
	Describe("Validate", func() {
		It("should not return an error if the definition contains a factory method", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewBaz",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should not return an error if the definition contains a type name", func() {
			t := main.TypeDefinition{
				Package:  "foo/bar",
				TypeName: "Baz",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should not return an error if the definition contains a func name", func() {
			t := main.TypeDefinition{
				Package:  "foo/bar",
				FuncName: "DoFoo",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should return an error if the definition both contains a func name and a factory method", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewFpp",
				FuncName:      "DoFoo",
			}
			Expect(t.Validate("foobar")).To(MatchError(`type definition of "foobar" can not have both a factory and a function. Please decide for one of them`))
		})

		It("should return an error if the definition is for a func type but contains arguments", func() {
			t := main.TypeDefinition{
				Package:      "foo/bar",
				FuncName:     "DoFoo",
				RawArguments: []interface{}{"test", 42},
			}
			Expect(t.Validate("foobar")).To(MatchError(`type definition of "foobar" is a function type but contains arguments. Function types do not accept arguments`))
		})

		It("should return an error if the definition does not contain a factory method or a type or func name", func() {
			t := main.TypeDefinition{
				Package: "foo/bar",
			}
			Expect(t.Validate("foobar")).To(MatchError(`type definition of "foobar" is missing the required "factory" key`))
		})

		It("should return an error if the configurator does not have exactly two arguments", func() {
			t := main.TypeDefinition{
				Package: "foo/bar", TypeName: "Blup",
				Configurator: []string{"@configurator"},
			}
			Expect(t.Validate("foobar")).To(MatchError(`configurator of type "foobar" needs exactly 2 arguments but got 1`))
		})

		It("should return an error if one of the configurator arguments or both are empty", func() {
			t := main.TypeDefinition{Package: "foo/bar", TypeName: "Blup"}
			invalidArguments := [][]string{{"", ""}, {"@foo", ""}, {"", "Blup"}, {"\t", "  \n "}}
			for _, invalid := range invalidArguments {
				t.Configurator = invalid
				Expect(t.Validate("foobar")).To(MatchError(`configurator of type "foobar" can not have empty arguments`))
			}
		})

		It("should return an error if the configurator type ID does not start with `@`", func() {
			t := main.TypeDefinition{
				Package: "foo/bar", TypeName: "Blup",
				Configurator: []string{"configurator", "Configure"},
			}
			Expect(t.Validate("foobar")).To(MatchError(`configurator of type "foobar" is no valid type ID (does not start with @)`))
		})

		It("should return an error if the configurator method is not exported", func() {
			t := main.TypeDefinition{
				Package:      "foo/bar",
				TypeName:     "Blup",
				Configurator: []string{"@configurator", "configure"},
			}
			Expect(t.Validate("foobar")).To(MatchError(`configurator method of type "foobar" is not exported (lowercase)`))
		})

		It("should not return an error if a func reference type does not contain a package name", func() {
			t := main.TypeDefinition{
				FuncName: "@blup::DoStuff",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should not return an error if a proxy type does not contain a package name", func() {
			t := main.TypeDefinition{
				FactoryMethod: "@blup::DoStuff",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})
	})

	Describe("PackageName", func() {
		It("should return the package name", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewBaz",
			}
			Expect(t.PackageName()).To(Equal("bar"))
		})

		It("should strip versions at the end of package names", func() {
			t := main.TypeDefinition{
				Package:       "github.com/fgrosse/servo.v1",
				FactoryMethod: "NewFoo",
			}
			Expect(t.PackageName()).To(Equal("servo"))

			t.Package = "github.com/fgrosse/servov1"
			Expect(t.PackageName()).To(Equal("servov1"))
		})
	})

	Describe("Arguments", func() {
		It("should return all parameters such that they can be used in go code directly", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewBaz",
				RawArguments: []interface{}{
					"Hello World",
					true,
					42,
					3.1415,
					"%some_parameter%",
					"Hello\t\tWorld",
				},
			}

			arguments := t.Arguments()
			Expect(arguments).To(HaveLen(6))
			Expect(arguments[0]).To(Equal(`"Hello World"`))
			Expect(arguments[1]).To(Equal(`true`))
			Expect(arguments[2]).To(Equal(`42`))
			Expect(arguments[3]).To(Equal(`3.1415`))
			Expect(arguments[4]).To(Equal(`"%some_parameter%"`))
			Expect(arguments[5]).To(Equal("\"Hello\t\tWorld\""))
		})

		It("should return all arguments from RawArgumentsShort", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewBaz",
				RawArgumentsShort: []interface{}{
					"Hello World",
					true,
					42,
					3.1415,
					"%some_parameter%",
					"Hello\t\tWorld",
				},
			}

			arguments := t.Arguments()
			Expect(arguments).To(HaveLen(6))
			Expect(arguments[0]).To(Equal(`"Hello World"`))
			Expect(arguments[1]).To(Equal(`true`))
			Expect(arguments[2]).To(Equal(`42`))
			Expect(arguments[3]).To(Equal(`3.1415`))
			Expect(arguments[4]).To(Equal(`"%some_parameter%"`))
			Expect(arguments[5]).To(Equal("\"Hello\t\tWorld\""))
		})
	})
})
<commit_msg>Test type definition validator alias.<commit_after>package main_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/fgrosse/goldi/goldigen"
)

var _ = Describe("TypeDefinition", func() {
	Describe("Validate", func() {
		It("should not return an error if the definition contains a factory method", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewBaz",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should not return an error if the definition contains a type name", func() {
			t := main.TypeDefinition{
				Package:  "foo/bar",
				TypeName: "Baz",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should not return an error if the definition contains a func name", func() {
			t := main.TypeDefinition{
				Package:  "foo/bar",
				FuncName: "DoFoo",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should not return an error if the definition contains a type alias", func() {
			t := main.TypeDefinition{
				AliasForType: "type",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should return an error if the definition both contains a func name and a factory method", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewFpp",
				FuncName:      "DoFoo",
			}
			Expect(t.Validate("foobar")).To(MatchError(`type definition of "foobar" can not have both a factory and a function. Please decide for one of them`))
		})

		It("should return an error if the definition is for a func type but contains arguments", func() {
			t := main.TypeDefinition{
				Package:      "foo/bar",
				FuncName:     "DoFoo",
				RawArguments: []interface{}{"test", 42},
			}
			Expect(t.Validate("foobar")).To(MatchError(`type definition of "foobar" is a function type but contains arguments. Function types do not accept arguments`))
		})

		It("should return an error if the definition does not contain a factory method or a type or func name", func() {
			t := main.TypeDefinition{
				Package: "foo/bar",
			}
			Expect(t.Validate("foobar")).To(MatchError(`type definition of "foobar" is missing the required "factory" key`))
		})

		It("should return an error if the configurator does not have exactly two arguments", func() {
			t := main.TypeDefinition{
				Package: "foo/bar", TypeName: "Blup",
				Configurator: []string{"@configurator"},
			}
			Expect(t.Validate("foobar")).To(MatchError(`configurator of type "foobar" needs exactly 2 arguments but got 1`))
		})

		It("should return an error if one of the configurator arguments or both are empty", func() {
			t := main.TypeDefinition{Package: "foo/bar", TypeName: "Blup"}
			invalidArguments := [][]string{{"", ""}, {"@foo", ""}, {"", "Blup"}, {"\t", "  \n "}}
			for _, invalid := range invalidArguments {
				t.Configurator = invalid
				Expect(t.Validate("foobar")).To(MatchError(`configurator of type "foobar" can not have empty arguments`))
			}
		})

		It("should return an error if the configurator type ID does not start with `@`", func() {
			t := main.TypeDefinition{
				Package: "foo/bar", TypeName: "Blup",
				Configurator: []string{"configurator", "Configure"},
			}
			Expect(t.Validate("foobar")).To(MatchError(`configurator of type "foobar" is no valid type ID (does not start with @)`))
		})

		It("should return an error if the configurator method is not exported", func() {
			t := main.TypeDefinition{
				Package:      "foo/bar",
				TypeName:     "Blup",
				Configurator: []string{"@configurator", "configure"},
			}
			Expect(t.Validate("foobar")).To(MatchError(`configurator method of type "foobar" is not exported (lowercase)`))
		})

		It("should not return an error if a func reference type does not contain a package name", func() {
			t := main.TypeDefinition{
				FuncName: "@blup::DoStuff",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})

		It("should not return an error if a proxy type does not contain a package name", func() {
			t := main.TypeDefinition{
				FactoryMethod: "@blup::DoStuff",
			}
			Expect(t.Validate("foobar")).To(Succeed())
		})
	})

	Describe("PackageName", func() {
		It("should return the package name", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewBaz",
			}
			Expect(t.PackageName()).To(Equal("bar"))
		})

		It("should strip versions at the end of package names", func() {
			t := main.TypeDefinition{
				Package:       "github.com/fgrosse/servo.v1",
				FactoryMethod: "NewFoo",
			}
			Expect(t.PackageName()).To(Equal("servo"))

			t.Package = "github.com/fgrosse/servov1"
			Expect(t.PackageName()).To(Equal("servov1"))
		})
	})

	Describe("Arguments", func() {
		It("should return all parameters such that they can be used in go code directly", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewBaz",
				RawArguments: []interface{}{
					"Hello World",
					true,
					42,
					3.1415,
					"%some_parameter%",
					"Hello\t\tWorld",
				},
			}

			arguments := t.Arguments()
			Expect(arguments).To(HaveLen(6))
			Expect(arguments[0]).To(Equal(`"Hello World"`))
			Expect(arguments[1]).To(Equal(`true`))
			Expect(arguments[2]).To(Equal(`42`))
			Expect(arguments[3]).To(Equal(`3.1415`))
			Expect(arguments[4]).To(Equal(`"%some_parameter%"`))
			Expect(arguments[5]).To(Equal("\"Hello\t\tWorld\""))
		})

		It("should return all arguments from RawArgumentsShort", func() {
			t := main.TypeDefinition{
				Package:       "foo/bar",
				FactoryMethod: "NewBaz",
				RawArgumentsShort: []interface{}{
					"Hello World",
					true,
					42,
					3.1415,
					"%some_parameter%",
					"Hello\t\tWorld",
				},
			}

			arguments := t.Arguments()
			Expect(arguments).To(HaveLen(6))
			Expect(arguments[0]).To(Equal(`"Hello World"`))
			Expect(arguments[1]).To(Equal(`true`))
			Expect(arguments[2]).To(Equal(`42`))
			Expect(arguments[3]).To(Equal(`3.1415`))
			Expect(arguments[4]).To(Equal(`"%some_parameter%"`))
			Expect(arguments[5]).To(Equal("\"Hello\t\tWorld\""))
		})
	})
})
<|endoftext|>