<commit_before>package git

import (
	"container/list"
	"errors"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"strings"
	"sync"

	"github.com/Unknwon/com"
)

var (
	refRexp = regexp.MustCompile("ref: (.*)\n")
)

// get branch's last commit or a special commit by id string
func (repo *Repository) GetCommitOfBranch(branchName string) (*Commit, error) {
	commitId, err := repo.GetCommitIdOfBranch(branchName)
	if err != nil {
		return nil, err
	}

	return repo.GetCommit(commitId)
}

func (repo *Repository) GetCommitIdOfBranch(branchName string) (string, error) {
	return repo.getCommitIdOfRef("refs/heads/" + branchName)
}

func (repo *Repository) getCommitIdOfRef(refpath string) (string, error) {
start:
	f, err := ioutil.ReadFile(filepath.Join(repo.Path, refpath))
	if err != nil {
		return "", err
	}

	allMatches := refRexp.FindAllStringSubmatch(string(f), 1)
	if allMatches == nil {
		// let's assume this is a sha1
		sha1 := string(f[:40])
		if !IsSha1(sha1) {
			return "", fmt.Errorf("heads file wrong sha1 string %s", sha1)
		}
		return sha1, nil
	}
	// yes, it's "ref: something". Now let's lookup "something"
	refpath = allMatches[0][1]
	goto start
}

// Find the commit object in the repository.
func (repo *Repository) GetCommit(commitId string) (*Commit, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.getCommit(id)
}

func (repo *Repository) getCommit(id sha1) (*Commit, error) {
	if repo.commitCache != nil {
		if c, ok := repo.commitCache[id]; ok {
			return c, nil
		}
	} else {
		repo.commitCache = make(map[sha1]*Commit, 10)
	}

	_, _, data, err := repo.getRawObject(id)
	if err != nil {
		return nil, err
	}
	commit, err := parseCommitData(data)
	if err != nil {
		return nil, err
	}
	commit.repo = repo
	commit.Id = id

	repo.commitCache[id] = commit

	return commit, nil
}

func (repo *Repository) CommitsCount(commitId string) (int, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return 0, err
	}
	return repo.commitsCount(id)
}

func (repo *Repository) commitsCount(id sha1) (int, error) {
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count", id.String())
	if err != nil {
		return 0, err
	} else if len(stderr) > 0 {
		return 0, errors.New(stderr)
	}
	return StrToInt(strings.TrimSpace(stdout))
}

// used only for single tree, (]
func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List, error) {
	l := list.New()
	if last == nil || last.ParentCount() == 0 {
		return l, nil
	}

	var err error
	cur := last
	for {
		if cur.Id.Equal(before.Id) {
			break
		}
		l.PushBack(cur)
		if cur.ParentCount() == 0 {
			break
		}
		cur, err = cur.Parent(0)
		if err != nil {
			return nil, err
		}
	}
	return l, nil
}

func (repo *Repository) CommitsBefore(commitId string) (*list.List, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.getCommitsBefore(id)
}

func (repo *Repository) getCommitsBefore(id sha1) (*list.List, error) {
	l := list.New()
	lock := new(sync.Mutex)
	err := repo.commitsBefore(lock, l, nil, id, 0)
	return l, err
}

func (repo *Repository) commitsBefore(lock *sync.Mutex, l *list.List, parent *list.Element, id sha1, limit int) error {
	commit, err := repo.getCommit(id)
	if err != nil {
		return err
	}

	var e *list.Element
	if parent == nil {
		e = l.PushBack(commit)
	} else {
		var in = parent
		//lock.Lock()
		for {
			if in == nil {
				break
			} else if in.Value.(*Commit).Id.Equal(commit.Id) {
				//lock.Unlock()
				return nil
			} else {
				if in.Next() == nil {
					break
				}
				if in.Value.(*Commit).Committer.When.Equal(commit.Committer.When) {
					break
				}

				if in.Value.(*Commit).Committer.When.After(commit.Committer.When) &&
					in.Next().Value.(*Commit).Committer.When.Before(commit.Committer.When) {
					break
				}
			}
			in = in.Next()
		}

		e = l.InsertAfter(commit, in)
		//lock.Unlock()
	}

	var pr = parent
	if commit.ParentCount() > 1 {
		pr = e
	}

	for i := 0; i < commit.ParentCount(); i++ {
		id, err := commit.ParentId(i)
		if err != nil {
			return err
		}
		err = repo.commitsBefore(lock, l, pr, id, 0)
		if err != nil {
			return err
		}
	}

	return nil
}

// SearchCommits searches commits in given commitId and keyword of repository.
func (repo *Repository) SearchCommits(commitId, keyword string) (*list.List, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.searchCommits(id, keyword)
}
func (repo *Repository) searchCommits(id sha1, keyword string) (*list.List, error) {
	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(), "-100",
		"-i", "--grep="+keyword, prettyLogFormat)
	if err != nil {
		return nil, err
	} else if len(stderr) > 0 {
		return nil, errors.New(string(stderr))
	}
	return parsePrettyFormatLog(repo, stdout)
}

// GetCommitsByRange returns certain number of commits with given page of repository.
func (repo *Repository) CommitsByRange(commitId string, page int) (*list.List, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.commitsByRange(id, page)
}

func (repo *Repository) commitsByRange(id sha1, page int) (*list.List, error) {
	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(),
		"--skip="+IntToStr((page-1)*50), "--max-count=50", prettyLogFormat)
	if err != nil {
		return nil, err
	} else if len(stderr) > 0 {
		return nil, errors.New(string(stderr))
	}
	return parsePrettyFormatLog(repo, stdout)
}

func (repo *Repository) GetCommitOfRelPath(commitId, relPath string) (*Commit, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.getCommitOfRelPath(id, relPath)
}

func (repo *Repository) getCommitOfRelPath(id sha1, relPath string) (*Commit, error) {
	stdout, _, err := com.ExecCmdDir(repo.Path, "git", "log", "-1", "--pretty=format:%H", id.String(), "--", relPath)
	if err != nil {
		return nil, err
	}

	id, err = NewIdFromString(string(stdout))
	if err != nil {
		return nil, err
	}

	return repo.getCommit(id)
}
<commit_msg>add api GetCommitOfTag GetCommitIdOfTag<commit_after>package git

import (
	"container/list"
	"errors"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"strings"
	"sync"

	"github.com/Unknwon/com"
)

var (
	refRexp = regexp.MustCompile("ref: (.*)\n")
)

// get branch's last commit or a special commit by id string
func (repo *Repository) GetCommitOfBranch(branchName string) (*Commit, error) {
	commitId, err := repo.GetCommitIdOfBranch(branchName)
	if err != nil {
		return nil, err
	}

	return repo.GetCommit(commitId)
}

func (repo *Repository) GetCommitIdOfBranch(branchName string) (string, error) {
	return repo.getCommitIdOfRef("refs/heads/" + branchName)
}

func (repo *Repository) GetCommitOfTag(tagName string) (*Commit, error) {
	commitId, err := repo.GetCommitIdOfTag(tagName)
	if err != nil {
		return nil, err
	}

	return repo.GetCommit(commitId)
}

func (repo *Repository) GetCommitIdOfTag(tagName string) (string, error) {
	return repo.getCommitIdOfRef("refs/tags/" + tagName)
}

func (repo *Repository) getCommitIdOfRef(refpath string) (string, error) {
start:
	f, err := ioutil.ReadFile(filepath.Join(repo.Path, refpath))
	if err != nil {
		return "", err
	}

	allMatches := refRexp.FindAllStringSubmatch(string(f), 1)
	if allMatches == nil {
		// let's assume this is a sha1
		sha1 := string(f[:40])
		if !IsSha1(sha1) {
			return "", fmt.Errorf("heads file wrong sha1 string %s", sha1)
		}
		return sha1, nil
	}
	// yes, it's "ref: something". Now let's lookup "something"
	refpath = allMatches[0][1]
	goto start
}

// Find the commit object in the repository.
func (repo *Repository) GetCommit(commitId string) (*Commit, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.getCommit(id)
}

func (repo *Repository) getCommit(id sha1) (*Commit, error) {
	if repo.commitCache != nil {
		if c, ok := repo.commitCache[id]; ok {
			return c, nil
		}
	} else {
		repo.commitCache = make(map[sha1]*Commit, 10)
	}

	_, _, data, err := repo.getRawObject(id)
	if err != nil {
		return nil, err
	}
	commit, err := parseCommitData(data)
	if err != nil {
		return nil, err
	}
	commit.repo = repo
	commit.Id = id

	repo.commitCache[id] = commit

	return commit, nil
}

func (repo *Repository) CommitsCount(commitId string) (int, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return 0, err
	}
	return repo.commitsCount(id)
}

func (repo *Repository) commitsCount(id sha1) (int, error) {
	stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count", id.String())
	if err != nil {
		return 0, err
	} else if len(stderr) > 0 {
		return 0, errors.New(stderr)
	}
	return StrToInt(strings.TrimSpace(stdout))
}

// used only for single tree, (]
func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List, error) {
	l := list.New()
	if last == nil || last.ParentCount() == 0 {
		return l, nil
	}

	var err error
	cur := last
	for {
		if cur.Id.Equal(before.Id) {
			break
		}
		l.PushBack(cur)
		if cur.ParentCount() == 0 {
			break
		}
		cur, err = cur.Parent(0)
		if err != nil {
			return nil, err
		}
	}
	return l, nil
}

func (repo *Repository) CommitsBefore(commitId string) (*list.List, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.getCommitsBefore(id)
}

func (repo *Repository) getCommitsBefore(id sha1) (*list.List, error) {
	l := list.New()
	lock := new(sync.Mutex)
	err := repo.commitsBefore(lock, l, nil, id, 0)
	return l, err
}

func (repo *Repository) commitsBefore(lock *sync.Mutex, l *list.List, parent *list.Element, id sha1, limit int) error {
	commit, err := repo.getCommit(id)
	if err != nil {
		return err
	}

	var e *list.Element
	if parent == nil {
		e = l.PushBack(commit)
	} else {
		var in = parent
		//lock.Lock()
		for {
			if in == nil {
				break
			} else if in.Value.(*Commit).Id.Equal(commit.Id) {
				//lock.Unlock()
				return nil
			} else {
				if in.Next() == nil {
					break
				}
				if in.Value.(*Commit).Committer.When.Equal(commit.Committer.When) {
					break
				}

				if in.Value.(*Commit).Committer.When.After(commit.Committer.When) &&
					in.Next().Value.(*Commit).Committer.When.Before(commit.Committer.When) {
					break
				}
			}
			in = in.Next()
		}

		e = l.InsertAfter(commit, in)
		//lock.Unlock()
	}

	var pr = parent
	if commit.ParentCount() > 1 {
		pr = e
	}

	for i := 0; i < commit.ParentCount(); i++ {
		id, err := commit.ParentId(i)
		if err != nil {
			return err
		}
		err = repo.commitsBefore(lock, l, pr, id, 0)
		if err != nil {
			return err
		}
	}

	return nil
}

// SearchCommits searches commits in given commitId and keyword of repository.
func (repo *Repository) SearchCommits(commitId, keyword string) (*list.List, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.searchCommits(id, keyword)
}
func (repo *Repository) searchCommits(id sha1, keyword string) (*list.List, error) {
	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(), "-100",
		"-i", "--grep="+keyword, prettyLogFormat)
	if err != nil {
		return nil, err
	} else if len(stderr) > 0 {
		return nil, errors.New(string(stderr))
	}
	return parsePrettyFormatLog(repo, stdout)
}

// GetCommitsByRange returns certain number of commits with given page of repository.
func (repo *Repository) CommitsByRange(commitId string, page int) (*list.List, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.commitsByRange(id, page)
}

func (repo *Repository) commitsByRange(id sha1, page int) (*list.List, error) {
	stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(),
		"--skip="+IntToStr((page-1)*50), "--max-count=50", prettyLogFormat)
	if err != nil {
		return nil, err
	} else if len(stderr) > 0 {
		return nil, errors.New(string(stderr))
	}
	return parsePrettyFormatLog(repo, stdout)
}

func (repo *Repository) GetCommitOfRelPath(commitId, relPath string) (*Commit, error) {
	id, err := NewIdFromString(commitId)
	if err != nil {
		return nil, err
	}

	return repo.getCommitOfRelPath(id, relPath)
}

func (repo *Repository) getCommitOfRelPath(id sha1, relPath string) (*Commit, error) {
	stdout, _, err := com.ExecCmdDir(repo.Path, "git", "log", "-1", "--pretty=format:%H", id.String(), "--", relPath)
	if err != nil {
		return nil, err
	}

	id, err = NewIdFromString(string(stdout))
	if err != nil {
		return nil, err
	}

	return repo.getCommit(id)
}
<|endoftext|>


<commit_before>package report

import (
	"reflect"

	"github.com/ugorji/go/codec"
	"github.com/weaveworks/ps"
)

// Sets is a string->set-of-strings map.
// It is immutable.
type Sets struct {
	psMap ps.Map
}

// EmptySets is an empty Sets.  Starts with this.
var emptySets = Sets{ps.NewMap()}

// MakeSets returns EmptySets
func MakeSets() Sets {
	return emptySets
}

// Keys returns the keys for this set
func (s Sets) Keys() []string {
	if s.psMap == nil {
		return nil
	}
	return s.psMap.Keys()
}

// Add the given value to the Sets.
func (s Sets) Add(key string, value StringSet) Sets {
	if s.psMap == nil {
		s = emptySets
	}
	if existingValue, ok := s.psMap.Lookup(key); ok {
		value = value.Merge(existingValue.(StringSet))
	}
	return Sets{
		psMap: s.psMap.Set(key, value),
	}
}

