<commit_before>// Copyright 2019 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

// Package mock defines a fake storage implementation for use in testing.
package mock

import (
	"context"
	"fmt"
	"github.com/open-policy-agent/opa/ast"
	"github.com/open-policy-agent/opa/storage"
	"github.com/open-policy-agent/opa/storage/inmem"
	"testing"
)

// Transaction is a mock storage.Transaction implementation for use in testing.
// It uses an internal storage.Transaction pointer with some added functionality.
type Transaction struct {
	txn       storage.Transaction
	Committed int
	Aborted   int
}

// ID returns the underlying transaction ID
func (t *Transaction) ID() uint64 {
	return t.txn.ID()
}

// Validate returns an error if the transaction is in an invalid state
func (t *Transaction) Validate() error {
	if t.Committed > 1 {
		return fmt.Errorf("transaction %d has too many commits (%d)", t.ID(), t.Committed)
	}
	if t.Aborted > 1 {
		return fmt.Errorf("transaction %d has too many aborts (%d)", t.ID(), t.Committed)
	}
	return nil
}

func (t *Transaction) safeToUse() bool {
	return t.Committed == 0 && t.Aborted == 0
}

// Store is a mock storage.Store implementation for use in testing.
type Store struct {
	inmem        storage.Store
	baseData     map[string]interface{}
	Transactions []*Transaction
	Reads        []*ReadCall
	Writes       []*WriteCall
}

// ReadCall captures the parameters for a Read call
type ReadCall struct {
	Transaction *Transaction
	Path        storage.Path
	Error       error
	Safe        bool
}

// WriteCall captures the parameters for a write call
type WriteCall struct {
	Transaction *Transaction
	Op          storage.PatchOp
	Path        storage.Path
	Error       error
	Safe        bool
}

// New creates a new mock Store
func New() *Store {
	s := &Store{}
	s.Reset()
	return s
}

// NewWithData creates a store with some initial data
func NewWithData(data map[string]interface{}) *Store {
	s := &Store{
		baseData: data,
	}
	s.Reset()
	return s
}

// Reset the store
func (s *Store) Reset() {
	s.Transactions = []*Transaction{}
	s.Reads = []*ReadCall{}
	s.Writes = []*WriteCall{}
	if s.baseData != nil {
		s.inmem = inmem.NewFromObject(s.baseData)
	} else {
		s.inmem = inmem.New()
	}
}

// GetTransaction will a transaction with a specific ID
// that was associated with this Store.
func (s *Store) GetTransaction(id uint64) *Transaction {
	for _, txn := range s.Transactions {
		if txn.ID() == id {
			return txn
		}
	}
	return nil
}

// Errors returns a list of errors for each invalid state found.
// If any Transactions are invalid or reads/writes were
// unsafe an error will be returned for each problem.
func (s *Store) Errors() []error {
	var errs []error
	for _, txn := range s.Transactions {
		err := txn.Validate()
		if err != nil {
			errs = append(errs, err)
		}
	}

	for _, read := range s.Reads {
		if !read.Safe {
			errs = append(errs, fmt.Errorf("unsafe Read call %+v", *read))
		}
	}

	for _, write := range s.Writes {
		if !write.Safe {
			errs = append(errs, fmt.Errorf("unsafe Write call %+v", *write))
		}
	}

	return errs
}

// AssertValid will raise an error with the provided testing.T if
// there are any errors on the store.
func (s *Store) AssertValid(t *testing.T) {
	t.Helper()
	for _, err := range s.Errors() {
		t.Errorf("Error detected on store: %s", err)
	}
}

// storage.Store interface implementation

// Register just shims the call to the underlying inmem store
func (s *Store) Register(ctx context.Context, txn storage.Transaction, config storage.TriggerConfig) (storage.TriggerHandle, error) {
	return s.inmem.Register(ctx, txn, config)
}

// ListPolicies just shims the call to the underlying inmem store
func (s *Store) ListPolicies(ctx context.Context, txn storage.Transaction) ([]string, error) {
	return s.ListPolicies(ctx, txn)
}

// GetPolicy just shims the call to the underlying inmem store
func (s *Store) GetPolicy(ctx context.Context, txn storage.Transaction, name string) ([]byte, error) {
	return s.inmem.GetPolicy(ctx, txn, name)
}

// UpsertPolicy just shims the call to the underlying inmem store
func (s *Store) UpsertPolicy(ctx context.Context, txn storage.Transaction, name string, policy []byte) error {
	return s.inmem.UpsertPolicy(ctx, txn, name, policy)
}

// DeletePolicy just shims the call to the underlying inmem store
func (s *Store) DeletePolicy(ctx context.Context, txn storage.Transaction, name string) error {
	return s.inmem.DeletePolicy(ctx, txn, name)
}

// Build just shims the call to the underlying inmem store
func (s *Store) Build(ctx context.Context, txn storage.Transaction, ref ast.Ref) (storage.Index, error) {
	return s.inmem.Build(ctx, txn, ref)
}

// NewTransaction will create a new transaction on the underlying inmem store
// but wraps it with a mock Transaction. These are then tracked on the store.
func (s *Store) NewTransaction(ctx context.Context, params ...storage.TransactionParams) (storage.Transaction, error) {
	realTxn, err := s.inmem.NewTransaction(ctx, params...)
	if err != nil {
		return nil, err
	}
	txn := &Transaction{
		txn:       realTxn,
		Committed: 0,
		Aborted:   0,
	}
	s.Transactions = append(s.Transactions, txn)
	return txn, nil
}

// Read will make a read from the underlying inmem store and
// add a new entry to the mock store Reads list. If there
// is an error are the read is unsafe it will be noted in
// the ReadCall.
func (s *Store) Read(ctx context.Context, txn storage.Transaction, path storage.Path) (interface{}, error) {
	mockTxn := txn.(*Transaction)

	data, err := s.inmem.Read(ctx, mockTxn.txn, path)

	s.Reads = append(s.Reads, &ReadCall{
		Transaction: mockTxn,
		Path:        path,
		Error:       err,
		Safe:        mockTxn.safeToUse(),
	})

	return data, err
}

// Write will make a read from the underlying inmem store and
// add a new entry to the mock store Writes list. If there
// is an error are the write is unsafe it will be noted in
// the WriteCall.
func (s *Store) Write(ctx context.Context, txn storage.Transaction, op storage.PatchOp, path storage.Path, value interface{}) error {
	mockTxn := txn.(*Transaction)

	err := s.inmem.Write(ctx, mockTxn.txn, op, path, value)

	s.Writes = append(s.Writes, &WriteCall{
		Transaction: mockTxn,
		Op:          op,
		Path:        path,
		Error:       err,
		Safe:        mockTxn.safeToUse(),
	})

	return nil
}

// Commit will commit the underlying transaction while
// also updating the mock Transaction
func (s *Store) Commit(ctx context.Context, txn storage.Transaction) error {
	mockTxn := txn.(*Transaction)

	err := s.inmem.Commit(ctx, mockTxn.txn)
	if err != nil {
		return err
	}

	mockTxn.Committed++
	return nil
}

// Abort will abort the underlying transaction while
// also updating the mock Transaction
func (s *Store) Abort(ctx context.Context, txn storage.Transaction) {
	mockTxn := txn.(*Transaction)
	s.inmem.Abort(ctx, mockTxn.txn)
	mockTxn.Aborted++
	return
}
<commit_msg>internal/storage: Fix bug with underlying transaction<commit_after>// Copyright 2019 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

// Package mock defines a fake storage implementation for use in testing.
package mock

import (
	"context"
	"fmt"
	"testing"

	"github.com/open-policy-agent/opa/ast"
	"github.com/open-policy-agent/opa/storage"
	"github.com/open-policy-agent/opa/storage/inmem"
)

// Transaction is a mock storage.Transaction implementation for use in testing.
// It uses an internal storage.Transaction pointer with some added functionality.
type Transaction struct {
	txn       storage.Transaction
	Committed int
	Aborted   int
}

// ID returns the underlying transaction ID
func (t *Transaction) ID() uint64 {
	return t.txn.ID()
}

// Validate returns an error if the transaction is in an invalid state
func (t *Transaction) Validate() error {
	if t.Committed > 1 {
		return fmt.Errorf("transaction %d has too many commits (%d)", t.ID(), t.Committed)
	}
	if t.Aborted > 1 {
		return fmt.Errorf("transaction %d has too many aborts (%d)", t.ID(), t.Committed)
	}
	return nil
}

func (t *Transaction) safeToUse() bool {
	return t.Committed == 0 && t.Aborted == 0
}

// Store is a mock storage.Store implementation for use in testing.
type Store struct {
	inmem        storage.Store
	baseData     map[string]interface{}
	Transactions []*Transaction
	Reads        []*ReadCall
	Writes       []*WriteCall
}

// ReadCall captures the parameters for a Read call
type ReadCall struct {
	Transaction *Transaction
	Path        storage.Path
	Error       error
	Safe        bool
}

// WriteCall captures the parameters for a write call
type WriteCall struct {
	Transaction *Transaction
	Op          storage.PatchOp
	Path        storage.Path
	Error       error
	Safe        bool
}

// New creates a new mock Store
func New() *Store {
	s := &Store{}
	s.Reset()
	return s
}

// NewWithData creates a store with some initial data
func NewWithData(data map[string]interface{}) *Store {
	s := &Store{
		baseData: data,
	}
	s.Reset()
	return s
}

// Reset the store
func (s *Store) Reset() {
	s.Transactions = []*Transaction{}
	s.Reads = []*ReadCall{}
	s.Writes = []*WriteCall{}
	if s.baseData != nil {
		s.inmem = inmem.NewFromObject(s.baseData)
	} else {
		s.inmem = inmem.New()
	}
}

// GetTransaction will a transaction with a specific ID
// that was associated with this Store.
func (s *Store) GetTransaction(id uint64) *Transaction {
	for _, txn := range s.Transactions {
		if txn.ID() == id {
			return txn
		}
	}
	return nil
}

// Errors returns a list of errors for each invalid state found.
// If any Transactions are invalid or reads/writes were
// unsafe an error will be returned for each problem.
func (s *Store) Errors() []error {
	var errs []error
	for _, txn := range s.Transactions {
		err := txn.Validate()
		if err != nil {
			errs = append(errs, err)
		}
	}

	for _, read := range s.Reads {
		if !read.Safe {
			errs = append(errs, fmt.Errorf("unsafe Read call %+v", *read))
		}
	}

	for _, write := range s.Writes {
		if !write.Safe {
			errs = append(errs, fmt.Errorf("unsafe Write call %+v", *write))
		}
	}

	return errs
}

// AssertValid will raise an error with the provided testing.T if
// there are any errors on the store.
func (s *Store) AssertValid(t *testing.T) {
	t.Helper()
	for _, err := range s.Errors() {
		t.Errorf("Error detected on store: %s", err)
	}
}

// storage.Store interface implementation

// Register just shims the call to the underlying inmem store
func (s *Store) Register(ctx context.Context, txn storage.Transaction, config storage.TriggerConfig) (storage.TriggerHandle, error) {
	return s.inmem.Register(ctx, getRealTxn(txn), config)
}

// ListPolicies just shims the call to the underlying inmem store
func (s *Store) ListPolicies(ctx context.Context, txn storage.Transaction) ([]string, error) {
	return s.inmem.ListPolicies(ctx, getRealTxn(txn))
}

// GetPolicy just shims the call to the underlying inmem store
func (s *Store) GetPolicy(ctx context.Context, txn storage.Transaction, name string) ([]byte, error) {
	return s.inmem.GetPolicy(ctx, getRealTxn(txn), name)
}

// UpsertPolicy just shims the call to the underlying inmem store
func (s *Store) UpsertPolicy(ctx context.Context, txn storage.Transaction, name string, policy []byte) error {
	return s.inmem.UpsertPolicy(ctx, getRealTxn(txn), name, policy)
}

// DeletePolicy just shims the call to the underlying inmem store
func (s *Store) DeletePolicy(ctx context.Context, txn storage.Transaction, name string) error {
	return s.inmem.DeletePolicy(ctx, getRealTxn(txn), name)
}

// Build just shims the call to the underlying inmem store
func (s *Store) Build(ctx context.Context, txn storage.Transaction, ref ast.Ref) (storage.Index, error) {
	return s.inmem.Build(ctx, getRealTxn(txn), ref)
}

