<commit_before>package server

import (
	"time"

	"gopkg.in/mgo.v2/bson"
)

type Team struct {
	Id     bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
	Number int           `json:"number"`
	Name   string        `json:"name"`
	Ip     string        `json:"ip"`
	Hash   string        `json:"-"`
}

type Challenge struct {
	Id          bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
	Group       string        `json:"group"`
	Name        string        `json:"name"`
	Description string        `json:"description"`
	Flag        string        `json:"-" bson:"-"`
	Points      int           `json:"points"`
}

type Result struct {
	Id         bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
	Type       string        `json:"type" bson:"type"`
	Group      string        `json:"group" bson:"group"`
	Teamname   string        `json:"teamname" bson:"teamname"`
	Teamnumber int           `json:"teamnumber" bson:"teamnumber"`
	Details    string        `json:"details" bson:"details"`
	Points     int           `json:"points" bson:"points"`
}

// Authentication Queries
func GetTeamByTeamname(teamname string) (Team, error) {
	t := Team{}

	session, teamCollection := GetSessionAndCollection("teams")
	defer session.Close()

	err := teamCollection.Find(bson.M{"name": teamname}).One(&t)
	if err != nil {
		Logger.Printf("Error finding team by Teamname %s err: %v\n", teamname, err)
		return t, err
	}
	return t, nil
}

func GetTeamById(id *bson.ObjectId) (Team, error) {
	t := Team{}

	session, teamCollection := GetSessionAndCollection("teams")
	defer session.Close()

	err := teamCollection.Find(bson.M{"_id": id}).One(&t)
	if err != nil {
		Logger.Printf("Error finding team by ID %v err: %v\n", id, err)
		return t, err
	}
	return t, nil
}

// Get Team name and ip only used for service checking
func DataGetTeamIps() ([]Team, error) {
	t := []Team{}

	session, teamCollection := GetSessionAndCollection("teams")
	defer session.Close()

	err := teamCollection.Find(nil).Select(bson.M{"_id": false, "name": true, "number": true, "ip": true}).All(&t)
	if err != nil {
		//Logger.Printf("Error finding teams: %v\n", err)
		return t, err
	}
	return t, nil
}

func DataGetTeams() []Team {
	t := []Team{}

	session, chalCollection := GetSessionAndCollection("teams")
	defer session.Close()

	err := chalCollection.Find(nil).Sort("number").Select(bson.M{"_id": 0, "number": 1, "name": 1}).All(&t)
	if err != nil {
		Logger.Printf("Could not get team info: %v\n", err)
		return t
	}
	return t
}

// Query statements
func DataGetChallenges(group string) ([]Challenge, error) {
	challenges := []Challenge{}

	session, chalCollection := GetSessionAndCollection("challenges")
	defer session.Close()

	err := chalCollection.Find(bson.M{"group": group}).Sort("description").Select(bson.M{"_id": 0, "flag": 0}).All(&challenges)
	if err != nil {
		return challenges, err
	}
	return challenges, nil
}

func DataCheckFlag(team Team, chal Challenge) (int, error) {
	session, chalCollection := GetSessionAndCollection("challenges")
	defer session.Close()
	var err error

	if len(chal.Name) > 0 {
		err = chalCollection.Find(bson.M{"flag": chal.Flag, "name": chal.Name}).Select(bson.M{"_id": 0, "flag": 0}).One(&chal)
	} else {
		err = chalCollection.Find(bson.M{"flag": chal.Flag}).Select(bson.M{"_id": 0, "flag": 0}).One(&chal)
	}
	if err != nil {
		// Wrong flag = 1
		return 1, err
	} else {
		if !HasFlag(team.Name, chal.Name) {
			// Correct flag = 0
			result := Result{
				Type:       "CTF",
				Group:      chal.Group,
				Teamname:   team.Name,
				Teamnumber: team.Number,
				Details:    chal.Name,
				Points:     chal.Points,
			}
			return 0, DataAddResult(result)
		} else {
			// Got challenge already
			return 2, nil
		}
	}
}

func HasFlag(teamname, challengeName string) bool {
	chal := Challenge{}

	session, resultCollection := GetSessionAndCollection("results")
	defer session.Close()

	// TODO: Do not need the returned document.
	// Need to find better way to check if exists
	err := resultCollection.Find(bson.M{"teamname": teamname, "details": challengeName}).One(&chal)
	if err != nil {
		// TODO: Log error
		return false
	}
	return true
}

func DataGetTotalChallenges() (map[string]int, error) {
	session, collection := GetSessionAndCollection("challenges")
	defer session.Close()
	totals := make(map[string]int)
	t := bson.M{}
	pipe := collection.Pipe([]bson.M{
		{"$group": bson.M{"_id": "$group", "total": bson.M{"$sum": 1}}},
		{"$sort": bson.M{"_id": -1}},
	})
	iter := pipe.Iter()
	for iter.Next(&t) {
		totals[t["_id"].(string)] = t["total"].(int)
	}
	if err := iter.Close(); err != nil {
		Logger.Printf("Error getting challenges: %v\n", err)
		return totals, err
	}
	return totals, nil
}

func DataGetTeamChallenges(teamname string) (map[string]int, error) {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	acquired := make(map[string]int)
	a := bson.M{}
	pipe := collection.Pipe([]bson.M{
		{"$match": bson.M{"teamname": teamname, "type": "CTF"}},
		{"$group": bson.M{"_id": "$group", "acquired": bson.M{"$sum": 1}}},
		{"$sort": bson.M{"_id": -1}},
	})
	iter := pipe.Iter()
	for iter.Next(&a) {
		acquired[a["_id"].(string)] = a["acquired"].(int)
	}
	if err := iter.Close(); err != nil {
		Logger.Printf("Error getting challenges: %v\n", err)
		return acquired, err
	}
	return acquired, nil
}

func DataGetTeamScore(teamname string) int {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	points := bson.M{}
	var p int
	pipe := collection.Pipe([]bson.M{
		{"$match": bson.M{"teamname": teamname}},
		{"$group": bson.M{"_id": nil, "points": bson.M{"$sum": "$points"}}},
		{"$project": bson.M{"_id": 0, "points": 1}},
	})
	err := pipe.One(&points)
	if err != nil {
		Logger.Printf("Error getting team points: %v\n", err)
	} else {
		p = points["points"].(int)
	}
	return p
}

func DataGetAllScore() []Result {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	tmScore := []Result{}

	teams := DataGetTeams()
	pipe := collection.Pipe([]bson.M{
		{"$group": bson.M{"_id": bson.M{"tname": "$teamname", "tnum": "$teamnumber"}, "points": bson.M{"$sum": "$points"}}},
		{"$project": bson.M{"_id": 0, "points": 1, "teamnumber": "$_id.tnum", "teamname": "$_id.tname"}},
		{"$sort": bson.M{"teamnumber": 1}},
	})
	err := pipe.All(&tmScore)
	if err != nil {
		Logger.Printf("Error getting all team scores: %v\n", err)
	}
	// Get defaults for teams that do not have a score
	if l := len(tmScore); l < len(teams) {
		if l == 0 {
			for _, t := range teams {
				tmScore = append(tmScore, Result{Teamname: t.Name, Teamnumber: t.Number, Points: 0})
			}
		} else {
			for i := l; i < len(teams); i++ {
				tmScore = append(tmScore, Result{Teamname: teams[i].Name, Teamnumber: teams[i].Number, Points: 0})
			}
		}
	}
	return tmScore
}

func DataGetServiceStatus() []interface{} {
	session, results := GetSessionAndCollection("results")
	defer session.Close()
	var cResults []interface{}

	pipe := results.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service"}},
		{"$group": bson.M{"_id": bson.M{"service": "$group", "tnum": "$teamnumber", "tname": "$teamname"}, "status": bson.M{"$last": "$details"}}},
		{"$group": bson.M{"_id": "$_id.service", "teams": bson.M{"$addToSet": bson.M{"number": "$_id.tnum", "name": "$_id.tname", "status": "$status"}}}},
	})
	err := pipe.All(&cResults)
	if err != nil {
		Logger.Printf("Error getting all team scores: %v\n", err)
	}
	/*
		for iter.Next(&check) {
				teams := check["teams"]
				for _, t := range teams {
					result := Result{
						Group:      check["_id"].(string),
						Teamname:   t["teamname"].(string),
						Teamnumber: t["teamnnumber"].(int),
						Details:    t["status"].(string),
					}
					cResults = append(cResults, result)
				}
		}
		if err := iter.Close(); err != nil {
			Logger.Printf("Error getting service status: %v\n", err)
		}
	*/
	return cResults
}

func DataGetServiceResult() []Result {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	sList := []Result{}

	err := collection.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service"}},
		{"$group": bson.M{"_id": bson.M{"service": "$group", "tnum": "$teamnumber", "tname": "$teamname"}, "status": bson.M{"$last": "$details"}}},
		{"$group": bson.M{"_id": "$_id.service", "teams": bson.M{"$addToSet": bson.M{"number": "$_id.tnum", "name": "$_id.tname", "status": "$status"}}}},
		{"$unwind": "$teams"},
		{"$project": bson.M{"_id": 0, "group": "$_id", "teamnumber": "$teams.number", "teamname": "$teams.name", "details": "$teams.status"}},
		{"$sort": bson.M{"group": 1, "teamnumber": 1}},
	}).All(&sList)
	if err != nil {
		Logger.Printf("Error getting all team scores: %v\n", err)
	}
	return sList
}

func DataGetResultByService(service string) []Result {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	teamStatus := []Result{}

	err := collection.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service", "group": service}},
		{"$group": bson.M{"_id": bson.M{"service": "$group", "tnum": "$teamnumber", "tname": "$teamname"}, "status": bson.M{"$last": "$details"}}},
		{"$project": bson.M{"_id": 0, "group": "$_id.service", "teamnumber": "$_id.tnum", "teamname": "$_id.tname", "details": "$status"}},
		{"$sort": bson.M{"teamnumber": 1}},
	}).All(&teamStatus)
	if err != nil {
		Logger.Printf("Error getting team status by service: %v\n", err)
	}
	return teamStatus
}

func DataGetServiceList() []string {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	var list []string
	res := bson.M{}

	pipe := collection.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service"}},
		{"$group": bson.M{"_id": "$group"}},
		{"$project": bson.M{"_id": 0, "group": "$_id"}},
		{"$sort": bson.M{"group": 1}},
	})
	iter := pipe.Iter()
	for iter.Next(&res) {
		list = append(list, res["group"].(string))
	}
	if err := iter.Close(); err != nil {
		Logger.Printf("Error getting service list: %v\n", err)
	}
	return list

}