// Delete the given set from the Sets.
func (s Sets) Delete(key string) Sets {
	if s.psMap == nil {
		return emptySets
	}
	return Sets{
		psMap: s.psMap.Delete(key),
	}
}

// Lookup returns the sets stored under key.
func (s Sets) Lookup(key string) (StringSet, bool) {
	if s.psMap == nil {
		return MakeStringSet(), false
	}
	if value, ok := s.psMap.Lookup(key); ok {
		return value.(StringSet), true
	}
	return MakeStringSet(), false
}

// Size returns the number of elements
func (s Sets) Size() int {
	if s.psMap == nil {
		return 0
	}
	return s.psMap.Size()
}

// Merge merges two sets maps into a fresh set, performing set-union merges as
// appropriate.
func (s Sets) Merge(other Sets) Sets {
	var (
		sSize     = s.Size()
		otherSize = other.Size()
		result    = s.psMap
		iter      = other.psMap
	)
	switch {
	case sSize == 0:
		return other
	case otherSize == 0:
		return s
	case sSize < otherSize:
		result, iter = iter, result
	}

	iter.ForEach(func(key string, value interface{}) {
		set := value.(StringSet)
		if existingSet, ok := result.Lookup(key); ok {
			set = set.Merge(existingSet.(StringSet))
		}
		result = result.Set(key, set)
	})

	return Sets{result}
}

// Copy is a noop
func (s Sets) Copy() Sets {
	return s
}

func (s Sets) String() string {
	return mapToString(s.psMap)
}

// DeepEqual tests equality with other Sets
func (s Sets) DeepEqual(t Sets) bool {
	return mapEqual(s.psMap, t.psMap, reflect.DeepEqual)
}

// CodecEncodeSelf implements codec.Selfer
func (s *Sets) CodecEncodeSelf(encoder *codec.Encoder) {
	mapWrite(s.psMap, encoder, func(encoder *codec.Encoder, val interface{}) {
		encoder.Encode(val.(StringSet))
	})
}

// CodecDecodeSelf implements codec.Selfer
func (s *Sets) CodecDecodeSelf(decoder *codec.Decoder) {
	out := mapRead(decoder, func(isNil bool) interface{} {
		var value StringSet
		if !isNil {
			decoder.Decode(&value)
		}
		return value
	})
	*s = Sets{out}
}

// MarshalJSON shouldn't be used, use CodecEncodeSelf instead
func (Sets) MarshalJSON() ([]byte, error) {
	panic("MarshalJSON shouldn't be used, use CodecEncodeSelf instead")
}

// UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead
func (*Sets) UnmarshalJSON(b []byte) error {
	panic("UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead")
}
<commit_msg>refactor: optimise report.Sets.Delete() going empty<commit_after>package report

import (
	"reflect"

	"github.com/ugorji/go/codec"
	"github.com/weaveworks/ps"
)

// Sets is a string->set-of-strings map.
// It is immutable.
type Sets struct {
	psMap ps.Map
}

// EmptySets is an empty Sets.  Starts with this.
var emptySets = Sets{ps.NewMap()}

// MakeSets returns EmptySets
func MakeSets() Sets {
	return emptySets
}

// Keys returns the keys for this set
func (s Sets) Keys() []string {
	if s.psMap == nil {
		return nil
	}
	return s.psMap.Keys()
}

// Add the given value to the Sets.
func (s Sets) Add(key string, value StringSet) Sets {
	if s.psMap == nil {
		s = emptySets
	}
	if existingValue, ok := s.psMap.Lookup(key); ok {
		value = value.Merge(existingValue.(StringSet))
	}
	return Sets{
		psMap: s.psMap.Set(key, value),
	}
}

// Delete the given set from the Sets.
func (s Sets) Delete(key string) Sets {
	if s.psMap == nil {
		return emptySets
	}
	psMap := s.psMap.Delete(key)
	if psMap.IsNil() {
		return emptySets
	}
	return Sets{psMap: psMap}
}

// Lookup returns the sets stored under key.
func (s Sets) Lookup(key string) (StringSet, bool) {
	if s.psMap == nil {
		return MakeStringSet(), false
	}
	if value, ok := s.psMap.Lookup(key); ok {
		return value.(StringSet), true
	}
	return MakeStringSet(), false
}

// Size returns the number of elements
func (s Sets) Size() int {
	if s.psMap == nil {
		return 0
	}
	return s.psMap.Size()
}

// Merge merges two sets maps into a fresh set, performing set-union merges as
// appropriate.
func (s Sets) Merge(other Sets) Sets {
	var (
		sSize     = s.Size()
		otherSize = other.Size()
		result    = s.psMap
		iter      = other.psMap
	)
	switch {
	case sSize == 0:
		return other
	case otherSize == 0:
		return s
	case sSize < otherSize:
		result, iter = iter, result
	}

	iter.ForEach(func(key string, value interface{}) {
		set := value.(StringSet)
		if existingSet, ok := result.Lookup(key); ok {
			set = set.Merge(existingSet.(StringSet))
		}
		result = result.Set(key, set)
	})

	return Sets{result}
}

// Copy is a noop
func (s Sets) Copy() Sets {
	return s
}

func (s Sets) String() string {
	return mapToString(s.psMap)
}

// DeepEqual tests equality with other Sets
func (s Sets) DeepEqual(t Sets) bool {
	return mapEqual(s.psMap, t.psMap, reflect.DeepEqual)
}

// CodecEncodeSelf implements codec.Selfer
func (s *Sets) CodecEncodeSelf(encoder *codec.Encoder) {
	mapWrite(s.psMap, encoder, func(encoder *codec.Encoder, val interface{}) {
		encoder.Encode(val.(StringSet))
	})
}

// CodecDecodeSelf implements codec.Selfer
func (s *Sets) CodecDecodeSelf(decoder *codec.Decoder) {
	out := mapRead(decoder, func(isNil bool) interface{} {
		var value StringSet
		if !isNil {
			decoder.Decode(&value)
		}
		return value
	})
	*s = Sets{out}
}

// MarshalJSON shouldn't be used, use CodecEncodeSelf instead
func (Sets) MarshalJSON() ([]byte, error) {
	panic("MarshalJSON shouldn't be used, use CodecEncodeSelf instead")
}

// UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead
func (*Sets) UnmarshalJSON(b []byte) error {
	panic("UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead")
}
<|endoftext|>


<commit_before>package graph

import (
	"context"
	"fmt"

	"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
)

func UserGetByObjectId(client *graphrbac.UsersClient, ctx context.Context, objectId string) (*graphrbac.User, error) {
	filter := fmt.Sprintf("objectId eq '%s'", objectId)
	resp, err := client.ListComplete(ctx, filter, "")
	if err != nil {
		return nil, fmt.Errorf("Error listing Azure AD Users for filter %q: %+v", filter, err)
	}

	values := resp.Response().Value
	if values == nil {
		return nil, fmt.Errorf("nil values for AD Users matching %q", filter)
	}
	if len(*values) == 0 {
		return nil, fmt.Errorf("Found no AD Users matching %q", filter)
	}
	if len(*values) > 2 {
		return nil, fmt.Errorf("Found multiple AD Users matching %q", filter)
	}

	user := (*values)[0]
	if user.DisplayName == nil {
		return nil, fmt.Errorf("nil DisplayName for AD Users matching %q", filter)
	}
	if *user.ObjectID != objectId {
		return nil, fmt.Errorf("objectID for AD Users matching %q does is does not match(%q!=%q)", filter, *user.ObjectID, objectId)
	}

	return &user, nil
}