// NewTransaction will create a new transaction on the underlying inmem store
// but wraps it with a mock Transaction. These are then tracked on the store.
func (s *Store) NewTransaction(ctx context.Context, params ...storage.TransactionParams) (storage.Transaction, error) {
	realTxn, err := s.inmem.NewTransaction(ctx, params...)
	if err != nil {
		return nil, err
	}
	txn := &Transaction{
		txn:       realTxn,
		Committed: 0,
		Aborted:   0,
	}
	s.Transactions = append(s.Transactions, txn)
	return txn, nil
}

// Read will make a read from the underlying inmem store and
// add a new entry to the mock store Reads list. If there
// is an error are the read is unsafe it will be noted in
// the ReadCall.
func (s *Store) Read(ctx context.Context, txn storage.Transaction, path storage.Path) (interface{}, error) {
	mockTxn := txn.(*Transaction)

	data, err := s.inmem.Read(ctx, mockTxn.txn, path)

	s.Reads = append(s.Reads, &ReadCall{
		Transaction: mockTxn,
		Path:        path,
		Error:       err,
		Safe:        mockTxn.safeToUse(),
	})

	return data, err
}

// Write will make a read from the underlying inmem store and
// add a new entry to the mock store Writes list. If there
// is an error are the write is unsafe it will be noted in
// the WriteCall.
func (s *Store) Write(ctx context.Context, txn storage.Transaction, op storage.PatchOp, path storage.Path, value interface{}) error {
	mockTxn := txn.(*Transaction)

	err := s.inmem.Write(ctx, mockTxn.txn, op, path, value)

	s.Writes = append(s.Writes, &WriteCall{
		Transaction: mockTxn,
		Op:          op,
		Path:        path,
		Error:       err,
		Safe:        mockTxn.safeToUse(),
	})

	return nil
}

// Commit will commit the underlying transaction while
// also updating the mock Transaction
func (s *Store) Commit(ctx context.Context, txn storage.Transaction) error {
	mockTxn := txn.(*Transaction)

	err := s.inmem.Commit(ctx, mockTxn.txn)
	if err != nil {
		return err
	}

	mockTxn.Committed++
	return nil
}

// Abort will abort the underlying transaction while
// also updating the mock Transaction
func (s *Store) Abort(ctx context.Context, txn storage.Transaction) {
	mockTxn := txn.(*Transaction)
	s.inmem.Abort(ctx, mockTxn.txn)
	mockTxn.Aborted++
	return
}

func getRealTxn(txn storage.Transaction) storage.Transaction {
	return txn.(*Transaction).txn

}
<|endoftext|>


<commit_before>package parser

import (
	"errors"
	"fmt"
	"unicode"

	"github.com/richardwilkes/goblin/interpreter"
)

const (
	// EOF - end of file
	EOF = -1
	// EOL - end of line
	EOL = '\n'
)

var opName = map[string]int{
	"func":     FUNC,
	"return":   RETURN,
	"var":      VAR,
	"throw":    THROW,
	"if":       IF,
	"for":      FOR,
	"break":    BREAK,
	"continue": CONTINUE,
	"in":       IN,
	"else":     ELSE,
	"new":      NEW,
	"true":     TRUE,
	"false":    FALSE,
	"nil":      NIL,
	"module":   MODULE,
	"try":      TRY,
	"catch":    CATCH,
	"finally":  FINALLY,
	"switch":   SWITCH,
	"case":     CASE,
	"default":  DEFAULT,
	"make":     MAKE,
}

// Scanner holds informations for the lexer.
type Scanner struct {
	src      []rune
	offset   int
	lineHead int
	line     int
}

// Init resets code to scan.
func (s *Scanner) Init(src string) {
	s.src = []rune(src)
}