// TODO: Combine queries since this has repeating code
func DataGetLastServiceResult() time.Time {
	session, results := GetSessionAndCollection("results")
	defer session.Close()
	id := bson.M{}
	err := results.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service"}},
		{"$sort": bson.M{"_id": 1}},
		{"$group": bson.M{"_id": nil, "last": bson.M{"$last": "$_id"}}},
		{"$project": bson.M{"_id": 0, "last": 1}},
	}).One(&id)
	var time time.Time
	if err != nil {
		Logger.Printf("Error getting last Service result: %v\n", err)
	} else {
		time = id["last"].(bson.ObjectId).Time()
	}
	return time
}

func DataGetLastResult() time.Time {
	session, results := GetSessionAndCollection("results")
	defer session.Close()
	id := bson.M{}
	err := results.Pipe([]bson.M{
		{"$sort": bson.M{"_id": 1}},
		{"$group": bson.M{"_id": nil, "last": bson.M{"$last": "$_id"}}},
		{"$project": bson.M{"_id": 0, "last": 1}},
	}).One(&id)
	var time time.Time
	if err != nil {
		Logger.Printf("Error getting last document: %v\n", err)
	} else {
		time = id["last"].(bson.ObjectId).Time()
	}
	return time
}

// Insert statements
func DataAddResult(result Result) error {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	err := collection.Insert(result)
	if err != nil {
		//Logger.Printf("Error inserting %s to team %s: %v", result.Details, result.Teamname, err)
		return err
	}
	return nil
}
<commit_msg>Fix queries for teams to select by group<commit_after>package server

import (
	"time"

	"gopkg.in/mgo.v2/bson"
)

type Team struct {
	Id     bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
	Group  string        `json:"-"`
	Number int           `json:"number"`
	Name   string        `json:"name"`
	Ip     string        `json:"ip"`
	Hash   string        `json:"-"`
}

type Challenge struct {
	Id          bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
	Group       string        `json:"group"`
	Name        string        `json:"name"`
	Description string        `json:"description"`
	Flag        string        `json:"-" bson:"-"`
	Points      int           `json:"points"`
}

type Result struct {
	Id         bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
	Type       string        `json:"type" bson:"type"`
	Group      string        `json:"group" bson:"group"`
	Teamname   string        `json:"teamname" bson:"teamname"`
	Teamnumber int           `json:"teamnumber" bson:"teamnumber"`
	Details    string        `json:"details" bson:"details"`
	Points     int           `json:"points" bson:"points"`
}

// Authentication Queries
func GetTeamByTeamname(teamname string) (Team, error) {
	t := Team{}

	session, teamCollection := GetSessionAndCollection("teams")
	defer session.Close()

	err := teamCollection.Find(bson.M{"group": "blueteam", "name": teamname}).One(&t)
	if err != nil {
		Logger.Printf("Error finding team by Teamname %s err: %v\n", teamname, err)
		return t, err
	}
	return t, nil
}

func GetTeamById(id *bson.ObjectId) (Team, error) {
	t := Team{}

	session, teamCollection := GetSessionAndCollection("teams")
	defer session.Close()

	err := teamCollection.Find(bson.M{"_id": id}).One(&t)
	if err != nil {
		Logger.Printf("Error finding team by ID %v err: %v\n", id, err)
		return t, err
	}
	return t, nil
}

// Get Team name and ip only used for service checking
func DataGetTeamIps() ([]Team, error) {
	t := []Team{}

	session, teamCollection := GetSessionAndCollection("teams")
	defer session.Close()

	err := teamCollection.Find(bson.M{"group": "blueteam"}).Select(bson.M{"_id": false, "name": true, "number": true, "ip": true}).All(&t)
	if err != nil {
		//Logger.Printf("Error finding teams: %v\n", err)
		return t, err
	}
	return t, nil
}

func DataGetTeams() []Team {
	t := []Team{}

	session, chalCollection := GetSessionAndCollection("teams")
	defer session.Close()

	err := chalCollection.Find(bson.M{"group": "blueteam"}).Sort("number").Select(bson.M{"_id": 0, "number": 1, "name": 1}).All(&t)
	if err != nil {
		Logger.Printf("Could not get team info: %v\n", err)
		return t
	}
	return t
}

// Query statements
func DataGetChallenges(group string) ([]Challenge, error) {
	challenges := []Challenge{}

	session, chalCollection := GetSessionAndCollection("challenges")
	defer session.Close()

	err := chalCollection.Find(bson.M{"group": group}).Sort("description").Select(bson.M{"_id": 0, "flag": 0}).All(&challenges)
	if err != nil {
		return challenges, err
	}
	return challenges, nil
}

func DataCheckFlag(team Team, chal Challenge) (int, error) {
	session, chalCollection := GetSessionAndCollection("challenges")
	defer session.Close()
	var err error

	if len(chal.Name) > 0 {
		err = chalCollection.Find(bson.M{"flag": chal.Flag, "name": chal.Name}).Select(bson.M{"_id": 0, "flag": 0}).One(&chal)
	} else {
		err = chalCollection.Find(bson.M{"flag": chal.Flag}).Select(bson.M{"_id": 0, "flag": 0}).One(&chal)
	}
	if err != nil {
		// Wrong flag = 1
		return 1, err
	} else {
		if !HasFlag(team.Name, chal.Name) {
			// Correct flag = 0
			result := Result{
				Type:       "CTF",
				Group:      chal.Group,
				Teamname:   team.Name,
				Teamnumber: team.Number,
				Details:    chal.Name,
				Points:     chal.Points,
			}
			return 0, DataAddResult(result)
		} else {
			// Got challenge already
			return 2, nil
		}
	}
}

func HasFlag(teamname, challengeName string) bool {
	chal := Challenge{}

	session, resultCollection := GetSessionAndCollection("results")
	defer session.Close()

	// TODO: Do not need the returned document.
	// Need to find better way to check if exists
	err := resultCollection.Find(bson.M{"teamname": teamname, "details": challengeName}).One(&chal)
	if err != nil {
		// TODO: Log error
		return false
	}
	return true
}

func DataGetTotalChallenges() (map[string]int, error) {
	session, collection := GetSessionAndCollection("challenges")
	defer session.Close()
	totals := make(map[string]int)
	t := bson.M{}
	pipe := collection.Pipe([]bson.M{
		{"$group": bson.M{"_id": "$group", "total": bson.M{"$sum": 1}}},
		{"$sort": bson.M{"_id": -1}},
	})
	iter := pipe.Iter()
	for iter.Next(&t) {
		totals[t["_id"].(string)] = t["total"].(int)
	}
	if err := iter.Close(); err != nil {
		Logger.Printf("Error getting challenges: %v\n", err)
		return totals, err
	}
	return totals, nil
}

func DataGetTeamChallenges(teamname string) (map[string]int, error) {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	acquired := make(map[string]int)
	a := bson.M{}
	pipe := collection.Pipe([]bson.M{
		{"$match": bson.M{"teamname": teamname, "type": "CTF"}},
		{"$group": bson.M{"_id": "$group", "acquired": bson.M{"$sum": 1}}},
		{"$sort": bson.M{"_id": -1}},
	})
	iter := pipe.Iter()
	for iter.Next(&a) {
		acquired[a["_id"].(string)] = a["acquired"].(int)
	}
	if err := iter.Close(); err != nil {
		Logger.Printf("Error getting challenges: %v\n", err)
		return acquired, err
	}
	return acquired, nil
}

func DataGetTeamScore(teamname string) int {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	points := bson.M{}
	var p int
	pipe := collection.Pipe([]bson.M{
		{"$match": bson.M{"teamname": teamname}},
		{"$group": bson.M{"_id": nil, "points": bson.M{"$sum": "$points"}}},
		{"$project": bson.M{"_id": 0, "points": 1}},
	})
	err := pipe.One(&points)
	if err != nil {
		Logger.Printf("Error getting team points: %v\n", err)
	} else {
		p = points["points"].(int)
	}
	return p
}

func DataGetAllScore() []Result {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	tmScore := []Result{}

	teams := DataGetTeams()
	pipe := collection.Pipe([]bson.M{
		{"$group": bson.M{"_id": bson.M{"tname": "$teamname", "tnum": "$teamnumber"}, "points": bson.M{"$sum": "$points"}}},
		{"$project": bson.M{"_id": 0, "points": 1, "teamnumber": "$_id.tnum", "teamname": "$_id.tname"}},
		{"$sort": bson.M{"teamnumber": 1}},
	})
	err := pipe.All(&tmScore)
	if err != nil {
		Logger.Printf("Error getting all team scores: %v\n", err)
	}
	// Get defaults for teams that do not have a score
	if l := len(tmScore); l < len(teams) {
		if l == 0 {
			for _, t := range teams {
				tmScore = append(tmScore, Result{Teamname: t.Name, Teamnumber: t.Number, Points: 0})
			}
		} else {
			for i := l; i < len(teams); i++ {
				tmScore = append(tmScore, Result{Teamname: teams[i].Name, Teamnumber: teams[i].Number, Points: 0})
			}
		}
	}
	return tmScore
}

func DataGetServiceStatus() []interface{} {
	session, results := GetSessionAndCollection("results")
	defer session.Close()
	var cResults []interface{}

	pipe := results.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service"}},
		{"$group": bson.M{"_id": bson.M{"service": "$group", "tnum": "$teamnumber", "tname": "$teamname"}, "status": bson.M{"$last": "$details"}}},
		{"$group": bson.M{"_id": "$_id.service", "teams": bson.M{"$addToSet": bson.M{"number": "$_id.tnum", "name": "$_id.tname", "status": "$status"}}}},
	})
	err := pipe.All(&cResults)
	if err != nil {
		Logger.Printf("Error getting all team scores: %v\n", err)
	}
	return cResults
}

func DataGetServiceResult() []Result {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	sList := []Result{}

	err := collection.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service"}},
		{"$group": bson.M{"_id": bson.M{"service": "$group", "tnum": "$teamnumber", "tname": "$teamname"}, "status": bson.M{"$last": "$details"}}},
		{"$group": bson.M{"_id": "$_id.service", "teams": bson.M{"$addToSet": bson.M{"number": "$_id.tnum", "name": "$_id.tname", "status": "$status"}}}},
		{"$unwind": "$teams"},
		{"$project": bson.M{"_id": 0, "group": "$_id", "teamnumber": "$teams.number", "teamname": "$teams.name", "details": "$teams.status"}},
		{"$sort": bson.M{"group": 1, "teamnumber": 1}},
	}).All(&sList)
	if err != nil {
		Logger.Printf("Error getting all team scores: %v\n", err)
	}
	return sList
}

func DataGetResultByService(service string) []Result {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	teamStatus := []Result{}

	err := collection.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service", "group": service}},
		{"$group": bson.M{"_id": bson.M{"service": "$group", "tnum": "$teamnumber", "tname": "$teamname"}, "status": bson.M{"$last": "$details"}}},
		{"$project": bson.M{"_id": 0, "group": "$_id.service", "teamnumber": "$_id.tnum", "teamname": "$_id.tname", "details": "$status"}},
		{"$sort": bson.M{"teamnumber": 1}},
	}).All(&teamStatus)
	if err != nil {
		Logger.Printf("Error getting team status by service: %v\n", err)
	}
	return teamStatus
}