func UserGetByMailNickname(client *graphrbac.UsersClient, ctx context.Context, mailNickname string) (*graphrbac.User, error) {
	filter := fmt.Sprintf("startswith(mailNickname,'%s')", mailNickname)
	resp, err := client.ListComplete(ctx, filter, "")
	if err != nil {
		return nil, fmt.Errorf("Error listing Azure AD Users for filter %q: %+v", filter, err)
	}

	values := resp.Response().Value
	if values == nil {
		return nil, fmt.Errorf("nil values for AD Users matching %q", filter)
	}
	if len(*values) == 0 {
		return nil, fmt.Errorf("Found no AD Users matching %q", filter)
	}
	if len(*values) > 2 {
		return nil, fmt.Errorf("Found multiple AD Users matching %q", filter)
	}

	user := (*values)[0]
	if user.DisplayName == nil {
		return nil, fmt.Errorf("nil DisplayName for AD Users matching %q", filter)
	}

	return &user, nil
}
<commit_msg>data.azuread_user[s] - use equals insteadof startsWith when finding users by mailNickname (#251)<commit_after>package graph

import (
	"context"
	"fmt"

	"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
)

func UserGetByObjectId(client *graphrbac.UsersClient, ctx context.Context, objectId string) (*graphrbac.User, error) {
	filter := fmt.Sprintf("objectId eq '%s'", objectId)
	resp, err := client.ListComplete(ctx, filter, "")
	if err != nil {
		return nil, fmt.Errorf("Error listing Azure AD Users for filter %q: %+v", filter, err)
	}

	values := resp.Response().Value
	if values == nil {
		return nil, fmt.Errorf("nil values for AD Users matching %q", filter)
	}
	if len(*values) == 0 {
		return nil, fmt.Errorf("Found no AD Users matching %q", filter)
	}
	if len(*values) > 2 {
		return nil, fmt.Errorf("Found multiple AD Users matching %q", filter)
	}

	user := (*values)[0]
	if user.DisplayName == nil {
		return nil, fmt.Errorf("nil DisplayName for AD Users matching %q", filter)
	}
	if *user.ObjectID != objectId {
		return nil, fmt.Errorf("objectID for AD Users matching %q does is does not match(%q!=%q)", filter, *user.ObjectID, objectId)
	}

	return &user, nil
}

func UserGetByMailNickname(client *graphrbac.UsersClient, ctx context.Context, mailNickname string) (*graphrbac.User, error) {
	filter := fmt.Sprintf("mailNickname eq '%s'", mailNickname)
	resp, err := client.ListComplete(ctx, filter, "")
	if err != nil {
		return nil, fmt.Errorf("Error listing Azure AD Users for filter %q: %+v", filter, err)
	}

	values := resp.Response().Value
	if values == nil {
		return nil, fmt.Errorf("nil values for AD Users matching %q", filter)
	}
	if len(*values) == 0 {
		return nil, fmt.Errorf("Found no AD Users matching %q", filter)
	}
	if len(*values) > 2 {
		return nil, fmt.Errorf("Found multiple AD Users matching %q", filter)
	}

	user := (*values)[0]
	if user.DisplayName == nil {
		return nil, fmt.Errorf("nil DisplayName for AD Users matching %q", filter)
	}

	return &user, nil
}
<|endoftext|>


<commit_before>package solver

import (
	"fmt"
	"os"
	"strings"
	"testing"
)

// A test associates a path with an expected output.
type test struct {
	path     string
	expected Status
}

func runTest(test test, t *testing.T) {
	f, err := os.Open(test.path)
	if err != nil {
		t.Error(err.Error())
		return
	}
	defer func() { _ = f.Close() }()
	var pb *Problem
	if strings.HasSuffix(test.path, "cnf") {
		pb, err = ParseCNF(f)
	} else {
		pb, err = ParseOPB(f)
	}
	if err != nil {
		t.Error(err.Error())
		return
	}
	s := New(pb)
	if status := s.Solve(); status != test.expected {
		t.Errorf("Invalid result for %q: expected %v, got %v", test.path, test.expected, status)
	}
}

var tests = []test{
	{"testcnf/25.cnf", Sat},
	{"testcnf/50.cnf", Sat},
	{"testcnf/75.cnf", Sat},
	{"testcnf/100.cnf", Sat},
	{"testcnf/125.cnf", Unsat},
	{"testcnf/150.cnf", Unsat},
	{"testcnf/175.cnf", Unsat},
	{"testcnf/200.cnf", Unsat},
	{"testcnf/225.cnf", Sat},
	{"testcnf/hoons-vbmc-lucky7.cnf", Unsat},
	{"testcnf/3col-almost3reg-l010-r009-n1.opb", Unsat},
	{"testcnf/simple.opb", Sat},
	{"testcnf/fixed-bandwidth-10.cnf.gz-extracted.pb", Unsat},
	{"testcnf/ex1.opb", Unsat},
	{"testcnf/lo_8x8_009.opb", Sat},
}

func TestSolver(t *testing.T) {
	for _, test := range tests {
		runTest(test, t)
	}
}

func runBench(path string, b *testing.B) {
	f, err := os.Open(path)
	if err != nil {
		b.Fatal(err.Error())
	}
	defer func() { _ = f.Close() }()
	for i := 0; i < b.N; i++ {
		pb, err := ParseCNF(f)
		if err != nil {
			b.Fatal(err.Error())
		}
		s := New(pb)
		s.Solve()
	}
}

func TestParseSlice(t *testing.T) {
	cnf := [][]int{{1, 2, 3}, {-1}, {-2}, {-3}}
	pb := ParseSlice(cnf)
	s := New(pb)
	if status := s.Solve(); status != Unsat {
		t.Fatalf("expected unsat for problem %v, got %v", cnf, status)
	}
}

func TestParseSliceSat(t *testing.T) {
	cnf := [][]int{{1}, {-2, 3}, {-2, 4}, {-5, 3}, {-5, 6}, {-7, 3}, {-7, 8}, {-9, 10}, {-9, 4}, {-1, 10}, {-1, 6}, {3, 10}, {-3, -10}, {4, 6, 8}}
	pb := ParseSlice(cnf)
	s := New(pb)
	if status := s.Solve(); status != Sat {
		t.Fatalf("expected sat for problem %v, got %v", cnf, status)
	}
}

func TestParseSliceTrivial(t *testing.T) {
	cnf := [][]int{{1}, {-1}}
	pb := ParseSlice(cnf)
	s := New(pb)
	if status := s.Solve(); status != Unsat {
		t.Fatalf("expected unsat for problem %v, got %v", cnf, status)
	}
}

func TestParseCardConstrs(t *testing.T) {
	clauses := []CardConstr{
		{Lits: []int{1, 2, 3}, AtLeast: 3},
		{Lits: []int{-1, -2}, AtLeast: 0},
		{Lits: []int{2, 3, -4}, AtLeast: 2},
		AtLeast1(-1, -4),
	}
	pb := ParseCardConstrs(clauses)
	s := New(pb)
	if status := s.Solve(); status != Sat {
		t.Fatalf("expected sat for cardinality problem %v, got %v", clauses, status)
	}
	model := s.Model()
	if !model[IntToVar(1)] || !model[IntToVar(2)] || !model[IntToVar(3)] || model[IntToVar(4)] {
		t.Fatalf("expected model 1, 2, 3, -4, got: %v", model)
	}
}

func TestAtMost1(t *testing.T) {
	c := AtMost1(1, -2, 3)
	if c.Lits[0] != -1 || c.Lits[1] != 2 || c.Lits[2] != -3 {
		t.Errorf("invalid constraint: expected [[-1 2 -3] 2], got %v", c)
	}
	if c.AtLeast != 2 {
		t.Errorf("invalid cardinality: expected 2, got %d", c.AtLeast)
	}
}

func TestParseCardConstrsTrivial(t *testing.T) {
	pb := ParseCardConstrs([]CardConstr{{Lits: []int{1, 2}, AtLeast: 3}})
	s := New(pb)
	if status := s.Solve(); status != Unsat {
		t.Errorf("expected unsat, got %v", status)
	}
	pb = ParseCardConstrs([]CardConstr{{Lits: []int{1, 2, 3}, AtLeast: 3}})
	s = New(pb)
	if status := s.Solve(); status != Sat {
		t.Errorf("expected sat, got %v", status)
	} else {
		model := s.Model()
		if !model[IntToVar(1)] || !model[IntToVar(2)] || !model[IntToVar(3)] {
			t.Errorf("invalid model, expected all true bindings, got %v", model)
		}
	}
	pb = ParseCardConstrs([]CardConstr{{Lits: []int{1, -2, 3}, AtLeast: 2}, AtLeast1(2)})
	s = New(pb)
	if status := s.Solve(); status != Sat {
		t.Errorf("expected sat, got %v", status)
	} else {
		model := s.Model()
		if !model[IntToVar(1)] || !model[IntToVar(2)] || !model[IntToVar(3)] {
			t.Errorf("invalid model, expected all true bindings, got %v", model)
		}
	}
}

func TestPigeonCard(t *testing.T) {
	pb := ParseCardConstrs([]CardConstr{
		AtLeast1(1, 2, 3),
		AtMost1(1, 2, 3),
		AtLeast1(4, 5, 6),
		AtMost1(4, 5, 6),
		AtLeast1(7, 8, 9),
		AtMost1(7, 8, 9),
		AtLeast1(10, 11, 12),
		AtMost1(10, 11, 12),
		AtMost1(1, 4, 7, 10),
		AtMost1(2, 5, 8, 11),
		AtMost1(3, 6, 9, 12),
	})
	s := New(pb)
	if status := s.Solve(); status == Sat {
		model := s.Model()
		t.Errorf("model found for pigeon problem: %v", model)
	}
}

func ExampleParseCardConstrs() {
	clauses := []CardConstr{
		{Lits: []int{1, 2, 3}, AtLeast: 3},
		{Lits: []int{2, 3, -4}, AtLeast: 2},
		AtLeast1(-1, -4),
		AtLeast1(-2, -3, 4),
	}
	pb := ParseCardConstrs(clauses)
	s := New(pb)
	if status := s.Solve(); status == Unsat {
		fmt.Println("Problem is not satisfiable")
	} else {
		fmt.Printf("Model found: %v\n", s.Model())
	}
	// Output:
	// Problem is not satisfiable
}

func TestCountModel(t *testing.T) {
	clauses := []CardConstr{
		AtLeast1(1, 2, 3),
		AtLeast1(-1, -2, -3),
		AtLeast1(2, 3, 4),
		AtLeast1(2, 3, 5),
		AtLeast1(3, 4, 5),
		AtLeast1(2, 4, 5),
	}
	pb := ParseCardConstrs(clauses)
	s := New(pb)
	if nb := s.CountModels(); nb != 17 {
		t.Errorf("Invalid #models: expected %d, got %d", 17, nb)
	}
}

func TestEnumerate(t *testing.T) {
	clauses := []CardConstr{
		AtLeast1(1, 2, 3),
		AtLeast1(-1, -2, -3),
		AtLeast1(2, 3, 4),
		AtLeast1(2, 3, 5),
		AtLeast1(3, 4, 5),
		AtLeast1(2, 4, 5),
	}
	pb := ParseCardConstrs(clauses)
	s := New(pb)
	if nb := s.Enumerate(nil, nil); nb != 17 {
		t.Errorf("Invalid #models returned: expected %d, got %d", 17, nb)
	}
	models := make(chan []bool)
	pb = ParseCardConstrs(clauses)
	s = New(pb)
	go s.Enumerate(models, nil)
	nb := 0
	for range models {
		nb++
	}
	if nb != 17 {
		t.Errorf("Invalid #models on chan models: expected %d, got %d", 17, nb)
	}

}

func BenchmarkCountModels(b *testing.B) {
	clauses := []CardConstr{
		AtLeast1(1, 2, 3),
		AtLeast1(-1, -2, -3),
		AtLeast1(2, 3, 4),
		AtLeast1(2, 3, 5),
		AtLeast1(3, 4, 5),
		AtLeast1(2, 4, 5),
		AtLeast1(-2, -3, -6),
		AtLeast1(4, 5, 6),
		AtLeast1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
		AtLeast1(-7, -10),
		//AtLeast1(11, 12, 13, 14, 15, 16, 17, 18, 19, 20),
		//AtLeast1(21, 22, 23, 24, 25, 26, 27, 28, 29, 30),
		//AtLeast1(50, 100),
	}
	for i := 0; i < b.N; i++ {
		pb := ParseCardConstrs(clauses)
		s := New(pb)
		s.CountModels()
	}
}

func BenchmarkSolverHoons(b *testing.B) {
	runBench("testcnf/hoons-vbmc-lucky7.cnf", b)
}

func BenchmarkSolverGss(b *testing.B) {
	runBench("testcnf/gss-13-s100.cnf", b)
}

func BenchmarkSolverXinetd(b *testing.B) {
	runBench("testcnf/xinetd_vc56703.cnf", b)
}

func BenchmarkSolverSmulo(b *testing.B) {
	runBench("testcnf/smulo016.cnf", b)
}

func BenchmarkSolverVMPC(b *testing.B) {
	runBench("testcnf/vmpc_24.cnf", b)
}

func BenchmarkSolverACG(b *testing.B) {
	runBench("testcnf/ACG-10-5p0.cnf", b)
}

func BenchmarkSolverGSS(b *testing.B) {
	runBench("testcnf/gss-13-s100.cnf", b)
}

func BenchmarkSolverGUS(b *testing.B) {
	runBench("testcnf/gus-md5-04.cnf", b)
}

func BenchmarkSolverHSAT(b *testing.B) {
	runBench("testcnf/hsat_vc11803.cnf", b)
}

func BenchmarkSolverEqAtree(b *testing.B) {
	runBench("testcnf/eq.atree.braun.9.unsat.cnf", b)
}

func BenchmarkSolverManolPipe(b *testing.B) {
	runBench("testcnf/manol-pipe-c9.cnf", b)
}
<commit_msg>removed duplicate benchmark<commit_after>package solver

import (
	"fmt"
	"os"
	"strings"
	"testing"
)

// A test associates a path with an expected output.
type test struct {
	path     string
	expected Status
}

func runTest(test test, t *testing.T) {
	f, err := os.Open(test.path)
	if err != nil {
		t.Error(err.Error())
		return
	}
	defer func() { _ = f.Close() }()
	var pb *Problem
	if strings.HasSuffix(test.path, "cnf") {
		pb, err = ParseCNF(f)
	} else {
		pb, err = ParseOPB(f)
	}
	if err != nil {
		t.Error(err.Error())
		return
	}
	s := New(pb)
	if status := s.Solve(); status != test.expected {
		t.Errorf("Invalid result for %q: expected %v, got %v", test.path, test.expected, status)
	}
}

var tests = []test{
	{"testcnf/25.cnf", Sat},
	{"testcnf/50.cnf", Sat},
	{"testcnf/75.cnf", Sat},
	{"testcnf/100.cnf", Sat},
	{"testcnf/125.cnf", Unsat},
	{"testcnf/150.cnf", Unsat},
	{"testcnf/175.cnf", Unsat},
	{"testcnf/200.cnf", Unsat},
	{"testcnf/225.cnf", Sat},
	{"testcnf/hoons-vbmc-lucky7.cnf", Unsat},
	{"testcnf/3col-almost3reg-l010-r009-n1.opb", Unsat},
	{"testcnf/simple.opb", Sat},
	{"testcnf/fixed-bandwidth-10.cnf.gz-extracted.pb", Unsat},
	{"testcnf/ex1.opb", Unsat},
	{"testcnf/lo_8x8_009.opb", Sat},
}

func TestSolver(t *testing.T) {
	for _, test := range tests {
		runTest(test, t)
	}
}

func runBench(path string, b *testing.B) {
	f, err := os.Open(path)
	if err != nil {
		b.Fatal(err.Error())
	}
	defer func() { _ = f.Close() }()
	for i := 0; i < b.N; i++ {
		pb, err := ParseCNF(f)
		if err != nil {
			b.Fatal(err.Error())
		}
		s := New(pb)
		s.Solve()
	}
}

func TestParseSlice(t *testing.T) {
	cnf := [][]int{{1, 2, 3}, {-1}, {-2}, {-3}}
	pb := ParseSlice(cnf)
	s := New(pb)
	if status := s.Solve(); status != Unsat {
		t.Fatalf("expected unsat for problem %v, got %v", cnf, status)
	}
}

func TestParseSliceSat(t *testing.T) {
	cnf := [][]int{{1}, {-2, 3}, {-2, 4}, {-5, 3}, {-5, 6}, {-7, 3}, {-7, 8}, {-9, 10}, {-9, 4}, {-1, 10}, {-1, 6}, {3, 10}, {-3, -10}, {4, 6, 8}}
	pb := ParseSlice(cnf)
	s := New(pb)
	if status := s.Solve(); status != Sat {
		t.Fatalf("expected sat for problem %v, got %v", cnf, status)
	}
}

func TestParseSliceTrivial(t *testing.T) {
	cnf := [][]int{{1}, {-1}}
	pb := ParseSlice(cnf)
	s := New(pb)
	if status := s.Solve(); status != Unsat {
		t.Fatalf("expected unsat for problem %v, got %v", cnf, status)
	}
}

func TestParseCardConstrs(t *testing.T) {
	clauses := []CardConstr{
		{Lits: []int{1, 2, 3}, AtLeast: 3},
		{Lits: []int{-1, -2}, AtLeast: 0},
		{Lits: []int{2, 3, -4}, AtLeast: 2},
		AtLeast1(-1, -4),
	}
	pb := ParseCardConstrs(clauses)
	s := New(pb)
	if status := s.Solve(); status != Sat {
		t.Fatalf("expected sat for cardinality problem %v, got %v", clauses, status)
	}
	model := s.Model()
	if !model[IntToVar(1)] || !model[IntToVar(2)] || !model[IntToVar(3)] || model[IntToVar(4)] {
		t.Fatalf("expected model 1, 2, 3, -4, got: %v", model)
	}
}

func TestAtMost1(t *testing.T) {
	c := AtMost1(1, -2, 3)
	if c.Lits[0] != -1 || c.Lits[1] != 2 || c.Lits[2] != -3 {
		t.Errorf("invalid constraint: expected [[-1 2 -3] 2], got %v", c)
	}
	if c.AtLeast != 2 {
		t.Errorf("invalid cardinality: expected 2, got %d", c.AtLeast)
	}
}

func TestParseCardConstrsTrivial(t *testing.T) {
	pb := ParseCardConstrs([]CardConstr{{Lits: []int{1, 2}, AtLeast: 3}})
	s := New(pb)
	if status := s.Solve(); status != Unsat {
		t.Errorf("expected unsat, got %v", status)
	}
	pb = ParseCardConstrs([]CardConstr{{Lits: []int{1, 2, 3}, AtLeast: 3}})
	s = New(pb)
	if status := s.Solve(); status != Sat {
		t.Errorf("expected sat, got %v", status)
	} else {
		model := s.Model()
		if !model[IntToVar(1)] || !model[IntToVar(2)] || !model[IntToVar(3)] {
			t.Errorf("invalid model, expected all true bindings, got %v", model)
		}
	}
	pb = ParseCardConstrs([]CardConstr{{Lits: []int{1, -2, 3}, AtLeast: 2}, AtLeast1(2)})
	s = New(pb)
	if status := s.Solve(); status != Sat {
		t.Errorf("expected sat, got %v", status)
	} else {
		model := s.Model()
		if !model[IntToVar(1)] || !model[IntToVar(2)] || !model[IntToVar(3)] {
			t.Errorf("invalid model, expected all true bindings, got %v", model)
		}
	}
}

func TestPigeonCard(t *testing.T) {
	pb := ParseCardConstrs([]CardConstr{
		AtLeast1(1, 2, 3),
		AtMost1(1, 2, 3),
		AtLeast1(4, 5, 6),
		AtMost1(4, 5, 6),
		AtLeast1(7, 8, 9),
		AtMost1(7, 8, 9),
		AtLeast1(10, 11, 12),
		AtMost1(10, 11, 12),
		AtMost1(1, 4, 7, 10),
		AtMost1(2, 5, 8, 11),
		AtMost1(3, 6, 9, 12),
	})
	s := New(pb)
	if status := s.Solve(); status == Sat {
		model := s.Model()
		t.Errorf("model found for pigeon problem: %v", model)
	}
}

func ExampleParseCardConstrs() {
	clauses := []CardConstr{
		{Lits: []int{1, 2, 3}, AtLeast: 3},
		{Lits: []int{2, 3, -4}, AtLeast: 2},
		AtLeast1(-1, -4),
		AtLeast1(-2, -3, 4),
	}
	pb := ParseCardConstrs(clauses)
	s := New(pb)
	if status := s.Solve(); status == Unsat {
		fmt.Println("Problem is not satisfiable")
	} else {
		fmt.Printf("Model found: %v\n", s.Model())
	}
	// Output:
	// Problem is not satisfiable
}

func TestCountModel(t *testing.T) {
	clauses := []CardConstr{
		AtLeast1(1, 2, 3),
		AtLeast1(-1, -2, -3),
		AtLeast1(2, 3, 4),
		AtLeast1(2, 3, 5),
		AtLeast1(3, 4, 5),
		AtLeast1(2, 4, 5),
	}
	pb := ParseCardConstrs(clauses)
	s := New(pb)
	if nb := s.CountModels(); nb != 17 {
		t.Errorf("Invalid #models: expected %d, got %d", 17, nb)
	}
}

func TestEnumerate(t *testing.T) {
	clauses := []CardConstr{
		AtLeast1(1, 2, 3),
		AtLeast1(-1, -2, -3),
		AtLeast1(2, 3, 4),
		AtLeast1(2, 3, 5),
		AtLeast1(3, 4, 5),
		AtLeast1(2, 4, 5),
	}
	pb := ParseCardConstrs(clauses)
	s := New(pb)
	if nb := s.Enumerate(nil, nil); nb != 17 {
		t.Errorf("Invalid #models returned: expected %d, got %d", 17, nb)
	}
	models := make(chan []bool)
	pb = ParseCardConstrs(clauses)
	s = New(pb)
	go s.Enumerate(models, nil)
	nb := 0
	for range models {
		nb++
	}
	if nb != 17 {
		t.Errorf("Invalid #models on chan models: expected %d, got %d", 17, nb)
	}

}

func BenchmarkCountModels(b *testing.B) {
	clauses := []CardConstr{
		AtLeast1(1, 2, 3),
		AtLeast1(-1, -2, -3),
		AtLeast1(2, 3, 4),
		AtLeast1(2, 3, 5),
		AtLeast1(3, 4, 5),
		AtLeast1(2, 4, 5),
		AtLeast1(-2, -3, -6),
		AtLeast1(4, 5, 6),
		AtLeast1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
		AtLeast1(-7, -10),
		//AtLeast1(11, 12, 13, 14, 15, 16, 17, 18, 19, 20),
		//AtLeast1(21, 22, 23, 24, 25, 26, 27, 28, 29, 30),
		//AtLeast1(50, 100),
	}
	for i := 0; i < b.N; i++ {
		pb := ParseCardConstrs(clauses)
		s := New(pb)
		s.CountModels()
	}
}

func BenchmarkSolverHoons(b *testing.B) {
	runBench("testcnf/hoons-vbmc-lucky7.cnf", b)
}

func BenchmarkSolverXinetd(b *testing.B) {
	runBench("testcnf/xinetd_vc56703.cnf", b)
}

func BenchmarkSolverSmulo(b *testing.B) {
	runBench("testcnf/smulo016.cnf", b)
}

func BenchmarkSolverVMPC(b *testing.B) {
	runBench("testcnf/vmpc_24.cnf", b)
}

func BenchmarkSolverACG(b *testing.B) {
	runBench("testcnf/ACG-10-5p0.cnf", b)
}

func BenchmarkSolverGSS(b *testing.B) {
	runBench("testcnf/gss-13-s100.cnf", b)
}

func BenchmarkSolverGUS(b *testing.B) {
	runBench("testcnf/gus-md5-04.cnf", b)
}

func BenchmarkSolverHSAT(b *testing.B) {
	runBench("testcnf/hsat_vc11803.cnf", b)
}

func BenchmarkSolverEqAtree(b *testing.B) {
	runBench("testcnf/eq.atree.braun.9.unsat.cnf", b)
}

func BenchmarkSolverManolPipe(b *testing.B) {
	runBench("testcnf/manol-pipe-c9.cnf", b)
}
<|endoftext|>


<commit_before>package handlers

import (
	"net/http"
	"encoding/json"
	"fmt"
)

type stateChillHandler struct {
	imageUrls map[string]string
}

func NewStateChillHandler(stateImagesLocation string) http.Handler {
	imageUrls := make(map[string]string)
	for state := range validStates {
		imageUrls[state] = fmt.Sprintf("%s/%s.jpg", stateImagesLocation, state)
	}
	return stateChillHandler{
		imageUrls: imageUrls,
	}
}

func (sc stateChillHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	rw.Header().Set("Content-Type", "text/json; charset=utf-8")
	sc.processRequest(rw, req)
}

func (sc stateChillHandler) processRequest(rw http.ResponseWriter, req *http.Request) {
	state := req.FormValue("state")
	if state == "" {
		sc.writeBadRequestResponse(rw)
		return
	}

	if !validStates[state] {
		sc.writeInvalidStateResponse(rw, state)
	}

	sc.writeChillResponse(rw, state)
}

func (sc stateChillHandler) writeBadRequestResponse(rw http.ResponseWriter) {
	rw.WriteHeader(http.StatusBadRequest)
	response := map[string]string{"error": "missing \"state\" parameter"}
	encoder := json.NewEncoder(rw)
	encoder.Encode(response)
}

func (sc stateChillHandler) writeInvalidStateResponse(rw http.ResponseWriter, missingState string) {
	rw.WriteHeader(http.StatusNotFound)
	response := map[string]string{"error": fmt.Sprintf("Could not find state %q", missingState)}
	encoder := json.NewEncoder(rw)
	encoder.Encode(response)
}

func (sc stateChillHandler) writeChillResponse(rw http.ResponseWriter, state string) {
	rw.WriteHeader(http.StatusOK)
	response := map[string]string{"chill image": sc.imageUrls[state]}
	encoder := json.NewEncoder(rw)
	encoder.Encode(response)
}

<commit_msg>Make chill state more Robust<commit_after>package handlers

import (
	"net/http"
	"encoding/json"
	"fmt"
)

type stateChillHandler struct {
	imageUrls map[string]string
}

func NewStateChillHandler(stateImagesLocation string) http.Handler {
	imageUrls := make(map[string]string)
	for state := range validStates {
		imageUrls[state] = fmt.Sprintf("%s/%s.jpg", stateImagesLocation, state)
	}
	return stateChillHandler{
		imageUrls: imageUrls,
	}
}

func (sc stateChillHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	rw.Header().Set("Content-Type", "text/json; charset=utf-8")
	sc.processRequest(rw, req)
}

func (sc stateChillHandler) processRequest(rw http.ResponseWriter, req *http.Request) {
	state := strings.ToUpper(req.FormValue("state"))
	if state == "" {
		sc.writeBadRequestResponse(rw)
		return
	}

	if !validStates[state] {
		sc.writeInvalidStateResponse(rw, state)
	}

	sc.writeChillResponse(rw, state)
}

func (sc stateChillHandler) writeBadRequestResponse(rw http.ResponseWriter) {
	rw.WriteHeader(http.StatusBadRequest)
	response := map[string]string{"error": "missing \"state\" parameter"}
	encoder := json.NewEncoder(rw)
	encoder.Encode(response)
}

func (sc stateChillHandler) writeInvalidStateResponse(rw http.ResponseWriter, missingState string) {
	rw.WriteHeader(http.StatusNotFound)
	response := map[string]string{"error": fmt.Sprintf("Could not find state %q", missingState)}
	encoder := json.NewEncoder(rw)
	encoder.Encode(response)
}

func (sc stateChillHandler) writeChillResponse(rw http.ResponseWriter, state string) {
	rw.WriteHeader(http.StatusOK)
	response := map[string]string{"chill image": sc.imageUrls[state]}
	encoder := json.NewEncoder(rw)
	encoder.Encode(response)
}

<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"os"
	"io"
	"path"
	"strings"
	"bytes"

	"github.com/coreos/go-etcd/etcd"
	"github.com/headzoo/etcdsh/etcdsh"
	"github.com/headzoo/etcdsh/config"
	"github.com/bobappleyard/readline"
	"github.com/headzoo/etcdsh/parser"
	"net/url"
)