// Scan for the next token.
func (s *Scanner) Scan() (tok int, lit string, pos interpreter.Position, err error) {
retry:
	s.skipBlank()
	pos = s.pos()
	switch ch := s.peek(); {
	case isLetter(ch):
		lit, err = s.scanIdentifier()
		if err != nil {
			return
		}
		if name, ok := opName[lit]; ok {
			tok = name
		} else {
			tok = IDENT
		}
	case isDigit(ch):
		tok = NUMBER
		lit, err = s.scanNumber()
		if err != nil {
			return
		}
	case ch == '"':
		tok = STRING
		lit, err = s.scanString('"')
		if err != nil {
			return
		}
	case ch == '\'':
		tok = STRING
		lit, err = s.scanString('\'')
		if err != nil {
			return
		}
	case ch == '`':
		tok = STRING
		lit, err = s.scanRawString()
		if err != nil {
			return
		}
	default:
		switch ch {
		case EOF:
			tok = EOF
		case '#':
			for !isEOL(s.peek()) {
				s.next()
			}
			goto retry
		case '!':
			s.next()
			switch s.peek() {
			case '=':
				tok = NEQ
				lit = "!="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '=':
			s.next()
			switch s.peek() {
			case '=':
				tok = EQEQ
				lit = "=="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '+':
			s.next()
			switch s.peek() {
			case '+':
				tok = PLUSPLUS
				lit = "++"
			case '=':
				tok = PLUSEQ
				lit = "+="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '-':
			s.next()
			switch s.peek() {
			case '-':
				tok = MINUSMINUS
				lit = "--"
			case '=':
				tok = MINUSEQ
				lit = "-="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '*':
			s.next()
			switch s.peek() {
			case '*':
				tok = POW
				lit = "**"
			case '=':
				tok = MULEQ
				lit = "*="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '/':
			s.next()
			switch s.peek() {
			case '=':
				tok = DIVEQ
				lit = "/="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '>':
			s.next()
			switch s.peek() {
			case '=':
				tok = GE
				lit = ">="
			case '>':
				tok = SHIFTRIGHT
				lit = ">>"
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '<':
			s.next()
			switch s.peek() {
			case '=':
				tok = LE
				lit = "<="
			case '<':
				tok = SHIFTLEFT
				lit = "<<"
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '|':
			s.next()
			switch s.peek() {
			case '|':
				tok = OROR
				lit = "||"
			case '=':
				tok = OREQ
				lit = "|="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '&':
			s.next()
			switch s.peek() {
			case '&':
				tok = ANDAND
				lit = "&&"
			case '=':
				tok = ANDEQ
				lit = "&="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '.':
			s.next()
			if s.peek() == '.' {
				s.next()
				if s.peek() == '.' {
					tok = VARARG
				} else {
					err = fmt.Errorf(`syntax error "%s"`, "..")
					return
				}
			} else {
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '\n':
			tok = int(ch)
			lit = string(ch)
		case '(', ')', ':', ';', '%', '?', '{', '}', ',', '[', ']', '^':
			s.next()
			if ch == '[' && s.peek() == ']' {
				s.next()
				if isLetter(s.peek()) {
					s.back()
					tok = ARRAYLIT
					lit = "[]"
				} else {
					s.back()
					s.back()
					tok = int(ch)
					lit = string(ch)
				}
			} else {
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		default:
			err = fmt.Errorf(`syntax error "%s"`, string(ch))
			tok = int(ch)
			lit = string(ch)
			return
		}
		s.next()
	}
	return
}

func (s *Scanner) peek() rune {
	if s.reachEOF() {
		return EOF
	}
	return s.src[s.offset]
}

func (s *Scanner) next() {
	if !s.reachEOF() {
		if s.peek() == '\n' {
			s.lineHead = s.offset + 1
			s.line++
		}
		s.offset++
	}
}

func (s *Scanner) current() int {
	return s.offset
}

func (s *Scanner) set(o int) {
	s.offset = o
}

func (s *Scanner) back() {
	s.offset--
}

func (s *Scanner) reachEOF() bool {
	return len(s.src) <= s.offset
}

func (s *Scanner) pos() interpreter.Position {
	return interpreter.Position{Line: s.line + 1, Column: s.offset - s.lineHead + 1}
}

func (s *Scanner) skipBlank() {
	for isBlank(s.peek()) {
		s.next()
	}
}

func (s *Scanner) scanIdentifier() (string, error) {
	var ret []rune
	for {
		if !isLetter(s.peek()) && !isDigit(s.peek()) {
			break
		}
		ret = append(ret, s.peek())
		s.next()
	}
	return string(ret), nil
}

func (s *Scanner) scanNumber() (string, error) {
	var ret []rune
	ch := s.peek()
	ret = append(ret, ch)
	s.next()
	if ch == '0' && s.peek() == 'x' {
		ret = append(ret, s.peek())
		s.next()
		for isHex(s.peek()) {
			ret = append(ret, s.peek())
			s.next()
		}
	} else {
		for isDigit(s.peek()) || s.peek() == '.' {
			ret = append(ret, s.peek())
			s.next()
		}
		if s.peek() == 'e' {
			ret = append(ret, s.peek())
			s.next()
			if isDigit(s.peek()) || s.peek() == '+' || s.peek() == '-' {
				ret = append(ret, s.peek())
				s.next()
				for isDigit(s.peek()) || s.peek() == '.' {
					ret = append(ret, s.peek())
					s.next()
				}
			}
			for isDigit(s.peek()) || s.peek() == '.' {
				ret = append(ret, s.peek())
				s.next()
			}
		}
		if isLetter(s.peek()) {
			return "", errors.New("identifier starts immediately after numeric literal")
		}
	}
	return string(ret), nil
}

func (s *Scanner) scanRawString() (string, error) {
	var ret []rune
	for {
		s.next()
		if s.peek() == EOF {
			return "", errors.New("unexpected EOF")
		}
		if s.peek() == '`' {
			s.next()
			break
		}
		ret = append(ret, s.peek())
	}
	return string(ret), nil
}

func (s *Scanner) scanString(l rune) (string, error) {
	var ret []rune
eos:
	for {
		s.next()
		switch s.peek() {
		case EOL:
			return "", errors.New("unexpected EOL")
		case EOF:
			return "", errors.New("unexpected EOF")
		case l:
			s.next()
			break eos
		case '\\':
			s.next()
			switch s.peek() {
			case 'b':
				ret = append(ret, '\b')
				continue
			case 'f':
				ret = append(ret, '\f')
				continue
			case 'r':
				ret = append(ret, '\r')
				continue
			case 'n':
				ret = append(ret, '\n')
				continue
			case 't':
				ret = append(ret, '\t')
				continue
			}
			ret = append(ret, s.peek())
			continue
		default:
			ret = append(ret, s.peek())
		}
	}
	return string(ret), nil
}

func isLetter(ch rune) bool {
	return unicode.IsLetter(ch) || ch == '_'
}

func isDigit(ch rune) bool {
	return '0' <= ch && ch <= '9'
}

func isHex(ch rune) bool {
	return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
}

func isEOL(ch rune) bool {
	return ch == EOL || ch == EOF
}

func isBlank(ch rune) bool {
	return ch == ' ' || ch == '\t' || ch == '\r'
}
<commit_msg>Add // and /* */ style comment support<commit_after>package parser

import (
	"errors"
	"fmt"
	"unicode"

	"github.com/richardwilkes/goblin/interpreter"
)

const (
	// EOF - end of file
	EOF = -1
	// EOL - end of line
	EOL = '\n'
)

var opName = map[string]int{
	"func":     FUNC,
	"return":   RETURN,
	"var":      VAR,
	"throw":    THROW,
	"if":       IF,
	"for":      FOR,
	"break":    BREAK,
	"continue": CONTINUE,
	"in":       IN,
	"else":     ELSE,
	"new":      NEW,
	"true":     TRUE,
	"false":    FALSE,
	"nil":      NIL,
	"module":   MODULE,
	"try":      TRY,
	"catch":    CATCH,
	"finally":  FINALLY,
	"switch":   SWITCH,
	"case":     CASE,
	"default":  DEFAULT,
	"make":     MAKE,
}

// Scanner holds informations for the lexer.
type Scanner struct {
	src      []rune
	offset   int
	lineHead int
	line     int
}

// Init resets code to scan.
func (s *Scanner) Init(src string) {
	s.src = []rune(src)
}

// Scan for the next token.
func (s *Scanner) Scan() (tok int, lit string, pos interpreter.Position, err error) {
retry:
	s.skipBlank()
	pos = s.pos()
	switch ch := s.peek(); {
	case isLetter(ch):
		lit, err = s.scanIdentifier()
		if err != nil {
			return
		}
		if name, ok := opName[lit]; ok {
			tok = name
		} else {
			tok = IDENT
		}
	case isDigit(ch):
		tok = NUMBER
		lit, err = s.scanNumber()
		if err != nil {
			return
		}
	case ch == '"':
		tok = STRING
		lit, err = s.scanString('"')
		if err != nil {
			return
		}
	case ch == '\'':
		tok = STRING
		lit, err = s.scanString('\'')
		if err != nil {
			return
		}
	case ch == '`':
		tok = STRING
		lit, err = s.scanRawString()
		if err != nil {
			return
		}
	default:
		switch ch {
		case EOF:
			tok = EOF
		case '#':
			for !isEOL(s.peek()) {
				s.next()
			}
			goto retry
		case '!':
			s.next()
			switch s.peek() {
			case '=':
				tok = NEQ
				lit = "!="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '=':
			s.next()
			switch s.peek() {
			case '=':
				tok = EQEQ
				lit = "=="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '+':
			s.next()
			switch s.peek() {
			case '+':
				tok = PLUSPLUS
				lit = "++"
			case '=':
				tok = PLUSEQ
				lit = "+="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '-':
			s.next()
			switch s.peek() {
			case '-':
				tok = MINUSMINUS
				lit = "--"
			case '=':
				tok = MINUSEQ
				lit = "-="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '*':
			s.next()
			switch s.peek() {
			case '*':
				tok = POW
				lit = "**"
			case '=':
				tok = MULEQ
				lit = "*="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '/':
			s.next()
			switch s.peek() {
			case '/':
				s.next()
				for !isEOL(s.peek()) {
					s.next()
				}
				goto retry
			case '*':
				s.next()
				for {
					ch = s.peek()
					if ch == EOF {
						goto retry
					}
					s.next()
					if ch == '*' && s.peek() == '/' {
						s.next()
						goto retry
					}
				}
			case '=':
				tok = DIVEQ
				lit = "/="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '>':
			s.next()
			switch s.peek() {
			case '=':
				tok = GE
				lit = ">="
			case '>':
				tok = SHIFTRIGHT
				lit = ">>"
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '<':
			s.next()
			switch s.peek() {
			case '=':
				tok = LE
				lit = "<="
			case '<':
				tok = SHIFTLEFT
				lit = "<<"
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '|':
			s.next()
			switch s.peek() {
			case '|':
				tok = OROR
				lit = "||"
			case '=':
				tok = OREQ
				lit = "|="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '&':
			s.next()
			switch s.peek() {
			case '&':
				tok = ANDAND
				lit = "&&"
			case '=':
				tok = ANDEQ
				lit = "&="
			default:
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '.':
			s.next()
			if s.peek() == '.' {
				s.next()
				if s.peek() == '.' {
					tok = VARARG
				} else {
					err = fmt.Errorf(`syntax error "%s"`, "..")
					return
				}
			} else {
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		case '\n':
			tok = int(ch)
			lit = string(ch)
		case '(', ')', ':', ';', '%', '?', '{', '}', ',', '[', ']', '^':
			s.next()
			if ch == '[' && s.peek() == ']' {
				s.next()
				if isLetter(s.peek()) {
					s.back()
					tok = ARRAYLIT
					lit = "[]"
				} else {
					s.back()
					s.back()
					tok = int(ch)
					lit = string(ch)
				}
			} else {
				s.back()
				tok = int(ch)
				lit = string(ch)
			}
		default:
			err = fmt.Errorf(`syntax error "%s"`, string(ch))
			tok = int(ch)
			lit = string(ch)
			return
		}
		s.next()
	}
	return
}

func (s *Scanner) peek() rune {
	if s.reachEOF() {
		return EOF
	}
	return s.src[s.offset]
}

func (s *Scanner) next() {
	if !s.reachEOF() {
		if s.peek() == '\n' {
			s.lineHead = s.offset + 1
			s.line++
		}
		s.offset++
	}
}

func (s *Scanner) current() int {
	return s.offset
}

func (s *Scanner) set(o int) {
	s.offset = o
}

func (s *Scanner) back() {
	s.offset--
}

func (s *Scanner) reachEOF() bool {
	return len(s.src) <= s.offset
}

func (s *Scanner) pos() interpreter.Position {
	return interpreter.Position{Line: s.line + 1, Column: s.offset - s.lineHead + 1}
}

func (s *Scanner) skipBlank() {
	for isBlank(s.peek()) {
		s.next()
	}
}

func (s *Scanner) scanIdentifier() (string, error) {
	var ret []rune
	for {
		if !isLetter(s.peek()) && !isDigit(s.peek()) {
			break
		}
		ret = append(ret, s.peek())
		s.next()
	}
	return string(ret), nil
}

func (s *Scanner) scanNumber() (string, error) {
	var ret []rune
	ch := s.peek()
	ret = append(ret, ch)
	s.next()
	if ch == '0' && s.peek() == 'x' {
		ret = append(ret, s.peek())
		s.next()
		for isHex(s.peek()) {
			ret = append(ret, s.peek())
			s.next()
		}
	} else {
		for isDigit(s.peek()) || s.peek() == '.' {
			ret = append(ret, s.peek())
			s.next()
		}
		if s.peek() == 'e' {
			ret = append(ret, s.peek())
			s.next()
			if isDigit(s.peek()) || s.peek() == '+' || s.peek() == '-' {
				ret = append(ret, s.peek())
				s.next()
				for isDigit(s.peek()) || s.peek() == '.' {
					ret = append(ret, s.peek())
					s.next()
				}
			}
			for isDigit(s.peek()) || s.peek() == '.' {
				ret = append(ret, s.peek())
				s.next()
			}
		}
		if isLetter(s.peek()) {
			return "", errors.New("identifier starts immediately after numeric literal")
		}
	}
	return string(ret), nil
}

func (s *Scanner) scanRawString() (string, error) {
	var ret []rune
	for {
		s.next()
		if s.peek() == EOF {
			return "", errors.New("unexpected EOF")
		}
		if s.peek() == '`' {
			s.next()
			break
		}
		ret = append(ret, s.peek())
	}
	return string(ret), nil
}

func (s *Scanner) scanString(l rune) (string, error) {
	var ret []rune
eos:
	for {
		s.next()
		switch s.peek() {
		case EOL:
			return "", errors.New("unexpected EOL")
		case EOF:
			return "", errors.New("unexpected EOF")
		case l:
			s.next()
			break eos
		case '\\':
			s.next()
			switch s.peek() {
			case 'b':
				ret = append(ret, '\b')
				continue
			case 'f':
				ret = append(ret, '\f')
				continue
			case 'r':
				ret = append(ret, '\r')
				continue
			case 'n':
				ret = append(ret, '\n')
				continue
			case 't':
				ret = append(ret, '\t')
				continue
			}
			ret = append(ret, s.peek())
			continue
		default:
			ret = append(ret, s.peek())
		}
	}
	return string(ret), nil
}

func isLetter(ch rune) bool {
	return unicode.IsLetter(ch) || ch == '_'
}

func isDigit(ch rune) bool {
	return '0' <= ch && ch <= '9'
}

func isHex(ch rune) bool {
	return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
}

func isEOL(ch rune) bool {
	return ch == EOL || ch == EOF
}

func isBlank(ch rune) bool {
	return ch == ' ' || ch == '\t' || ch == '\r'
}
<|endoftext|>


<commit_before>// +build linux,cgo darwin,cgo !windows
// +build 386 amd64

/*
 * magic.go
 *
 * Copyright 2013 Krzysztof Wilczynski
 *
 * 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 magic

/*
#cgo LDFLAGS: -lmagic
#include "functions.h"
*/
import "C"

import (
	"runtime"
	"strings"
	"sync"
	"unsafe"
)

type magic struct {
	sync.Mutex
	cookie C.magic_t
}

func (m *magic) close() {
	if m != nil && m.cookie != nil {
		C.magic_close(m.cookie)
		m.cookie = nil
	}
	runtime.SetFinalizer(m, nil)
}

type Magic struct {
	*magic
}

func New() *Magic {
	mgc := &Magic{&magic{cookie: C.magic_open(C.int(NONE))}}
	runtime.SetFinalizer(mgc.magic, (*magic).close)
	return mgc
}

func (mgc *Magic) Close() {
	mgc.Lock()
	defer mgc.Unlock()

	mgc.magic.close()
}

func (mgc *Magic) String() string {
	return fmt.Sprintf("Magic{cookie:%p}", mgc.cookie)
}

func (mgc *Magic) GetPath() []string {
	mgc.Lock()
	defer mgc.Unlock()

	path := C.GoString(C.magic_getpath(nil, C.int(0)))
	return strings.Split(path, ":")
}

func (mgc *Magic) SetFlags(flags int) error {
	mgc.Lock()
	defer mgc.Unlock()

	if rv := C.magic_setflags(mgc.cookie, C.int(flags)); rv < 0 {
		return mgc.error()
	}
	return nil
}

func (mgc *Magic) Load(files ...string) error {
	mgc.Lock()
	defer mgc.Unlock()

	var cfiles *C.char
	if len(files) != 0 {
		cfiles = C.CString(strings.Join(files, ":"))
		defer C.free(unsafe.Pointer(cfiles))
	}

	if rv := C.magic_load_wrapper(mgc.cookie, cfiles); rv < 0 {
		return mgc.error()
	}
	return nil
}

func (mgc *Magic) Compile(files ...string) error {
	mgc.Lock()
	defer mgc.Unlock()

	var cfiles *C.char
	if len(files) != 0 {
		cfiles = C.CString(strings.Join(files, ":"))
		defer C.free(unsafe.Pointer(cfiles))
	}

	if rv := C.magic_compile_wrapper(mgc.cookie, cfiles); rv < 0 {
		return mgc.error()
	}
	return nil
}

func (mgc *Magic) Check(files ...string) error {
	mgc.Lock()
	defer mgc.Unlock()

	var cfiles *C.char
	if len(files) != 0 {
		cfiles = C.CString(strings.Join(files, ":"))
		defer C.free(unsafe.Pointer(cfiles))
	}

	if rv := C.magic_check_wrapper(mgc.cookie, cfiles); rv < 0 {
		return mgc.error()
	}
	return nil
}

func (mgc *Magic) File(filename string) (string, error) {
	mgc.Lock()
	defer mgc.Unlock()

	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))

	cstring := C.magic_file(mgc.cookie, cfilename)
	if cstring == nil {
		return "", mgc.error()
	}
	return C.GoString(cstring), nil
}

func (mgc *Magic) Buffer(buffer []byte) (string, error) {
	mgc.Lock()
	defer mgc.Unlock()

	p, length := unsafe.Pointer(&buffer[0]), C.size_t(len(buffer))

	cstring := C.magic_buffer(mgc.cookie, p, length)
	if cstring == nil {
		return "", mgc.error()
	}
	return C.GoString(cstring), nil
}

func (mgc *Magic) Descriptor(fd uintptr) (string, error) {
	mgc.Lock()
	defer mgc.Unlock()

	cstring := C.magic_descriptor(mgc.cookie, C.int(fd))
	if cstring == nil {
		return "", mgc.error()
	}
	return C.GoString(cstring), nil
}

func (mgc *Magic) Version() (int, error) {
	mgc.Lock()
	defer mgc.Unlock()

	v := int(C.magic_version_wrapper())
	if v < 0 {
		return v, &MagicError{v, "function not implemented"}
	}
	return v, nil
}

func (mgc *Magic) error() *MagicError {
	errno := int(C.magic_errno(mgc.cookie))
	cstring := C.magic_error(mgc.cookie)
	if cstring != nil {
		return &MagicError{errno, C.GoString(cstring)}
	}
	return nil
}

func (mgc *Magic) destroy() {
	mgc.Close()
}

func Compile(files ...string) error {
	mgc := New()
	if err := mgc.Compile(files...); err != nil {
		return err
	}
	defer mgc.Close()
	return nil
}

func Check(files ...string) error {
	mgc := New()
	if err := mgc.Check(files...); err != nil {
		return err
	}
	defer mgc.Close()
	return nil
}

func FileMime(filename string, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME)
	return mgc.File(filename)
}

func FileEncoding(filename string, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME_ENCODING)
	return mgc.File(filename)
}

func FileType(filename string, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME_TYPE)
	return mgc.File(filename)
}

func BufferMime(buffer []byte, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME)
	return mgc.Buffer(buffer)
}

func BufferEncoding(buffer []byte, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME_ENCODING)
	return mgc.Buffer(buffer)
}

func BufferType(buffer []byte, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME_TYPE)
	return mgc.Buffer(buffer)
}
<commit_msg>Add missing "fmt" import.<commit_after>// +build linux,cgo darwin,cgo !windows
// +build 386 amd64

/*
 * magic.go
 *
 * Copyright 2013 Krzysztof Wilczynski
 *
 * 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 magic

/*
#cgo LDFLAGS: -lmagic
#include "functions.h"
*/
import "C"

import (
	"fmt"
	"runtime"
	"strings"
	"sync"
	"unsafe"
)

type magic struct {
	sync.Mutex
	cookie C.magic_t
}

func (m *magic) close() {
	if m != nil && m.cookie != nil {
		C.magic_close(m.cookie)
		m.cookie = nil
	}
	runtime.SetFinalizer(m, nil)
}

type Magic struct {
	*magic
}

func New() *Magic {
	mgc := &Magic{&magic{cookie: C.magic_open(C.int(NONE))}}
	runtime.SetFinalizer(mgc.magic, (*magic).close)
	return mgc
}

func (mgc *Magic) Close() {
	mgc.Lock()
	defer mgc.Unlock()

	mgc.magic.close()
}

func (mgc *Magic) String() string {
	return fmt.Sprintf("Magic{cookie:%p}", mgc.cookie)
}

func (mgc *Magic) GetPath() []string {
	mgc.Lock()
	defer mgc.Unlock()

	path := C.GoString(C.magic_getpath(nil, C.int(0)))
	return strings.Split(path, ":")
}

func (mgc *Magic) SetFlags(flags int) error {
	mgc.Lock()
	defer mgc.Unlock()

	if rv := C.magic_setflags(mgc.cookie, C.int(flags)); rv < 0 {
		return mgc.error()
	}
	return nil
}

func (mgc *Magic) Load(files ...string) error {
	mgc.Lock()
	defer mgc.Unlock()

	var cfiles *C.char
	if len(files) != 0 {
		cfiles = C.CString(strings.Join(files, ":"))
		defer C.free(unsafe.Pointer(cfiles))
	}

	if rv := C.magic_load_wrapper(mgc.cookie, cfiles); rv < 0 {
		return mgc.error()
	}
	return nil
}

func (mgc *Magic) Compile(files ...string) error {
	mgc.Lock()
	defer mgc.Unlock()

	var cfiles *C.char
	if len(files) != 0 {
		cfiles = C.CString(strings.Join(files, ":"))
		defer C.free(unsafe.Pointer(cfiles))
	}

	if rv := C.magic_compile_wrapper(mgc.cookie, cfiles); rv < 0 {
		return mgc.error()
	}
	return nil
}

func (mgc *Magic) Check(files ...string) error {
	mgc.Lock()
	defer mgc.Unlock()

	var cfiles *C.char
	if len(files) != 0 {
		cfiles = C.CString(strings.Join(files, ":"))
		defer C.free(unsafe.Pointer(cfiles))
	}

	if rv := C.magic_check_wrapper(mgc.cookie, cfiles); rv < 0 {
		return mgc.error()
	}
	return nil
}

func (mgc *Magic) File(filename string) (string, error) {
	mgc.Lock()
	defer mgc.Unlock()

	cfilename := C.CString(filename)
	defer C.free(unsafe.Pointer(cfilename))

	cstring := C.magic_file(mgc.cookie, cfilename)
	if cstring == nil {
		return "", mgc.error()
	}
	return C.GoString(cstring), nil
}

func (mgc *Magic) Buffer(buffer []byte) (string, error) {
	mgc.Lock()
	defer mgc.Unlock()

	p, length := unsafe.Pointer(&buffer[0]), C.size_t(len(buffer))

	cstring := C.magic_buffer(mgc.cookie, p, length)
	if cstring == nil {
		return "", mgc.error()
	}
	return C.GoString(cstring), nil
}

func (mgc *Magic) Descriptor(fd uintptr) (string, error) {
	mgc.Lock()
	defer mgc.Unlock()

	cstring := C.magic_descriptor(mgc.cookie, C.int(fd))
	if cstring == nil {
		return "", mgc.error()
	}
	return C.GoString(cstring), nil
}

func (mgc *Magic) Version() (int, error) {
	mgc.Lock()
	defer mgc.Unlock()

	v := int(C.magic_version_wrapper())
	if v < 0 {
		return v, &MagicError{v, "function not implemented"}
	}
	return v, nil
}

func (mgc *Magic) error() *MagicError {
	errno := int(C.magic_errno(mgc.cookie))
	cstring := C.magic_error(mgc.cookie)
	if cstring != nil {
		return &MagicError{errno, C.GoString(cstring)}
	}
	return nil
}

func (mgc *Magic) destroy() {
	mgc.Close()
}

func Compile(files ...string) error {
	mgc := New()
	if err := mgc.Compile(files...); err != nil {
		return err
	}
	defer mgc.Close()
	return nil
}

func Check(files ...string) error {
	mgc := New()
	if err := mgc.Check(files...); err != nil {
		return err
	}
	defer mgc.Close()
	return nil
}

func FileMime(filename string, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME)
	return mgc.File(filename)
}

func FileEncoding(filename string, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME_ENCODING)
	return mgc.File(filename)
}

func FileType(filename string, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME_TYPE)
	return mgc.File(filename)
}

func BufferMime(buffer []byte, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME)
	return mgc.Buffer(buffer)
}

func BufferEncoding(buffer []byte, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME_ENCODING)
	return mgc.Buffer(buffer)
}

func BufferType(buffer []byte, files ...string) (string, error) {
	mgc := New()
	if err := mgc.Load(files...); err != nil {
		return "", err
	}
	defer mgc.Close()

	mgc.SetFlags(MIME_TYPE)
	return mgc.Buffer(buffer)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strconv"
	"strings"
)

const pathToDokugenAnalysis = "../../"
const pathFromDokugenAnalysis = "internal/a-b-tester/"

const pathToWekaTrainer = "../weka-trainer/"
const pathFromWekaTrainer = "../a-b-tester/"

//TODO: amek this resilient to not being run in the package's directory

//TODO: allow the user to specify multiple branches/configs to test, and it reports the best config.

//TODO: allow the user to generate relativedifficulties from scratch, too, which automates the entire pipeline.

type appOptions struct {
	relativeDifficultiesFile string
	solvesFile               string
	analysisFile             string
	branches                 string
	branchesList             []string
	help                     bool
	flagSet                  *flag.FlagSet
}

func (a *appOptions) defineFlags() {
	if a.flagSet == nil {
		return
	}
	a.flagSet.StringVar(&a.branches, "b", "", "Git branch to checkout. Can also be a space delimited list of multiple branches to checkout.")
	a.flagSet.StringVar(&a.relativeDifficultiesFile, "r", "relativedifficulties_SAMPLED.csv", "The file to use as relative difficulties input")
	a.flagSet.StringVar(&a.solvesFile, "s", "solves.csv", "The file to output solves to")
	a.flagSet.StringVar(&a.analysisFile, "a", "analysis.txt", "The file to output analysis to")
	a.flagSet.BoolVar(&a.help, "h", false, "If provided, will print help and exit.")
}

func (a *appOptions) fixUp() {
	a.branchesList = strings.Split(a.branches, " ")
	a.solvesFile = strings.Replace(a.solvesFile, ".csv", "", -1)
	a.analysisFile = strings.Replace(a.analysisFile, ".txt", "", -1)
}

func (a *appOptions) parse(args []string) {
	a.flagSet.Parse(args)
	a.fixUp()
}

func newAppOptions(flagSet *flag.FlagSet) *appOptions {
	a := &appOptions{
		flagSet: flagSet,
	}
	a.defineFlags()
	return a
}

func main() {
	a := newAppOptions(flag.CommandLine)
	a.parse(os.Args[1:])

	results := make(map[string]float64)

	for _, branch := range a.branchesList {

		if branch == "" {
			log.Println("Staying on the current branch.")
		} else {
			log.Println("Switching to branch", branch)
		}

		//a.analysisFile and a.solvesFile have had their extension removed, if they had one.
		effectiveSolvesFile := a.solvesFile + ".csv"
		effectiveAnalysisFile := a.analysisFile + ".txt"

		if branch != "" {

			effectiveSolvesFile = a.solvesFile + "_" + strings.ToUpper(branch) + ".csv"
			effectiveAnalysisFile = a.analysisFile + "_" + strings.ToUpper(branch) + ".txt"
		}

		if !checkoutGitBranch(branch) {
			log.Println("Couldn't switch to branch", branch, " (perhaps you have uncommitted changes?). Quitting.")
			return
		}

		//TODO: support sampling from relative_difficulties via command line option here.

		runSolves(a.relativeDifficultiesFile, effectiveSolvesFile)

		branchKey := branch

		if branchKey == "" {
			branchKey = "DEFAULT"
		}

		results[branchKey] = runWeka(effectiveSolvesFile, effectiveAnalysisFile)
	}

	fmt.Println("Results:")
	for key, val := range results {
		//TODO: pretty print in a table
		fmt.Println(key, "=", val)
	}

	//TODO: highlight the branch with highest r2

	//TODO: should we be cleaning up the files we output (perhaps only if option provided?0)

	//TODO: switch back to the branch we started on.
}

func runSolves(difficultiesFile, solvesOutputFile string) {

	os.Chdir(pathToDokugenAnalysis)

	defer func() {
		os.Chdir(pathFromDokugenAnalysis)
	}()

	//Build the dokugen-analysis executable to make sure we get the freshest version of the sudoku pacakge.
	cmd := exec.Command("go", "build")
	err := cmd.Run()

	if err != nil {
		log.Println(err)
		return
	}

	outFile, err := os.Create(path.Join(pathFromDokugenAnalysis, solvesOutputFile))

	if err != nil {
		log.Println(err)
		return
	}

	analysisCmd := exec.Command("./dokugen-analysis", "-a", "-v", "-w", "-t", "-h", "-no-cache", path.Join(pathFromDokugenAnalysis, difficultiesFile))
	analysisCmd.Stdout = outFile
	analysisCmd.Stderr = os.Stderr
	err = analysisCmd.Run()

	if err != nil {
		log.Println(err)
	}
}

func runWeka(solvesFile string, analysisFile string) float64 {

	os.Chdir(pathToWekaTrainer)

	defer func() {
		os.Chdir(pathFromWekaTrainer)
	}()

	//Build the weka-trainer executable to make sure we get the freshest version of the sudoku pacakge.
	cmd := exec.Command("go", "build")
	err := cmd.Run()

	if err != nil {
		log.Println(err)
		return 0.0
	}

	trainCmd := exec.Command("./weka-trainer", "-i", path.Join(pathFromWekaTrainer, solvesFile), "-o", path.Join(pathFromWekaTrainer, analysisFile))
	trainCmd.Stderr = os.Stderr
	output, err := trainCmd.Output()

	if err != nil {
		log.Println(err)
		return 0.0
	}

	fmt.Printf("%s", string(output))

	return extractR2(string(output))

}

//extractR2 extracts R2 out of the string formatted like "R2 = <float>"
func extractR2(input string) float64 {

	input = strings.TrimPrefix(input, "R2 = ")

	result, _ := strconv.ParseFloat(input, 64)

	return result

}

//gitCurrentBranch returns the current branch that the current repo is in.
func gitCurrentBranch() string {
	branchCmd := exec.Command("git", "branch")

	output, err := branchCmd.Output()

	if err != nil {
		log.Println(err)
		return ""
	}

	for _, line := range strings.Split(string(output), "\n") {
		if strings.Contains(line, "*") {
			//Found it!
			line = strings.Replace(line, "*", "", -1)
			line = strings.TrimSpace(line)
			return line
		}
	}

	return ""
}

func checkoutGitBranch(branch string) bool {

	if branch == "" {
		return true
	}

	checkoutCmd := exec.Command("git", "checkout", branch)
	checkoutCmd.Run()

	if gitCurrentBranch() != branch {
		return false
	}

	return true

}
<commit_msg>Fixed it so we print out the right r2 (fixed extractR2)<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strconv"
	"strings"
)

const pathToDokugenAnalysis = "../../"
const pathFromDokugenAnalysis = "internal/a-b-tester/"

const pathToWekaTrainer = "../weka-trainer/"
const pathFromWekaTrainer = "../a-b-tester/"

//TODO: amek this resilient to not being run in the package's directory

//TODO: allow the user to specify multiple branches/configs to test, and it reports the best config.

//TODO: allow the user to generate relativedifficulties from scratch, too, which automates the entire pipeline.

type appOptions struct {
	relativeDifficultiesFile string
	solvesFile               string
	analysisFile             string
	branches                 string
	branchesList             []string
	help                     bool
	flagSet                  *flag.FlagSet
}

func (a *appOptions) defineFlags() {
	if a.flagSet == nil {
		return
	}
	a.flagSet.StringVar(&a.branches, "b", "", "Git branch to checkout. Can also be a space delimited list of multiple branches to checkout.")
	a.flagSet.StringVar(&a.relativeDifficultiesFile, "r", "relativedifficulties_SAMPLED.csv", "The file to use as relative difficulties input")
	a.flagSet.StringVar(&a.solvesFile, "s", "solves.csv", "The file to output solves to")
	a.flagSet.StringVar(&a.analysisFile, "a", "analysis.txt", "The file to output analysis to")
	a.flagSet.BoolVar(&a.help, "h", false, "If provided, will print help and exit.")
}

func (a *appOptions) fixUp() {
	a.branchesList = strings.Split(a.branches, " ")
	a.solvesFile = strings.Replace(a.solvesFile, ".csv", "", -1)
	a.analysisFile = strings.Replace(a.analysisFile, ".txt", "", -1)
}

func (a *appOptions) parse(args []string) {
	a.flagSet.Parse(args)
	a.fixUp()
}

func newAppOptions(flagSet *flag.FlagSet) *appOptions {
	a := &appOptions{
		flagSet: flagSet,
	}
	a.defineFlags()
	return a
}

func main() {
	a := newAppOptions(flag.CommandLine)
	a.parse(os.Args[1:])

	results := make(map[string]float64)

	for _, branch := range a.branchesList {

		if branch == "" {
			log.Println("Staying on the current branch.")
		} else {
			log.Println("Switching to branch", branch)
		}

		//a.analysisFile and a.solvesFile have had their extension removed, if they had one.
		effectiveSolvesFile := a.solvesFile + ".csv"
		effectiveAnalysisFile := a.analysisFile + ".txt"

		if branch != "" {

			effectiveSolvesFile = a.solvesFile + "_" + strings.ToUpper(branch) + ".csv"
			effectiveAnalysisFile = a.analysisFile + "_" + strings.ToUpper(branch) + ".txt"
		}

		if !checkoutGitBranch(branch) {
			log.Println("Couldn't switch to branch", branch, " (perhaps you have uncommitted changes?). Quitting.")
			return
		}

		//TODO: support sampling from relative_difficulties via command line option here.

		runSolves(a.relativeDifficultiesFile, effectiveSolvesFile)

		branchKey := branch

		if branchKey == "" {
			branchKey = "DEFAULT"
		}

		results[branchKey] = runWeka(effectiveSolvesFile, effectiveAnalysisFile)
	}

	fmt.Println("Results:")
	for key, val := range results {
		//TODO: pretty print in a table
		fmt.Println(key, "=", val)
	}

	//TODO: highlight the branch with highest r2

	//TODO: should we be cleaning up the files we output (perhaps only if option provided?0)

	//TODO: switch back to the branch we started on.
}

func runSolves(difficultiesFile, solvesOutputFile string) {

	os.Chdir(pathToDokugenAnalysis)

	defer func() {
		os.Chdir(pathFromDokugenAnalysis)
	}()

	//Build the dokugen-analysis executable to make sure we get the freshest version of the sudoku pacakge.
	cmd := exec.Command("go", "build")
	err := cmd.Run()

	if err != nil {
		log.Println(err)
		return
	}

	outFile, err := os.Create(path.Join(pathFromDokugenAnalysis, solvesOutputFile))

	if err != nil {
		log.Println(err)
		return
	}

	analysisCmd := exec.Command("./dokugen-analysis", "-a", "-v", "-w", "-t", "-h", "-no-cache", path.Join(pathFromDokugenAnalysis, difficultiesFile))
	analysisCmd.Stdout = outFile
	analysisCmd.Stderr = os.Stderr
	err = analysisCmd.Run()

	if err != nil {
		log.Println(err)
	}
}

func runWeka(solvesFile string, analysisFile string) float64 {

	os.Chdir(pathToWekaTrainer)

	defer func() {
		os.Chdir(pathFromWekaTrainer)
	}()

	//Build the weka-trainer executable to make sure we get the freshest version of the sudoku pacakge.
	cmd := exec.Command("go", "build")
	err := cmd.Run()

	if err != nil {
		log.Println(err)
		return 0.0
	}

	trainCmd := exec.Command("./weka-trainer", "-i", path.Join(pathFromWekaTrainer, solvesFile), "-o", path.Join(pathFromWekaTrainer, analysisFile))
	trainCmd.Stderr = os.Stderr
	output, err := trainCmd.Output()

	if err != nil {
		log.Println(err)
		return 0.0
	}

	fmt.Printf("%s", string(output))

	return extractR2(string(output))

}

//extractR2 extracts R2 out of the string formatted like "R2 = <float>"
func extractR2(input string) float64 {

	input = strings.TrimPrefix(input, "R2 = ")
	input = strings.TrimSpace(input)

	result, _ := strconv.ParseFloat(input, 64)

	return result

}

//gitCurrentBranch returns the current branch that the current repo is in.
func gitCurrentBranch() string {
	branchCmd := exec.Command("git", "branch")

	output, err := branchCmd.Output()

	if err != nil {
		log.Println(err)
		return ""
	}

	for _, line := range strings.Split(string(output), "\n") {
		if strings.Contains(line, "*") {
			//Found it!
			line = strings.Replace(line, "*", "", -1)
			line = strings.TrimSpace(line)
			return line
		}
	}

	return ""
}

func checkoutGitBranch(branch string) bool {

	if branch == "" {
		return true
	}

	checkoutCmd := exec.Command("git", "checkout", branch)
	checkoutCmd.Run()

	if gitCurrentBranch() != branch {
		return false
	}

	return true

}
<|endoftext|>


<commit_before>// TODO: Make these into real *testing.T tests
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strings"

	"github.com/yext/yext-go"
)

func main() {
	client := yext.NewClient(yext.NewDefaultConfig().WithEnvCredentials())

	llr, _, err := client.LocationService.List(nil)
	fatalif(err)
	log.Println(printllr(llr))

	llr, _, err = client.LocationService.List(&yext.ListOptions{})
	fatalif(err)
	log.Println(printllr(llr))

	llr, _, err = client.LocationService.List(&yext.ListOptions{Limit: 2})
	fatalif(err)
	log.Println(printllr(llr))

	llr, _, err = client.LocationService.List(&yext.ListOptions{Offset: 1})
	fatalif(err)
	log.Println(printllr(llr))

	llr, _, err = client.LocationService.List(&yext.ListOptions{Offset: 5})
	fatalif(err)
	log.Println(printllr(llr))

	locs, err := client.LocationService.ListAll()
	fatalif(err)
	log.Println(printlocs(locs))

	cfs, err := client.CustomFieldService.ListAll()
	fatalif(err)
	log.Println(printjson(cfs))

	fs, err := client.FolderService.ListAll()
	fatalif(err)
	log.Println(printjson(fs))

	plr, _, err := client.ListService.ListProductLists(nil)
	fatalif(err)
	log.Println(printjson(plr.ProductLists))

	ps, err := client.ListService.ListAllProductLists()
	fatalif(err)
	log.Println(printjson(ps))

	blr, _, err := client.ListService.ListBioLists(nil)
	fatalif(err)
	log.Println(printjson(blr.BioLists))

	bs, err := client.ListService.ListAllBioLists()
	fatalif(err)
	log.Println(printjson(bs))

	elr, _, err := client.ListService.ListEventLists(nil)
	fatalif(err)
	log.Println(printjson(elr.EventLists))

	es, err := client.ListService.ListAllEventLists()
	fatalif(err)
	log.Println(printjson(es))

	us, err := client.UserService.ListAll()
	fatalif(err)
	log.Println(printjson(us))

	rs, _, err := client.UserService.ListRoles()
	fatalif(err)
	log.Println(printjson(rs))
}

func fatalif(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func printllr(llr *yext.LocationListResponse) string {
	return fmt.Sprintf("count=%d, locs=%s", llr.Count, printlocs(llr.Locations))
}

func printlocs(locs []*yext.Location) string {
	var ids []string
	for _, loc := range locs {
		ids = append(ids, loc.GetId())
	}
	return strings.Join(ids, ",")
}

func printjson(v interface{}) string {
	data, _ := json.Marshal(v)
	return string(data)
}
<commit_msg>fix compliation for test script by pointing to the correct package<commit_after>// TODO: Make these into real *testing.T tests
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strings"

	"gopkg.in/yext/yext-go.v2"
)

func main() {
	client := yext.NewClient(yext.NewDefaultConfig().WithEnvCredentials())

	llr, _, err := client.LocationService.List(nil)
	fatalif(err)
	log.Println(printllr(llr))

	llr, _, err = client.LocationService.List(&yext.ListOptions{})
	fatalif(err)
	log.Println(printllr(llr))

	llr, _, err = client.LocationService.List(&yext.ListOptions{Limit: 2})
	fatalif(err)
	log.Println(printllr(llr))

	llr, _, err = client.LocationService.List(&yext.ListOptions{Offset: 1})
	fatalif(err)
	log.Println(printllr(llr))

	llr, _, err = client.LocationService.List(&yext.ListOptions{Offset: 5})
	fatalif(err)
	log.Println(printllr(llr))

	locs, err := client.LocationService.ListAll()
	fatalif(err)
	log.Println(printlocs(locs))

	cfs, err := client.CustomFieldService.ListAll()
	fatalif(err)
	log.Println(printjson(cfs))

	fs, err := client.FolderService.ListAll()
	fatalif(err)
	log.Println(printjson(fs))

	plr, _, err := client.ListService.ListProductLists(nil)
	fatalif(err)
	log.Println(printjson(plr.ProductLists))

	ps, err := client.ListService.ListAllProductLists()
	fatalif(err)
	log.Println(printjson(ps))

	blr, _, err := client.ListService.ListBioLists(nil)
	fatalif(err)
	log.Println(printjson(blr.BioLists))

	bs, err := client.ListService.ListAllBioLists()
	fatalif(err)
	log.Println(printjson(bs))

	elr, _, err := client.ListService.ListEventLists(nil)
	fatalif(err)
	log.Println(printjson(elr.EventLists))

	es, err := client.ListService.ListAllEventLists()
	fatalif(err)
	log.Println(printjson(es))

	us, err := client.UserService.ListAll()
	fatalif(err)
	log.Println(printjson(us))

	rs, _, err := client.UserService.ListRoles()
	fatalif(err)
	log.Println(printjson(rs))
}

func fatalif(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func printllr(llr *yext.LocationListResponse) string {
	return fmt.Sprintf("count=%d, locs=%s", llr.Count, printlocs(llr.Locations))
}

func printlocs(locs []*yext.Location) string {
	var ids []string
	for _, loc := range locs {
		ids = append(ids, loc.GetId())
	}
	return strings.Join(ids, ",")
}

func printjson(v interface{}) string {
	data, _ := json.Marshal(v)
	return string(data)
}
<|endoftext|>


<commit_before>package loggenrunner

import (
	"bytes"
	"math/rand"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
)

// DataStore holds all the data info for a given simulated log line
type DataStore struct {
	Text string `json:"text"`
}

// RunLogLineParams holds all the data to be passed to RunLogLine
type RunLogLineParams struct {
	HTTPLoc        string
	PostBody       string
	IntervalSecs   int
	IntervalStdDev float64
}

// randomizeString takes a string, looks for the random tokens (int and string), and replaces them
func randomizeString(text string, timeformat string) string {
	// Bail if we can't get any randomizers
	goodstring, err := regexp.MatchString(`\$\[[^\]]+\]`, text)
	if err != nil {
		log.Error("Something broke on parsing the text string with a regular expression")
	}

	//Return original string if no randomizers
	if !goodstring {
		return text
	}

	// Find all randomizing tokens
	re := regexp.MustCompile(`\$\[[^\]]+\]`)
	randos := re.FindAllString(text, -1)
	log.Debug("Random tokens: ", randos)

	// Create a list of new strings to be inserted where the tokens were
	var newstrings []string
	replacer := strings.NewReplacer("$[", "", "]", "")

	// Append the properly randomized values to the newstrings slice
	for _, rando := range randos {
		// Take off the leading and trailing formatting
		tempstring := replacer.Replace(rando)
		log.Debug("tempstring: ", tempstring)

		// Split the rnadomizer into individual items
		tempstrings := strings.Split(tempstring, ",")
		log.Debug("tempstrings: ", tempstrings)

		// Numeric ranges will only have two items for an upper and lower bound, timestamps have "time" and "stamp", all the rest are string groups
		var randType string
		num0, err := strconv.Atoi(string(tempstrings[0]))
		num1, err2 := strconv.Atoi(string(tempstrings[1]))
		log.Debug("num0 parsed: ", num0, err)
		log.Debug("num1 parsed: ", num1, err2)
		log.Debug("Length of tempstrings: ", len(tempstrings))
		log.Debug("Numbers?: ", len(tempstrings) == 2 && err == nil && err2 == nil)
		log.Debug("Timestamp?: ", tempstrings[0] == "time" && tempstrings[1] == "stamp")

		if len(tempstrings) == 2 && err == nil && err2 == nil {
			randType = "Number"
		} else {
			if tempstrings[0] == "time" && tempstrings[1] == "stamp" {
				randType = "Timestamp"
			} else {
				randType = "Category"
			}

		}

		switch randType {
		case "Category":
			log.Debug("Treating as Category")
			newstrings = append(newstrings, tempstrings[rand.Intn(len(tempstrings))])
		case "Number":
			log.Debug("Treating as Number")

			// Get a random number in the range
			diff := num1 - num0
			log.Debug("diff parsed: ", diff)
			tempnum := rand.Intn(diff)
			log.Debug("random number: ", tempnum)
			log.Debug("random number as string: ", strconv.Itoa(tempnum+num0))
			newstrings = append(newstrings, strconv.Itoa(tempnum+num0))
		case "Timestamp":
			t := time.Now()
			log.Debug("Current time: ", t)
			timeformatted := t.Format(timeformat)
			log.Debug("Formatted time: ", timeformatted)

			newstrings = append(newstrings, timeformatted)
		}
	}

	nonRandomStrings := re.Split(text, -1)
	var newLogLine []string

	for i := 0; i < len(nonRandomStrings); i++ {
		newLogLine = append(newLogLine, nonRandomStrings[i])
		if i != len(nonRandomStrings)-1 {
			newLogLine = append(newLogLine, newstrings[i])
		}
	}

	log.Info("Randomization complete. New string: ", strings.Join(newLogLine, ""))

	return strings.Join(newLogLine, "")
}

// RunLogLine makes repeated calls to an endpoint given the configs of the log line
func RunLogLine(HTTPLoc string, PostBody string, IntervalSecs int, IntervalStdDev float64, TimeFormat string, SumoCategory string, SumoHost string, SumoName string) {
	log.Info("Starting log runner")

	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	client := &http.Client{}

	// Begin loop to post the value until we're done
	for {
		// Randomize the post body if need be
		var stringBody = []byte(randomizeString(PostBody, TimeFormat))

		// Post to Sumo
		log.Info("Sending log to Sumo: ", stringBody)
		req, err := http.NewRequest("POST", HTTPLoc, bytes.NewBuffer(stringBody))
		req.Header.Add("X-Sumo-Category", SumoCategory)
		req.Header.Add("X-Sumo-Host", SumoHost)
		req.Header.Add("X-Sumo-Name", SumoName)
		resp, err := client.Do(req)
		if err != nil {
			log.Error("something went amiss on submitting to Sumo")
			return
		}
		defer resp.Body.Close()
		log.Debug("Response from Sumo: ", resp)

		// Sleep until the next run
		// Randomize the sleep by specifying the std dev and adding the desired mean... targeting 3%
		milliseconds := IntervalSecs * 1000
		stdDevMilli := IntervalStdDev * 1000.0
		nextInterval := int(r.NormFloat64()*stdDevMilli + float64(milliseconds))
		time.Sleep(time.Duration(nextInterval) * time.Millisecond)
	}

}
<commit_msg>Change if/else to case<commit_after>package loggenrunner

import (
	"bytes"
	"math/rand"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
)

// DataStore holds all the data info for a given simulated log line
type DataStore struct {
	Text string `json:"text"`
}

// RunLogLineParams holds all the data to be passed to RunLogLine
type RunLogLineParams struct {
	HTTPLoc        string
	PostBody       string
	IntervalSecs   int
	IntervalStdDev float64
}

// randomizeString takes a string, looks for the random tokens (int and string), and replaces them
func randomizeString(text string, timeformat string) string {
	// Bail if we can't get any randomizers
	goodstring, err := regexp.MatchString(`\$\[[^\]]+\]`, text)
	if err != nil {
		log.Error("Something broke on parsing the text string with a regular expression")
	}

	//Return original string if no randomizers
	if !goodstring {
		return text
	}

	// Find all randomizing tokens
	re := regexp.MustCompile(`\$\[[^\]]+\]`)
	randos := re.FindAllString(text, -1)
	log.Debug("Random tokens: ", randos)

	// Create a list of new strings to be inserted where the tokens were
	var newstrings []string
	replacer := strings.NewReplacer("$[", "", "]", "")

	// Append the properly randomized values to the newstrings slice
	for _, rando := range randos {
		// Take off the leading and trailing formatting
		tempstring := replacer.Replace(rando)
		log.Debug("tempstring: ", tempstring)

		// Split the rnadomizer into individual items
		tempstrings := strings.Split(tempstring, ",")
		log.Debug("tempstrings: ", tempstrings)

		// Numeric ranges will only have two items for an upper and lower bound, timestamps have "time" and "stamp", all the rest are string groups
		var randType string
		num0, err := strconv.Atoi(string(tempstrings[0]))
		num1, err2 := strconv.Atoi(string(tempstrings[1]))
		log.Debug("num0 parsed: ", num0, err)
		log.Debug("num1 parsed: ", num1, err2)
		log.Debug("Length of tempstrings: ", len(tempstrings))
		log.Debug("Numbers?: ", len(tempstrings) == 2 && err == nil && err2 == nil)
		log.Debug("Timestamp?: ", tempstrings[0] == "time" && tempstrings[1] == "stamp")

		switch {
		case len(tempstrings) == 2 && err == nil && err2 == nil:
			randType = "Number"
		case tempstrings[0] == "time" && tempstrings[1] == "stamp":
			randType = "Timestamp"
		default:
			randType = "Category"
		}

		switch randType {
		case "Category":
			log.Debug("Treating as Category")
			newstrings = append(newstrings, tempstrings[rand.Intn(len(tempstrings))])
		case "Number":
			log.Debug("Treating as Number")

			// Get a random number in the range
			diff := num1 - num0
			log.Debug("diff parsed: ", diff)
			tempnum := rand.Intn(diff)
			log.Debug("random number: ", tempnum)
			log.Debug("random number as string: ", strconv.Itoa(tempnum+num0))
			newstrings = append(newstrings, strconv.Itoa(tempnum+num0))
		case "Timestamp":
			t := time.Now()
			log.Debug("Current time: ", t)
			timeformatted := t.Format(timeformat)
			log.Debug("Formatted time: ", timeformatted)

			newstrings = append(newstrings, timeformatted)
		}
	}

	nonRandomStrings := re.Split(text, -1)
	var newLogLine []string

	for i := 0; i < len(nonRandomStrings); i++ {
		newLogLine = append(newLogLine, nonRandomStrings[i])
		if i != len(nonRandomStrings)-1 {
			newLogLine = append(newLogLine, newstrings[i])
		}
	}

	log.Info("Randomization complete. New string: ", strings.Join(newLogLine, ""))

	return strings.Join(newLogLine, "")
}

// RunLogLine makes repeated calls to an endpoint given the configs of the log line
func RunLogLine(HTTPLoc string, PostBody string, IntervalSecs int, IntervalStdDev float64, TimeFormat string, SumoCategory string, SumoHost string, SumoName string) {
	log.Info("Starting log runner")

	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	client := &http.Client{}

	// Begin loop to post the value until we're done
	for {
		// Randomize the post body if need be
		var stringBody = []byte(randomizeString(PostBody, TimeFormat))

		// Post to Sumo
		log.Info("Sending log to Sumo: ", stringBody)
		req, err := http.NewRequest("POST", HTTPLoc, bytes.NewBuffer(stringBody))
		req.Header.Add("X-Sumo-Category", SumoCategory)
		req.Header.Add("X-Sumo-Host", SumoHost)
		req.Header.Add("X-Sumo-Name", SumoName)
		resp, err := client.Do(req)
		if err != nil {
			log.Error("something went amiss on submitting to Sumo")
			return
		}
		defer resp.Body.Close()
		log.Debug("Response from Sumo: ", resp)

		// Sleep until the next run
		// Randomize the sleep by specifying the std dev and adding the desired mean... targeting 3%
		milliseconds := IntervalSecs * 1000
		stdDevMilli := IntervalStdDev * 1000.0
		nextInterval := int(r.NormFloat64()*stdDevMilli + float64(milliseconds))
		time.Sleep(time.Duration(nextInterval) * time.Millisecond)
	}

}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

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 generators has the generators for the client-gen utility.
package generators

import (
	"fmt"
	"path/filepath"
	"strings"

	"k8s.io/gengo/args"
	"k8s.io/gengo/generator"
	"k8s.io/gengo/namer"
	"k8s.io/gengo/types"
	clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/fake"
	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/scheme"
	clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"

	"github.com/golang/glog"
)

// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
	pluralExceptions := map[string]string{
		"Endpoints":                  "Endpoints",
		"SecurityContextConstraints": "SecurityContextConstraints",
	}

	publicNamer := &ExceptionNamer{
		Exceptions: map[string]string{
			// these exceptions are used to deconflict the generated code
			"github.com/openshift/origin/pkg/build/api/v1.Build":       "BuildResource",
			"github.com/openshift/origin/pkg/build/api.Build":          "BuildResource",
			"github.com/openshift/origin/pkg/image/api/v1.Image":       "ImageResource",
			"github.com/openshift/origin/pkg/image/api.Image":          "ImageResource",
			"github.com/openshift/origin/pkg/project/api/v1.Project":   "ProjectResource",
			"github.com/openshift/origin/pkg/project/api.Project":      "ProjectResource",
			"github.com/openshift/origin/pkg/route/api/v1.Route":       "RouteResource",
			"github.com/openshift/origin/pkg/route/api.Route":          "RouteResource",
			"github.com/openshift/origin/pkg/template/api/v1.Template": "TemplateResource",
			"github.com/openshift/origin/pkg/template/api.Template":    "TemplateResource",
			"github.com/openshift/origin/pkg/user/api/v1.User":         "UserResource",
			"github.com/openshift/origin/pkg/user/api.User":            "UserResource",
		},
		KeyFunc: func(t *types.Type) string {
			return t.Name.Package + "." + t.Name.Name
		},
		Delegate: namer.NewPublicNamer(0),
	}

	return namer.NameSystems{
		"public":             publicNamer,
		"private":            namer.NewPrivateNamer(0),
		"raw":                namer.NewRawNamer("", nil),
		"publicPlural":       namer.NewPublicPluralNamer(pluralExceptions),
		"privatePlural":      namer.NewPrivatePluralNamer(pluralExceptions),
		"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
	}
}

type ExceptionNamer struct {
	Exceptions map[string]string
	KeyFunc    func(*types.Type) string

	Delegate namer.Namer
}

func (n *ExceptionNamer) Name(t *types.Type) string {
	key := n.KeyFunc(t)
	if exception, ok := n.Exceptions[key]; ok {
		return exception
	}

	return n.Delegate.Name(t)
}

// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
	return "public"
}

func generatedBy(customArgs clientgenargs.Args) string {
	if len(customArgs.CmdArgs) != 0 {
		return fmt.Sprintf("\n// This package is generated by client-gen with custom arguments.\n\n")
	}
	return fmt.Sprintf("\n// This package is generated by client-gen with the default arguments.\n\n")
}

func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetPackage string, apiPath string, srcTreePath string, inputPackage string, boilerplate []byte, generatedBy string) generator.Package {
	groupVersionClientPackage := strings.ToLower(filepath.Join(clientsetPackage, "typed", gv.Group.NonEmpty(), gv.Version.NonEmpty()))
	return &generator.DefaultPackage{
		PackageName: strings.ToLower(gv.Version.NonEmpty()),
		PackagePath: groupVersionClientPackage,
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package has the automatically generated typed clients.
`),
		// GeneratorFunc returns a list of generators. Each generator makes a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},
			}
			// Since we want a file per type that we generate a client for, we
			// have to provide a function for this.
			for _, t := range typeList {
				generators = append(generators, &genClientForType{
					DefaultGen: generator.DefaultGen{
						OptionalName: strings.ToLower(c.Namers["private"].Name(t)),
					},
					outputPackage:    groupVersionClientPackage,
					clientsetPackage: clientsetPackage,
					group:            gv.Group.NonEmpty(),
					version:          gv.Version.String(),
					typeToMatch:      t,
					imports:          generator.NewImportTracker(),
				})
			}

			generators = append(generators, &genGroup{
				DefaultGen: generator.DefaultGen{
					OptionalName: gv.Group.NonEmpty() + "_client",
				},
				outputPackage:    groupVersionClientPackage,
				inputPackage:     inputPackage,
				clientsetPackage: clientsetPackage,
				group:            gv.Group.NonEmpty(),
				version:          gv.Version.String(),
				apiPath:          apiPath,
				types:            typeList,
				imports:          generator.NewImportTracker(),
			})

			expansionFileName := "generated_expansion"
			generators = append(generators, &genExpansion{
				groupPackagePath: filepath.Join(srcTreePath, groupVersionClientPackage),
				DefaultGen: generator.DefaultGen{
					OptionalName: expansionFileName,
				},
				types: typeList,
			})

			return generators
		},
		FilterFunc: func(c *generator.Context, t *types.Type) bool {
			return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
		},
	}
}

func packageForClientset(customArgs clientgenargs.Args, clientsetPackage string, boilerplate []byte, generatedBy string) generator.Package {
	return &generator.DefaultPackage{
		PackageName: customArgs.ClientsetName,
		PackagePath: clientsetPackage,
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package has the automatically generated clientset.
`),
		// GeneratorFunc returns a list of generators. Each generator generates a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},

				&genClientset{
					DefaultGen: generator.DefaultGen{
						OptionalName: "clientset",
					},
					groups:           customArgs.Groups,
					clientsetPackage: clientsetPackage,
					outputPackage:    customArgs.ClientsetName,
					imports:          generator.NewImportTracker(),
				},
			}
			return generators
		},
	}
}

func packageForScheme(customArgs clientgenargs.Args, clientsetPackage string, srcTreePath string, boilerplate []byte, generatedBy string) generator.Package {
	schemePackage := filepath.Join(clientsetPackage, "scheme")

	// create runtime.Registry for internal client because it has to know about group versions
	internalClient := false
NextGroup:
	for _, group := range customArgs.Groups {
		for _, v := range group.Versions {
			if v == "" {
				internalClient = true
				break NextGroup
			}
		}
	}

	return &generator.DefaultPackage{
		PackageName: "scheme",
		PackagePath: schemePackage,
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package contains the scheme of the automatically generated clientset.
`),
		// GeneratorFunc returns a list of generators. Each generator generates a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},

				&scheme.GenScheme{
					DefaultGen: generator.DefaultGen{
						OptionalName: "register",
					},
					InputPackages:  customArgs.GroupVersionToInputPath,
					OutputPackage:  schemePackage,
					OutputPath:     filepath.Join(srcTreePath, schemePackage),
					Groups:         customArgs.Groups,
					ImportTracker:  generator.NewImportTracker(),
					CreateRegistry: internalClient,
				},
			}
			return generators
		},
	}
}

// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
	boilerplate, err := arguments.LoadGoBoilerplate()
	if err != nil {
		glog.Fatalf("Failed loading boilerplate: %v", err)
	}

	customArgs, ok := arguments.CustomArgs.(clientgenargs.Args)
	if !ok {
		glog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.Args")
	}
	includedTypesOverrides := customArgs.IncludedTypesOverrides

	generatedBy := generatedBy(customArgs)

	gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{}
	for gv, inputDir := range customArgs.GroupVersionToInputPath {
		p := context.Universe.Package(inputDir)
		for n, t := range p.Types {
			// filter out types which are not included in user specified overrides.
			typesOverride, ok := includedTypesOverrides[gv]
			if ok {
				found := false
				for _, typeStr := range typesOverride {
					if typeStr == n {
						found = true
						break
					}
				}
				if !found {
					continue
				}
			} else {
				// User has not specified any override for this group version.
				// filter out types which dont have genclient=true.
				if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
					continue
				}
			}
			if _, found := gvToTypes[gv]; !found {
				gvToTypes[gv] = []*types.Type{}
			}
			gvToTypes[gv] = append(gvToTypes[gv], t)
		}
	}

	var packageList []generator.Package
	clientsetPackage := filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName)

	packageList = append(packageList, packageForClientset(customArgs, clientsetPackage, boilerplate, generatedBy))
	packageList = append(packageList, packageForScheme(customArgs, clientsetPackage, arguments.OutputBase, boilerplate, generatedBy))
	if customArgs.FakeClient {
		packageList = append(packageList, fake.PackageForClientset(customArgs, clientsetPackage, boilerplate, generatedBy))
	}

	// If --clientset-only=true, we don't regenerate the individual typed clients.
	if customArgs.ClientsetOnly {
		return generator.Packages(packageList)
	}

	orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
	for _, group := range customArgs.Groups {
		for _, version := range group.Versions {
			gv := clientgentypes.GroupVersion{Group: group.Group, Version: version}
			types := gvToTypes[gv]
			inputPath := customArgs.GroupVersionToInputPath[gv]
			packageList = append(packageList, packageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, customArgs.ClientsetAPIPath, arguments.OutputBase, inputPath, boilerplate, generatedBy))
			if customArgs.FakeClient {
				packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, inputPath, boilerplate, generatedBy))
			}
		}
	}

	return generator.Packages(packageList)
}
<commit_msg>UPSTREAM: 45835: client-gen: honor groupName overrides in customArgs<commit_after>/*
Copyright 2015 The Kubernetes Authors.

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 generators has the generators for the client-gen utility.
package generators

import (
	"fmt"
	"path/filepath"
	"strings"

	"k8s.io/gengo/args"
	"k8s.io/gengo/generator"
	"k8s.io/gengo/namer"
	"k8s.io/gengo/types"
	clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/fake"
	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/scheme"
	clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"

	"github.com/golang/glog"
)

// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
	pluralExceptions := map[string]string{
		"Endpoints":                  "Endpoints",
		"SecurityContextConstraints": "SecurityContextConstraints",
	}

	publicNamer := &ExceptionNamer{
		Exceptions: map[string]string{
			// these exceptions are used to deconflict the generated code
			"github.com/openshift/origin/pkg/build/api/v1.Build":       "BuildResource",
			"github.com/openshift/origin/pkg/build/api.Build":          "BuildResource",
			"github.com/openshift/origin/pkg/image/api/v1.Image":       "ImageResource",
			"github.com/openshift/origin/pkg/image/api.Image":          "ImageResource",
			"github.com/openshift/origin/pkg/project/api/v1.Project":   "ProjectResource",
			"github.com/openshift/origin/pkg/project/api.Project":      "ProjectResource",
			"github.com/openshift/origin/pkg/route/api/v1.Route":       "RouteResource",
			"github.com/openshift/origin/pkg/route/api.Route":          "RouteResource",
			"github.com/openshift/origin/pkg/template/api/v1.Template": "TemplateResource",
			"github.com/openshift/origin/pkg/template/api.Template":    "TemplateResource",
			"github.com/openshift/origin/pkg/user/api/v1.User":         "UserResource",
			"github.com/openshift/origin/pkg/user/api.User":            "UserResource",
		},
		KeyFunc: func(t *types.Type) string {
			return t.Name.Package + "." + t.Name.Name
		},
		Delegate: namer.NewPublicNamer(0),
	}

	return namer.NameSystems{
		"public":             publicNamer,
		"private":            namer.NewPrivateNamer(0),
		"raw":                namer.NewRawNamer("", nil),
		"publicPlural":       namer.NewPublicPluralNamer(pluralExceptions),
		"privatePlural":      namer.NewPrivatePluralNamer(pluralExceptions),
		"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
	}
}

type ExceptionNamer struct {
	Exceptions map[string]string
	KeyFunc    func(*types.Type) string

	Delegate namer.Namer
}

func (n *ExceptionNamer) Name(t *types.Type) string {
	key := n.KeyFunc(t)
	if exception, ok := n.Exceptions[key]; ok {
		return exception
	}

	return n.Delegate.Name(t)
}

// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
	return "public"
}

func generatedBy(customArgs clientgenargs.Args) string {
	if len(customArgs.CmdArgs) != 0 {
		return fmt.Sprintf("\n// This package is generated by client-gen with custom arguments.\n\n")
	}
	return fmt.Sprintf("\n// This package is generated by client-gen with the default arguments.\n\n")
}

func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetPackage string, apiPath string, srcTreePath string, inputPackage string, boilerplate []byte, generatedBy string) generator.Package {
	groupVersionClientPackage := strings.ToLower(filepath.Join(clientsetPackage, "typed", gv.Group.NonEmpty(), gv.Version.NonEmpty()))
	return &generator.DefaultPackage{
		PackageName: strings.ToLower(gv.Version.NonEmpty()),
		PackagePath: groupVersionClientPackage,
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package has the automatically generated typed clients.
`),
		// GeneratorFunc returns a list of generators. Each generator makes a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},
			}
			// Since we want a file per type that we generate a client for, we
			// have to provide a function for this.
			for _, t := range typeList {
				generators = append(generators, &genClientForType{
					DefaultGen: generator.DefaultGen{
						OptionalName: strings.ToLower(c.Namers["private"].Name(t)),
					},
					outputPackage:    groupVersionClientPackage,
					clientsetPackage: clientsetPackage,
					group:            gv.Group.NonEmpty(),
					version:          gv.Version.String(),
					typeToMatch:      t,
					imports:          generator.NewImportTracker(),
				})
			}

			generators = append(generators, &genGroup{
				DefaultGen: generator.DefaultGen{
					OptionalName: gv.Group.NonEmpty() + "_client",
				},
				outputPackage:    groupVersionClientPackage,
				inputPackage:     inputPackage,
				clientsetPackage: clientsetPackage,
				group:            gv.Group.NonEmpty(),
				version:          gv.Version.String(),
				apiPath:          apiPath,
				types:            typeList,
				imports:          generator.NewImportTracker(),
			})

			expansionFileName := "generated_expansion"
			generators = append(generators, &genExpansion{
				groupPackagePath: filepath.Join(srcTreePath, groupVersionClientPackage),
				DefaultGen: generator.DefaultGen{
					OptionalName: expansionFileName,
				},
				types: typeList,
			})

			return generators
		},
		FilterFunc: func(c *generator.Context, t *types.Type) bool {
			return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
		},
	}
}