func DataGetServiceList() []string {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	var list []string
	res := bson.M{}

	pipe := collection.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service"}},
		{"$group": bson.M{"_id": "$group"}},
		{"$project": bson.M{"_id": 0, "group": "$_id"}},
		{"$sort": bson.M{"group": 1}},
	})
	iter := pipe.Iter()
	for iter.Next(&res) {
		list = append(list, res["group"].(string))
	}
	if err := iter.Close(); err != nil {
		Logger.Printf("Error getting service list: %v\n", err)
	}
	return list

}

// TODO: Combine queries since this has repeating code
func DataGetLastServiceResult() time.Time {
	session, results := GetSessionAndCollection("results")
	defer session.Close()
	id := bson.M{}
	err := results.Pipe([]bson.M{
		{"$match": bson.M{"type": "Service"}},
		{"$sort": bson.M{"_id": 1}},
		{"$group": bson.M{"_id": nil, "last": bson.M{"$last": "$_id"}}},
		{"$project": bson.M{"_id": 0, "last": 1}},
	}).One(&id)
	var time time.Time
	if err != nil {
		Logger.Printf("Error getting last Service result: %v\n", err)
	} else {
		time = id["last"].(bson.ObjectId).Time()
	}
	return time
}

func DataGetLastResult() time.Time {
	session, results := GetSessionAndCollection("results")
	defer session.Close()
	id := bson.M{}
	err := results.Pipe([]bson.M{
		{"$sort": bson.M{"_id": 1}},
		{"$group": bson.M{"_id": nil, "last": bson.M{"$last": "$_id"}}},
		{"$project": bson.M{"_id": 0, "last": 1}},
	}).One(&id)
	var time time.Time
	if err != nil {
		Logger.Printf("Error getting last document: %v\n", err)
	} else {
		time = id["last"].(bson.ObjectId).Time()
	}
	return time
}