// Controller stores handlers and calls them.
type Controller struct {
	wdir                  string
	handlers              HandlerMap
	config                *config.Config
	client                *etcd.Client
	stdout, stderr, stdin *os.File
	prompter              *parser.Prompt
}

// Create a new Controller.
func NewController(conf *config.Config, client *etcd.Client, stdout, stderr, stdin *os.File) *Controller {
	c := new(Controller)
	c.wdir = "/"
	c.config = conf
	c.client = client
	c.stdout, c.stderr, c.stdin = stdout, stderr, stdin
	c.handlers = make(HandlerMap)

	c.prompter = parser.NewPrompt()
	c.prompter.AddFormatter('w', func() string {
			return c.wdir
		})
	c.prompter.AddFormatter('W', func() string {
			return path.Base(c.wdir)
		})
	c.prompter.AddFormatter('v', func() string {
			return etcdsh.Version
		})
	c.prompter.AddFormatter('m', func() string {
			u, err := url.Parse(conf.Machine)
			if err == nil {
				return u.Host
			} else {
				return conf.Machine
			}
		})

	return c
}

// Starts the controller.
func (c *Controller) Start() int {
	c.welcome()

	prompt := ""
	buffer := bytes.NewBufferString("")

	for {
		if buffer.Len() == 0 {
			prompt = c.ps1()
		} else {
			prompt = c.ps2()
		}

		line, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}

		line = strings.TrimSpace(line)
		if strings.ToLower(line) == "q" || strings.ToLower(line) == "exit" {
			return 0
		}
		if strings.HasSuffix(line, "\\") {
			buffer.WriteString(strings.TrimSuffix(line, "\\") + "\n")
		} else {
			if buffer.Len() > 0 {
				buffer.WriteString(line)
				line = buffer.String()
				buffer.Reset()
			}

			parts := strings.SplitN(line, " ", 3)
			if parts[0] != "" {
				readline.AddHistory(line)
				c.handleInput(NewFromArray(parts))
			}
		}
	}

	return 0
}

// Client returns the etcd client
func (c *Controller) Client() *etcd.Client {
	return c.client
}

// Config returns the app configuration.
func (c *Controller) Config() *config.Config {
	return c.config
}

// Add appends a handler to the map.
func (c *Controller) Add(h Handler) {
	c.handlers[h.Command()] = h
}

// Handlers returns the complete list of added handlers.
func (c *Controller) Handlers() HandlerMap {
	return c.handlers
}

// WorkingDir returns the working directory. The value of a is appended to the value.
func (c *Controller) WorkingDir(a string) string {
	a = strings.Replace(a, "\n", "", -1)
	wdir := c.wdir + a
	return path.Clean(wdir)
}

// ChangeWorkingDir changes the current working directory.
func (c *Controller) ChangeWorkingDir(wdir string) string {
	if strings.HasPrefix(wdir, "/") {
		c.wdir = wdir
	} else {
		c.wdir = c.WorkingDir("/"+wdir)
	}

	return c.wdir
}

// ps1 returns the first type of prompt.
func (c *Controller) ps1() string {
	prompt, _ := c.prompter.Parse(c.config.PS1)
	return prompt
	//return fmt.Sprintf(c.config.PS1, os.Getenv("USER"), c.wdir)
}

// ps2 returns the second type of prompt.
func (c *Controller) ps2() string {
	return c.config.PS2
}

// hasHandler returns whether a command handler has been added with the given id.
func (c *Controller) hasHandler(id string) bool {
	_, ok := c.handlers[id]
	return ok
}

// Handles the user input.
func (c *Controller) handleInput(i *Input) {
	handler, ok := c.handlers[i.Cmd]
	if !ok {
		fmt.Fprintln(c.stderr, fmt.Sprintf("The command %s does not exist.", i.Cmd))
	} else if !handler.Validate(i) {
		fmt.Fprintln(c.stderr, fmt.Sprintf("Invalid use of command, use: %s", handler.Syntax()))
	} else {
		output, err := handler.Handle(i)
		if err == nil {
			fmt.Fprint(c.stdout, output)
		} else {
			fmt.Fprintln(c.stderr, err)
		}
	}
}

// Welcome displays a welcome message.
func (c *Controller) welcome() {
	fmt.Fprintln(c.stdout, "Interactive etcd shell started.")
	if c.hasHandler("help") {
		fmt.Fprintln(c.stdout, "Type 'help' for a list of commands.")
	}
	fmt.Fprintln(c.stdout, "Type 'q' to quit.")
	fmt.Fprintln(c.stdout, "")
}
<commit_msg>Added simple auto complete<commit_after>package handlers