func packageForClientset(customArgs clientgenargs.Args, clientsetPackage string, boilerplate []byte, generatedBy string) generator.Package {
	return &generator.DefaultPackage{
		PackageName: customArgs.ClientsetName,
		PackagePath: clientsetPackage,
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package has the automatically generated clientset.
`),
		// GeneratorFunc returns a list of generators. Each generator generates a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},

				&genClientset{
					DefaultGen: generator.DefaultGen{
						OptionalName: "clientset",
					},
					groups:           customArgs.Groups,
					clientsetPackage: clientsetPackage,
					outputPackage:    customArgs.ClientsetName,
					imports:          generator.NewImportTracker(),
				},
			}
			return generators
		},
	}
}

func packageForScheme(customArgs clientgenargs.Args, clientsetPackage string, srcTreePath string, boilerplate []byte, generatedBy string) generator.Package {
	schemePackage := filepath.Join(clientsetPackage, "scheme")

	// create runtime.Registry for internal client because it has to know about group versions
	internalClient := false
NextGroup:
	for _, group := range customArgs.Groups {
		for _, v := range group.Versions {
			if v == "" {
				internalClient = true
				break NextGroup
			}
		}
	}

	return &generator.DefaultPackage{
		PackageName: "scheme",
		PackagePath: schemePackage,
		HeaderText:  boilerplate,
		PackageDocumentation: []byte(
			generatedBy +
				`// This package contains the scheme of the automatically generated clientset.
`),
		// GeneratorFunc returns a list of generators. Each generator generates a
		// single file.
		GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
			generators = []generator.Generator{
				// Always generate a "doc.go" file.
				generator.DefaultGen{OptionalName: "doc"},

				&scheme.GenScheme{
					DefaultGen: generator.DefaultGen{
						OptionalName: "register",
					},
					InputPackages:  customArgs.GroupVersionToInputPath,
					OutputPackage:  schemePackage,
					OutputPath:     filepath.Join(srcTreePath, schemePackage),
					Groups:         customArgs.Groups,
					ImportTracker:  generator.NewImportTracker(),
					CreateRegistry: internalClient,
				},
			}
			return generators
		},
	}
}

// applyGroupOverrides applies group name overrides to each package, if applicable. If there is a
// comment of the form "// +groupName=somegroup" or "// +groupName=somegroup.foo.bar.io", use the
// first field (somegroup) as the name of the group when generating.
func applyGroupOverrides(universe types.Universe, customArgs *clientgenargs.Args) {
	// Create a map from "old GV" to "new GV" so we know what changes we need to make.
	changes := make(map[clientgentypes.GroupVersion]clientgentypes.GroupVersion)
	for gv, inputDir := range customArgs.GroupVersionToInputPath {
		p := universe.Package(inputDir)
		if override := types.ExtractCommentTags("+", p.DocComments)["groupName"]; override != nil {
			newGV := clientgentypes.GroupVersion{
				Group:   clientgentypes.Group(strings.SplitN(override[0], ".", 2)[0]),
				Version: gv.Version,
			}
			changes[gv] = newGV
		}
	}

	// Modify customArgs.Groups based on the groupName overrides.
	newGroups := make([]clientgentypes.GroupVersions, 0, len(customArgs.Groups))
	for _, gvs := range customArgs.Groups {
		gv := clientgentypes.GroupVersion{
			Group:   gvs.Group,
			Version: gvs.Versions[0], // we only need a version, and the first will do
		}
		if newGV, ok := changes[gv]; ok {
			// There's an override, so use it.
			newGVS := clientgentypes.GroupVersions{
				Group:    newGV.Group,
				Versions: gvs.Versions,
			}
			newGroups = append(newGroups, newGVS)
		} else {
			// No override.
			newGroups = append(newGroups, gvs)
		}
	}
	customArgs.Groups = newGroups

	// Modify customArgs.GroupVersionToInputPath based on the groupName overrides.
	newGVToInputPath := make(map[clientgentypes.GroupVersion]string)
	for gv, inputDir := range customArgs.GroupVersionToInputPath {
		if newGV, ok := changes[gv]; ok {
			// There's an override, so use it.
			newGVToInputPath[newGV] = inputDir
		} else {
			// No override.
			newGVToInputPath[gv] = inputDir
		}
	}
	customArgs.GroupVersionToInputPath = newGVToInputPath
}

// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
	boilerplate, err := arguments.LoadGoBoilerplate()
	if err != nil {
		glog.Fatalf("Failed loading boilerplate: %v", err)
	}

	customArgs, ok := arguments.CustomArgs.(clientgenargs.Args)
	if !ok {
		glog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.Args")
	}
	includedTypesOverrides := customArgs.IncludedTypesOverrides

	applyGroupOverrides(context.Universe, &customArgs)

	generatedBy := generatedBy(customArgs)

	gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{}
	for gv, inputDir := range customArgs.GroupVersionToInputPath {
		p := context.Universe.Package(inputDir)
		for n, t := range p.Types {
			// filter out types which are not included in user specified overrides.
			typesOverride, ok := includedTypesOverrides[gv]
			if ok {
				found := false
				for _, typeStr := range typesOverride {
					if typeStr == n {
						found = true
						break
					}
				}
				if !found {
					continue
				}
			} else {
				// User has not specified any override for this group version.
				// filter out types which dont have genclient=true.
				if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
					continue
				}
			}
			if _, found := gvToTypes[gv]; !found {
				gvToTypes[gv] = []*types.Type{}
			}
			gvToTypes[gv] = append(gvToTypes[gv], t)
		}
	}

	var packageList []generator.Package
	clientsetPackage := filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName)

	packageList = append(packageList, packageForClientset(customArgs, clientsetPackage, boilerplate, generatedBy))
	packageList = append(packageList, packageForScheme(customArgs, clientsetPackage, arguments.OutputBase, boilerplate, generatedBy))
	if customArgs.FakeClient {
		packageList = append(packageList, fake.PackageForClientset(customArgs, clientsetPackage, boilerplate, generatedBy))
	}

	// If --clientset-only=true, we don't regenerate the individual typed clients.
	if customArgs.ClientsetOnly {
		return generator.Packages(packageList)
	}

	orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
	for _, group := range customArgs.Groups {
		for _, version := range group.Versions {
			gv := clientgentypes.GroupVersion{Group: group.Group, Version: version}
			types := gvToTypes[gv]
			inputPath := customArgs.GroupVersionToInputPath[gv]
			packageList = append(packageList, packageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, customArgs.ClientsetAPIPath, arguments.OutputBase, inputPath, boilerplate, generatedBy))
			if customArgs.FakeClient {
				packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, inputPath, boilerplate, generatedBy))
			}
		}
	}

	return generator.Packages(packageList)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0

package integrationtest

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/terraform-providers/terraform-provider-oci/internal/acctest"
	tf_client "github.com/terraform-providers/terraform-provider-oci/internal/client"
	"github.com/terraform-providers/terraform-provider-oci/internal/tfresource"
	"github.com/terraform-providers/terraform-provider-oci/internal/utils"

	oci_common "github.com/oracle/oci-go-sdk/v55/common"
	oci_database "github.com/oracle/oci-go-sdk/v55/database"
	oci_identity "github.com/oracle/oci-go-sdk/v55/identity"
)

func createAdbInRegion(clients *tf_client.OracleClients, region string) (string, error) {
	compartmentId := utils.GetEnvSettingWithBlankDefault("compartment_ocid")

	databaseClient, err := oci_database.NewDatabaseClientWithConfigurationProvider(*clients.DatabaseClient().ConfigurationProvider())
	if err != nil {
		return "", fmt.Errorf("cannot Create client for the source region %s: %v", region, err)
	}
	err = tf_client.ConfigureClientVar(&databaseClient.BaseClient)
	if err != nil {
		return "", fmt.Errorf("cannot configure client for the source region: %v", err)
	}
	databaseClient.SetRegion(region)
	identityClient, err := oci_identity.NewIdentityClientWithConfigurationProvider(*clients.IdentityClient().ConfigurationProvider())
	if err != nil {
		return "", fmt.Errorf("cannot Create client for the source region %s: %v", region, err)
	}
	err = tf_client.ConfigureClientVar(&identityClient.BaseClient)
	if err != nil {
		return "", fmt.Errorf("cannot configure client for the source region: %v", err)
	}
	identityClient.SetRegion(region)

	cpu_core_count := 1
	data_storage_size_in_tbs := 1
	admin_password := string("BEstrO0ng_#11")
	db_name := utils.RandomString(13, utils.Charset)
	display_name := string("example_cr_source")
	is_dedicated := false

	createAdbResponse, err := databaseClient.CreateAutonomousDatabase(context.Background(), oci_database.CreateAutonomousDatabaseRequest{
		CreateAutonomousDatabaseDetails: oci_database.CreateAutonomousDatabaseDetails{
			CompartmentId:        &compartmentId,
			CpuCoreCount:         &cpu_core_count,
			DataStorageSizeInTBs: &data_storage_size_in_tbs,
			AdminPassword:        &admin_password,
			DbName:               &db_name,
			DisplayName:          &display_name,
			IsDedicated:          &is_dedicated,
		},
		RequestMetadata: oci_common.RequestMetadata{
			RetryPolicy: tfresource.GetRetryPolicy(false, "database"),
		},
	})
	if err != nil {
		return "", fmt.Errorf("[WARN] failed to Create adb with the error %v", err)
	}
	retryPolicy := tfresource.GetRetryPolicy(false, "database")
	retryPolicy.ShouldRetryOperation = acctest.ConditionShouldRetry(time.Duration(10*time.Minute), adbSweepWaitCondition, "database", false)

	if err != nil {
		return "", fmt.Errorf("[WARN] wait for adbSweepWaitCondition failed for %s resource with error %v", *createAdbResponse.Id, err)
	} else {
		log.Printf("[INFO] end of WaitTillCondition for resource %s ", *createAdbResponse.Id)
	}

	return *createAdbResponse.Id, nil
}

func adbSweepWaitCondition(response oci_common.OCIOperationResponse) bool {
	// Only stop if the resource is available beyond 3 mins. As there could be an issue for the sweeper to delete the resource and manual intervention required.
	if autonomousDatabaseResponse, ok := response.Response.(oci_database.GetAutonomousDatabaseResponse); ok {
		return autonomousDatabaseResponse.LifecycleState == oci_database.AutonomousDatabaseLifecycleStateProvisioning
	}
	return false
}
<commit_msg>fix import statement<commit_after>// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0

package integrationtest

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/terraform-providers/terraform-provider-oci/internal/acctest"
	tf_client "github.com/terraform-providers/terraform-provider-oci/internal/client"
	"github.com/terraform-providers/terraform-provider-oci/internal/tfresource"
	"github.com/terraform-providers/terraform-provider-oci/internal/utils"

	oci_common "github.com/oracle/oci-go-sdk/v56/common"
	oci_database "github.com/oracle/oci-go-sdk/v56/database"
	oci_identity "github.com/oracle/oci-go-sdk/v56/identity"
)

func createAdbInRegion(clients *tf_client.OracleClients, region string) (string, error) {
	compartmentId := utils.GetEnvSettingWithBlankDefault("compartment_ocid")

	databaseClient, err := oci_database.NewDatabaseClientWithConfigurationProvider(*clients.DatabaseClient().ConfigurationProvider())
	if err != nil {
		return "", fmt.Errorf("cannot Create client for the source region %s: %v", region, err)
	}
	err = tf_client.ConfigureClientVar(&databaseClient.BaseClient)
	if err != nil {
		return "", fmt.Errorf("cannot configure client for the source region: %v", err)
	}
	databaseClient.SetRegion(region)
	identityClient, err := oci_identity.NewIdentityClientWithConfigurationProvider(*clients.IdentityClient().ConfigurationProvider())
	if err != nil {
		return "", fmt.Errorf("cannot Create client for the source region %s: %v", region, err)
	}
	err = tf_client.ConfigureClientVar(&identityClient.BaseClient)
	if err != nil {
		return "", fmt.Errorf("cannot configure client for the source region: %v", err)
	}
	identityClient.SetRegion(region)

	cpu_core_count := 1
	data_storage_size_in_tbs := 1
	admin_password := string("BEstrO0ng_#11")
	db_name := utils.RandomString(13, utils.Charset)
	display_name := string("example_cr_source")
	is_dedicated := false

	createAdbResponse, err := databaseClient.CreateAutonomousDatabase(context.Background(), oci_database.CreateAutonomousDatabaseRequest{
		CreateAutonomousDatabaseDetails: oci_database.CreateAutonomousDatabaseDetails{
			CompartmentId:        &compartmentId,
			CpuCoreCount:         &cpu_core_count,
			DataStorageSizeInTBs: &data_storage_size_in_tbs,
			AdminPassword:        &admin_password,
			DbName:               &db_name,
			DisplayName:          &display_name,
			IsDedicated:          &is_dedicated,
		},
		RequestMetadata: oci_common.RequestMetadata{
			RetryPolicy: tfresource.GetRetryPolicy(false, "database"),
		},
	})
	if err != nil {
		return "", fmt.Errorf("[WARN] failed to Create adb with the error %v", err)
	}
	retryPolicy := tfresource.GetRetryPolicy(false, "database")
	retryPolicy.ShouldRetryOperation = acctest.ConditionShouldRetry(time.Duration(10*time.Minute), adbSweepWaitCondition, "database", false)

	if err != nil {
		return "", fmt.Errorf("[WARN] wait for adbSweepWaitCondition failed for %s resource with error %v", *createAdbResponse.Id, err)
	} else {
		log.Printf("[INFO] end of WaitTillCondition for resource %s ", *createAdbResponse.Id)
	}

	return *createAdbResponse.Id, nil
}

func adbSweepWaitCondition(response oci_common.OCIOperationResponse) bool {
	// Only stop if the resource is available beyond 3 mins. As there could be an issue for the sweeper to delete the resource and manual intervention required.
	if autonomousDatabaseResponse, ok := response.Response.(oci_database.GetAutonomousDatabaseResponse); ok {
		return autonomousDatabaseResponse.LifecycleState == oci_database.AutonomousDatabaseLifecycleStateProvisioning
	}
	return false
}
<|endoftext|>