// Insert statements
func DataAddResult(result Result) error {
	session, collection := GetSessionAndCollection("results")
	defer session.Close()
	err := collection.Insert(result)
	if err != nil {
		//Logger.Printf("Error inserting %s to team %s: %v", result.Details, result.Teamname, err)
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package server

import (
	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/server/webserver"

	"fmt"
	"github.com/docker/distribution/health"
	"net/http"
	"reflect"
	"time"
)

const (
	healthEndpointPrefix        = "/health"
	defaultStopGracePeriod      = time.Second * 5
	defaultHealthCheckFrequency = time.Second * 60
	defaultHealthCheckThreshold = 1
)

// Startable interface for modules which provide a start mechanism
type Startable interface {
	Start() error
}

// Stopable interface for modules which provide a stop mechanism
type Stopable interface {
	Stop() error
}

// Endpoint adds a HTTP handler for the `GetPrefix()` to the webserver
type Endpoint interface {
	http.Handler
	GetPrefix() string
}

// Service is the main class for simple control of a server
type Service struct {
	webserver            *webserver.WebServer
	router               Router
	modules              []interface{}
	StopGracePeriod      time.Duration // The timeout given to each Module on Stop()
	healthCheckFrequency time.Duration
	healthCheckThreshold int
}

// NewService registers the Main Router, where other modules can subscribe for messages
func NewService(router Router, webserver *webserver.WebServer) *Service {
	service := &Service{
		webserver:            webserver,
		router:               router,
		StopGracePeriod:      defaultStopGracePeriod,
		healthCheckFrequency: defaultHealthCheckFrequency,
		healthCheckThreshold: defaultHealthCheckThreshold,
	}
	service.registerModule(service.router)
	service.registerModule(service.webserver)

	return service
}

func (s *Service) RegisterModules(modules []interface{}) {
	for _, module := range modules {
		s.registerModule(module)
	}
}

func (s *Service) registerModule(module interface{}) {
	s.modules = append(s.modules, module)
}

// Start checks the modules for the following interfaces and registers and/or starts:
//   Startable:
//   health.Checker:
//   Endpoint: Register the handler function of the Endpoint in the http service at prefix
func (s *Service) Start() error {
	el := protocol.NewErrorList("service: errors occured while starting: ")
	s.webserver.Handle(healthEndpointPrefix, http.HandlerFunc(health.StatusHandler))
	for _, module := range s.modules {
		name := reflect.TypeOf(module).String()
		if startable, ok := module.(Startable); ok {
			protocol.Info("service: starting module %v", name)
			if err := startable.Start(); err != nil {
				protocol.Err("service: error while starting module %v", name)
				el.Add(err)
			}
		}
		if checker, ok := module.(health.Checker); ok {
			protocol.Info("service: registering %v as HealthChecker", name)
			health.RegisterPeriodicThresholdFunc(name, s.healthCheckFrequency, s.healthCheckThreshold, health.CheckFunc(checker.Check))
		}
		if endpoint, ok := module.(Endpoint); ok {
			prefix := endpoint.GetPrefix()
			protocol.Info("service: registering %v as Endpoint to %v", name, prefix)
			s.webserver.Handle(prefix, endpoint)
		}
	}
	return el.ErrorOrNil()
}

func (s *Service) Stop() error {
	stopables := make([]Stopable, 0)
	for _, module := range s.modules {
		name := reflect.TypeOf(module).String()
		if stopable, ok := module.(Stopable); ok {
			protocol.Info("service: %v is Stopable", name)
			stopables = append(stopables, stopable)
		}
	}
	// stopOrder allows the customized stopping of the modules,
	// and not necessarily in the exact reverse order of their Registrations.
	// Now, router is first to stop, the rest of the modules are stopped in reverse-registration-order.
	stopOrder := make([]int, len(stopables))
	for i := 1; i < len(stopables); i++ {
		stopOrder[i] = len(stopables) - i
	}

	protocol.Debug("service: stopping %d modules with a %v timeout, in this order relative to registration: %v",
		len(stopOrder), s.StopGracePeriod, stopOrder)
	errors := make(map[string]error)
	for _, order := range stopOrder {
		name := reflect.TypeOf(stopables[order]).String()
		protocol.Info("service: stopping [%d] %v", order, name)
		err := s.stopModule(stopables[order], name)
		if err != nil {
			errors[name] = err
		}
	}
	if len(errors) > 0 {
		return fmt.Errorf("service: errors while stopping modules: %q", errors)
	}
	return nil
}

func (s *Service) Modules() []interface{} {
	return s.modules
}

func (s *Service) WebServer() *webserver.WebServer {
	return s.webserver
}

func (s *Service) stopModule(stopable Stopable, name string) error {
	if _, ok := stopable.(Router); ok {
		protocol.Debug("service: %v is a Router and requires a blocking stop", name)
		return stopable.Stop()
	}
	return stopWithTimeout(stopable, name, s.StopGracePeriod)
}

// stopWithTimeout waits for channel to respond with an error, or until time expires - and returns an error.
// If Stopable stopped correctly, it returns nil.
func stopWithTimeout(stopable Stopable, name string, timeout time.Duration) error {
	select {
	case err, opened := <-stopChannel(stopable):
		if opened {
			protocol.Err("service: error while stopping %v: %v", name, err.Error)
			return err
		}
	case <-time.After(timeout):
		errTimeout := fmt.Errorf("service: error while stopping %v: did not stop after timeout %v", name, timeout)
		protocol.Err(errTimeout.Error())
		return errTimeout
	}
	protocol.Info("service: stopped %v", name)
	return nil
}

func stopChannel(stopable Stopable) chan error {
	errorC := make(chan error)
	go func() {
		err := stopable.Stop()
		if err != nil {
			errorC <- err
			return
		}
		close(errorC)
	}()
	return errorC
}
<commit_msg>minor refactoring; doc; logging<commit_after>package server

import (
	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/server/webserver"

	"fmt"
	"github.com/docker/distribution/health"
	"net/http"
	"reflect"
	"time"
)

const (
	healthEndpointPrefix        = "/health"
	defaultStopGracePeriod      = time.Second * 5
	defaultHealthCheckFrequency = time.Second * 60
	defaultHealthCheckThreshold = 1
)

// Startable interface for modules which provide a start mechanism
type Startable interface {
	Start() error
}

// Stopable interface for modules which provide a stop mechanism
type Stopable interface {
	Stop() error
}

// Endpoint adds a HTTP handler for the `GetPrefix()` to the webserver
type Endpoint interface {
	http.Handler
	GetPrefix() string
}

// Service is the main class for simple control of a server
type Service struct {
	webserver            *webserver.WebServer
	router               Router
	modules              []interface{}
	StopGracePeriod      time.Duration // The timeout given to each Module on Stop()
	healthCheckFrequency time.Duration
	healthCheckThreshold int
}

// NewService registers the Main Router, where other modules can subscribe for messages
func NewService(router Router, webserver *webserver.WebServer) *Service {
	service := &Service{
		webserver:            webserver,
		router:               router,
		StopGracePeriod:      defaultStopGracePeriod,
		healthCheckFrequency: defaultHealthCheckFrequency,
		healthCheckThreshold: defaultHealthCheckThreshold,
	}
	service.registerModule(service.router)
	service.registerModule(service.webserver)

	return service
}

func (s *Service) RegisterModules(modules []interface{}) {
	for _, module := range modules {
		s.registerModule(module)
	}
}

func (s *Service) registerModule(module interface{}) {
	s.modules = append(s.modules, module)
}

// Start checks the modules for the following interfaces and registers and/or starts:
//   Startable:
//   health.Checker:
//   Endpoint: Register the handler function of the Endpoint in the http service at prefix
func (s *Service) Start() error {
	el := protocol.NewErrorList("service: errors occured while starting: ")
	s.webserver.Handle(healthEndpointPrefix, http.HandlerFunc(health.StatusHandler))
	for _, module := range s.modules {
		name := reflect.TypeOf(module).String()
		if startable, ok := module.(Startable); ok {
			protocol.Info("service: starting module %v", name)
			if err := startable.Start(); err != nil {
				protocol.Err("service: error while starting module %v", name)
				el.Add(err)
			}
		}
		if checker, ok := module.(health.Checker); ok {
			protocol.Info("service: registering module %v as HealthChecker", name)
			health.RegisterPeriodicThresholdFunc(name, s.healthCheckFrequency, s.healthCheckThreshold, health.CheckFunc(checker.Check))
		}
		if endpoint, ok := module.(Endpoint); ok {
			prefix := endpoint.GetPrefix()
			protocol.Info("service: registering module %v as Endpoint to %v", name, prefix)
			s.webserver.Handle(prefix, endpoint)
		}
	}
	return el.ErrorOrNil()
}

func (s *Service) Stop() error {
	stopables := make([]Stopable, 0)
	for _, module := range s.modules {
		name := reflect.TypeOf(module).String()
		if stopable, ok := module.(Stopable); ok {
			protocol.Info("service: %v is Stopable", name)
			stopables = append(stopables, stopable)
		}
	}
	// stopOrder allows the customized stopping of the modules
	// (not necessarily in the exact reverse order of their registrations).
	// Router is first to stop, then the rest of the modules are stopped in reverse-registration-order.
	stopOrder := make([]int, len(stopables))
	for i := 1; i < len(stopables); i++ {
		stopOrder[i] = len(stopables) - i
	}

	protocol.Debug("service: stopping %d modules with a %v timeout, in this order relative to registration: %v",
		len(stopOrder), s.StopGracePeriod, stopOrder)
	errors := make(map[string]error)
	for _, order := range stopOrder {
		name := reflect.TypeOf(stopables[order]).String()
		protocol.Info("service: stopping [%d] %v", order, name)
		err := s.stopModule(stopables[order], name)
		if err != nil {
			errors[name] = err
		}
	}
	if len(errors) > 0 {
		return fmt.Errorf("service: errors while stopping modules: %q", errors)
	}
	return nil
}

func (s *Service) Modules() []interface{} {
	return s.modules
}

func (s *Service) WebServer() *webserver.WebServer {
	return s.webserver
}

func (s *Service) stopModule(stopable Stopable, name string) error {
	if _, ok := stopable.(Router); ok {
		protocol.Debug("service: %v is a Router and requires a blocking stop", name)
		return stopable.Stop()
	}
	return stopModuleWithTimeout(stopable, name, s.StopGracePeriod)
}

// stopWithTimeout waits for channel to respond with an error, or until time expires - and returns an error.
// If Stopable stopped correctly, it returns nil.
func stopModuleWithTimeout(stopable Stopable, name string, timeout time.Duration) error {
	select {
	case err, opened := <-stopChannel(stopable):
		if opened {
			protocol.Err("service: error while stopping %v: %v", name, err.Error)
			return err
		}
	case <-time.After(timeout):
		errTimeout := fmt.Errorf("service: error while stopping %v: did not stop after timeout %v", name, timeout)
		protocol.Err(errTimeout.Error())
		return errTimeout
	}
	protocol.Info("service: stopped %v", name)
	return nil
}

func stopChannel(stopable Stopable) chan error {
	errorC := make(chan error)
	go func() {
		err := stopable.Stop()
		if err != nil {
			errorC <- err
			return
		}
		close(errorC)
	}()
	return errorC
}
<|endoftext|>


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

package ghutil_test

import (
	"context"
	"testing"

	"github.com/golang/mock/gomock"

	"github.com/google/code-review-bot/ghutil"
	"github.com/google/go-github/github"
)

type MockGitHubClient struct {
	Organizations *ghutil.MockOrganizationsService
	PullRequests  *ghutil.MockPullRequestsService
	Issues        *ghutil.MockIssuesService
	Repositories  *ghutil.MockRepositoriesService
}

func NewMockGitHubClient(ghc *ghutil.GitHubClient, ctrl *gomock.Controller) *MockGitHubClient {
	mockGhc := &MockGitHubClient{
		Organizations: ghutil.NewMockOrganizationsService(ctrl),
		PullRequests:  ghutil.NewMockPullRequestsService(ctrl),
		Issues:        ghutil.NewMockIssuesService(ctrl),
		Repositories:  ghutil.NewMockRepositoriesService(ctrl),
	}

	// Patch the original GitHubClient with our mock services.
	ghc.Organizations = mockGhc.Organizations
	ghc.PullRequests = mockGhc.PullRequests
	ghc.Issues = mockGhc.Issues
	ghc.Repositories = mockGhc.Repositories

	return mockGhc
}

// Common parameters used across most, if not all, tests.
var (
	ctrl    *gomock.Controller
	ghc     *ghutil.GitHubClient
	mockGhc *MockGitHubClient

	noLabel *github.Label = nil
)

const (
	orgName   = "org"
	repoName  = "repo"
	emptyRepo = ""
)

func setUp(t *testing.T) {
	ctrl = gomock.NewController(t)
	ghc = &ghutil.GitHubClient{}
	mockGhc = NewMockGitHubClient(ghc, ctrl)
}

func tearDown(t *testing.T) {
	ctrl.Finish()
}

func TestGetAllRepos_OrgAndRepo(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	repo := github.Repository{}

	mockGhc.Repositories.EXPECT().Get(orgName, repoName).Return(&repo, nil, nil)

	repos := ghc.GetAllRepos(context.Background(), orgName, repoName)
	if len(repos) != 1 {
		t.Logf("repos is not of length 1: %v", repos)
		t.Fail()
	}
}

func TestGetAllRepos_OrgOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	expectedRepos := []*github.Repository{
		{},
		{},
	}

	mockGhc.Repositories.EXPECT().List(orgName, nil).Return(expectedRepos, nil, nil)

	actualRepos := ghc.GetAllRepos(context.Background(), orgName, "")
	if len(expectedRepos) != len(actualRepos) {
		t.Logf("Expected repos: %v, actual repos: %v", expectedRepos, actualRepos)
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_NoLabels(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(noLabel, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(noLabel, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_HasYesOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	label := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(&label, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(noLabel, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_HasNoOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	label := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(noLabel, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(&label, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_YesAndNoLabels(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	labelYes := github.Label{}
	labelNo := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(&labelYes, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(&labelNo, nil, nil)

	if !ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned true")
		t.Fail()
	}
}
<commit_msg>Remove unused constant<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ghutil_test

import (
	"context"
	"testing"

	"github.com/golang/mock/gomock"

	"github.com/google/code-review-bot/ghutil"
	"github.com/google/go-github/github"
)

type MockGitHubClient struct {
	Organizations *ghutil.MockOrganizationsService
	PullRequests  *ghutil.MockPullRequestsService
	Issues        *ghutil.MockIssuesService
	Repositories  *ghutil.MockRepositoriesService
}

func NewMockGitHubClient(ghc *ghutil.GitHubClient, ctrl *gomock.Controller) *MockGitHubClient {
	mockGhc := &MockGitHubClient{
		Organizations: ghutil.NewMockOrganizationsService(ctrl),
		PullRequests:  ghutil.NewMockPullRequestsService(ctrl),
		Issues:        ghutil.NewMockIssuesService(ctrl),
		Repositories:  ghutil.NewMockRepositoriesService(ctrl),
	}

	// Patch the original GitHubClient with our mock services.
	ghc.Organizations = mockGhc.Organizations
	ghc.PullRequests = mockGhc.PullRequests
	ghc.Issues = mockGhc.Issues
	ghc.Repositories = mockGhc.Repositories

	return mockGhc
}

// Common parameters used across most, if not all, tests.
var (
	ctrl    *gomock.Controller
	ghc     *ghutil.GitHubClient
	mockGhc *MockGitHubClient

	noLabel *github.Label = nil
)

const (
	orgName   = "org"
	repoName  = "repo"
)

func setUp(t *testing.T) {
	ctrl = gomock.NewController(t)
	ghc = &ghutil.GitHubClient{}
	mockGhc = NewMockGitHubClient(ghc, ctrl)
}

func tearDown(t *testing.T) {
	ctrl.Finish()
}

func TestGetAllRepos_OrgAndRepo(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	repo := github.Repository{}

	mockGhc.Repositories.EXPECT().Get(orgName, repoName).Return(&repo, nil, nil)

	repos := ghc.GetAllRepos(context.Background(), orgName, repoName)
	if len(repos) != 1 {
		t.Logf("repos is not of length 1: %v", repos)
		t.Fail()
	}
}

func TestGetAllRepos_OrgOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	expectedRepos := []*github.Repository{
		{},
		{},
	}

	mockGhc.Repositories.EXPECT().List(orgName, nil).Return(expectedRepos, nil, nil)

	actualRepos := ghc.GetAllRepos(context.Background(), orgName, "")
	if len(expectedRepos) != len(actualRepos) {
		t.Logf("Expected repos: %v, actual repos: %v", expectedRepos, actualRepos)
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_NoLabels(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(noLabel, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(noLabel, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_HasYesOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	label := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(&label, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(noLabel, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_HasNoOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	label := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(noLabel, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(&label, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_YesAndNoLabels(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	labelYes := github.Label{}
	labelNo := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(&labelYes, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(&labelNo, nil, nil)

	if !ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned true")
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package hoverfly_test

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"

	"strings"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Running Hoverfly", func() {

	Context("in capture mode", func() {

		var fakeServer *httptest.Server

		BeforeEach(func() {
			hoverflyCmd = startHoverfly(adminPort, proxyPort)
			SetHoverflyMode("capture")

			fakeServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.Header().Set("Content-Type", "text/plain")
				w.Header().Set("date", "date")
				w.Write([]byte("Hello world"))
			}))

		})

		AfterEach(func() {
			stopHoverfly()

			fakeServer.Close()
		})

		It("Should not capture capture if destination does not match", func() {
			SetHoverflyDestination("notlocalhost")

			resp := CallFakeServerThroughProxy(fakeServer)

			Expect(resp.StatusCode).To(Equal(200))
			Expect(resp.Header.Get("date")).To(Equal("date"))

			recordsJson, err := ioutil.ReadAll(ExportHoverflyRecords())
			Expect(err).To(BeNil())
			Expect(recordsJson).To(MatchJSON(fmt.Sprintf(
				`{
					  "data": null
					}`)))
		})

		It("Should capture capture if destination is 127.0.0.1", func() {
			SetHoverflyDestination("127.0.0.1")

			resp := CallFakeServerThroughProxy(fakeServer)

			Expect(resp.StatusCode).To(Equal(200))
			Expect(resp.Header.Get("date")).To(Equal("date"))

			recordsJson, err := ioutil.ReadAll(ExportHoverflyRecords())
			Expect(err).To(BeNil())
			Expect(recordsJson).To(MatchJSON(fmt.Sprintf(
				`{
					"data": [
						{
						"response": {
							"status": 200,
							"body": "Hello world",
							"encodedBody": false,
							"headers": {
							"Content-Length": [
								"11"
							],
							"Content-Type": [
								"text/plain"
							],
							"Date": [
								"date"
							],
							"Hoverfly": [
								"Was-Here"
							]
							}
						},
						"request": {
							"requestType": "recording",
							"path": "/",
							"method": "GET",
							"destination": "%v",
							"scheme": "http",
							"query": "",
							"body": "",
							"headers": {
							"Accept-Encoding": [
								"gzip"
							],
							"User-Agent": [
								"Go-http-client/1.1"
							]
							}
						}
						}
					]
					}`, strings.Replace(fakeServer.URL, "http://", "", 1))))
		})
	})
})
<commit_msg>Fixed typo in names of destination functional tests<commit_after>package hoverfly_test

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"

	"strings"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Running Hoverfly", func() {

	Context("in capture mode", func() {

		var fakeServer *httptest.Server

		BeforeEach(func() {
			hoverflyCmd = startHoverfly(adminPort, proxyPort)
			SetHoverflyMode("capture")

			fakeServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.Header().Set("Content-Type", "text/plain")
				w.Header().Set("date", "date")
				w.Write([]byte("Hello world"))
			}))

		})

		AfterEach(func() {
			stopHoverfly()

			fakeServer.Close()
		})

		It("Should not capture if destination does not match", func() {
			SetHoverflyDestination("notlocalhost")

			resp := CallFakeServerThroughProxy(fakeServer)

			Expect(resp.StatusCode).To(Equal(200))
			Expect(resp.Header.Get("date")).To(Equal("date"))

			recordsJson, err := ioutil.ReadAll(ExportHoverflyRecords())
			Expect(err).To(BeNil())
			Expect(recordsJson).To(MatchJSON(fmt.Sprintf(
				`{
					  "data": null
					}`)))
		})

		It("Should capture if destination is 127.0.0.1", func() {
			SetHoverflyDestination("127.0.0.1")

			resp := CallFakeServerThroughProxy(fakeServer)

			Expect(resp.StatusCode).To(Equal(200))
			Expect(resp.Header.Get("date")).To(Equal("date"))

			recordsJson, err := ioutil.ReadAll(ExportHoverflyRecords())
			Expect(err).To(BeNil())
			Expect(recordsJson).To(MatchJSON(fmt.Sprintf(
				`{
					"data": [
						{
						"response": {
							"status": 200,
							"body": "Hello world",
							"encodedBody": false,
							"headers": {
							"Content-Length": [
								"11"
							],
							"Content-Type": [
								"text/plain"
							],
							"Date": [
								"date"
							],
							"Hoverfly": [
								"Was-Here"
							]
							}
						},
						"request": {
							"requestType": "recording",
							"path": "/",
							"method": "GET",
							"destination": "%v",
							"scheme": "http",
							"query": "",
							"body": "",
							"headers": {
							"Accept-Encoding": [
								"gzip"
							],
							"User-Agent": [
								"Go-http-client/1.1"
							]
							}
						}
						}
					]
					}`, strings.Replace(fakeServer.URL, "http://", "", 1))))
		})
	})
})
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.432"
<commit_msg>fnserver: 0.3.433 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.433"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.594"
<commit_msg>fnserver: 0.3.595 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.595"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.746"
<commit_msg>fnserver: v0.3.747 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.747"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.179"
<commit_msg>functions: 0.3.180 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.180"
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package apiserver

import (
	"fmt"
	"net"

	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup/v1"
	testgroupetcd "k8s.io/kubernetes/examples/apiserver/rest"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/rest"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/apimachinery/registered"
	"k8s.io/kubernetes/pkg/genericapiserver"
	"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
	genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options"
	genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
	"k8s.io/kubernetes/pkg/registry/generic"
	"k8s.io/kubernetes/pkg/storage/storagebackend"

	// Install the testgroup API
	_ "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup/install"
)

const (
	// Ports on which to run the server.
	// Explicitly setting these to a different value than the default values, to prevent this from clashing with a local cluster.
	InsecurePort = 8081
	SecurePort   = 6444
)

func newStorageFactory() genericapiserver.StorageFactory {
	config := storagebackend.Config{
		Prefix:     genericoptions.DefaultEtcdPathPrefix,
		ServerList: []string{"http://127.0.0.1:2379"},
	}
	storageFactory := genericapiserver.NewDefaultStorageFactory(config, "application/json", api.Codecs, genericapiserver.NewDefaultResourceEncodingConfig(), genericapiserver.NewResourceConfig())

	return storageFactory
}

func NewServerRunOptions() *genericoptions.ServerRunOptions {
	serverOptions := genericoptions.NewServerRunOptions().WithEtcdOptions()
	serverOptions.InsecurePort = InsecurePort
	return serverOptions
}

func Run(serverOptions *genericoptions.ServerRunOptions, stopCh <-chan struct{}) error {
	// Set ServiceClusterIPRange
	_, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24")
	serverOptions.ServiceClusterIPRange = *serviceClusterIPRange
	serverOptions.StorageConfig.ServerList = []string{"http://127.0.0.1:2379"}
	genericvalidation.ValidateRunOptions(serverOptions)
	genericvalidation.VerifyEtcdServersList(serverOptions)
	config := genericapiserver.NewConfig().ApplyOptions(serverOptions).Complete()
	if err := config.MaybeGenerateServingCerts(); err != nil {
		// this wasn't treated as fatal for this process before
		fmt.Printf("Error creating cert: %v", err)
	}

	config.Authorizer = authorizer.NewAlwaysAllowAuthorizer()
	s, err := config.New()
	if err != nil {
		return fmt.Errorf("Error in bringing up the server: %v", err)
	}

	groupVersion := v1.SchemeGroupVersion
	groupName := groupVersion.Group
	groupMeta, err := registered.Group(groupName)
	if err != nil {
		return fmt.Errorf("%v", err)
	}
	storageFactory := newStorageFactory()
	storageConfig, err := storageFactory.NewConfig(unversioned.GroupResource{Group: groupName, Resource: "testtype"})
	if err != nil {
		return fmt.Errorf("Unable to get storage config: %v", err)
	}

	restStorageMap := map[string]rest.Storage{
		"testtypes": testgroupetcd.NewREST(storageConfig, generic.UndecoratedStorage),
	}
	apiGroupInfo := genericapiserver.APIGroupInfo{
		GroupMeta: *groupMeta,
		VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
			groupVersion.Version: restStorageMap,
		},
		Scheme:               api.Scheme,
		NegotiatedSerializer: api.Codecs,
	}
	if err := s.InstallAPIGroup(&apiGroupInfo); err != nil {
		return fmt.Errorf("Error in installing API: %v", err)
	}
	s.PrepareRun().Run(stopCh)
	return nil
}
<commit_msg>Move GroupVersion* to pkg/runtime/schema<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package apiserver

import (
	"fmt"
	"net"

	"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup/v1"
	testgroupetcd "k8s.io/kubernetes/examples/apiserver/rest"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/rest"
	"k8s.io/kubernetes/pkg/apimachinery/registered"
	"k8s.io/kubernetes/pkg/genericapiserver"
	"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
	genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options"
	genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
	"k8s.io/kubernetes/pkg/registry/generic"
	"k8s.io/kubernetes/pkg/runtime/schema"
	"k8s.io/kubernetes/pkg/storage/storagebackend"

	// Install the testgroup API
	_ "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup/install"
)

const (
	// Ports on which to run the server.
	// Explicitly setting these to a different value than the default values, to prevent this from clashing with a local cluster.
	InsecurePort = 8081
	SecurePort   = 6444
)

func newStorageFactory() genericapiserver.StorageFactory {
	config := storagebackend.Config{
		Prefix:     genericoptions.DefaultEtcdPathPrefix,
		ServerList: []string{"http://127.0.0.1:2379"},
	}
	storageFactory := genericapiserver.NewDefaultStorageFactory(config, "application/json", api.Codecs, genericapiserver.NewDefaultResourceEncodingConfig(), genericapiserver.NewResourceConfig())

	return storageFactory
}

func NewServerRunOptions() *genericoptions.ServerRunOptions {
	serverOptions := genericoptions.NewServerRunOptions().WithEtcdOptions()
	serverOptions.InsecurePort = InsecurePort
	return serverOptions
}

func Run(serverOptions *genericoptions.ServerRunOptions, stopCh <-chan struct{}) error {
	// Set ServiceClusterIPRange
	_, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24")
	serverOptions.ServiceClusterIPRange = *serviceClusterIPRange
	serverOptions.StorageConfig.ServerList = []string{"http://127.0.0.1:2379"}
	genericvalidation.ValidateRunOptions(serverOptions)
	genericvalidation.VerifyEtcdServersList(serverOptions)
	config := genericapiserver.NewConfig().ApplyOptions(serverOptions).Complete()
	if err := config.MaybeGenerateServingCerts(); err != nil {
		// this wasn't treated as fatal for this process before
		fmt.Printf("Error creating cert: %v", err)
	}

	config.Authorizer = authorizer.NewAlwaysAllowAuthorizer()
	s, err := config.New()
	if err != nil {
		return fmt.Errorf("Error in bringing up the server: %v", err)
	}

	groupVersion := v1.SchemeGroupVersion
	groupName := groupVersion.Group
	groupMeta, err := registered.Group(groupName)
	if err != nil {
		return fmt.Errorf("%v", err)
	}
	storageFactory := newStorageFactory()
	storageConfig, err := storageFactory.NewConfig(schema.GroupResource{Group: groupName, Resource: "testtype"})
	if err != nil {
		return fmt.Errorf("Unable to get storage config: %v", err)
	}

	restStorageMap := map[string]rest.Storage{
		"testtypes": testgroupetcd.NewREST(storageConfig, generic.UndecoratedStorage),
	}
	apiGroupInfo := genericapiserver.APIGroupInfo{
		GroupMeta: *groupMeta,
		VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
			groupVersion.Version: restStorageMap,
		},
		Scheme:               api.Scheme,
		NegotiatedSerializer: api.Codecs,
	}
	if err := s.InstallAPIGroup(&apiGroupInfo); err != nil {
		return fmt.Errorf("Error in installing API: %v", err)
	}
	s.PrepareRun().Run(stopCh)
	return nil
}
<|endoftext|>


<commit_before>package glib

// #include <gio/gio.h>
// #include <glib.h>
// #include <glib-object.h>
// #include "glib.go.h"
import "C"

type MainContext C.GMainContext

// native returns a pointer to the underlying GMainContext.
func (v *MainContext) native() *C.GMainContext {
	if v == nil {
		return nil
	}
	return (*C.GMainContext)(v)
}

// MainContextDefault is a wrapper around g_main_context_default().
func MainContextDefault() *MainContext {
	c := C.g_main_context_default()
	if c == nil {
		return nil
	}
	return (*MainContext)(c)
}

// MainDepth is a wrapper around g_main_depth().
func MainDepth() int {
	return int(C.g_main_depth())
}
<commit_msg>Add glib function for GlibMainContext<commit_after>package glib

// #include <gio/gio.h>
// #include <glib.h>
// #include <glib-object.h>
// #include "glib.go.h"
import "C"

type MainContext C.GMainContext

// native returns a pointer to the underlying GMainContext.
func (v *MainContext) native() *C.GMainContext {
	if v == nil {
		return nil
	}
	return (*C.GMainContext)(v)
}

// MainContextDefault is a wrapper around g_main_context_default().
func MainContextDefault() *MainContext {
	c := C.g_main_context_default()
	if c == nil {
		return nil
	}
	return (*MainContext)(c)
}

// MainDepth is a wrapper around g_main_depth().
func MainDepth() int {
	return int(C.g_main_depth())
}

// FindSourceById is a wrapper around g_main_context_find_source_by_id()
func (v *MainContext) FindSourceById(hdlSrc SourceHandle) *Source {
	c := C.g_main_context_find_source_by_id(v.native(), C.guint(hdlSrc))
	if c == nil {
		return nil
	}
	return (*Source)(c)
}

// SourceRemove is a wrapper around g_main_context_pending()
func (v *MainContext) Pending(src SourceHandle) bool {
	return gobool(C.g_main_context_pending(v.native()))
}
<|endoftext|>


<commit_before>// +build !linux

package selinux

import (
	"errors"
)

const (
	// Enforcing constant indicate SELinux is in enforcing mode
	Enforcing = 1
	// Permissive constant to indicate SELinux is in permissive mode
	Permissive = 0
	// Disabled constant to indicate SELinux is disabled
	Disabled = -1
)

var (
	// ErrMCSAlreadyExists is returned when trying to allocate a duplicate MCS.
	ErrMCSAlreadyExists = errors.New("MCS label already exists")
	// ErrEmptyPath is returned when an empty path has been specified.
	ErrEmptyPath = errors.New("empty path")
)

// Context is a representation of the SELinux label broken into 4 parts
type Context map[string]string

// SetDisabled disables selinux support for the package
func SetDisabled() {
	return
}

// SetFileLabel sets the SELinux label for this path or returns an error.
func SetFileLabel(fpath string, label string) error {
	return nil
}

// FileLabel returns the SELinux label for this path or returns an error.
func FileLabel(fpath string) (string, error) {
	return "", nil
}

/*
SetFSCreateLabel tells kernel the label to create all file system objects
created by this task. Setting label="" to return to default.
*/
func SetFSCreateLabel(label string) error {
	return nil
}

/*
FSCreateLabel returns the default label the kernel which the kernel is using
for file system objects created by this task. "" indicates default.
*/
func FSCreateLabel() (string, error) {
	return "", nil
}

// CurrentLabel returns the SELinux label of the current process thread, or an error.
func CurrentLabel() (string, error) {
	return "", nil
}

// PidLabel returns the SELinux label of the given pid, or an error.
func PidLabel(pid int) (string, error) {
	return "", nil
}

/*
ExecLabel returns the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error.
*/
func ExecLabel() (string, error) {
	return "", nil
}

/*
CanonicalizeContext takes a context string and writes it to the kernel
the function then returns the context that the kernel will use.  This function
can be used to see if two contexts are equivalent
*/
func CanonicalizeContext(val string) (string, error) {
	return "", nil
}

/*
SetExecLabel sets the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error.
*/
func SetExecLabel(label string) error {
	return nil
}

// Get returns the Context as a string
func (c Context) Get() string {
	return ""
}

// NewContext creates a new Context struct from the specified label
func NewContext(label string) Context {
	c := make(Context)
	return c
}

// ReserveLabel reserves the MLS/MCS level component of the specified label
func ReserveLabel(label string) {
	return
}

// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
func EnforceMode() int {
	return Disabled
}

/*
SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
Disabled is not valid, since this needs to be set at boot time.
*/
func SetEnforceMode(mode int) error {
	return nil
}

/*
DefaultEnforceMode returns the systems default SELinux mode Enforcing,
Permissive or Disabled. Note this is is just the default at boot time.
EnforceMode tells you the systems current mode.
*/
func DefaultEnforceMode() int {
	return Disabled
}

/*
ReleaseLabel will unreserve the MLS/MCS Level field of the specified label.
Allowing it to be used by another process.
*/
func ReleaseLabel(label string) {
	return
}

// ROFileLabel returns the specified SELinux readonly file label
func ROFileLabel() string {
	return ""
}

/*
ContainerLabels returns an allocated processLabel and fileLabel to be used for
container labeling by the calling process.
*/
func ContainerLabels() (processLabel string, fileLabel string) {
	return "", ""
}

// SecurityCheckContext validates that the SELinux label is understood by the kernel
func SecurityCheckContext(val string) error {
	return nil
}

/*
CopyLevel returns a label with the MLS/MCS level from src label replaced on
the dest label.
*/
func CopyLevel(src, dest string) (string, error) {
	return "", nil
}

// Chcon changes the `fpath` file object to the SELinux label `label`.
// If `fpath` is a directory and `recurse`` is true, Chcon will walk the
// directory tree setting the label.
func Chcon(fpath string, label string, recurse bool) error {
	return nil
}

// DupSecOpt takes an SELinux process label and returns security options that
// can be used to set the SELinux Type and Level for future container processes.
func DupSecOpt(src string) []string {
	return nil
}

// DisableSecOpt returns a security opt that can be used to disable SELinux
// labeling support for future container processes.
func DisableSecOpt() []string {
	return []string{"disable"}
}
<commit_msg>Another missing interface for non linux<commit_after>// +build !linux

package selinux

import (
	"errors"
)

const (
	// Enforcing constant indicate SELinux is in enforcing mode
	Enforcing = 1
	// Permissive constant to indicate SELinux is in permissive mode
	Permissive = 0
	// Disabled constant to indicate SELinux is disabled
	Disabled = -1
)

var (
	// ErrMCSAlreadyExists is returned when trying to allocate a duplicate MCS.
	ErrMCSAlreadyExists = errors.New("MCS label already exists")
	// ErrEmptyPath is returned when an empty path has been specified.
	ErrEmptyPath = errors.New("empty path")
)

// Context is a representation of the SELinux label broken into 4 parts
type Context map[string]string

// SetDisabled disables selinux support for the package
func SetDisabled() {
	return
}

// GetEnabled returns whether selinux is currently enabled.
func GetEnabled() bool {
	return false
}

// SetFileLabel sets the SELinux label for this path or returns an error.
func SetFileLabel(fpath string, label string) error {
	return nil
}

// FileLabel returns the SELinux label for this path or returns an error.
func FileLabel(fpath string) (string, error) {
	return "", nil
}

/*
SetFSCreateLabel tells kernel the label to create all file system objects
created by this task. Setting label="" to return to default.
*/
func SetFSCreateLabel(label string) error {
	return nil
}

/*
FSCreateLabel returns the default label the kernel which the kernel is using
for file system objects created by this task. "" indicates default.
*/
func FSCreateLabel() (string, error) {
	return "", nil
}

// CurrentLabel returns the SELinux label of the current process thread, or an error.
func CurrentLabel() (string, error) {
	return "", nil
}

// PidLabel returns the SELinux label of the given pid, or an error.
func PidLabel(pid int) (string, error) {
	return "", nil
}

/*
ExecLabel returns the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error.
*/
func ExecLabel() (string, error) {
	return "", nil
}

/*
CanonicalizeContext takes a context string and writes it to the kernel
the function then returns the context that the kernel will use.  This function
can be used to see if two contexts are equivalent
*/
func CanonicalizeContext(val string) (string, error) {
	return "", nil
}

/*
SetExecLabel sets the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error.
*/
func SetExecLabel(label string) error {
	return nil
}

// Get returns the Context as a string
func (c Context) Get() string {
	return ""
}

// NewContext creates a new Context struct from the specified label
func NewContext(label string) Context {
	c := make(Context)
	return c
}

// ReserveLabel reserves the MLS/MCS level component of the specified label
func ReserveLabel(label string) {
	return
}

// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
func EnforceMode() int {
	return Disabled
}

/*
SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
Disabled is not valid, since this needs to be set at boot time.
*/
func SetEnforceMode(mode int) error {
	return nil
}

/*
DefaultEnforceMode returns the systems default SELinux mode Enforcing,
Permissive or Disabled. Note this is is just the default at boot time.
EnforceMode tells you the systems current mode.
*/
func DefaultEnforceMode() int {
	return Disabled
}

/*
ReleaseLabel will unreserve the MLS/MCS Level field of the specified label.
Allowing it to be used by another process.
*/
func ReleaseLabel(label string) {
	return
}

// ROFileLabel returns the specified SELinux readonly file label
func ROFileLabel() string {
	return ""
}

/*
ContainerLabels returns an allocated processLabel and fileLabel to be used for
container labeling by the calling process.
*/
func ContainerLabels() (processLabel string, fileLabel string) {
	return "", ""
}

// SecurityCheckContext validates that the SELinux label is understood by the kernel
func SecurityCheckContext(val string) error {
	return nil
}

/*
CopyLevel returns a label with the MLS/MCS level from src label replaced on
the dest label.
*/
func CopyLevel(src, dest string) (string, error) {
	return "", nil
}

// Chcon changes the `fpath` file object to the SELinux label `label`.
// If `fpath` is a directory and `recurse`` is true, Chcon will walk the
// directory tree setting the label.
func Chcon(fpath string, label string, recurse bool) error {
	return nil
}

// DupSecOpt takes an SELinux process label and returns security options that
// can be used to set the SELinux Type and Level for future container processes.
func DupSecOpt(src string) []string {
	return nil
}

// DisableSecOpt returns a security opt that can be used to disable SELinux
// labeling support for future container processes.
func DisableSecOpt() []string {
	return []string{"disable"}
}
<|endoftext|>


<commit_before>package x86_16

import (
	"errors"
	"fmt"
	"strings"
	"syscall"

	co "github.com/lunixbochs/usercorn/go/kernel/common"
	"github.com/lunixbochs/usercorn/go/models"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
)

const (
	STACK_BASE = 0x8000
	STACK_SIZE = 0x1000
	NUM_FDS    = 256

	// Registers
	AH    = uc.X86_REG_AH
	AL    = uc.X86_REG_AL
	AX    = uc.X86_REG_AX
	BH    = uc.X86_REG_BH
	BL    = uc.X86_REG_BL
	BP    = uc.X86_REG_BP
	BX    = uc.X86_REG_BX
	CH    = uc.X86_REG_CH
	CL    = uc.X86_REG_CL
	CS    = uc.X86_REG_CS
	CX    = uc.X86_REG_CX
	DH    = uc.X86_REG_DH
	DI    = uc.X86_REG_DI
	DL    = uc.X86_REG_DL
	DS    = uc.X86_REG_DS
	DX    = uc.X86_REG_DX
	ES    = uc.X86_REG_ES
	FS    = uc.X86_REG_FS
	GS    = uc.X86_REG_GS
	IP    = uc.X86_REG_IP
	SI    = uc.X86_REG_SI
	SP    = uc.X86_REG_SP
	SS    = uc.X86_REG_SS
	FLAGS = uc.X86_REG_EFLAGS
)

func (k *DosKernel) reg16(enum int) uint16 {
	r, _ := k.U.RegRead(enum)
	return uint16(r)
}
func (k *DosKernel) reg8(enum int) uint8 {
	r, _ := k.U.RegRead(enum)
	return uint8(r)
}
func (k *DosKernel) wreg16(enum int, val uint16) {
	k.U.RegWrite(enum, uint64(val))
}
func (k *DosKernel) wreg8(enum int, val uint8) {
	k.U.RegWrite(enum, uint64(val))
}
func (k *DosKernel) setFlagC(set bool) {
	// TODO: Write setFlagX with enum for each flag
	// Unicorn doesn't have the non-extended FLAGS register, so we're
	// dealing with 32 bits here
	flags, _ := k.U.RegRead(FLAGS)
	if set {
		flags |= 1 // CF = 1
	} else {
		flags &= 0xfffffffe // CF = 0
	}
	k.U.RegWrite(FLAGS, flags)
}

var dosSysNum = map[int]string{
	0x00: "terminate",
	0x01: "char_in",
	0x02: "char_out",
	0x09: "display",
	0x30: "get_dos_version",
	0x3C: "create_or_truncate",
	0x3D: "open",
	0x3E: "close",
	0x3F: "read",
	0x40: "write",
	0x4C: "terminate_with_code",
}

// TODO: Create a reverse map of this for conciseness
var abiMap = map[int][]int{
	0x00: {},
	0x01: {DX},
	0x02: {DX}, // Actually DL
	0x09: {DX, DS},
	0x30: {},
	0x3C: {DX, DS, CX},
	0x3D: {DX, DS, AL},
	0x3E: {BX},
	0x3F: {BX, DX, CX, DS},
	0x40: {BX, DX, CX, DS},
	0x4C: {AL},
}

type PSP struct {
	CPMExit                     [2]byte
	FirstFreeSegment            uint16
	Reserved1                   uint8
	CPMCall5Compat              [5]byte
	OldTSRAddress               uint32
	OldBreakAddress             uint32
	CriticalErrorHandlerAddress uint32
	CallerPSPSegment            uint16
	JobFileTable                [20]byte
	EnvironmentSegment          uint16
	INT21SSSP                   uint32
	JobFileTableSize            uint16
	JobFileTablePointer         uint32
	PreviousPSP                 uint32
	Reserved2                   uint32
	DOSVersion                  uint16
	Reserved3                   [14]byte
	DOSFarCall                  [3]byte
	Reserved4                   uint16
	ExtendedFCB1                [7]byte
	FCB1                        [16]byte
	FCB2                        [20]byte
	CommandLineLength           uint8
	CommandLine                 [127]byte
}

type DosKernel struct {
	*co.KernelBase
	fds [NUM_FDS]int
}

func initPsp(argc int, argv []string) *PSP {
	psp := &PSP{
		CPMExit:    [2]byte{0xcd, 0x20},       // int 0x20
		DOSFarCall: [3]byte{0xcd, 0x21, 0xcd}, // int 0x21 + retf
	}

	psp.FCB1[0] = 0x01
	psp.FCB1[1] = 0x20

	// Combine all args into one string
	commandline := strings.Join(argv, " ")
	copy(psp.CommandLine[:126], commandline)
	if len(commandline) > 126 {
		psp.CommandLineLength = 126
	} else {
		psp.CommandLineLength = uint8(len(commandline))
	}

	return psp
}

func (k *DosKernel) readUntilChar(addr uint64, c byte) []byte {
	var mem []byte
	var i uint64
	var char byte = 0

	// TODO: Read ahead? This'll be slow
	for i = 1; char != c || i == 1; i++ {
		mem, _ = k.U.MemRead(addr, i)
		char = mem[i-1]
	}
	return mem[:i-2]
}

func (k *DosKernel) getFd(fd int) (uint16, error) {
	for i := uint16(0); i < NUM_FDS; i++ {
		if k.fds[i] == -1 {
			k.fds[i] = fd
			return i, nil
		}
	}
	return 0xFFFF, errors.New("DOS FD table exhausted")
}

func (k *DosKernel) freeFd(fd int) (int, error) {
	realfd := k.fds[fd]
	if realfd == -1 {
		return 0xFFFF, errors.New("FD not found in FD table")
	}
	k.fds[fd] = -1
	return realfd, nil
}

func (k *DosKernel) Terminate() {
	k.U.Exit(models.ExitStatus(0))
}

func (k *DosKernel) CharIn(buf co.Buf) byte {
	var char byte
	fmt.Scanf("%c", &char)
	k.U.MemWrite(buf.Addr, []byte{char})
	return char
}

func (k *DosKernel) CharOut(char uint16) byte {
	fmt.Printf("%c", byte(char&0xFF))
	return byte(char & 0xFF)
}

func (k *DosKernel) Display(buf co.Buf) int {
	mem := k.readUntilChar(buf.Addr, '$')

	syscall.Write(1, mem)
	k.wreg8(AL, 0x24)
	return 0x24
}

func (k *DosKernel) GetDosVersion() int {
	k.wreg16(AX, 0x7)
	return 0x7
}

func (k *DosKernel) openFile(filename string, mode int) uint16 {
	realfd, err := syscall.Open(filename, mode, 0)
	if err != nil {
		k.wreg16(AX, 0xFFFF)
		k.setFlagC(true)
		return 0xFFFF
	}

	// Find an internal fd number
	dosfd, err := k.getFd(realfd)
	if err != nil {
		k.wreg16(AX, dosfd)
		k.setFlagC(true)
		return 0xFFFF
	}
	k.setFlagC(false)
	k.wreg16(AX, dosfd)
	return dosfd
}

func (k *DosKernel) CreateOrTruncate(buf co.Buf, _ int, attr int) uint16 {
	filename := string(k.readUntilChar(buf.Addr, '$'))
	return k.openFile(filename, syscall.O_CREAT|syscall.O_TRUNC|syscall.O_RDWR)
}

func (k *DosKernel) Open(filename string, mode int) uint16 {
	return k.openFile(filename, mode)
}

func (k *DosKernel) Close(fd int) {
	// Find and free the internal fd
	realfd, _ := k.freeFd(fd)
	err := syscall.Close(realfd)
	if err != nil {
		k.setFlagC(true)
		// TODO: Set AX to error code
		k.wreg16(AX, 0xFFFF)
	}
	k.setFlagC(false)
	k.wreg16(AX, 0)
}

func (k *DosKernel) Read(fd int, buf co.Obuf, len co.Len) int {
	mem := make([]byte, len)
	n, err := syscall.Read(fd, mem)
	if err != nil {
		k.setFlagC(true)
		// TODO: Set AX to error code
		k.wreg16(AX, 0xFFFF)
	}
	k.U.MemWrite(buf.Addr, mem)
	k.setFlagC(false)
	k.wreg16(AX, uint16(n))
	return n
}

func (k *DosKernel) Write(fd uint, buf co.Buf, n co.Len) int {
	mem, _ := k.U.MemRead(buf.Addr, uint64(n))
	written, err := syscall.Write(k.fds[fd], mem)
	if err != nil {
		k.setFlagC(true)
		// TODO: Set AX to error code
		k.wreg16(AX, 0xFFFF)
	}
	k.setFlagC(false)
	k.wreg16(AX, uint16(written))
	return written
}

func (k *DosKernel) TerminateWithCode(code int) {
	k.U.Exit(models.ExitStatus(code))
}

func NewKernel() *DosKernel {
	k := &DosKernel{
		KernelBase: &co.KernelBase{},
	}

	// Init FDs
	for i := 0; i < NUM_FDS; i++ {
		k.fds[i] = -1
	}
	k.fds[0] = 0
	k.fds[1] = 1
	k.fds[2] = 2
	return k
}

func DosInit(u models.Usercorn, args, env []string) error {
	// Setup PSP
	// TODO: Setup args
	psp := initPsp(0, nil)
	u.StrucAt(0).Pack(psp)

	// Setup stack
	u.RegWrite(u.Arch().SP, STACK_BASE+STACK_SIZE)
	u.SetStackBase(STACK_BASE)
	u.SetStackSize(STACK_SIZE)
	u.SetEntry(0x100)
	return nil
}

func DosSyscall(u models.Usercorn) {
	num, _ := u.RegRead(AH)
	name, _ := dosSysNum[int(num)]
	// TODO: How are registers numbered from here?
	u.Syscall(int(num), name, dosArgs(u, int(num)))
	// TODO: Set error
}

func dosArgs(u models.Usercorn, num int) func(n int) ([]uint64, error) {
	return co.RegArgs(u, abiMap[num])
}

func DosInterrupt(u models.Usercorn, cause uint32) {
	intno := cause & 0xFF
	if intno == 0x21 {
		DosSyscall(u)
	} else if intno == 0x20 {
		u.Syscall(0, "terminate", func(int) ([]uint64, error) { return []uint64{}, nil })
	} else {
		panic(fmt.Sprintf("unhandled X86 interrupt %#X", intno))
	}
}
func DosKernels(u models.Usercorn) []interface{} {
	return []interface{}{NewKernel()}
}

func init() {
	Arch.RegisterOS(&models.OS{
		Name:      "DOS",
		Init:      DosInit,
		Interrupt: DosInterrupt,
		Kernels:   DosKernels,
	})
}
<commit_msg>DOS: Add unlink<commit_after>package x86_16

import (
	"errors"
	"fmt"
	"strings"
	"syscall"

	co "github.com/lunixbochs/usercorn/go/kernel/common"
	"github.com/lunixbochs/usercorn/go/models"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
)

const (
	STACK_BASE = 0x8000
	STACK_SIZE = 0x1000
	NUM_FDS    = 256

	// Registers
	AH    = uc.X86_REG_AH
	AL    = uc.X86_REG_AL
	AX    = uc.X86_REG_AX
	BH    = uc.X86_REG_BH
	BL    = uc.X86_REG_BL
	BP    = uc.X86_REG_BP
	BX    = uc.X86_REG_BX
	CH    = uc.X86_REG_CH
	CL    = uc.X86_REG_CL
	CS    = uc.X86_REG_CS
	CX    = uc.X86_REG_CX
	DH    = uc.X86_REG_DH
	DI    = uc.X86_REG_DI
	DL    = uc.X86_REG_DL
	DS    = uc.X86_REG_DS
	DX    = uc.X86_REG_DX
	ES    = uc.X86_REG_ES
	FS    = uc.X86_REG_FS
	GS    = uc.X86_REG_GS
	IP    = uc.X86_REG_IP
	SI    = uc.X86_REG_SI
	SP    = uc.X86_REG_SP
	SS    = uc.X86_REG_SS
	FLAGS = uc.X86_REG_EFLAGS
)

func (k *DosKernel) reg16(enum int) uint16 {
	r, _ := k.U.RegRead(enum)
	return uint16(r)
}
func (k *DosKernel) reg8(enum int) uint8 {
	r, _ := k.U.RegRead(enum)
	return uint8(r)
}
func (k *DosKernel) wreg16(enum int, val uint16) {
	k.U.RegWrite(enum, uint64(val))
}
func (k *DosKernel) wreg8(enum int, val uint8) {
	k.U.RegWrite(enum, uint64(val))
}
func (k *DosKernel) setFlagC(set bool) {
	// TODO: Write setFlagX with enum for each flag
	// Unicorn doesn't have the non-extended FLAGS register, so we're
	// dealing with 32 bits here
	flags, _ := k.U.RegRead(FLAGS)
	if set {
		flags |= 1 // CF = 1
	} else {
		flags &= 0xfffffffe // CF = 0
	}
	k.U.RegWrite(FLAGS, flags)
}

var dosSysNum = map[int]string{
	0x00: "terminate",
	0x01: "char_in",
	0x02: "char_out",
	0x09: "display",
	0x30: "get_dos_version",
	0x3C: "create_or_truncate",
	0x3D: "open",
	0x3E: "close",
	0x3F: "read",
	0x40: "write",
	0x41: "unlink",
	0x4C: "terminate_with_code",
}

// TODO: Create a reverse map of this for conciseness
var abiMap = map[int][]int{
	0x00: {},
	0x01: {DX},
	0x02: {DX},
	0x09: {DX, DS},
	0x30: {},
	0x3C: {DX, DS, CX},
	0x3D: {DX, DS, AL},
	0x3E: {BX},
	0x3F: {BX, DX, CX, DS},
	0x40: {BX, DX, CX, DS},
	0x41: {DX, DS, CX},
	0x4C: {AL},
}

type PSP struct {
	CPMExit                     [2]byte
	FirstFreeSegment            uint16
	Reserved1                   uint8
	CPMCall5Compat              [5]byte
	OldTSRAddress               uint32
	OldBreakAddress             uint32
	CriticalErrorHandlerAddress uint32
	CallerPSPSegment            uint16
	JobFileTable                [20]byte
	EnvironmentSegment          uint16
	INT21SSSP                   uint32
	JobFileTableSize            uint16
	JobFileTablePointer         uint32
	PreviousPSP                 uint32
	Reserved2                   uint32
	DOSVersion                  uint16
	Reserved3                   [14]byte
	DOSFarCall                  [3]byte
	Reserved4                   uint16
	ExtendedFCB1                [7]byte
	FCB1                        [16]byte
	FCB2                        [20]byte
	CommandLineLength           uint8
	CommandLine                 [127]byte
}

type DosKernel struct {
	*co.KernelBase
	fds [NUM_FDS]int
}

func initPsp(argc int, argv []string) *PSP {
	psp := &PSP{
		CPMExit:    [2]byte{0xcd, 0x20},       // int 0x20
		DOSFarCall: [3]byte{0xcd, 0x21, 0xcd}, // int 0x21 + retf
	}

	psp.FCB1[0] = 0x01
	psp.FCB1[1] = 0x20

	// Combine all args into one string
	commandline := strings.Join(argv, " ")
	copy(psp.CommandLine[:126], commandline)
	if len(commandline) > 126 {
		psp.CommandLineLength = 126
	} else {
		psp.CommandLineLength = uint8(len(commandline))
	}

	return psp
}

func (k *DosKernel) readUntilChar(addr uint64, c byte) []byte {
	var mem []byte
	var i uint64
	var char byte = 0

	// TODO: Read ahead? This'll be slow
	for i = 1; char != c || i == 1; i++ {
		mem, _ = k.U.MemRead(addr, i)
		char = mem[i-1]
	}
	return mem[:i-2]
}

func (k *DosKernel) getFd(fd int) (uint16, error) {
	for i := uint16(0); i < NUM_FDS; i++ {
		if k.fds[i] == -1 {
			k.fds[i] = fd
			return i, nil
		}
	}
	return 0xFFFF, errors.New("DOS FD table exhausted")
}

func (k *DosKernel) freeFd(fd int) (int, error) {
	realfd := k.fds[fd]
	if realfd == -1 {
		return 0xFFFF, errors.New("FD not found in FD table")
	}
	k.fds[fd] = -1
	return realfd, nil
}

func (k *DosKernel) Terminate() {
	k.U.Exit(models.ExitStatus(0))
}

func (k *DosKernel) CharIn(buf co.Buf) byte {
	var char byte
	fmt.Scanf("%c", &char)
	k.U.MemWrite(buf.Addr, []byte{char})
	return char
}

func (k *DosKernel) CharOut(char uint16) byte {
	fmt.Printf("%c", byte(char&0xFF))
	return byte(char & 0xFF)
}

func (k *DosKernel) Display(buf co.Buf) int {
	mem := k.readUntilChar(buf.Addr, '$')

	syscall.Write(1, mem)
	k.wreg8(AL, 0x24)
	return 0x24
}

func (k *DosKernel) GetDosVersion() int {
	k.wreg16(AX, 0x7)
	return 0x7
}

func (k *DosKernel) openFile(filename string, mode int) uint16 {
	realfd, err := syscall.Open(filename, mode, 0)
	if err != nil {
		k.wreg16(AX, 0xFFFF)
		k.setFlagC(true)
		return 0xFFFF
	}

	// Find an internal fd number
	dosfd, err := k.getFd(realfd)
	if err != nil {
		k.wreg16(AX, dosfd)
		k.setFlagC(true)
		return 0xFFFF
	}
	k.setFlagC(false)
	k.wreg16(AX, dosfd)
	return dosfd
}

func (k *DosKernel) CreateOrTruncate(buf co.Buf, _ int, attr int) uint16 {
	filename := string(k.readUntilChar(buf.Addr, '$'))
	return k.openFile(filename, syscall.O_CREAT|syscall.O_TRUNC|syscall.O_RDWR)
}

func (k *DosKernel) Open(filename string, mode int) uint16 {
	return k.openFile(filename, mode)
}

func (k *DosKernel) Close(fd int) {
	// Find and free the internal fd
	realfd, _ := k.freeFd(fd)
	err := syscall.Close(realfd)
	if err != nil {
		k.setFlagC(true)
		// TODO: Set AX to error code
		k.wreg16(AX, 0xFFFF)
	}
	k.setFlagC(false)
	k.wreg16(AX, 0)
}

func (k *DosKernel) Read(fd int, buf co.Obuf, len co.Len) int {
	mem := make([]byte, len)
	n, err := syscall.Read(fd, mem)
	if err != nil {
		k.setFlagC(true)
		// TODO: Set AX to error code
		k.wreg16(AX, 0xFFFF)
	}
	k.U.MemWrite(buf.Addr, mem)
	k.setFlagC(false)
	k.wreg16(AX, uint16(n))
	return n
}

func (k *DosKernel) Write(fd uint, buf co.Buf, n co.Len) int {
	mem, _ := k.U.MemRead(buf.Addr, uint64(n))
	written, err := syscall.Write(k.fds[fd], mem)
	if err != nil {
		k.setFlagC(true)
		// TODO: Set AX to error code
		k.wreg16(AX, 0xFFFF)
	}
	k.setFlagC(false)
	k.wreg16(AX, uint16(written))
	return written
}

func (k *DosKernel) Unlink(filename string, _ int, attr int) int {
	err := syscall.Unlink(filename)
	if err != nil {
		k.setFlagC(true)
		k.wreg16(AX, 0xFFFF)
		return 0xFFFF
	}
	k.setFlagC(false)
	k.wreg16(AX, 0)
	return 0
}

func (k *DosKernel) TerminateWithCode(code int) {
	k.U.Exit(models.ExitStatus(code))
}

func NewKernel() *DosKernel {
	k := &DosKernel{
		KernelBase: &co.KernelBase{},
	}

	// Init FDs
	for i := 0; i < NUM_FDS; i++ {
		k.fds[i] = -1
	}
	k.fds[0] = 0
	k.fds[1] = 1
	k.fds[2] = 2
	return k
}

func DosInit(u models.Usercorn, args, env []string) error {
	// Setup PSP
	// TODO: Setup args
	psp := initPsp(0, nil)
	u.StrucAt(0).Pack(psp)

	// Setup stack
	u.RegWrite(u.Arch().SP, STACK_BASE+STACK_SIZE)
	u.SetStackBase(STACK_BASE)
	u.SetStackSize(STACK_SIZE)
	u.SetEntry(0x100)
	return nil
}

func DosSyscall(u models.Usercorn) {
	num, _ := u.RegRead(AH)
	name, _ := dosSysNum[int(num)]
	// TODO: How are registers numbered from here?
	u.Syscall(int(num), name, dosArgs(u, int(num)))
	// TODO: Set error
}

func dosArgs(u models.Usercorn, num int) func(n int) ([]uint64, error) {
	return co.RegArgs(u, abiMap[num])
}

func DosInterrupt(u models.Usercorn, cause uint32) {
	intno := cause & 0xFF
	if intno == 0x21 {
		DosSyscall(u)
	} else if intno == 0x20 {
		u.Syscall(0, "terminate", func(int) ([]uint64, error) { return []uint64{}, nil })
	} else {
		panic(fmt.Sprintf("unhandled X86 interrupt %#X", intno))
	}
}
func DosKernels(u models.Usercorn) []interface{} {
	return []interface{}{NewKernel()}
}

func init() {
	Arch.RegisterOS(&models.OS{
		Name:      "DOS",
		Init:      DosInit,
		Interrupt: DosInterrupt,
		Kernels:   DosKernels,
	})
}
<|endoftext|>


<commit_before>// original code by Julian Friedman [1] and Liz Rice [2]
// [1] https://www.infoq.com/articles/build-a-container-golang
// [2] https://youtu.be/HPuvDm8IC-4?list=PLDWZ5uzn69eyh791ZTkEA9OaTxVpGY8_g

package main

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

func main() {

	if len(os.Args) < 3 {
		fmt.Println("usage: doccher run command")
		os.Exit(1)
	}
	switch os.Args[1] {
	case "run":
		parent()
	case "child":
		child()
	default:
		panic("wat?")
	}
}

func parent() {
	cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
	}
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	must(cmd.Run())

}

func child() {

	fmt.Printf("running %v as pid %d\n", os.Args[2:], os.Getpid())
	cmd := exec.Command(os.Args[2], os.Args[3:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	must(syscall.Chroot("/home/doccher"))
	must(syscall.Chdir("/"))
	must(syscall.Mount("proc", "proc", "proc", 0, ""))
	must(cmd.Run())
}

func must(err error) {
	if err != nil {
		panic(err)
	}
}
<commit_msg>added flag to build only on linux<commit_after>// +build linux

// original code by Julian Friedman [1] and Liz Rice [2]
// [1] https://www.infoq.com/articles/build-a-container-golang
// [2] https://youtu.be/HPuvDm8IC-4?list=PLDWZ5uzn69eyh791ZTkEA9OaTxVpGY8_g

package main

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

func main() {

	if len(os.Args) < 3 {
		fmt.Println("usage: doccher run command")
		os.Exit(1)
	}
	switch os.Args[1] {
	case "run":
		parent()
	case "child":
		child()
	default:
		panic("wat?")
	}
}

func parent() {
	cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
	}
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	must(cmd.Run())

}

func child() {

	fmt.Printf("running %v as pid %d\n", os.Args[2:], os.Getpid())
	cmd := exec.Command(os.Args[2], os.Args[3:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	must(syscall.Chroot("/home/doccher"))
	must(syscall.Chdir("/"))
	must(syscall.Mount("proc", "proc", "proc", 0, ""))
	must(cmd.Run())
}

func must(err error) {
	if err != nil {
		panic(err)
	}
}
<|endoftext|>