import (
	"fmt"
	"os"
	"io"
	"path"
	"strings"
	"bytes"

	"github.com/coreos/go-etcd/etcd"
	"github.com/headzoo/etcdsh/etcdsh"
	"github.com/headzoo/etcdsh/config"
	"github.com/bobappleyard/readline"
	"github.com/headzoo/etcdsh/parser"
	"net/url"
)

// Controller stores handlers and calls them.
type Controller struct {
	wdir                  string
	wdirKeys			  []string
	handlers              HandlerMap
	config                *config.Config
	client                *etcd.Client
	stdout, stderr, stdin *os.File
	prompter              *parser.Prompt
}

// Create a new Controller.
func NewController(conf *config.Config, client *etcd.Client, stdout, stderr, stdin *os.File) *Controller {
	c := new(Controller)

	c.config = conf
	c.client = client
	c.stdout, c.stderr, c.stdin = stdout, stderr, stdin
	c.wdir = "/"
	c.handlers = make(HandlerMap)

	c.prompter = parser.NewPrompt()
	c.prompter.AddFormatter('w', func() string {
			return c.wdir
		})
	c.prompter.AddFormatter('W', func() string {
			return path.Base(c.wdir)
		})
	c.prompter.AddFormatter('v', func() string {
			return etcdsh.Version
		})
	c.prompter.AddFormatter('m', func() string {
			u, err := url.Parse(conf.Machine)
			if err == nil {
				return u.Host
			} else {
				return conf.Machine
			}
		})

	return c
}

// Starts the controller.
func (c *Controller) Start() int {
	c.welcome()
	c.ChangeWorkingDir("/")

	readline.Completer = c.filenameCompleter
	buffer := bytes.NewBufferString("")
	prompt := ""

	for {
		if buffer.Len() == 0 {
			prompt = c.ps1()
		} else {
			prompt = c.ps2()
		}

		line, err := readline.String(prompt)
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}

		line = strings.TrimSpace(line)
		if strings.ToLower(line) == "q" || strings.ToLower(line) == "exit" {
			return 0
		}
		if strings.HasSuffix(line, "\\") {
			buffer.WriteString(strings.TrimSuffix(line, "\\") + "\n")
		} else {
			if buffer.Len() > 0 {
				buffer.WriteString(line)
				line = buffer.String()
				buffer.Reset()
			}

			parts := strings.SplitN(line, " ", 3)
			if parts[0] != "" {
				readline.AddHistory(line)
				c.handleInput(NewFromArray(parts))
			}
		}
	}

	return 0
}

// Client returns the etcd client
func (c *Controller) Client() *etcd.Client {
	return c.client
}

// Config returns the app configuration.
func (c *Controller) Config() *config.Config {
	return c.config
}

// Add appends a handler to the map.
func (c *Controller) Add(h Handler) {
	c.handlers[h.Command()] = h
}

// Handlers returns the complete list of added handlers.
func (c *Controller) Handlers() HandlerMap {
	return c.handlers
}

// WorkingDir returns the working directory. The value of a is appended to the value.
func (c *Controller) WorkingDir(a string) string {
	a = strings.Replace(a, "\n", "", -1)
	wdir := c.wdir + "/" + a
	return path.Clean(wdir)
}

// ChangeWorkingDir changes the current working directory.
func (c *Controller) ChangeWorkingDir(wdir string) string {
	if strings.HasPrefix(wdir, "/") {
		c.wdir = wdir
	} else {
		c.wdir = c.WorkingDir("/"+wdir)
	}

	resp, err := c.client.Get(c.wdir, false, false)
	if err != nil {
		panic(err)
	}

	c.wdirKeys = make([]string, len(resp.Node.Nodes))
	for i, node := range resp.Node.Nodes {
		c.wdirKeys[i] = node.Key
	}

	return c.wdir
}

// ps1 returns the first type of prompt.
func (c *Controller) ps1() string {
	prompt, _ := c.prompter.Parse(c.config.PS1)
	return prompt
}

// ps2 returns the second type of prompt.
func (c *Controller) ps2() string {
	prompt, _ := c.prompter.Parse(c.config.PS2)
	return prompt
}

// hasHandler returns whether a command handler has been added with the given id.
func (c *Controller) hasHandler(id string) bool {
	_, ok := c.handlers[id]
	return ok
}

// Handles the user input.
func (c *Controller) handleInput(i *Input) {
	handler, ok := c.handlers[i.Cmd]
	if !ok {
		fmt.Fprintln(c.stderr, fmt.Sprintf("The command %s does not exist.", i.Cmd))
	} else if !handler.Validate(i) {
		fmt.Fprintln(c.stderr, fmt.Sprintf("Invalid use of command, use: %s", handler.Syntax()))
	} else {
		output, err := handler.Handle(i)
		if err == nil {
			fmt.Fprint(c.stdout, output)
		} else {
			fmt.Fprintln(c.stderr, err)
		}
	}
}

// filenameCompleter is a callback function for the readline.Completer variable.
func (c *Controller) filenameCompleter(query, ctx string) []string {
	var keys []string
	total := len(c.wdirKeys)
	for i := 0; i < total; i++ {
		base := path.Base(c.wdirKeys[i])
		if strings.HasPrefix(base, query) {
			keys = append(keys, base)
		}
	}

	return keys
}

// Welcome displays a welcome message.
func (c *Controller) welcome() {
	fmt.Fprintln(c.stdout, "Interactive etcd shell started.")
	if c.hasHandler("help") {
		fmt.Fprintln(c.stdout, "Type 'help' for a list of commands.")
	}
	fmt.Fprintln(c.stdout, "Type 'q' to quit.")
	fmt.Fprintln(c.stdout, "")
}
<|endoftext|>


<commit_before>package task

import (
	"context"
	"encoding/json"
	"errors"
	"sync"

	log "github.com/sirupsen/logrus"
)

type ID string

type Status string

const (
	StatusNew       = Status("NEW")
	StatusWaiting   = Status("WAITING")
	StatusRunning   = Status("RUNNING")
	StatusReady     = Status("READY")
	StatusCancelled = Status("CANCELLED")
	StatusError     = Status("ERROR")
)

var ErrNotChild = errors.New("adding non required child")

var ErrChildAlreadyAdded = errors.New("child already added")

// DoFunc is task payload processing function.
// If DoFunc returns not nil value and there are no error the value  will be saved in context as value
// with task.ID as key.
type DoFunc func(ctx context.Context, payload interface{}) (interface{}, error)

type taskResult struct {
	id     ID
	result interface{}
}

type Task struct {
	sync.Mutex
	ID            ID
	Status        Status
	Requires      map[ID]bool
	Payload       interface{}
	do            DoFunc
	doResult      []byte
	undo          DoFunc
	undoResult    []byte
	RequiredFor   map[ID]bool
	waitingResult chan taskResult
	notifyResult  []chan<- taskResult
}

func NewTask(id ID, requires []ID, payload interface{}, doFunc DoFunc, undoFunc DoFunc) *Task {
	reqSet := make(map[ID]bool, len(requires))
	for _, req := range requires {
		reqSet[req] = true
	}
	var waitingID chan taskResult
	if len(requires) > 0 {
		waitingID = make(chan taskResult, len(requires))
	}
	return &Task{
		ID:            id,
		Status:        StatusNew,
		Requires:      reqSet,
		RequiredFor:   make(map[ID]bool),
		Payload:       payload,
		do:            doFunc,
		waitingResult: waitingID,
	}
}

// AddChild adds child task.
func (t *Task) AddChild(child *Task) error {
	t.Lock()
	defer t.Unlock()

	log.Debugf("Adding child %q to %q", child.ID, t.ID)
	if !child.Requires[t.ID] {
		return ErrNotChild
	}

	if added, ok := t.RequiredFor[child.ID]; ok && added {
		return ErrChildAlreadyAdded
	}

	t.notifyResult = append(t.notifyResult, child.waitingResult)
	t.RequiredFor[child.ID] = true
	return nil
}

func prepareResult(result *interface{}) []byte {
	if *result == nil {
		return nil
	}
	resMarsh, errMarsh := json.Marshal(*result)
	if errMarsh != nil {
		log.Errorf("Task execution result marshalling error: %v. Result: %v", errMarsh, result)
	}
	return resMarsh
}

func saveDoResult(task *Task, result *interface{}) {
	task.doResult = prepareResult(result)
}

func Do(ctx context.Context, cancelFunc context.CancelFunc, task *Task) error {
	// Task lock prevents events mess up in case of multiple Do calls with the same task object.
	task.Lock()
	defer task.Unlock()

	log.Debugf("Execution of task %q initiated", task.ID)

	if task.waitingResult != nil {
		task.Status = StatusWaiting
		received := make(map[ID]bool, len(task.Requires))

	loop:
		for {
			select {
			case res := <-task.waitingResult:
				log.Debugf("%v is notified: task %q is finished.", task.ID, res.id)
				received[res.id] = true

				if res.result != nil {
					log.Debugf("Adding task %v result into context", res.id)
					ctx = context.WithValue(ctx, res.id, res.result)
				}

				// Checking if all requirements are satisfied
				if len(received) == len(task.Requires) {
					log.Debugf("All required tasks completed for %v", task.ID)
					break loop
				}
			case <-ctx.Done():
				log.Infof("Cancelling task %q", task.ID)
				task.Status = StatusCancelled
				cancelFunc()
				return nil
			}
		}
	}

	log.Debugf("Running task %q", task.ID)
	task.Status = StatusRunning

	res, err := task.do(ctx, task.Payload)
	saveDoResult(task, &res)

	if err != nil {
		log.Errorf("Task %q failed: %v", task.ID, err)
		task.Status = StatusError
		log.Debugf("Execution cancellation initiated from task %q", task.ID)
		cancelFunc()
		return err
	}

	task.Status = StatusReady
	log.Debugf("Task %q is ready", task.ID)

	for _, notifCh := range task.notifyResult {
		log.Debugf("Sending notification about %v is finished to %v", task.ID, notifCh)
		notifCh <- taskResult{task.ID, res}
	}
	log.Infof("Task %q execution is finished", task.ID)

	return nil
}
<commit_msg>Waiting of required tasks extracted from Do func<commit_after>package task

import (
	"context"
	"encoding/json"
	"errors"
	"sync"

	log "github.com/sirupsen/logrus"
)

type ID string

type Status string

const (
	StatusNew       = Status("NEW")
	StatusWaiting   = Status("WAITING")
	StatusRunning   = Status("RUNNING")
	StatusReady     = Status("READY")
	StatusCancelled = Status("CANCELLED")
	StatusError     = Status("ERROR")
)

var ErrNotChild = errors.New("adding non required child")

var ErrChildAlreadyAdded = errors.New("child already added")

// DoFunc is task payload processing function.
// If DoFunc returns not nil value and there are no error the value  will be saved in context as value
// with task.ID as key.
type DoFunc func(ctx context.Context, payload interface{}) (interface{}, error)

type taskResult struct {
	id     ID
	result interface{}
}

type Task struct {
	sync.Mutex
	ID            ID
	Status        Status
	Requires      map[ID]bool
	Payload       interface{}
	do            DoFunc
	doResult      []byte
	undo          DoFunc
	undoResult    []byte
	RequiredFor   map[ID]bool
	waitingResult chan taskResult
	notifyResult  []chan<- taskResult
}

func NewTask(id ID, requires []ID, payload interface{}, doFunc DoFunc, undoFunc DoFunc) *Task {
	reqSet := make(map[ID]bool, len(requires))
	for _, req := range requires {
		reqSet[req] = true
	}
	var waitingID chan taskResult
	if len(requires) > 0 {
		waitingID = make(chan taskResult, len(requires))
	}
	return &Task{
		ID:            id,
		Status:        StatusNew,
		Requires:      reqSet,
		RequiredFor:   make(map[ID]bool),
		Payload:       payload,
		do:            doFunc,
		waitingResult: waitingID,
	}
}

// AddChild adds child task.
func (t *Task) AddChild(child *Task) error {
	t.Lock()
	defer t.Unlock()

	log.Debugf("Adding child %q to %q", child.ID, t.ID)
	if !child.Requires[t.ID] {
		return ErrNotChild
	}

	if added, ok := t.RequiredFor[child.ID]; ok && added {
		return ErrChildAlreadyAdded
	}

	t.notifyResult = append(t.notifyResult, child.waitingResult)
	t.RequiredFor[child.ID] = true
	return nil
}

func waitingReadiness(ctx context.Context, cancelFunc context.CancelFunc, task *Task) context.Context {
	if task.waitingResult != nil {
		log.Debugf("Task %v is waiting for completion of required tasks", task.ID)
		task.Status = StatusWaiting
		received := make(map[ID]bool, len(task.Requires))

	loop:
		for {
			select {
			case res := <-task.waitingResult:
				log.Debugf("%v is notified: task %q is finished.", task.ID, res.id)
				received[res.id] = true

				if res.result != nil {
					log.Debugf("Adding task %v result into context", res.id)
					ctx = context.WithValue(ctx, res.id, res.result)
				}

				// Checking if all requirements are satisfied
				if len(received) == len(task.Requires) {
					log.Debugf("All required tasks completed for %v", task.ID)
					break loop
				}
			case <-ctx.Done():
				log.Infof("Cancelling task %q", task.ID)
				task.Status = StatusCancelled
				cancelFunc()
				break loop
			}
		}
	}
	return ctx
}

func prepareResult(result *interface{}) []byte {
	if *result == nil {
		return nil
	}
	resMarsh, errMarsh := json.Marshal(*result)
	if errMarsh != nil {
		log.Errorf("Task execution result marshalling error: %v. Result: %v", errMarsh, result)
	}
	return resMarsh
}

func saveDoResult(task *Task, result *interface{}) {
	task.doResult = prepareResult(result)
}

func Do(ctx context.Context, cancelFunc context.CancelFunc, task *Task) error {
	// Task lock prevents events mess up in case of multiple Do calls with the same task object.
	task.Lock()
	defer task.Unlock()

	log.Debugf("Execution of task %q initiated", task.ID)

	ctx = waitingReadiness(ctx, cancelFunc, task)
	if task.Status == StatusCancelled {
		return nil
	}

	log.Debugf("Running task %q", task.ID)
	task.Status = StatusRunning
	res, err := task.do(ctx, task.Payload)
	saveDoResult(task, &res)

	if err != nil {
		log.Errorf("Task %q failed: %v", task.ID, err)
		task.Status = StatusError
		log.Debugf("Execution cancellation initiated from task %q", task.ID)
		cancelFunc()
		return err
	}

	task.Status = StatusReady
	log.Debugf("Task %q is ready", task.ID)

	for _, notifCh := range task.notifyResult {
		log.Debugf("Sending notification about %v is finished to %v", task.ID, notifCh)
		notifCh <- taskResult{task.ID, res}
	}
	log.Infof("Task %q execution is finished", task.ID)

	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

const (
	VnicResourceConfig = VnicResourceDependencies + `
resource "oci_core_vnic" "test_vnic" {
}
`
	VnicPropertyVariables = `

`
	VnicResourceDependencies = ""
)

func TestCoreVnicResource_basic(t *testing.T) {
	t.Skip("Skipping generated test for now as it has not been worked on.")
	provider := testAccProvider
	config := testProviderConfig()

	compartmentId := getRequiredEnvSetting("compartment_ocid")
	compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)

	resourceName := "oci_core_vnic.test_vnic"

	singularDatasourceName := "data.oci_core_vnic.test_vnic"

	var resId, resId2 string

	resource.Test(t, resource.TestCase{
		Providers: map[string]terraform.ResourceProvider{
			"oci": provider,
		},
		Steps: []resource.TestStep{
			// verify create
			{
				ImportState:       true,
				ImportStateVerify: true,
				Config:            config + VnicPropertyVariables + compartmentIdVariableStr + VnicResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttrSet(resourceName, "vnic_id"),

					func(s *terraform.State) (err error) {
						resId, err = fromInstanceState(s, resourceName, "id")
						return err
					},
				),
			},

			// verify updates to updatable parameters
			{
				Config: config + `

                ` + compartmentIdVariableStr + VnicResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttrSet(resourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(resourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(resourceName, "id"),
					resource.TestCheckResourceAttrSet(resourceName, "private_ip_address"),
					resource.TestCheckResourceAttrSet(resourceName, "state"),
					resource.TestCheckResourceAttrSet(resourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(resourceName, "time_created"),
					resource.TestCheckResourceAttrSet(resourceName, "vnic_id"),

					func(s *terraform.State) (err error) {
						resId2, err = fromInstanceState(s, resourceName, "id")
						if resId != resId2 {
							return fmt.Errorf("Resource recreated when it was supposed to be updated.")
						}
						return err
					},
				),
			},
			// verify singular datasource
			{
				Config: config + `

data "oci_core_vnic" "test_vnic" {
	#Required
	vnic_id = "${oci_core_vnic.test_vnic.id}"
}
                ` + compartmentIdVariableStr + VnicResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttrSet(singularDatasourceName, "vnic_id"),

					resource.TestCheckResourceAttrSet(singularDatasourceName, "availability_domain"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "compartment_id"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "id"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "private_ip_address"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "state"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "time_created"),
				),
			},
		},
	})
}
<commit_msg>Enable generated tests for vnics<commit_after>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

const (
	VnicResourceConfig = VnicResourceDependencies + `

`
	VnicPropertyVariables = `

`
	VnicResourceDependencies = ""
)

func TestCoreVnicResource_basic(t *testing.T) {
	provider := testAccProvider
	config := testProviderConfig()

	compartmentId := getRequiredEnvSetting("compartment_ocid")
	compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)

	singularDatasourceName := "data.oci_core_vnic.test_vnic"

	resource.Test(t, resource.TestCase{
		Providers: map[string]terraform.ResourceProvider{
			"oci": provider,
		},
		Steps: []resource.TestStep{
			// verify singular datasource
			{
				Config: config + instanceDnsConfig + `

data "oci_core_vnic_attachments" "t" {
	compartment_id = "${var.compartment_id}"
	instance_id = "${oci_core_instance.t.id}"
}
data "oci_core_vnic" "test_vnic" {
	#Required
	vnic_id = "${lookup(data.oci_core_vnic_attachments.t.vnic_attachments[0],"vnic_id")}"
}
                ` + compartmentIdVariableStr + VnicResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttrSet(singularDatasourceName, "vnic_id"),

					resource.TestCheckResourceAttrSet(singularDatasourceName, "availability_domain"),
					resource.TestCheckResourceAttr(singularDatasourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttr(singularDatasourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(singularDatasourceName, "display_name", "-tf-instance-vnic"),
					resource.TestCheckResourceAttr(singularDatasourceName, "freeform_tags.%", "1"),
					resource.TestCheckResourceAttr(singularDatasourceName, "hostname_label", "testinstance"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "id"),
					resource.TestCheckResourceAttr(singularDatasourceName, "is_primary", "true"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "mac_address"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "private_ip_address"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "public_ip_address"),
					resource.TestCheckResourceAttr(singularDatasourceName, "skip_source_dest_check", "false"),
					resource.TestCheckResourceAttr(singularDatasourceName, "state", "AVAILABLE"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "subnet_id"),
					resource.TestCheckResourceAttrSet(singularDatasourceName, "time_created"),
				),
			},
		},
	})
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"time"

	"github.com/danmane/abalone/go/game"
	"github.com/danmane/abalone/go/quickstart"
)

var (
	port = flag.String("port", "3423", "port the ai runs on")
)

func main() {
	flag.Parse()
	quickstart.Run(*port, func(s game.State, limit time.Duration) game.State {
		f := s.Futures()
		if len(f) == 0 {
			panic("Ah! There are no future states. Why'd the server send this to me? =( ")
		}
		return *f[0]
	})
}
<commit_msg>Factor example AI to be more clear<commit_after>package main

import (
	"flag"
	"time"

	"github.com/danmane/abalone/go/game"
	"github.com/danmane/abalone/go/quickstart"
)

var (
	port = flag.String("port", "3423", "port the ai runs on")
)

func play(s game.State, limit time.Duration) game.State {
	f := s.Futures()
	if len(f) == 0 {
		panic("Ah! There are no future states. Why'd the server send this to me? =( ")
	}
	return *f[0]
}

func main() {
	flag.Parse()
	quickstart.Run(*port, play)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 VMware, Inc. All Rights Reserved.
//
// This product is licensed to you under the Apache License, Version 2.0 (the "License").
// You may not use this product except in compliance with the License.
//
// This product may include a number of subcomponents with separate copyright notices and
// license terms. Your use of these subcomponents is subject to the terms and conditions
// of the subcomponent's license, as noted in the LICENSE file.

package photon

import (
	"crypto/rand"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

type restClient struct {
	httpClient *http.Client
	logger     *log.Logger
}

type request struct {
	Method      string
	URL         string
	ContentType string
	Body        io.Reader
	Token       string
}

type page struct {
	Items            []interface{} `json:"items"`
	NextPageLink     string        `json:"nextPageLink"`
	PreviousPageLink string        `json:"previousPageLink"`
}

type documentList struct {
	Items []interface{}
}

const appJson string = "application/json"

// From https://golang.org/src/mime/multipart/writer.go
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func (client *restClient) AppendSlice(origSlice []interface{}, dataToAppend []interface{}) []interface{} {
	origLen := len(origSlice)
	newLen := origLen + len(dataToAppend)

	if newLen > cap(origSlice) {
		newSlice := make([]interface{}, (newLen+1)*2)
		copy(newSlice, origSlice)
		origSlice = newSlice
	}

	origSlice = origSlice[0:newLen]
	copy(origSlice[origLen:newLen], dataToAppend)

	return origSlice
}

func (client *restClient) Get(url string, token string) (res *http.Response, err error) {
	req := request{"GET", url, "", nil, token}
	res, err = client.Do(&req)
	return
}

func (client *restClient) GetList(endpoint string, url string, token string) (result []byte, err error) {
	req := request{"GET", url, "", nil, token}
	res, err := client.Do(&req)
	if err != nil {
		return
	}
	res, err = getError(res)
	if err != nil {
		return
	}

	decoder := json.NewDecoder(res.Body)
	decoder.UseNumber()

	page := &page{}
	err = decoder.Decode(page)
	if err != nil {
		return
	}

	documentList := &documentList{}
	documentList.Items = client.AppendSlice(documentList.Items, page.Items)

	for page.NextPageLink != "" {
		req = request{"GET", endpoint + page.NextPageLink, "", nil, token}
		res, err = client.Do(&req)
		if err != nil {
			return
		}
		res, err = getError(res)
		if err != nil {
			return
		}

		decoder = json.NewDecoder(res.Body)
		decoder.UseNumber()

		page.NextPageLink = ""
		page.PreviousPageLink = ""

		err = decoder.Decode(page)
		if err != nil {
			return
		}

		documentList.Items = client.AppendSlice(documentList.Items, page.Items)
	}

	result, err = json.Marshal(documentList)

	return
}

func (client *restClient) Post(url string, contentType string, body io.Reader, token string) (res *http.Response, err error) {
	if contentType == "" {
		contentType = appJson
	}

	req := request{"POST", url, contentType, body, token}
	res, err = client.Do(&req)
	return
}

func (client *restClient) Delete(url string, token string) (res *http.Response, err error) {
	req := request{"DELETE", url, "", nil, token}
	res, err = client.Do(&req)
	return
}

func (client *restClient) Do(req *request) (res *http.Response, err error) {
	r, err := http.NewRequest(req.Method, req.URL, req.Body)
	if err != nil {
		return
	}
	if req.ContentType != "" {
		r.Header.Add("Content-Type", req.ContentType)
	}
	if req.Token != "" {
		r.Header.Add("Authorization", "Bearer "+req.Token)
	}
	res, err = client.httpClient.Do(r)
	if err != nil {
		client.logger.Printf("An error occured when calling %s on %s. Error: %s", req.Method, req.URL, err)
		return
	}

	client.logger.Printf("%s %s %s", req.Method, req.URL, res.Status)
	return
}

func (client *restClient) MultipartUploadFile(url, filePath string, params map[string]string, token string) (res *http.Response, err error) {
	file, err := os.Open(filePath)
	if err != nil {
		return
	}
	defer file.Close()
	return client.MultipartUpload(url, file, filepath.Base(filePath), params, token)
}

func (client *restClient) MultipartUpload(url string, reader io.Reader, filename string, params map[string]string, token string) (res *http.Response, err error) {
	// The mime/multipart package does not support streaming multipart data from disk,
	// at least not without complicated, problematic goroutines that simultaneously read/write into a buffer.
	// A much easier approach is to just construct the multipart request by hand, using io.MultiPart to
	// concatenate the parts of the request together into a single io.Reader.
	boundary := client.randomBoundary()
	parts := []io.Reader{}

	// Create a part for each key, val pair in params
	for k, v := range params {
		parts = append(parts, client.createFieldPart(k, v, boundary))
	}

	start := fmt.Sprintf("\r\n--%s\r\n", boundary)
	start += fmt.Sprintf("Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n", quoteEscaper.Replace(filename))
	start += fmt.Sprintf("Content-Type: application/octet-stream\r\n\r\n")
	end := fmt.Sprintf("\r\n--%s--", boundary)

	// The request will consist of a reader to begin the request, a reader which points
	// to the file data on disk, and a reader containing the closing boundary of the request.
	parts = append(parts, strings.NewReader(start), reader, strings.NewReader(end))

	contentType := fmt.Sprintf("multipart/form-data; boundary=%s", boundary)

	res, err = client.Do(&request{"POST", url, contentType, io.MultiReader(parts...), token})

	return
}

// From https://golang.org/src/mime/multipart/writer.go
func (client *restClient) randomBoundary() string {
	var buf [30]byte
	_, err := io.ReadFull(rand.Reader, buf[:])
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", buf[:])
}

// Creates a reader that encapsulates a single multipart form part
func (client *restClient) createFieldPart(fieldname, value, boundary string) io.Reader {
	str := fmt.Sprintf("\r\n--%s\r\n", boundary)
	str += fmt.Sprintf("Content-Disposition: form-data; name=\"%s\"\r\n\r\n", quoteEscaper.Replace(fieldname))
	str += value
	return strings.NewReader(str)
}
<commit_msg>restclient: improve logging<commit_after>// Copyright (c) 2016 VMware, Inc. All Rights Reserved.
//
// This product is licensed to you under the Apache License, Version 2.0 (the "License").
// You may not use this product except in compliance with the License.
//
// This product may include a number of subcomponents with separate copyright notices and
// license terms. Your use of these subcomponents is subject to the terms and conditions
// of the subcomponent's license, as noted in the LICENSE file.

package photon

import (
	"crypto/rand"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

type restClient struct {
	httpClient *http.Client
	logger     *log.Logger
}

type request struct {
	Method      string
	URL         string
	ContentType string
	Body        io.Reader
	Token       string
}

type page struct {
	Items            []interface{} `json:"items"`
	NextPageLink     string        `json:"nextPageLink"`
	PreviousPageLink string        `json:"previousPageLink"`
}

type documentList struct {
	Items []interface{}
}

const appJson string = "application/json"

// From https://golang.org/src/mime/multipart/writer.go
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func (client *restClient) AppendSlice(origSlice []interface{}, dataToAppend []interface{}) []interface{} {
	origLen := len(origSlice)
	newLen := origLen + len(dataToAppend)

	if newLen > cap(origSlice) {
		newSlice := make([]interface{}, (newLen+1)*2)
		copy(newSlice, origSlice)
		origSlice = newSlice
	}

	origSlice = origSlice[0:newLen]
	copy(origSlice[origLen:newLen], dataToAppend)

	return origSlice
}

func (client *restClient) Get(url string, token string) (res *http.Response, err error) {
	req := request{"GET", url, "", nil, token}
	res, err = client.Do(&req)
	return
}

func (client *restClient) GetList(endpoint string, url string, token string) (result []byte, err error) {
	req := request{"GET", url, "", nil, token}
	res, err := client.Do(&req)
	if err != nil {
		return
	}
	res, err = getError(res)
	if err != nil {
		return
	}

	decoder := json.NewDecoder(res.Body)
	decoder.UseNumber()

	page := &page{}
	err = decoder.Decode(page)
	if err != nil {
		return
	}

	documentList := &documentList{}
	documentList.Items = client.AppendSlice(documentList.Items, page.Items)

	for page.NextPageLink != "" {
		req = request{"GET", endpoint + page.NextPageLink, "", nil, token}
		res, err = client.Do(&req)
		if err != nil {
			return
		}
		res, err = getError(res)
		if err != nil {
			return
		}

		decoder = json.NewDecoder(res.Body)
		decoder.UseNumber()

		page.NextPageLink = ""
		page.PreviousPageLink = ""

		err = decoder.Decode(page)
		if err != nil {
			return
		}

		documentList.Items = client.AppendSlice(documentList.Items, page.Items)
	}

	result, err = json.Marshal(documentList)

	return
}

func (client *restClient) Post(url string, contentType string, body io.Reader, token string) (res *http.Response, err error) {
	if contentType == "" {
		contentType = appJson
	}

	req := request{"POST", url, contentType, body, token}
	res, err = client.Do(&req)
	return
}

func (client *restClient) Delete(url string, token string) (res *http.Response, err error) {
	req := request{"DELETE", url, "", nil, token}
	res, err = client.Do(&req)
	return
}

func (client *restClient) Do(req *request) (res *http.Response, err error) {
	r, err := http.NewRequest(req.Method, req.URL, req.Body)
	if err != nil {
		client.logger.Printf("An error occured creating request %s on %s. Error: %s", req.Method, req.URL, err)
		return
	}
	if req.ContentType != "" {
		r.Header.Add("Content-Type", req.ContentType)
	}
	if req.Token != "" {
		r.Header.Add("Authorization", "Bearer "+req.Token)
	}
	res, err = client.httpClient.Do(r)
	if err != nil {
		client.logger.Printf("An error occured when calling %s on %s. Error: %s", req.Method, req.URL, err)
		return
	}

	client.logger.Printf("[%s] %s - %s %s", res.Header.Get("request-id"), res.Status, req.Method, req.URL)
	return
}

func (client *restClient) MultipartUploadFile(url, filePath string, params map[string]string, token string) (res *http.Response, err error) {
	file, err := os.Open(filePath)
	if err != nil {
		return
	}
	defer file.Close()
	return client.MultipartUpload(url, file, filepath.Base(filePath), params, token)
}

func (client *restClient) MultipartUpload(url string, reader io.Reader, filename string, params map[string]string, token string) (res *http.Response, err error) {
	// The mime/multipart package does not support streaming multipart data from disk,
	// at least not without complicated, problematic goroutines that simultaneously read/write into a buffer.
	// A much easier approach is to just construct the multipart request by hand, using io.MultiPart to
	// concatenate the parts of the request together into a single io.Reader.
	boundary := client.randomBoundary()
	parts := []io.Reader{}

	// Create a part for each key, val pair in params
	for k, v := range params {
		parts = append(parts, client.createFieldPart(k, v, boundary))
	}

	start := fmt.Sprintf("\r\n--%s\r\n", boundary)
	start += fmt.Sprintf("Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n", quoteEscaper.Replace(filename))
	start += fmt.Sprintf("Content-Type: application/octet-stream\r\n\r\n")
	end := fmt.Sprintf("\r\n--%s--", boundary)

	// The request will consist of a reader to begin the request, a reader which points
	// to the file data on disk, and a reader containing the closing boundary of the request.
	parts = append(parts, strings.NewReader(start), reader, strings.NewReader(end))

	contentType := fmt.Sprintf("multipart/form-data; boundary=%s", boundary)

	res, err = client.Do(&request{"POST", url, contentType, io.MultiReader(parts...), token})

	return
}

// From https://golang.org/src/mime/multipart/writer.go
func (client *restClient) randomBoundary() string {
	var buf [30]byte
	_, err := io.ReadFull(rand.Reader, buf[:])
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", buf[:])
}

// Creates a reader that encapsulates a single multipart form part
func (client *restClient) createFieldPart(fieldname, value, boundary string) io.Reader {
	str := fmt.Sprintf("\r\n--%s\r\n", boundary)
	str += fmt.Sprintf("Content-Disposition: form-data; name=\"%s\"\r\n\r\n", quoteEscaper.Replace(fieldname))
	str += value
	return strings.NewReader(str)
}
<|endoftext|>


<commit_before>package memberlist

import (
	"math"
	"time"
)

type suspicion struct {
	k             float64
	min           float64
	max           float64
	start         time.Time
	timer         *time.Timer
	confirmations map[string]struct{}
}

func newSuspicion(k int, min time.Duration, max time.Duration, f func()) *suspicion {
	return &suspicion{
		k:             float64(k),
		min:           min.Seconds(),
		max:           max.Seconds(),
		start:         time.Now(),
		timer:         time.AfterFunc(max, f),
		confirmations: make(map[string]struct{}),
	}
}

func (s *suspicion) Corroborate(from string) {
	// Only allow one confirmation from each possible peer.
	if _, ok := s.confirmations[from]; ok {
		return
	}
	s.confirmations[from] = struct{}{}

	// Compute the new timeout given the current number of confirmations.
	n := float64(len(s.confirmations))
	timeout := math.Max(s.min, s.max-(s.max-s.min)*math.Log(n+1.0)/math.Log(s.k+1.0))

	// Reset the timer. Note we don't care if this returns false (the timer
	// already fired). We have to take into account the amount of time that
	// has passed so far, so we get the right overall timeout.
	remaining := math.Max(0.0, s.start.Sub(time.Now()).Seconds()+timeout)
	duration := time.Duration(math.Floor(1000.0*remaining)) * time.Millisecond
	s.timer.Reset(duration)
}
<commit_msg>Adds documentation for the suspicion class.<commit_after>package memberlist

import (
	"math"
	"time"
)

// suspicion manages the suspect timer for a node and provides an interface
// to accelerate the timeout as we get more independent confirmations that
// a node is suspect.
type suspicion struct {
	// k is the number of independent confirmations we'd like to see in
	// order to drive the timer to its minimum value. This is a float so
	// we don't have to cast it later.
	k float64

	// min is the minimum timer value in seconds.
	min float64

	// max is the maximum timer value in seconds.
	max float64

	// start captures the timestamp when we began the timer. This is used
	// so we can calculate durations to feed the timer during updates in
	// a way the achieves the overall time we'd like.
	start time.Time

	// timer is the underlying timer that implements the timeout.
	timer *time.Timer

	// confirmations is a map of "from" nodes that have confirmed a given
	// node is suspect. This prevents double counting, and also serves as
	// our source of truth for counting confirmations.
	confirmations map[string]struct{}
}

// newSuspicion returns a timer started with the max time, and that will drive
// to the min time after seeing k or more confirmations.
func newSuspicion(k int, min time.Duration, max time.Duration, f func()) *suspicion {
	return &suspicion{
		k:             float64(k),
		min:           min.Seconds(),
		max:           max.Seconds(),
		start:         time.Now(),
		timer:         time.AfterFunc(max, f),
		confirmations: make(map[string]struct{}),
	}
}

// Corroborate registers that a possibly new peer has also determined the given
// node is suspect.
func (s *suspicion) Corroborate(from string) {
	// Only allow one confirmation from each possible peer.
	if _, ok := s.confirmations[from]; ok {
		return
	}
	s.confirmations[from] = struct{}{}

	// Compute the new timeout given the current number of confirmations.
	n := float64(len(s.confirmations))
	timeout := math.Max(s.min, s.max-(s.max-s.min)*math.Log(n+1.0)/math.Log(s.k+1.0))

	// Reset the timer. Note we don't care if this returns false (the timer
	// already fired). We have to take into account the amount of time that
	// has passed so far, so we get the right overall timeout.
	remaining := math.Max(0.0, s.start.Sub(time.Now()).Seconds()+timeout)
	duration := time.Duration(math.Floor(1000.0*remaining)) * time.Millisecond
	s.timer.Reset(duration)
}
<|endoftext|>


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

package rootio

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

type Reader interface {
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Closer
}

// A ROOT file is a suite of consecutive data records (TKey's) with
// the following format (see also the TKey class). If the key is
// located past the 32 bit file limit (> 2 GB) then some fields will
// be 8 instead of 4 bytes:
//    1->4            Nbytes    = Length of compressed object (in bytes)
//    5->6            Version   = TKey version identifier
//    7->10           ObjLen    = Length of uncompressed object
//    11->14          Datime    = Date and time when object was written to file
//    15->16          KeyLen    = Length of the key structure (in bytes)
//    17->18          Cycle     = Cycle of key
//    19->22 [19->26] SeekKey   = Pointer to record itself (consistency check)
//    23->26 [27->34] SeekPdir  = Pointer to directory header
//    27->27 [35->35] lname     = Number of bytes in the class name
//    28->.. [36->..] ClassName = Object Class Name
//    ..->..          lname     = Number of bytes in the object name
//    ..->..          Name      = lName bytes with the name of the object
//    ..->..          lTitle    = Number of bytes in the object title
//    ..->..          Title     = Title of the object
//    ----->          DATA      = Data bytes associated to the object
//
// The first data record starts at byte fBEGIN (currently set to kBEGIN).
// Bytes 1->kBEGIN contain the file description, when fVersion >= 1000000
// it is a large file (> 2 GB) and the offsets will be 8 bytes long and
// fUnits will be set to 8:
//    1->4            "root"      = Root file identifier
//    5->8            fVersion    = File format version
//    9->12           fBEGIN      = Pointer to first data record
//    13->16 [13->20] fEND        = Pointer to first free word at the EOF
//    17->20 [21->28] fSeekFree   = Pointer to FREE data record
//    21->24 [29->32] fNbytesFree = Number of bytes in FREE data record
//    25->28 [33->36] nfree       = Number of free data records
//    29->32 [37->40] fNbytesName = Number of bytes in TNamed at creation time
//    33->33 [41->41] fUnits      = Number of bytes for file pointers
//    34->37 [42->45] fCompress   = Compression level and algorithm
//    38->41 [46->53] fSeekInfo   = Pointer to TStreamerInfo record
//    42->45 [54->57] fNbytesInfo = Number of bytes in TStreamerInfo record
//    46->63 [58->75] fUUID       = Universal Unique ID
type File struct {
	Reader
	id string //non-root, identifies filename, etc.

	magic   [4]byte
	version int32
	begin   int64

	// Remainder of record is variable length, 4 or 8 bytes per pointer
	end         int64
	seekfree    int64 // first available record
	nbytesfree  int32 // total bytes available
	nfree       int32 // total free bytes
	nbytesname  int32 // number of bytes in TNamed at creation time
	units       byte
	compression int32
	seekinfo    int64 // pointer to TStreamerInfo
	nbytesinfo  int32 // sizeof(TStreamerInfo)
	uuid        [18]byte

	dir    tdirectory // root directory of this file
	siKey  Key
	sinfos []StreamerInfo
}

// Open opens the named ROOT file for reading. If successful, methods on the
// returned file can be used for reading; the associated file descriptor
// has mode os.O_RDONLY.
func Open(path string) (*File, error) {
	fd, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("rootio: unable to open %q (%q)", path, err.Error())
	}

	f := &File{
		Reader: fd,
		id:     path,
	}
	f.dir = tdirectory{file: f}

	err = f.readHeader()
	if err != nil {
		return nil, fmt.Errorf("rootio: failed to read header %q: %v", path, err)
	}

	return f, nil
}

// NewReader creates a new ROOT file reader.
func NewReader(r Reader, name string) (*File, error) {
	f := &File{
		Reader: r,
		id:     name,
	}
	f.dir = tdirectory{file: f}

	err := f.readHeader()
	if err != nil {
		return nil, fmt.Errorf("rootio: failed to read header: %v", err)
	}

	return f, nil
}

// Version returns the ROOT version this file was created with.
func (f *File) Version() int {
	return int(f.version)
}

func (f *File) readHeader() error {

	buf := make([]byte, 64)
	if _, err := f.ReadAt(buf, 0); err != nil {
		return err
	}

	r := NewRBuffer(buf, nil, 0)

	// Header

	if _, err := io.ReadFull(r.r, f.magic[:]); err != nil || string(f.magic[:]) != "root" {
		if err != nil {
			return fmt.Errorf("rootio: failed to read ROOT file magic header: %v", err)
		}
		return fmt.Errorf("rootio: %q is not a root file", f.id)
	}

	f.version = r.ReadI32()
	f.begin = int64(r.ReadI32())
	if f.version < 1000000 { // small file
		f.end = int64(r.ReadI32())
		f.seekfree = int64(r.ReadI32())
		f.nbytesfree = r.ReadI32()
		f.nfree = r.ReadI32()
		f.nbytesname = r.ReadI32()
		f.units = r.ReadU8()
		f.compression = r.ReadI32()
		f.seekinfo = int64(r.ReadI32())
		f.nbytesinfo = r.ReadI32()
	} else { // large files
		f.end = r.ReadI64()
		f.seekfree = r.ReadI64()
		f.nbytesfree = r.ReadI32()
		f.nfree = r.ReadI32()
		f.nbytesname = r.ReadI32()
		f.units = r.ReadU8()
		f.compression = r.ReadI32()
		f.seekinfo = r.ReadI64()
		f.nbytesinfo = r.ReadI32()
	}
	f.version %= 1000000

	if _, err := io.ReadFull(r.r, f.uuid[:]); err != nil || r.Err() != nil {
		if err != nil {
			return fmt.Errorf("rootio: failed to read ROOT's UUID file: %v", err)
		}
		return r.Err()
	}

	var err error

	err = f.dir.readDirInfo()
	if err != nil {
		return fmt.Errorf("rootio: failed to read ROOT directory infos: %v", err)
	}

	err = f.readStreamerInfo()
	if err != nil {
		return fmt.Errorf("rootio: failed to read ROOT streamer infos: %v", err)
	}

	err = f.dir.readKeys()
	if err != nil {
		return fmt.Errorf("rootio: failed to read ROOT file keys: %v", err)
	}

	return nil
}

func (f *File) Map() {
	for _, k := range f.dir.keys {
		if k.class == "TBasket" {
			//b := k.AsBasket()
			fmt.Printf("%8s %60s %6v %6v %f\n", k.class, k.name, k.bytes-k.keylen, k.objlen, float64(k.objlen)/float64(k.bytes-k.keylen))
		} else {
			//println(k.classname, k.name, k.title)
			fmt.Printf("%8s %60s %6v %6v %f\n", k.class, k.name, k.bytes-k.keylen, k.objlen, float64(k.objlen)/float64(k.bytes-k.keylen))
		}
	}
}

func (f *File) Tell() int64 {
	where, err := f.Seek(0, ioSeekCurrent)
	if err != nil {
		panic(err)
	}
	return where
}

// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (f *File) Close() error {
	for _, k := range f.dir.keys {
		k.f = nil
	}
	f.dir.keys = nil
	f.dir.file = nil
	return f.Reader.Close()
}

// Keys returns the list of keys this File contains
func (f *File) Keys() []Key {
	return f.dir.keys
}

func (f *File) Name() string {
	return f.dir.Name()
}

func (f *File) Title() string {
	return f.dir.Title()
}

func (f *File) Class() string {
	return "TFile"
}

// readStreamerInfo reads the list of StreamerInfo from this file
func (f *File) readStreamerInfo() error {
	if f.seekinfo <= 0 || f.seekinfo >= f.end {
		return fmt.Errorf("rootio: invalid pointer to StreamerInfo (pos=%v end=%v)", f.seekinfo, f.end)

	}
	buf := make([]byte, int(f.nbytesinfo))
	nbytes, err := f.ReadAt(buf, f.seekinfo)
	if err != nil {
		return err
	}
	if nbytes != int(f.nbytesinfo) {
		return fmt.Errorf("rootio: requested [%v] bytes. read [%v] bytes from file", f.nbytesinfo, nbytes)
	}

	err = f.siKey.UnmarshalROOT(NewRBuffer(buf, nil, 0))
	f.siKey.f = f
	if err != nil {
		return err
	}

	objs := f.siKey.Value().(List)
	f.sinfos = make([]StreamerInfo, 0, objs.Len())
	for i := 0; i < objs.Len(); i++ {
		obj, ok := objs.At(i).(StreamerInfo)
		if !ok {
			continue
		}
		f.sinfos = append(f.sinfos, obj)
		streamers.add(obj)
	}
	return nil
}

// StreamerInfo returns the list of StreamerInfos of this file.
func (f *File) StreamerInfo() []StreamerInfo {
	return f.sinfos
}

// Get returns the object identified by namecycle
//   namecycle has the format name;cycle
//   name  = * is illegal, cycle = * is illegal
//   cycle = "" or cycle = 9999 ==> apply to a memory object
//
//   examples:
//     foo   : get object named foo in memory
//             if object is not in memory, try with highest cycle from file
//     foo;1 : get cycle 1 of foo on file
func (f *File) Get(namecycle string) (Object, bool) {
	return f.dir.Get(namecycle)
}

var _ Object = (*File)(nil)
var _ Named = (*File)(nil)
var _ Directory = (*File)(nil)
<commit_msg>rootio: remove internal File.magic field<commit_after>// Copyright 2017 The go-hep Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rootio

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

type Reader interface {
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Closer
}

// A ROOT file is a suite of consecutive data records (TKey's) with
// the following format (see also the TKey class). If the key is
// located past the 32 bit file limit (> 2 GB) then some fields will
// be 8 instead of 4 bytes:
//    1->4            Nbytes    = Length of compressed object (in bytes)
//    5->6            Version   = TKey version identifier
//    7->10           ObjLen    = Length of uncompressed object
//    11->14          Datime    = Date and time when object was written to file
//    15->16          KeyLen    = Length of the key structure (in bytes)
//    17->18          Cycle     = Cycle of key
//    19->22 [19->26] SeekKey   = Pointer to record itself (consistency check)
//    23->26 [27->34] SeekPdir  = Pointer to directory header
//    27->27 [35->35] lname     = Number of bytes in the class name
//    28->.. [36->..] ClassName = Object Class Name
//    ..->..          lname     = Number of bytes in the object name
//    ..->..          Name      = lName bytes with the name of the object
//    ..->..          lTitle    = Number of bytes in the object title
//    ..->..          Title     = Title of the object
//    ----->          DATA      = Data bytes associated to the object
//
// The first data record starts at byte fBEGIN (currently set to kBEGIN).
// Bytes 1->kBEGIN contain the file description, when fVersion >= 1000000
// it is a large file (> 2 GB) and the offsets will be 8 bytes long and
// fUnits will be set to 8:
//    1->4            "root"      = Root file identifier
//    5->8            fVersion    = File format version
//    9->12           fBEGIN      = Pointer to first data record
//    13->16 [13->20] fEND        = Pointer to first free word at the EOF
//    17->20 [21->28] fSeekFree   = Pointer to FREE data record
//    21->24 [29->32] fNbytesFree = Number of bytes in FREE data record
//    25->28 [33->36] nfree       = Number of free data records
//    29->32 [37->40] fNbytesName = Number of bytes in TNamed at creation time
//    33->33 [41->41] fUnits      = Number of bytes for file pointers
//    34->37 [42->45] fCompress   = Compression level and algorithm
//    38->41 [46->53] fSeekInfo   = Pointer to TStreamerInfo record
//    42->45 [54->57] fNbytesInfo = Number of bytes in TStreamerInfo record
//    46->63 [58->75] fUUID       = Universal Unique ID
type File struct {
	Reader
	id string //non-root, identifies filename, etc.

	version int32
	begin   int64

	// Remainder of record is variable length, 4 or 8 bytes per pointer
	end         int64
	seekfree    int64 // first available record
	nbytesfree  int32 // total bytes available
	nfree       int32 // total free bytes
	nbytesname  int32 // number of bytes in TNamed at creation time
	units       byte
	compression int32
	seekinfo    int64 // pointer to TStreamerInfo
	nbytesinfo  int32 // sizeof(TStreamerInfo)
	uuid        [18]byte

	dir    tdirectory // root directory of this file
	siKey  Key
	sinfos []StreamerInfo
}

// Open opens the named ROOT file for reading. If successful, methods on the
// returned file can be used for reading; the associated file descriptor
// has mode os.O_RDONLY.
func Open(path string) (*File, error) {
	fd, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("rootio: unable to open %q (%q)", path, err.Error())
	}

	f := &File{
		Reader: fd,
		id:     path,
	}
	f.dir = tdirectory{file: f}

	err = f.readHeader()
	if err != nil {
		return nil, fmt.Errorf("rootio: failed to read header %q: %v", path, err)
	}

	return f, nil
}

// NewReader creates a new ROOT file reader.
func NewReader(r Reader, name string) (*File, error) {
	f := &File{
		Reader: r,
		id:     name,
	}
	f.dir = tdirectory{file: f}

	err := f.readHeader()
	if err != nil {
		return nil, fmt.Errorf("rootio: failed to read header: %v", err)
	}

	return f, nil
}

// Version returns the ROOT version this file was created with.
func (f *File) Version() int {
	return int(f.version)
}

func (f *File) readHeader() error {

	buf := make([]byte, 64)
	if _, err := f.ReadAt(buf, 0); err != nil {
		return err
	}

	r := NewRBuffer(buf, nil, 0)

	// Header

	var magic [4]byte
	if _, err := io.ReadFull(r.r, magic[:]); err != nil || string(magic[:]) != "root" {
		if err != nil {
			return fmt.Errorf("rootio: failed to read ROOT file magic header: %v", err)
		}
		return fmt.Errorf("rootio: %q is not a root file", f.id)
	}

	f.version = r.ReadI32()
	f.begin = int64(r.ReadI32())
	if f.version < 1000000 { // small file
		f.end = int64(r.ReadI32())
		f.seekfree = int64(r.ReadI32())
		f.nbytesfree = r.ReadI32()
		f.nfree = r.ReadI32()
		f.nbytesname = r.ReadI32()
		f.units = r.ReadU8()
		f.compression = r.ReadI32()
		f.seekinfo = int64(r.ReadI32())
		f.nbytesinfo = r.ReadI32()
	} else { // large files
		f.end = r.ReadI64()
		f.seekfree = r.ReadI64()
		f.nbytesfree = r.ReadI32()
		f.nfree = r.ReadI32()
		f.nbytesname = r.ReadI32()
		f.units = r.ReadU8()
		f.compression = r.ReadI32()
		f.seekinfo = r.ReadI64()
		f.nbytesinfo = r.ReadI32()
	}
	f.version %= 1000000

	if _, err := io.ReadFull(r.r, f.uuid[:]); err != nil || r.Err() != nil {
		if err != nil {
			return fmt.Errorf("rootio: failed to read ROOT's UUID file: %v", err)
		}
		return r.Err()
	}

	var err error

	err = f.dir.readDirInfo()
	if err != nil {
		return fmt.Errorf("rootio: failed to read ROOT directory infos: %v", err)
	}

	err = f.readStreamerInfo()
	if err != nil {
		return fmt.Errorf("rootio: failed to read ROOT streamer infos: %v", err)
	}

	err = f.dir.readKeys()
	if err != nil {
		return fmt.Errorf("rootio: failed to read ROOT file keys: %v", err)
	}

	return nil
}

func (f *File) Map() {
	for _, k := range f.dir.keys {
		if k.class == "TBasket" {
			//b := k.AsBasket()
			fmt.Printf("%8s %60s %6v %6v %f\n", k.class, k.name, k.bytes-k.keylen, k.objlen, float64(k.objlen)/float64(k.bytes-k.keylen))
		} else {
			//println(k.classname, k.name, k.title)
			fmt.Printf("%8s %60s %6v %6v %f\n", k.class, k.name, k.bytes-k.keylen, k.objlen, float64(k.objlen)/float64(k.bytes-k.keylen))
		}
	}
}

func (f *File) Tell() int64 {
	where, err := f.Seek(0, ioSeekCurrent)
	if err != nil {
		panic(err)
	}
	return where
}

// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (f *File) Close() error {
	for _, k := range f.dir.keys {
		k.f = nil
	}
	f.dir.keys = nil
	f.dir.file = nil
	return f.Reader.Close()
}

// Keys returns the list of keys this File contains
func (f *File) Keys() []Key {
	return f.dir.keys
}

func (f *File) Name() string {
	return f.dir.Name()
}

func (f *File) Title() string {
	return f.dir.Title()
}

func (f *File) Class() string {
	return "TFile"
}

// readStreamerInfo reads the list of StreamerInfo from this file
func (f *File) readStreamerInfo() error {
	if f.seekinfo <= 0 || f.seekinfo >= f.end {
		return fmt.Errorf("rootio: invalid pointer to StreamerInfo (pos=%v end=%v)", f.seekinfo, f.end)

	}
	buf := make([]byte, int(f.nbytesinfo))
	nbytes, err := f.ReadAt(buf, f.seekinfo)
	if err != nil {
		return err
	}
	if nbytes != int(f.nbytesinfo) {
		return fmt.Errorf("rootio: requested [%v] bytes. read [%v] bytes from file", f.nbytesinfo, nbytes)
	}

	err = f.siKey.UnmarshalROOT(NewRBuffer(buf, nil, 0))
	f.siKey.f = f
	if err != nil {
		return err
	}

	objs := f.siKey.Value().(List)
	f.sinfos = make([]StreamerInfo, 0, objs.Len())
	for i := 0; i < objs.Len(); i++ {
		obj, ok := objs.At(i).(StreamerInfo)
		if !ok {
			continue
		}
		f.sinfos = append(f.sinfos, obj)
		streamers.add(obj)
	}
	return nil
}

// StreamerInfo returns the list of StreamerInfos of this file.
func (f *File) StreamerInfo() []StreamerInfo {
	return f.sinfos
}

// Get returns the object identified by namecycle
//   namecycle has the format name;cycle
//   name  = * is illegal, cycle = * is illegal
//   cycle = "" or cycle = 9999 ==> apply to a memory object
//
//   examples:
//     foo   : get object named foo in memory
//             if object is not in memory, try with highest cycle from file
//     foo;1 : get cycle 1 of foo on file
func (f *File) Get(namecycle string) (Object, bool) {
	return f.dir.Get(namecycle)
}

var _ Object = (*File)(nil)
var _ Named = (*File)(nil)
var _ Directory = (*File)(nil)
<|endoftext|>