<commit_before>package main

import (
    "log"
    "flag"
    "code.google.com/p/gorest"
    "net/http"
    "nowac/kegg"
    "strings"
    "math"
    "runtime/pprof"
    "os"
    "github.com/fjukstad/rpcman" // rpc to the statistics man
    "strconv"
    "encoding/json"
    "io/ioutil"

)

type RestService struct  {

    // REST service details
    gorest.RestService `root:"/"
                        consumes:"application/json"
                        produces: "application/json" `

    geneExpression gorest.EndPoint `method:"GET"
                                    path:"/gene/{Id:string}"
                                    output:"[]float64"`

    avgDiff gorest.EndPoint `method:"GET"
                            path:"/gene/{Id:string}/avg"
                            output:"float64"`

    std gorest.EndPoint `method:"GET"
                            path:"/gene/{Id:string}/stddev"
                            output:"float64"`

    variance gorest.EndPoint `method:"GET"
                            path:"/gene/{Id:string}/vari"
                            output:"float64"`

    setScale gorest.EndPoint `method:"POST"
                             path:"/setscale/"
                             postdata:"string"`

    bg gorest.EndPoint `method:"GET"
                        path:"/gene/{GeneId:string}/{Exprs:string}/bg"
                        output:"string"`

    // Dataset holding nowac data
    Dataset *Dataset

    // RPC Server for performing statistics
    RPC rpcman.RPCMan

}

func (serv RestService) SetScale (PostData string) {
    log.Print("setting scale to ", PostData)

    serv.Dataset.setScale(PostData)

    log.Print("---------------------------------------------")
}

func (dataset *Dataset) setScale(scale string) {
    // changing scale to the same as before
    if(dataset.Scale == scale){
        return
    }

    log.Println("--------- old scale -------- ", dataset.Scale)
    dataset.Scale = scale
    log.Println("--------- new scale -------- ",  dataset.Scale)

    var tmpIdExprs map[string][]float64
    var tmpGeneExprs map[string]map[string]*CaseCtrl

    tmpIdExprs = dataset.Exprs.IdExpression
    tmpGeneExprs = dataset.Exprs.GeneExpression

    dataset.Exprs.IdExpression = dataset.Exprs.DiffIdExpression
    dataset.Exprs.GeneExpression = dataset.Exprs.DiffGeneExpression

    dataset.Exprs.DiffIdExpression = tmpIdExprs
    dataset.Exprs.DiffGeneExpression = tmpGeneExprs

}

// convert
func log2(input []float64) [] float64 {
    new_vals := make([] float64, len(input))

    for i, value := range(input){
        v := math.Log2(value)
        new_vals[i] = v
    }

    return new_vals
}

func exp2(input []float64) []float64 {

    new_vals := make([] float64, len(input))

    for i, value := range(input){
        v := math.Exp2(value)
        new_vals[i] = v
    }

    return new_vals
}

// Get gene expression for given gene
func (serv RestService) GeneExpression(Id string) []float64 {
    log.Print("Returning gene expression for gene ", Id)
    id := strings.Trim(Id, "hsa:")
    gene := kegg.GetGene(id)

    log.Print("hsa:",id," ==> ", gene.Name)

    if(gene.Name == "") {
        log.Println("Gene with id ",Id," not found in database")

        // return slice with all zeros
        emptySlice := make([]float64, len(serv.Dataset.Exprs.Genes))
        return emptySlice
    }

    log.Println("hepp")

    name := strings.Split(gene.Name, ", ")[0]

    var ret []float64
    // return difference between case & ctrl
    for _, cc := range(serv.Dataset.Exprs.GeneExpression[name]) {
        ret = append(ret, cc.Case - cc.Ctrl)
    }

    return ret
}

// Get standard deviation for expression values of a given gene
func (serv RestService) Std(GeneId string) float64 {
    exprs := serv.GeneExpression(GeneId)

    if(len(exprs) == 0){
        log.Print("Expression values for gene ", GeneId, " not found")
        return 0
    }
    ret, err := serv.RPC.Call("std",exprs)
    if err != nil {
        log.Println("RPC FAILED", err)
        return 0
    }

    std, ok := ret.(float64)
    if !ok{
        log.Println("conversion to float64 went bad: ",ret)
        return 0
    }

    log.Println("Standard deviation for expression of gene ", GeneId, " is ",std)
    return std

}

// Get variation for expression values of a given gene
func (serv RestService) Variance(GeneId string) float64{
    exprs := serv.GeneExpression(GeneId)

    if(len(exprs) == 0){
        log.Print("Expression values for gene ", GeneId, " not found")
        return 0
    }

    ret, err := serv.RPC.Call("var",exprs)
    if err != nil {
        log.Println("RPC FAILED", err)
        return 0
    }

    variance, ok := ret.(float64)
    if !ok{
        log.Println("conversion to float64 went bad: ",ret)
        return 0
    }

    log.Println("Variance for expression of gene ", GeneId, " is ",variance)
    return variance

}

func (serv RestService) AvgDiff(Id string) float64 {
    exprs := serv.GeneExpression(Id)

    if(len(exprs) == 0){
        log.Print("Expression values for gene ", Id, " not found")
        return 0
    }

    // avg := avg(exprs)

    ret, err := serv.RPC.Call("mean",exprs)
    if err != nil {
        log.Println("RPC FAILED", err)
    }
    avg, ok := ret.(float64)
    if !ok{
        log.Println("conversion to float64 went bad: ",ret)
    }

    log.Println("Average difference for gene ", Id, " is ",avg)
    return avg
}

func avg(nums [] float64) float64 {

    var total float64

    for _, num := range(nums) {
        total += num
    }

    return total / float64(len(nums))

}

// Find dataset id that has the given expression value
func expressionToId(dataset *Dataset, GeneId, Exprs string) string {

    id := strings.Trim(GeneId, "hsa:")
    gene := kegg.GetGene(id)

    if(gene.Name == "") {
        log.Println("Gene with id ",GeneId," not found in database")
        return ""
    }

    name := strings.Split(gene.Name, ", ")[0]

    dsId := ""

    exprsVal, err := strconv.ParseFloat(Exprs,64)
    if err != nil {
        log.Println("could not convert ",Exprs,"to float")
        return ""
    }

    // return difference between case & ctrl
    for i, cc := range(dataset.Exprs.GeneExpression[name]) {
        ex := cc.Case - cc.Ctrl
        if(ex == exprsVal) {
            dsId = i
            break
        }

    }

    return dsId

}

func (serv RestService) Bg(GeneId, Exprs string) string {
    dsId := expressionToId(serv.Dataset, GeneId, Exprs)

    bg := serv.Dataset.Bg.IdInfo[dsId]

    b, err := json.Marshal(bg)
    if err != nil {
        log.Print("marshaling went bad: ",err)
        return ""
    }

    return string(b)
}

func Init(path string) *RestService {
    ds := NewDataset(path) //Dataset{} // := NewDataset(*path)

    log.Print("dataset found at ", path)

    ds.PrintDebugInfo()

    restService := new(RestService)
    restService.Dataset = &ds

    // connect to statistics engine that will run statistics and that
    rpcaddr := "tcp://localhost:5555" // "ipc:///tmp/datastore/0" //"tcp://localhost:5555"
    restService.RPC = rpcman.Init(rpcaddr)
    restService.RPC.Connect()

    return restService
}

func main() {

    // enable debugging

        log.SetOutput(ioutil.Discard)
    //defer log.SetOutput(os.Stdout)

    var path = flag.String("path", "/Users/bjorn/stallo/data" , "path where data files are stored")
    var ip = flag.String("ip", "localhost", "ip to run on")
    var port = flag.String("port", ":8888" ,"port to run on")

    flag.Parse()

    restService := Init(*path)
    log.Print("Starting datastore at ", *ip, *port)

    f, err := os.Create("memprofile.prof")
    if err != nil {
        log.Print(err)
        return
    }
    pprof.WriteHeapProfile(f)
    f.Close()

    gorest.RegisterService(restService)

    http.Handle("/", gorest.Handle())
    http.ListenAndServe(*port, nil)

/*

// Profiling
// $ go tool pprof /home/bfj001/master/src/bin/datastore memprofile.prof
// (pprof) top5
    f, err := os.Create("memprofile.prof")
    if err != nil {
        log.Fatal(err)
    }
    pprof.WriteHeapProfile(f)
    f.Close()
    return
*/
}

<commit_msg>Avg. diffs for multiple genes<commit_after>package main

import (
    "log"
    "flag"
    "code.google.com/p/gorest"
    "net/http"
    "nowac/kegg"
    "strings"
    "math"
    "runtime/pprof"
    "os"
    "github.com/fjukstad/rpcman" // rpc to the statistics man
    "strconv"
    "encoding/json"
//    "io/ioutil"

)

type RestService struct  {

    // REST service details
    gorest.RestService `root:"/"
                        consumes:"application/json"
                        produces: "application/json" `

    geneExpression gorest.EndPoint `method:"GET"
                                    path:"/gene/{Id:string}"
                                    output:"[]float64"`

    avgDiff gorest.EndPoint `method:"GET"
                            path:"/gene/{Id:string}/avg"
                            output:"float64"`

    avgDiffs gorest.EndPoint `method:"GET"
                            path:"/genes/{...:string}/avg"
                            output:"string"`

    std gorest.EndPoint `method:"GET"
                            path:"/gene/{Id:string}/stddev"
                            output:"float64"`

    variance gorest.EndPoint `method:"GET"
                            path:"/gene/{Id:string}/vari"
                            output:"float64"`

    setScale gorest.EndPoint `method:"POST"
                             path:"/setscale/"
                             postdata:"string"`

    bg gorest.EndPoint `method:"GET"
                        path:"/gene/{GeneId:string}/{Exprs:string}/bg"
                        output:"string"`

    // Dataset holding nowac data
    Dataset *Dataset

    // RPC Server for performing statistics
    RPC rpcman.RPCMan

}

type Ex struct {
    Expression map[string] float64
}

func (serv RestService) AvgDiffs(args ...string) string {

    if len(args) < 2 {
        return ""
    }

    // Last item in args is avg
    genes := args[0:len(args)-1]
    genes = strings.Split(genes[0], " ")
    resp := make(map[string]float64,0)

    for _, gene  := range(genes) {
        resp[gene] = serv.AvgDiff(gene)
    }

    exp := Ex{resp}

    b, err := json.Marshal(exp)
    if err != nil {
        log.Println("Could not marshal reply in avgdiffs",err)
        return ""
    }

    return string(b)

}

func (serv RestService) SetScale (PostData string) {
    log.Print("setting scale to ", PostData)

    serv.Dataset.setScale(PostData)

    log.Print("---------------------------------------------")
}

func (dataset *Dataset) setScale(scale string) {
    // changing scale to the same as before
    if(dataset.Scale == scale){
        return
    }

    log.Println("--------- old scale -------- ", dataset.Scale)
    dataset.Scale = scale
    log.Println("--------- new scale -------- ",  dataset.Scale)

    var tmpIdExprs map[string][]float64
    var tmpGeneExprs map[string]map[string]*CaseCtrl

    tmpIdExprs = dataset.Exprs.IdExpression
    tmpGeneExprs = dataset.Exprs.GeneExpression

    dataset.Exprs.IdExpression = dataset.Exprs.DiffIdExpression
    dataset.Exprs.GeneExpression = dataset.Exprs.DiffGeneExpression

    dataset.Exprs.DiffIdExpression = tmpIdExprs
    dataset.Exprs.DiffGeneExpression = tmpGeneExprs

}

// convert
func log2(input []float64) [] float64 {
    new_vals := make([] float64, len(input))

    for i, value := range(input){
        v := math.Log2(value)
        new_vals[i] = v
    }

    return new_vals
}

func exp2(input []float64) []float64 {

    new_vals := make([] float64, len(input))

    for i, value := range(input){
        v := math.Exp2(value)
        new_vals[i] = v
    }

    return new_vals
}

// Get gene expression for given gene
func (serv RestService) GeneExpression(Id string) []float64 {
    log.Print("Returning gene expression for gene ", Id)
    id := strings.Trim(Id, "hsa:")
    gene := kegg.GetGene(id)

    log.Print("hsa:",id," ==> ", gene.Name)

    if(gene.Name == "") {
        log.Println("Gene with id ",Id," not found in database")

        // return slice with all zeros
        emptySlice := make([]float64, len(serv.Dataset.Exprs.Genes))
        return emptySlice
    }

    log.Println("hepp")

    name := strings.Split(gene.Name, ", ")[0]

    var ret []float64
    // return difference between case & ctrl
    for _, cc := range(serv.Dataset.Exprs.GeneExpression[name]) {
        ret = append(ret, cc.Case - cc.Ctrl)
    }

    /*
    if(serv.Context != nil){
        serv.RB().ConnectionClose()
    }
    */

    return ret
}

// Get standard deviation for expression values of a given gene
func (serv RestService) Std(GeneId string) float64 {
    exprs := serv.GeneExpression(GeneId)

    if(len(exprs) == 0){
        log.Print("Expression values for gene ", GeneId, " not found")
        return 0
    }
    ret, err := serv.RPC.Call("std",exprs)
    if err != nil {
        log.Println("RPC FAILED", err)
        return 0
    }

    std, ok := ret.(float64)
    if !ok{
        log.Println("conversion to float64 went bad: ",ret)
        return 0
    }

    log.Println("Standard deviation for expression of gene ", GeneId, " is ",std)
    return std

}

// Get variation for expression values of a given gene
func (serv RestService) Variance(GeneId string) float64{
    exprs := serv.GeneExpression(GeneId)

    if(len(exprs) == 0){
        log.Print("Expression values for gene ", GeneId, " not found")
        return 0
    }

    ret, err := serv.RPC.Call("var",exprs)
    if err != nil {
        log.Println("RPC FAILED", err)
        return 0
    }

    variance, ok := ret.(float64)
    if !ok{
        log.Println("conversion to float64 went bad: ",ret)
        return 0
    }

    log.Println("Variance for expression of gene ", GeneId, " is ",variance)
    return variance

}

func (serv RestService) AvgDiff(Id string) float64 {
    exprs := serv.GeneExpression(Id)

    if(len(exprs) == 0){
        log.Print("Expression values for gene ", Id, " not found")
        return 0
    }

    // avg := avg(exprs)

    ret, err := serv.RPC.Call("mean",exprs)
    if err != nil {
        log.Println("RPC FAILED", err)
    }
    avg, ok := ret.(float64)
    if !ok{
        log.Println("conversion to float64 went bad: ",ret)
    }

    log.Println("Average difference for gene ", Id, " is ",avg)

    /*
    if(serv.Context != nil){
        serv.RB().ConnectionClose()
    }
    */

    return avg
}

func avg(nums [] float64) float64 {

    var total float64

    for _, num := range(nums) {
        total += num
    }

    return total / float64(len(nums))

}

// Find dataset id that has the given expression value
func expressionToId(dataset *Dataset, GeneId, Exprs string) string {

    id := strings.Trim(GeneId, "hsa:")
    gene := kegg.GetGene(id)

    if(gene.Name == "") {
        log.Println("Gene with id ",GeneId," not found in database")
        return ""
    }

    name := strings.Split(gene.Name, ", ")[0]

    dsId := ""

    exprsVal, err := strconv.ParseFloat(Exprs,64)
    if err != nil {
        log.Println("could not convert ",Exprs,"to float")
        return ""
    }

    // return difference between case & ctrl
    for i, cc := range(dataset.Exprs.GeneExpression[name]) {
        ex := cc.Case - cc.Ctrl
        if(ex == exprsVal) {
            dsId = i
            break
        }

    }

    return dsId

}

func (serv RestService) Bg(GeneId, Exprs string) string {
    dsId := expressionToId(serv.Dataset, GeneId, Exprs)

    bg := serv.Dataset.Bg.IdInfo[dsId]

    b, err := json.Marshal(bg)
    if err != nil {
        log.Print("marshaling went bad: ",err)
        return ""
    }

    return string(b)
}

func Init(path string) *RestService {
    ds := NewDataset(path) //Dataset{} // := NewDataset(*path)

    log.Print("dataset found at ", path)

    ds.PrintDebugInfo()

    restService := new(RestService)
    restService.Dataset = &ds

    // connect to statistics engine that will run statistics and that
    rpcaddr := "tcp://localhost:5555" // "ipc:///tmp/datastore/0" //"tcp://localhost:5555"
    restService.RPC = rpcman.Init(rpcaddr)
    //err := restService.RPC.Connect()

    //log.Println("connecting to statsman")

    //if err != nil{
    //    log.Panic("Connection statistics engine failed.",err)
    //}

    return restService
}

func main() {

    // enable debugging

    //log.SetOutput(ioutil.Discard)
    //defer log.SetOutput(os.Stdout)

    var path = flag.String("path", "/Users/bjorn/stallo/data" , "path where data files are stored")
    var ip = flag.String("ip", "localhost", "ip to run on")
    var port = flag.String("port", ":8888" ,"port to run on")

    flag.Parse()

    restService := Init(*path)
    log.Print("Starting datastore at ", *ip, *port)

    f, err := os.Create("memprofile.prof")
    if err != nil {
        log.Print(err)
        return
    }
    pprof.WriteHeapProfile(f)
    f.Close()

    gorest.RegisterService(restService)

    http.Handle("/", gorest.Handle())
    http.ListenAndServe(*port, nil)

/*

// Profiling
// $ go tool pprof /home/bfj001/master/src/bin/datastore memprofile.prof
// (pprof) top5
    f, err := os.Create("memprofile.prof")
    if err != nil {
        log.Fatal(err)
    }
    pprof.WriteHeapProfile(f)
    f.Close()
    return
*/
}

<|endoftext|>


<commit_before>package ripper

import (
	"github.com/goby-lang/goby/compiler"
	"github.com/goby-lang/goby/compiler/bytecode"
	"github.com/goby-lang/goby/compiler/lexer"
	"github.com/goby-lang/goby/compiler/parser"
	"github.com/goby-lang/goby/compiler/token"
	"github.com/goby-lang/goby/vm"
	"github.com/goby-lang/goby/vm/classes"
	"github.com/goby-lang/goby/vm/errors"
	"strings"
)

// Ripper is a loadable library and has abilities to parse/lex/tokenize/get instructions of Goby codes from String.
// The library would be convenient for validating Goby codes when building lint tools,
// as well as the tests for Goby's compiler.
// For now, Ripper is a class and has only class methods, but I think this should finally be a 'newable' module with more sophisticated instance methods.

// Imported objects from vm
type Object = vm.Object
type VM = vm.VM
type Thread = vm.Thread
type Method = vm.Method
type StringObject = vm.StringObject
type HashObject = vm.HashObject
type ArrayObject = vm.ArrayObject

// Class methods --------------------------------------------------------

// Returns the list of instruction code generated from Goby code.
// Returns `[]` when the Goby code is invalid.
// The return value is a "tuple" style nested array:
// - `Array`: contains an instruction set
//   - `arg_types:` (none if `nil`)
// 		 - `names:` array of names (string)
//     - `types:` array of types (integer)
//   - `instructions:` array of instructions
//     - `action:` string
//     - `anchor:` integer
//     - `line:` integer
//     - `params:` array of parameters (string)
//     - `source_line:` integer
//     - `arg_set:` (none if `nil`)
//   		 - `names:` array of names (string)
//       - `types:` array of types (integer)
//
// ```ruby
// require 'ripper'; Ripper.instruction "10.times do |i| puts i end"
// #=>
//
// require 'ripper'; Ripper.instruction "10.times do |i| puts i" # the code is invalid
// #=> []
// ```
//
// @param Goby code [String]
// @return [Array]
func instruction(receiver Object, sourceLine int, t *Thread, args []Object) Object {
	if len(args) != 1 {
		return t.VM().InitErrorObject(errors.ArgumentError, sourceLine, "Expect 1 argument. got=%d", len(args))
	}

	arg, ok := args[0].(*StringObject)
	if !ok {
		return t.VM().InitErrorObject(errors.TypeError, sourceLine, errors.WrongArgumentTypeFormat, classes.StringClass, args[0].Class().Name)
	}

	i, _ := compiler.CompileToInstructions(arg.Value().(string), parser.NormalMode)

	return convertToTuple(i, t.VM())
}

// Returns a nested array that contains the line #, type of the tokenize, and the literal of the tokenize.
// Note that the class method does not return any errors even though the provided Goby code is invalid.
//
// ```ruby
// require 'ripper'; Ripper.lex "10.times do |i| puts i end"
// #=> [[0, "on_int", "10"], [0, "on_dot", "."], [0, "on_ident", "times"], [0, "on_do", "do"], [0, "on_bar", "|"], [0, "on_ident", "i"], [0, "on_bar", "|"], [0, "on_ident", "puts"], [0, "on_ident", "i"], [0, "on_end", "end"], [0, "on_eof", ""]]
//
// require 'ripper'; Ripper.lex "10.times do |i| puts i" # the code is invalid
// #=> [[0, "on_int", "10"], [0, "on_dot", "."], [0, "on_ident", "times"], [0, "on_do", "do"], [0, "on_bar", "|"], [0, "on_ident", "i"], [0, "on_bar", "|"], [0, "on_ident", "puts"], [0, "on_ident", "i"], [0, "on_eof", ""]]
// ```
//
// @param Goby code [String]
// @return [Array]
func lex(receiver Object, sourceLine int, t *Thread, args []Object) Object  {
	if len(args) != 1 {
		return t.VM().InitErrorObject(errors.ArgumentError, sourceLine, "Expect 1 argument. got=%d", len(args))
	}

	arg, ok := args[0].(*StringObject)
	if !ok {
		return t.VM().InitErrorObject(errors.TypeError, sourceLine, errors.WrongArgumentTypeFormat, classes.StringClass, args[0].Class().Name)
	}

	l := lexer.New(arg.Value().(string))
	array := t.VM().InitArrayObject([]Object{})
	var elements []Object
	var nextToken token.Token
	for i := 0; ; i++ {
		nextToken = l.NextToken()
		elements = append(elements, t.VM().InitIntegerObject(nextToken.Line))
		elements = append(elements, t.VM().InitStringObject(convertLex(nextToken.Type)))
		elements = append(elements, t.VM().InitStringObject(nextToken.Literal))
		array.Elements = append(array.Elements, t.VM().InitArrayObject(elements))
		if nextToken.Type == token.EOF {
			break
		}
		elements = nil
	}
	return array
}

// Just to disable creating instances.
func new(receiver Object, sourceLine int, t *Thread, args []Object) Object {
	return t.VM().InitUnsupportedMethodError(sourceLine, "#new", receiver)
}

// Returns the parsed Goby codes as a String object.
// Returns an error when the code is invalid.
//
// ```ruby
// require 'ripper'; Ripper.parse "10.times do |i| puts i end"
// #=> "10.times() do |i|
// #=> self.puts(i)
// #=> end"
//
// require 'ripper'; Ripper.parse "10.times do |i| puts i" # the code is invalid
// #=> TypeError: InternalError%!(EXTRA string=String, string=Invalid Goby code)
// ```
//
// @param Goby code [String]
// @return [String]
func parse(receiver Object, sourceLine int, t *Thread, args []Object) Object {
	if len(args) != 1 {
		return t.VM().InitErrorObject(errors.ArgumentError, sourceLine, "Expect 1 argument. got=%d", len(args))
	}

	arg, ok := args[0].(*StringObject)
	if !ok {
		return t.VM().InitErrorObject(errors.TypeError, sourceLine, errors.WrongArgumentTypeFormat, classes.StringClass, args[0].Class().Name)
	}

	l := lexer.New(arg.Value().(string))
	p := parser.New(l)
	program, _ := p.ParseProgram()

	return t.VM().InitStringObject(program.String())
}

// Returns a tokenized Goby codes as an Array object.
// Note that this does not return any errors even though the provided code is invalid.
//
// ```ruby
// require 'ripper'; Ripper.tokenize "10.times do |i| puts i end"
// #=> ["10", ".", "times", "do", "|", "i", "|", "puts", "i", "end", "EOF"]
//
// require 'ripper'; Ripper.parse "10.times do |i| puts i" # the code is invalid
// #=> ["10", ".", "times", "do", "|", "i", "|", "puts", "i", "EOF"]
// ```
//
// @param Goby code [String]
// @return [String]
func tokenize(receiver Object, sourceLine int, t *Thread, args []Object) Object {
	if len(args) != 1 {
		return t.VM().InitErrorObject(errors.ArgumentError, sourceLine, "Expect 1 argument. got=%d", len(args))
	}

	arg, ok := args[0].(*StringObject)
	if !ok {
		return t.VM().InitErrorObject(errors.TypeError, sourceLine, errors.WrongArgumentTypeFormat, classes.StringClass, args[0].Class().Name)
	}

	l := lexer.New(arg.Value().(string))
	el := []Object{}
	var nt token.Token
	for i := 0; ; i++ {
		nt = l.NextToken()
		if nt.Type == token.EOF {
			el = append(el, t.VM().InitStringObject("EOF"))
			break
		}
		el = append(el, t.VM().InitStringObject(nt.Literal))
	}
	return t.VM().InitArrayObject(el)
}

// Internal functions ===================================================
func init() {
	vm.RegisterExternalClass("ripper", vm.ExternalClass("Ripper", "ripper.gb",
		// class methods
		map[string]vm.Method{
			"instruction": instruction,
			"lex":         lex,
			"new": 				 new,
			"parse":       parse,
			"tokenize":    tokenize,
		},
		// instance methods
		map[string]vm.Method{},
	))
}

// Other helper functions ----------------------------------------------

func convertToTuple(instSet []*bytecode.InstructionSet, v *VM) *ArrayObject {
	ary := []Object{}
	for _, instruction := range instSet {
		hashInstLevel1 := make(map[string]Object)
		hashInstLevel1["name"] = v.InitStringObject(instruction.Name())
		hashInstLevel1["type"] = v.InitStringObject(instruction.Type())
		if instruction.ArgTypes() != nil {
			hashInstLevel1["arg_types"] = getArgNameType(instruction.ArgTypes(), v)
		}
		ary = append(ary, v.InitHashObject(hashInstLevel1))

		arrayInst := []Object{}
		for _, ins := range instruction.Instructions {
			hashInstLevel2 := make(map[string]Object)
			hashInstLevel2["action"] = v.InitStringObject(ins.Action)
			hashInstLevel2["line"] = v.InitIntegerObject(ins.Line())
			hashInstLevel2["source_line"] = v.InitIntegerObject(ins.SourceLine())
			anchor, _ := ins.AnchorLine()
			hashInstLevel2["anchor"] = v.InitIntegerObject(anchor)

			arrayParams := []Object{}
			for _, param := range ins.Params {
				arrayParams = append(arrayParams, v.InitStringObject(param))
			}
			hashInstLevel2["params"] = v.InitArrayObject(arrayParams)

			if ins.ArgSet != nil {
				hashInstLevel1["arg_set"] = getArgNameType(ins.ArgSet, v)
			}

			arrayInst = append(arrayInst, v.InitHashObject(hashInstLevel2))
		}

		hashInstLevel1["instructions"] = v.InitArrayObject(arrayInst)
		ary = append(ary, v.InitHashObject(hashInstLevel1))
	}
	return v.InitArrayObject(ary)
}

func getArgNameType(argSet *bytecode.ArgSet, v *VM) *HashObject {
	h := make(map[string]Object)

	aName := []Object{}
	for _, argname := range argSet.Names() {
		aName = append(aName, v.InitStringObject(argname))
	}
	h["names"] = v.InitArrayObject(aName)

	aType := []Object{}
	for _, argtype := range argSet.Types() {
		aType = append(aType, v.InitIntegerObject(argtype))
	}

	h["types"] = v.InitArrayObject(aType)
	return v.InitHashObject(h)
}

// TODO: This should finally be auto-generated from tokenize.go
func convertLex(t token.Type) string {
	var s string
	switch t {
	case token.Asterisk:
		s = "asterisk"
	case token.And:
		s = "and"
	case token.Assign:
		s = "assign"
	case token.Bang:
		s = "bang"
	case token.Bar:
		s = "bar"
	case token.Colon:
		s = "colon"
	case token.Comma:
		s = "comma"
	case token.COMP:
		s = "comp"
	case token.Dot:
		s = "dot"
	case token.Eq:
		s = "eq"
	case token.GT:
		s = "gt"
	case token.GTE:
		s = "gte"
	case token.LBrace:
		s = "lbrace"
	case token.LBracket:
		s = "lbracket"
	case token.LParen:
		s = "lparen"
	case token.LT:
		s = "lt"
	case token.LTE:
		s = "lte"
	case token.Match:
		s = "match"
	case token.Minus:
		s = "minus"
	case token.MinusEq:
		s = "minuseq"
	case token.Modulo:
		s = "modulo"
	case token.NotEq:
		s = "noteq"
	case token.Or:
		s = "or"
	case token.OrEq:
		s = "oreq"
	case token.Plus:
		s = "plus"
	case token.PlusEq:
		s = "pluseq"
	case token.Pow:
		s = "pow"
	case token.Range:
		s = "range"
	case token.RBrace:
		s = "rbrace"
	case token.RBracket:
		s = "rbracket"
	case token.ResolutionOperator:
		s = "resolutionoperator"
	case token.RParen:
		s = "rparen"
	case token.Semicolon:
		s = "semicolon"
	case token.Slash:
		s = "slash"
	default:
		s = strings.ToLower(string(t))
	}

	return "on_" + s
}
<commit_msg>Fix Ripper.<commit_after>package ripper

import (
	"github.com/goby-lang/goby/compiler"
	"github.com/goby-lang/goby/compiler/bytecode"
	"github.com/goby-lang/goby/compiler/lexer"
	"github.com/goby-lang/goby/compiler/parser"
	"github.com/goby-lang/goby/compiler/token"
	"github.com/goby-lang/goby/vm"
	"github.com/goby-lang/goby/vm/classes"
	"github.com/goby-lang/goby/vm/errors"
	"strings"
	"fmt"
)

// Ripper is a loadable library and has abilities to parse/lex/tokenize/get instructions of Goby codes from String.
// The library would be convenient for validating Goby codes when building lint tools,
// as well as the tests for Goby's compiler.
// For now, Ripper is a class and has only class methods, but I think this should finally be a 'newable' module with more sophisticated instance methods.

// Imported objects from vm
type Object = vm.Object
type VM = vm.VM
type Thread = vm.Thread
type Method = vm.Method
type StringObject = vm.StringObject
type HashObject = vm.HashObject
type ArrayObject = vm.ArrayObject

// Class methods --------------------------------------------------------

// Returns the list of instruction code generated from Goby code.
// Returns `[]` when the Goby code is invalid.
// The return value is a "tuple" style nested array:
// - `Array`: contains an instruction set
//   - `arg_types:` (none if `nil`)
// 		 - `names:` array of names (string)
//     - `types:` array of types (integer)
//   - `instructions:` array of instructions
//     - `action:` string
//     - `anchor:` integer
//     - `line:` integer
//     - `params:` array of parameters (string)
//     - `source_line:` integer
//     - `arg_set:` (none if `nil`)
//   		 - `names:` array of names (string)
//       - `types:` array of types (integer)
//
// ```ruby
// require 'ripper'; Ripper.instruction "10.times do |i| puts i end"
// #=>
//
// require 'ripper'; Ripper.instruction "10.times do |i| puts i" # the code is invalid
// #=> []
// ```
//
// @param Goby code [String]
// @return [Array]
func instruction(receiver Object, sourceLine int, t *Thread, args []Object) Object {
	if len(args) != 1 {
		return t.VM().InitErrorObject(errors.ArgumentError, sourceLine, "Expect 1 argument. got=%d", len(args))
	}

	arg, ok := args[0].(*StringObject)
	if !ok {
		return t.VM().InitErrorObject(errors.TypeError, sourceLine, errors.WrongArgumentTypeFormat, classes.StringClass, args[0].Class().Name)
	}

	i, _ := compiler.CompileToInstructions(arg.Value().(string), parser.NormalMode)

	return convertToTuple(i, t.VM())
}

// Returns a nested array that contains the line #, type of the tokenize, and the literal of the tokenize.
// Note that the class method does not return any errors even though the provided Goby code is invalid.
//
// ```ruby
// require 'ripper'; Ripper.lex "10.times do |i| puts i end"
// #=> [[0, "on_int", "10"], [0, "on_dot", "."], [0, "on_ident", "times"], [0, "on_do", "do"], [0, "on_bar", "|"], [0, "on_ident", "i"], [0, "on_bar", "|"], [0, "on_ident", "puts"], [0, "on_ident", "i"], [0, "on_end", "end"], [0, "on_eof", ""]]
//
// require 'ripper'; Ripper.lex "10.times do |i| puts i" # the code is invalid
// #=> [[0, "on_int", "10"], [0, "on_dot", "."], [0, "on_ident", "times"], [0, "on_do", "do"], [0, "on_bar", "|"], [0, "on_ident", "i"], [0, "on_bar", "|"], [0, "on_ident", "puts"], [0, "on_ident", "i"], [0, "on_eof", ""]]
// ```
//
// @param Goby code [String]
// @return [Array]
func lex(receiver Object, sourceLine int, t *Thread, args []Object) Object  {
	if len(args) != 1 {
		return t.VM().InitErrorObject(errors.ArgumentError, sourceLine, "Expect 1 argument. got=%d", len(args))
	}

	arg, ok := args[0].(*StringObject)
	if !ok {
		return t.VM().InitErrorObject(errors.TypeError, sourceLine, errors.WrongArgumentTypeFormat, classes.StringClass, args[0].Class().Name)
	}

	l := lexer.New(arg.Value().(string))
	array := t.VM().InitArrayObject([]Object{})
	var elements []Object
	var nextToken token.Token
	for i := 0; ; i++ {
		nextToken = l.NextToken()
		elements = append(elements, t.VM().InitIntegerObject(nextToken.Line))
		elements = append(elements, t.VM().InitStringObject(convertLex(nextToken.Type)))
		elements = append(elements, t.VM().InitStringObject(nextToken.Literal))
		array.Elements = append(array.Elements, t.VM().InitArrayObject(elements))
		if nextToken.Type == token.EOF {
			break
		}
		elements = nil
	}
	return array
}

// Just to disable creating instances.
func new(receiver Object, sourceLine int, t *Thread, args []Object) Object {
	return t.VM().InitUnsupportedMethodError(sourceLine, "#new", receiver)
}

// Returns the parsed Goby codes as a String object.
// Returns an error when the code is invalid.
//
// ```ruby
// require 'ripper'; Ripper.parse "10.times do |i| puts i end"
// #=> "10.times() do |i|
// #=> self.puts(i)
// #=> end"
//
// require 'ripper'; Ripper.parse "10.times do |i| puts i" # the code is invalid
// #=> TypeError: InternalError%!(EXTRA string=String, string=Invalid Goby code)
// ```
//
// @param Goby code [String]
// @return [String]
func parse(receiver Object, sourceLine int, t *Thread, args []Object) Object {
	if len(args) != 1 {
		return t.VM().InitErrorObject(errors.ArgumentError, sourceLine, "Expect 1 argument. got=%d", len(args))
	}

	arg, ok := args[0].(*StringObject)
	if !ok {
		return t.VM().InitErrorObject(errors.TypeError, sourceLine, errors.WrongArgumentTypeFormat, classes.StringClass, args[0].Class().Name)
	}

	l := lexer.New(arg.Value().(string))
	p := parser.New(l)
	program, _ := p.ParseProgram()

	return t.VM().InitStringObject(program.String())
}

// Returns a tokenized Goby codes as an Array object.
// Note that this does not return any errors even though the provided code is invalid.
//
// ```ruby
// require 'ripper'; Ripper.tokenize "10.times do |i| puts i end"
// #=> ["10", ".", "times", "do", "|", "i", "|", "puts", "i", "end", "EOF"]
//
// require 'ripper'; Ripper.parse "10.times do |i| puts i" # the code is invalid
// #=> ["10", ".", "times", "do", "|", "i", "|", "puts", "i", "EOF"]
// ```
//
// @param Goby code [String]
// @return [String]
func tokenize(receiver Object, sourceLine int, t *Thread, args []Object) Object {
	if len(args) != 1 {
		return t.VM().InitErrorObject(errors.ArgumentError, sourceLine, "Expect 1 argument. got=%d", len(args))
	}

	arg, ok := args[0].(*StringObject)
	if !ok {
		return t.VM().InitErrorObject(errors.TypeError, sourceLine, errors.WrongArgumentTypeFormat, classes.StringClass, args[0].Class().Name)
	}

	l := lexer.New(arg.Value().(string))
	el := []Object{}
	var nt token.Token
	for i := 0; ; i++ {
		nt = l.NextToken()
		if nt.Type == token.EOF {
			el = append(el, t.VM().InitStringObject("EOF"))
			break
		}
		el = append(el, t.VM().InitStringObject(nt.Literal))
	}
	return t.VM().InitArrayObject(el)
}

// Internal functions ===================================================
func init() {
	vm.RegisterExternalClass("ripper", vm.ExternalClass("Ripper", "ripper.gb",
		// class methods
		map[string]vm.Method{
			"instruction": instruction,
			"lex":         lex,
			"new": 				 new,
			"parse":       parse,
			"tokenize":    tokenize,
		},
		// instance methods
		map[string]vm.Method{},
	))
}

// Other helper functions ----------------------------------------------

func convertToTuple(instSet []*bytecode.InstructionSet, v *VM) *ArrayObject {
	ary := []Object{}
	for _, instruction := range instSet {
		hashInstLevel1 := make(map[string]Object)
		hashInstLevel1["name"] = v.InitStringObject(instruction.Name())
		hashInstLevel1["type"] = v.InitStringObject(instruction.Type())
		if instruction.ArgTypes() != nil {
			hashInstLevel1["arg_types"] = getArgNameType(instruction.ArgTypes(), v)
		}
		ary = append(ary, v.InitHashObject(hashInstLevel1))

		arrayInst := []Object{}
		for _, ins := range instruction.Instructions {
			hashInstLevel2 := make(map[string]Object)
			hashInstLevel2["action"] = v.InitStringObject(ins.Action)
			hashInstLevel2["line"] = v.InitIntegerObject(ins.Line())
			hashInstLevel2["source_line"] = v.InitIntegerObject(ins.SourceLine())
			anchor, _ := ins.AnchorLine()
			hashInstLevel2["anchor"] = v.InitIntegerObject(anchor)

			arrayParams := []Object{}
			for _, param := range ins.Params {
				arrayParams = append(arrayParams, v.InitStringObject(covertTypesToString(param)))
			}
			hashInstLevel2["params"] = v.InitArrayObject(arrayParams)

			if ins.ArgSet != nil {
				hashInstLevel1["arg_set"] = getArgNameType(ins.ArgSet, v)
			}

			arrayInst = append(arrayInst, v.InitHashObject(hashInstLevel2))
		}

		hashInstLevel1["instructions"] = v.InitArrayObject(arrayInst)
		ary = append(ary, v.InitHashObject(hashInstLevel1))
	}
	return v.InitArrayObject(ary)
}

func getArgNameType(argSet *bytecode.ArgSet, v *VM) *HashObject {
	h := make(map[string]Object)

	aName := []Object{}
	for _, argname := range argSet.Names() {
		aName = append(aName, v.InitStringObject(argname))
	}
	h["names"] = v.InitArrayObject(aName)

	aType := []Object{}
	for _, argtype := range argSet.Types() {
		aType = append(aType, v.InitIntegerObject(argtype))
	}

	h["types"] = v.InitArrayObject(aType)
	return v.InitHashObject(h)
}

// TODO: This should finally be auto-generated from tokenize.go
func convertLex(t token.Type) string {
	var s string
	switch t {
	case token.Asterisk:
		s = "asterisk"
	case token.And:
		s = "and"
	case token.Assign:
		s = "assign"
	case token.Bang:
		s = "bang"
	case token.Bar:
		s = "bar"
	case token.Colon:
		s = "colon"
	case token.Comma:
		s = "comma"
	case token.COMP:
		s = "comp"
	case token.Dot:
		s = "dot"
	case token.Eq:
		s = "eq"
	case token.GT:
		s = "gt"
	case token.GTE:
		s = "gte"
	case token.LBrace:
		s = "lbrace"
	case token.LBracket:
		s = "lbracket"
	case token.LParen:
		s = "lparen"
	case token.LT:
		s = "lt"
	case token.LTE:
		s = "lte"
	case token.Match:
		s = "match"
	case token.Minus:
		s = "minus"
	case token.MinusEq:
		s = "minuseq"
	case token.Modulo:
		s = "modulo"
	case token.NotEq:
		s = "noteq"
	case token.Or:
		s = "or"
	case token.OrEq:
		s = "oreq"
	case token.Plus:
		s = "plus"
	case token.PlusEq:
		s = "pluseq"
	case token.Pow:
		s = "pow"
	case token.Range:
		s = "range"
	case token.RBrace:
		s = "rbrace"
	case token.RBracket:
		s = "rbracket"
	case token.ResolutionOperator:
		s = "resolutionoperator"
	case token.RParen:
		s = "rparen"
	case token.Semicolon:
		s = "semicolon"
	case token.Slash:
		s = "slash"
	default:
		s = strings.ToLower(string(t))
	}

	return "on_" + s
}

func covertTypesToString(v interface{}) string {
	return fmt.Sprint(v)
}
<|endoftext|>


<commit_before>package isolated

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"

	helpers "code.cloudfoundry.org/cli/integration/helpers"
	"code.cloudfoundry.org/cli/util/configv3"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("Verbose", func() {
	Context("v2 legacy", func() {
		DescribeTable("displays verbose output",
			func(command func() *Session) {
				login := exec.Command("cf", "auth", "admin", "admin")
				loginSession, err := Start(login, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())
				Eventually(loginSession).Should(Exit(0))

				session := command()
				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("GET /v2/organizations"))
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Exit(0))
			},

			Entry("when the -v option is provided with additional command", func() *Session {
				return helpers.CF("-v", "orgs")
			}),

			Entry("when the CF_TRACE env variable is set", func() *Session {
				return helpers.CFWithEnv(map[string]string{"CF_TRACE": "true"}, "orgs")
			}),
		)
	})

	Context("v2 refactor", func() {
		DescribeTable("displays verbose output to terminal",
			func(env string, configTrace string, flag bool) {
				tmpDir, err := ioutil.TempDir("", "")
				defer os.RemoveAll(tmpDir)
				Expect(err).NotTo(HaveOccurred())

				setupCF(ReadOnlyOrg, ReadOnlySpace)

				var envMap map[string]string
				if env != "" {
					if string(env[0]) == "/" {
						env = filepath.Join(tmpDir, env)
					}
					envMap = map[string]string{"CF_TRACE": env}
				}

				// We use 'create-user' because it makes a request via the UAA client
				// and a request via the CC client, testing the logging wrapper in both
				// clients.
				randomUsername := helpers.RandomUsername()
				randomPassword := helpers.RandomPassword()
				command := []string{"create-user", randomUsername, randomPassword}

				if flag {
					command = append(command, "-v")
				}

				if configTrace != "" {
					if string(configTrace[0]) == "/" {
						configTrace = filepath.Join(tmpDir, configTrace)
					}
					session := helpers.CF("config", "--trace", configTrace)
					Eventually(session).Should(Exit(0))
				}

				session := helpers.CFWithEnv(envMap, command...)

				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("POST /Users"))
				Eventually(session).Should(Say("User-Agent: cf/[\\w.+]+ \\(%s; %s %s\\)", runtime.Version(), runtime.GOARCH, runtime.GOOS))
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("POST /v2/users"))
				Eventually(session).Should(Say("User-Agent: cf/[\\w.+]+ \\(%s; %s %s\\)", runtime.Version(), runtime.GOARCH, runtime.GOOS))
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Exit(0))
			},

			Entry("CF_TRACE true: enables verbose", "true", "", false),
			Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false),
			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo/bar", false),

			Entry("CF_TRACE false, '-v': enables verbose", "false", "", true),
			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo/bar", true),

			Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true),
			Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false),
			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo/bar", true),

			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo/bar", "", true),
			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo/bar", "true", false),
			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo/bar", "/baz", true),
		)

		DescribeTable("displays verbose output to multiple files",
			func(env string, configTrace string, flag bool, location []string) {
				tmpDir, err := ioutil.TempDir("", "")
				defer os.RemoveAll(tmpDir)
				Expect(err).NotTo(HaveOccurred())

				setupCF(ReadOnlyOrg, ReadOnlySpace)

				var envMap map[string]string
				if env != "" {
					if string(env[0]) == "/" {
						env = filepath.Join(tmpDir, env)
					}
					envMap = map[string]string{"CF_TRACE": env}
				}

				// We use 'create-user' because it makes a request via the UAA client
				// and a request via the CC client, testing the logging wrapper in both
				// clients.
				randomUsername := helpers.RandomUsername()
				randomPassword := helpers.RandomPassword()
				command := []string{"create-user", randomUsername, randomPassword}

				if flag {
					command = append(command, "-v")
				}

				if configTrace != "" {
					if string(configTrace[0]) == "/" {
						configTrace = filepath.Join(tmpDir, configTrace)
					}
					session := helpers.CF("config", "--trace", configTrace)
					Eventually(session).Should(Exit(0))
				}

				session := helpers.CFWithEnv(envMap, command...)
				Eventually(session).Should(Exit(0))

				for _, filePath := range location {
					contents, err := ioutil.ReadFile(tmpDir + filePath)
					Expect(err).ToNot(HaveOccurred())

					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
					Expect(string(contents)).To(MatchRegexp("POST /Users"))
					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))
					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
					Expect(string(contents)).To(MatchRegexp("POST /v2/users"))
					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))

					stat, err := os.Stat(tmpDir + filePath)
					Expect(err).ToNot(HaveOccurred())

					if runtime.GOOS == "windows" {
						Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String()))
					} else {
						Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String()))
					}
				}
			},

			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false, []string{"/foo"}),

			Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", false, []string{"/foo"}),
			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true, []string{"/foo"}),

			Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", false, []string{"/foo"}),
			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true, []string{"/foo"}),

			Entry("CF_TRACE filepath: enables logging to file", "/foo", "", false, []string{"/foo"}),
			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true, []string{"/foo"}),
			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false, []string{"/foo"}),
			Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", false, []string{"/foo", "/bar"}),
			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true, []string{"/foo", "/bar"}),
		)
	})

	Context("v3", func() {
		DescribeTable("displays verbose output to terminal",
			func(env string, configTrace string, flag bool) {
				tmpDir, err := ioutil.TempDir("", "")
				defer os.RemoveAll(tmpDir)
				Expect(err).NotTo(HaveOccurred())

				setupCF(ReadOnlyOrg, ReadOnlySpace)

				// Invalidate the access token to cause a token refresh in order to
				// test the call to the UAA.
				helpers.SetConfig(func(config *configv3.Config) {
					config.ConfigFile.AccessToken = fmt.Sprintf("%sfoo", config.ConfigFile.AccessToken)
				})

				var envMap map[string]string
				if env != "" {
					if string(env[0]) == "/" {
						env = filepath.Join(tmpDir, env)
					}
					envMap = map[string]string{"CF_TRACE": env}
				}

				command := []string{"run-task", "app", "echo"}

				if flag {
					command = append(command, "-v")
				}

				if configTrace != "" {
					if string(configTrace[0]) == "/" {
						configTrace = filepath.Join(tmpDir, configTrace)
					}
					session := helpers.CF("config", "--trace", configTrace)
					Eventually(session).Should(Exit(0))
				}

				session := helpers.CFWithEnv(envMap, command...)

				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("GET /v3/apps"))
				Eventually(session).Should(Say("User-Agent: cf/[\\w.+]+ \\(%s; %s %s\\)", runtime.Version(), runtime.GOARCH, runtime.GOOS))
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("POST /oauth/token"))
				Eventually(session).Should(Say("User-Agent: cf/[\\w.+]+ \\(%s; %s %s\\)", runtime.Version(), runtime.GOARCH, runtime.GOOS))
				Eventually(session).Should(Say("grant_type=refresh_token")) //This is required to test the previous line. If it fails, the previous matcher went too far.
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Exit(1))
			},

			Entry("CF_TRACE true: enables verbose", "true", "", false),
			Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false),
			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo/bar", false),

			Entry("CF_TRACE false, '-v': enables verbose", "false", "", true),
			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo/bar", true),

			Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true),
			Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false),
			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo/bar", true),

			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo/bar", "", true),
			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo/bar", "true", false),
			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo/bar", "/baz", true),
		)

		DescribeTable("displays verbose output to multiple files",
			func(env string, configTrace string, flag bool, location []string) {
				tmpDir, err := ioutil.TempDir("", "")
				defer os.RemoveAll(tmpDir)
				Expect(err).NotTo(HaveOccurred())

				setupCF(ReadOnlyOrg, ReadOnlySpace)

				// Invalidate the access token to cause a token refresh in order to
				// test the call to the UAA.
				helpers.SetConfig(func(config *configv3.Config) {
					config.ConfigFile.AccessToken = fmt.Sprintf("%sfoo", config.ConfigFile.AccessToken)
				})

				var envMap map[string]string
				if env != "" {
					if string(env[0]) == "/" {
						env = filepath.Join(tmpDir, env)
					}
					envMap = map[string]string{"CF_TRACE": env}
				}

				command := []string{"run-task", "app", "echo"}

				if flag {
					command = append(command, "-v")
				}

				if configTrace != "" {
					if string(configTrace[0]) == "/" {
						configTrace = filepath.Join(tmpDir, configTrace)
					}
					session := helpers.CF("config", "--trace", configTrace)
					Eventually(session).Should(Exit(0))
				}

				session := helpers.CFWithEnv(envMap, command...)
				Eventually(session).Should(Exit(1))

				for _, filePath := range location {
					contents, err := ioutil.ReadFile(tmpDir + filePath)
					Expect(err).ToNot(HaveOccurred())

					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
					Expect(string(contents)).To(MatchRegexp("GET /v3/apps"))
					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))
					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
					Expect(string(contents)).To(MatchRegexp("POST /oauth/token"))
					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))

					stat, err := os.Stat(tmpDir + filePath)
					Expect(err).ToNot(HaveOccurred())

					if runtime.GOOS == "windows" {
						Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String()))
					} else {
						Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String()))
					}
				}
			},

			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false, []string{"/foo"}),

			Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", false, []string{"/foo"}),
			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true, []string{"/foo"}),

			Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", false, []string{"/foo"}),
			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true, []string{"/foo"}),

			Entry("CF_TRACE filepath: enables logging to file", "/foo", "", false, []string{"/foo"}),
			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true, []string{"/foo"}),
			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false, []string{"/foo"}),
			Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", false, []string{"/foo", "/bar"}),
			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true, []string{"/foo", "/bar"}),
		)
	})
})
<commit_msg>the verbose integration test should be testing against a redacted request body<commit_after>package isolated

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"

	helpers "code.cloudfoundry.org/cli/integration/helpers"
	"code.cloudfoundry.org/cli/util/configv3"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("Verbose", func() {
	Context("v2 legacy", func() {
		DescribeTable("displays verbose output",
			func(command func() *Session) {
				login := exec.Command("cf", "auth", "admin", "admin")
				loginSession, err := Start(login, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())
				Eventually(loginSession).Should(Exit(0))

				session := command()
				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("GET /v2/organizations"))
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Exit(0))
			},

			Entry("when the -v option is provided with additional command", func() *Session {
				return helpers.CF("-v", "orgs")
			}),

			Entry("when the CF_TRACE env variable is set", func() *Session {
				return helpers.CFWithEnv(map[string]string{"CF_TRACE": "true"}, "orgs")
			}),
		)
	})

	Context("v2 refactor", func() {
		DescribeTable("displays verbose output to terminal",
			func(env string, configTrace string, flag bool) {
				tmpDir, err := ioutil.TempDir("", "")
				defer os.RemoveAll(tmpDir)
				Expect(err).NotTo(HaveOccurred())

				setupCF(ReadOnlyOrg, ReadOnlySpace)

				var envMap map[string]string
				if env != "" {
					if string(env[0]) == "/" {
						env = filepath.Join(tmpDir, env)
					}
					envMap = map[string]string{"CF_TRACE": env}
				}

				// We use 'create-user' because it makes a request via the UAA client
				// and a request via the CC client, testing the logging wrapper in both
				// clients.
				randomUsername := helpers.RandomUsername()
				randomPassword := helpers.RandomPassword()
				command := []string{"create-user", randomUsername, randomPassword}

				if flag {
					command = append(command, "-v")
				}

				if configTrace != "" {
					if string(configTrace[0]) == "/" {
						configTrace = filepath.Join(tmpDir, configTrace)
					}
					session := helpers.CF("config", "--trace", configTrace)
					Eventually(session).Should(Exit(0))
				}

				session := helpers.CFWithEnv(envMap, command...)

				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("POST /Users"))
				Eventually(session).Should(Say("User-Agent: cf/[\\w.+]+ \\(%s; %s %s\\)", runtime.Version(), runtime.GOARCH, runtime.GOOS))
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("POST /v2/users"))
				Eventually(session).Should(Say("User-Agent: cf/[\\w.+]+ \\(%s; %s %s\\)", runtime.Version(), runtime.GOARCH, runtime.GOOS))
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Exit(0))
			},

			Entry("CF_TRACE true: enables verbose", "true", "", false),
			Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false),
			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo/bar", false),

			Entry("CF_TRACE false, '-v': enables verbose", "false", "", true),
			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo/bar", true),

			Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true),
			Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false),
			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo/bar", true),

			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo/bar", "", true),
			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo/bar", "true", false),
			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo/bar", "/baz", true),
		)

		DescribeTable("displays verbose output to multiple files",
			func(env string, configTrace string, flag bool, location []string) {
				tmpDir, err := ioutil.TempDir("", "")
				defer os.RemoveAll(tmpDir)
				Expect(err).NotTo(HaveOccurred())

				setupCF(ReadOnlyOrg, ReadOnlySpace)

				var envMap map[string]string
				if env != "" {
					if string(env[0]) == "/" {
						env = filepath.Join(tmpDir, env)
					}
					envMap = map[string]string{"CF_TRACE": env}
				}

				// We use 'create-user' because it makes a request via the UAA client
				// and a request via the CC client, testing the logging wrapper in both
				// clients.
				randomUsername := helpers.RandomUsername()
				randomPassword := helpers.RandomPassword()
				command := []string{"create-user", randomUsername, randomPassword}

				if flag {
					command = append(command, "-v")
				}

				if configTrace != "" {
					if string(configTrace[0]) == "/" {
						configTrace = filepath.Join(tmpDir, configTrace)
					}
					session := helpers.CF("config", "--trace", configTrace)
					Eventually(session).Should(Exit(0))
				}

				session := helpers.CFWithEnv(envMap, command...)
				Eventually(session).Should(Exit(0))

				for _, filePath := range location {
					contents, err := ioutil.ReadFile(tmpDir + filePath)
					Expect(err).ToNot(HaveOccurred())

					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
					Expect(string(contents)).To(MatchRegexp("POST /Users"))
					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))
					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
					Expect(string(contents)).To(MatchRegexp("POST /v2/users"))
					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))

					stat, err := os.Stat(tmpDir + filePath)
					Expect(err).ToNot(HaveOccurred())

					if runtime.GOOS == "windows" {
						Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String()))
					} else {
						Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String()))
					}
				}
			},

			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false, []string{"/foo"}),

			Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", false, []string{"/foo"}),
			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true, []string{"/foo"}),

			Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", false, []string{"/foo"}),
			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true, []string{"/foo"}),

			Entry("CF_TRACE filepath: enables logging to file", "/foo", "", false, []string{"/foo"}),
			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true, []string{"/foo"}),
			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false, []string{"/foo"}),
			Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", false, []string{"/foo", "/bar"}),
			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true, []string{"/foo", "/bar"}),
		)
	})

	Context("v3", func() {
		DescribeTable("displays verbose output to terminal",
			func(env string, configTrace string, flag bool) {
				tmpDir, err := ioutil.TempDir("", "")
				defer os.RemoveAll(tmpDir)
				Expect(err).NotTo(HaveOccurred())

				setupCF(ReadOnlyOrg, ReadOnlySpace)

				// Invalidate the access token to cause a token refresh in order to
				// test the call to the UAA.
				helpers.SetConfig(func(config *configv3.Config) {
					config.ConfigFile.AccessToken = fmt.Sprintf("%sfoo", config.ConfigFile.AccessToken)
				})

				var envMap map[string]string
				if env != "" {
					if string(env[0]) == "/" {
						env = filepath.Join(tmpDir, env)
					}
					envMap = map[string]string{"CF_TRACE": env}
				}

				command := []string{"run-task", "app", "echo"}

				if flag {
					command = append(command, "-v")
				}

				if configTrace != "" {
					if string(configTrace[0]) == "/" {
						configTrace = filepath.Join(tmpDir, configTrace)
					}
					session := helpers.CF("config", "--trace", configTrace)
					Eventually(session).Should(Exit(0))
				}

				session := helpers.CFWithEnv(envMap, command...)

				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("GET /v3/apps"))
				Eventually(session).Should(Say("User-Agent: cf/[\\w.+]+ \\(%s; %s %s\\)", runtime.Version(), runtime.GOARCH, runtime.GOOS))
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Say("REQUEST:"))
				Eventually(session).Should(Say("POST /oauth/token"))
				Eventually(session).Should(Say("User-Agent: cf/[\\w.+]+ \\(%s; %s %s\\)", runtime.Version(), runtime.GOARCH, runtime.GOOS))
				Eventually(session).Should(Say("\\[PRIVATE DATA HIDDEN\\]")) //This is required to test the previous line. If it fails, the previous matcher went too far.
				Eventually(session).Should(Say("RESPONSE:"))
				Eventually(session).Should(Exit(1))
			},

			Entry("CF_TRACE true: enables verbose", "true", "", false),
			Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false),
			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo/bar", false),

			Entry("CF_TRACE false, '-v': enables verbose", "false", "", true),
			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo/bar", true),

			Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true),
			Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false),
			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo/bar", true),

			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo/bar", "", true),
			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo/bar", "true", false),
			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo/bar", "/baz", true),
		)

		DescribeTable("displays verbose output to multiple files",
			func(env string, configTrace string, flag bool, location []string) {
				tmpDir, err := ioutil.TempDir("", "")
				defer os.RemoveAll(tmpDir)
				Expect(err).NotTo(HaveOccurred())

				setupCF(ReadOnlyOrg, ReadOnlySpace)

				// Invalidate the access token to cause a token refresh in order to
				// test the call to the UAA.
				helpers.SetConfig(func(config *configv3.Config) {
					config.ConfigFile.AccessToken = fmt.Sprintf("%sfoo", config.ConfigFile.AccessToken)
				})

				var envMap map[string]string
				if env != "" {
					if string(env[0]) == "/" {
						env = filepath.Join(tmpDir, env)
					}
					envMap = map[string]string{"CF_TRACE": env}
				}

				command := []string{"run-task", "app", "echo"}

				if flag {
					command = append(command, "-v")
				}

				if configTrace != "" {
					if string(configTrace[0]) == "/" {
						configTrace = filepath.Join(tmpDir, configTrace)
					}
					session := helpers.CF("config", "--trace", configTrace)
					Eventually(session).Should(Exit(0))
				}

				session := helpers.CFWithEnv(envMap, command...)
				Eventually(session).Should(Exit(1))

				for _, filePath := range location {
					contents, err := ioutil.ReadFile(tmpDir + filePath)
					Expect(err).ToNot(HaveOccurred())

					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
					Expect(string(contents)).To(MatchRegexp("GET /v3/apps"))
					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))
					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
					Expect(string(contents)).To(MatchRegexp("POST /oauth/token"))
					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))

					stat, err := os.Stat(tmpDir + filePath)
					Expect(err).ToNot(HaveOccurred())

					if runtime.GOOS == "windows" {
						Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String()))
					} else {
						Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String()))
					}
				}
			},

			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false, []string{"/foo"}),

			Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", false, []string{"/foo"}),
			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true, []string{"/foo"}),

			Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", false, []string{"/foo"}),
			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true, []string{"/foo"}),

			Entry("CF_TRACE filepath: enables logging to file", "/foo", "", false, []string{"/foo"}),
			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true, []string{"/foo"}),
			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false, []string{"/foo"}),
			Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", false, []string{"/foo", "/bar"}),
			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true, []string{"/foo", "/bar"}),
		)
	})
})
<|endoftext|>


<commit_before>package net

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"net"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	configutil "github.com/stuphlabs/pullcord/config/util"
)

func TestBasicTlsListenerType(t *testing.T) {
	b := new(BasicTlsListener)

	assert.Implements(
		t,
		(*net.Listener)(nil),
		b,
		"A BasicTlsListener should be a net.Listener, but this"+
			" BasicTlsListener has the wrong type.",
	)
}

func TestBasicTlsListenerConfig(t *testing.T) {
	test := configutil.ConfigTest{
		ResourceType: "basictlslistener",
		ListenerTest: true,
		SyntacticallyBad: []configutil.ConfigTestData{
			{
				Data:        ``,
				Explanation: "empty config",
			},
			{
				Data:        `42`,
				Explanation: "numeric config",
			},
			{
				Data:        `"test"`,
				Explanation: "string config",
			},
			{
				Data: `{
				}`,
				Explanation: "empty object",
			},
			{
				Data: `{
					"listener": null,
					"certgetter": null
				}`,
				Explanation: "bad protocol",
			},
			{
				Data: `{
					"listener": {
						"type": "testcertgetter",
						"data": null
					},
					"certgetter": {
						"type": "testcertgetter",
						"data": null
					}
				}`,
				Explanation: "bad listener",
			},
			{
				Data: `{
					"listener": {
						"type": "testlistener",
						"data": null
					},
					"certgetter": {
						"type": "testlistener",
						"data": null
					}
				}`,
				Explanation: "bad certgetter",
			},
		},
		Good: []configutil.ConfigTestData{
			{
				Data: `{
					"listener": {
						"type": "testlistener",
						"data": null
					},
					"certgetter": {
						"type": "testcertgetter",
						"data": null
					}
				}`,
				Explanation: "good config",
			},
		},
	}

	test.Run(t)
}

func TestBasicTlsListenerBehavior(t *testing.T) {
	nl, e := net.Listen("tcp", "127.0.0.1:0")
	assert.NoError(
		t,
		e,
		"Attempting to create a valid basic listener should not"+
			" produce an error, but an error was produced.",
	)
	assert.NotNil(
		t,
		nl,
		"Attempting to create a valid basic listener should produce"+
			" a non-nil listener, but a nil listener was produced.",
	)

	tlsCert, x509Cert, e := GenSelfSignedLocalhostCertificate(
		3 * time.Minute,
	)
	require.NoError(t, e, "Valid certificates are needed for testing.")

	bel := &BufferedEavesdropListener{
		Target: nl,
	}

	l := &BasicTlsListener{
		Listener:   bel,
		CertGetter: &TestCertificateGetter{Cert: tlsCert},
	}

	if l == nil {
		return
	}

	defer func() {
		err := l.Close()
		assert.NoError(
			t,
			err,
			"Attempting to close a basic listener should not"+
				" produce an error, but an error was produced.",
		)
	}()

	addr := l.Addr()
	assert.NotNil(
		t,
		addr,
		"Attempting to get the address from a basic listener should"+
			" return a non-nil address, but a nil address was returned.",
	)

	if addr == nil {
		return
	}

	expected := "testing"

	done := make(chan interface{})
	defer func(done <-chan interface{}) {
		<-done
	}(done)

	go func(
		t *testing.T,
		l *BasicTlsListener,
		bel *BufferedEavesdropListener,
		expected string,
		done chan<- interface{},
	) {
		defer func(done chan<- interface{}) {
			close(done)
		}(done)

		c, err := l.Accept()
		assert.NoError(
			t,
			err,
			"Attempting to accept a connection from a valid"+
				" basic listener should not produce an error, but an"+
				" error was produced.",
		)
		assert.NotNil(
			t,
			c,
			"Attempting to accept a connection from a valid"+
				" basic listener should produce a non-nil"+
				" connection, but a nil connection was produced.",
		)
		if c == nil {
			return
		}

		endToEndBuffer := new(bytes.Buffer)

		_, err = endToEndBuffer.ReadFrom(c)
		assert.NoError(
			t,
			err,
			"Attempting to read from an accepted connection that"+
				" came from a valid basic listener should not"+
				" produce an error, but an error was produced.",
		)

		actualEndToEndMsg := endToEndBuffer.String()
		assert.Equal(
			t,
			expected,
			actualEndToEndMsg,
			"Attempting to transmit data through a basic"+
				" listener should not result in alterred data, but"+
				" the actual data received was not identical to the"+
				" data expected to have been sent.",
		)

		actualTransportMsg := bel.Inbound.String()
		assert.NotEqual(
			t,
			expected,
			actualTransportMsg,
			"Transmitting data through a basic TLS listener"+
				" should not result in the original message"+
				" being sent in the clear of the raw"+
				" transport layer.",
		)
	}(t, l, bel, expected, done)

	certPool := x509.NewCertPool()
	certPool.AddCert(x509Cert)

	var c net.Conn
	c, e = tls.Dial(
		addr.Network(),
		addr.String(),
		&tls.Config{
			RootCAs: certPool,
		},
	)
	assert.NoError(
		t,
		e,
		"Attempting to connect as a client to a basic listener"+
			" should not produce an error, but an error was produced.",
	)
	assert.NotNil(
		t,
		c,
		"Attempting to connect as a client to a basic listener"+
			" should produce a non-nil connection, but a nil connection"+
			" was produced.",
	)

	if c == nil {
		return
	}

	defer func(t *testing.T, c net.Conn) {
		err := c.Close()
		assert.NoError(
			t,
			err,
			"Attempting to close a client connection to a basic"+
				" listener should not produce an error, but an error"+
				" was produced.",
		)
	}(t, c)

	_, e = c.Write([]byte(expected))
	assert.NoError(
		t,
		e,
		"Attempting to write to a client connection of a basic"+
			" listener should not produce an error, but an error was"+
			" produced.",
	)
}
<commit_msg>Missed capitalization errors in the test file.<commit_after>package net

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"net"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	configutil "github.com/stuphlabs/pullcord/config/util"
)

func TestBasicTLSListenerType(t *testing.T) {
	b := new(BasicTLSListener)

	assert.Implements(
		t,
		(*net.Listener)(nil),
		b,
		"A BasicTLSListener should be a net.Listener, but this"+
			" BasicTLSListener has the wrong type.",
	)
}

func TestBasicTLSListenerConfig(t *testing.T) {
	test := configutil.ConfigTest{
		ResourceType: "basictlslistener",
		ListenerTest: true,
		SyntacticallyBad: []configutil.ConfigTestData{
			{
				Data:        ``,
				Explanation: "empty config",
			},
			{
				Data:        `42`,
				Explanation: "numeric config",
			},
			{
				Data:        `"test"`,
				Explanation: "string config",
			},
			{
				Data: `{
				}`,
				Explanation: "empty object",
			},
			{
				Data: `{
					"listener": null,
					"certgetter": null
				}`,
				Explanation: "bad protocol",
			},
			{
				Data: `{
					"listener": {
						"type": "testcertgetter",
						"data": null
					},
					"certgetter": {
						"type": "testcertgetter",
						"data": null
					}
				}`,
				Explanation: "bad listener",
			},
			{
				Data: `{
					"listener": {
						"type": "testlistener",
						"data": null
					},
					"certgetter": {
						"type": "testlistener",
						"data": null
					}
				}`,
				Explanation: "bad certgetter",
			},
		},
		Good: []configutil.ConfigTestData{
			{
				Data: `{
					"listener": {
						"type": "testlistener",
						"data": null
					},
					"certgetter": {
						"type": "testcertgetter",
						"data": null
					}
				}`,
				Explanation: "good config",
			},
		},
	}

	test.Run(t)
}

func TestBasicTLSListenerBehavior(t *testing.T) {
	nl, e := net.Listen("tcp", "127.0.0.1:0")
	assert.NoError(
		t,
		e,
		"Attempting to create a valid basic listener should not"+
			" produce an error, but an error was produced.",
	)
	assert.NotNil(
		t,
		nl,
		"Attempting to create a valid basic listener should produce"+
			" a non-nil listener, but a nil listener was produced.",
	)

	tlsCert, x509Cert, e := GenSelfSignedLocalhostCertificate(
		3 * time.Minute,
	)
	require.NoError(t, e, "Valid certificates are needed for testing.")

	bel := &BufferedEavesdropListener{
		Target: nl,
	}

	l := &BasicTLSListener{
		Listener:   bel,
		CertGetter: &TestCertificateGetter{Cert: tlsCert},
	}

	if l == nil {
		return
	}

	defer func() {
		err := l.Close()
		assert.NoError(
			t,
			err,
			"Attempting to close a basic listener should not"+
				" produce an error, but an error was produced.",
		)
	}()

	addr := l.Addr()
	assert.NotNil(
		t,
		addr,
		"Attempting to get the address from a basic listener should"+
			" return a non-nil address, but a nil address was returned.",
	)

	if addr == nil {
		return
	}

	expected := "testing"

	done := make(chan interface{})
	defer func(done <-chan interface{}) {
		<-done
	}(done)

	go func(
		t *testing.T,
		l *BasicTLSListener,
		bel *BufferedEavesdropListener,
		expected string,
		done chan<- interface{},
	) {
		defer func(done chan<- interface{}) {
			close(done)
		}(done)

		c, err := l.Accept()
		assert.NoError(
			t,
			err,
			"Attempting to accept a connection from a valid"+
				" basic listener should not produce an error, but an"+
				" error was produced.",
		)
		assert.NotNil(
			t,
			c,
			"Attempting to accept a connection from a valid"+
				" basic listener should produce a non-nil"+
				" connection, but a nil connection was produced.",
		)
		if c == nil {
			return
		}

		endToEndBuffer := new(bytes.Buffer)

		_, err = endToEndBuffer.ReadFrom(c)
		assert.NoError(
			t,
			err,
			"Attempting to read from an accepted connection that"+
				" came from a valid basic listener should not"+
				" produce an error, but an error was produced.",
		)

		actualEndToEndMsg := endToEndBuffer.String()
		assert.Equal(
			t,
			expected,
			actualEndToEndMsg,
			"Attempting to transmit data through a basic"+
				" listener should not result in alterred data, but"+
				" the actual data received was not identical to the"+
				" data expected to have been sent.",
		)

		actualTransportMsg := bel.Inbound.String()
		assert.NotEqual(
			t,
			expected,
			actualTransportMsg,
			"Transmitting data through a basic TLS listener"+
				" should not result in the original message"+
				" being sent in the clear of the raw"+
				" transport layer.",
		)
	}(t, l, bel, expected, done)

	certPool := x509.NewCertPool()
	certPool.AddCert(x509Cert)

	var c net.Conn
	c, e = tls.Dial(
		addr.Network(),
		addr.String(),
		&tls.Config{
			RootCAs: certPool,
		},
	)
	assert.NoError(
		t,
		e,
		"Attempting to connect as a client to a basic listener"+
			" should not produce an error, but an error was produced.",
	)
	assert.NotNil(
		t,
		c,
		"Attempting to connect as a client to a basic listener"+
			" should produce a non-nil connection, but a nil connection"+
			" was produced.",
	)

	if c == nil {
		return
	}

	defer func(t *testing.T, c net.Conn) {
		err := c.Close()
		assert.NoError(
			t,
			err,
			"Attempting to close a client connection to a basic"+
				" listener should not produce an error, but an error"+
				" was produced.",
		)
	}(t, c)

	_, e = c.Write([]byte(expected))
	assert.NoError(
		t,
		e,
		"Attempting to write to a client connection of a basic"+
			" listener should not produce an error, but an error was"+
			" produced.",
	)
}
<|endoftext|>


<commit_before>package db

import (
	"fmt"
	"github.com/google/btree"
	turtle "github.com/gtfierro/hod/goraptor"
)

type QueryResult struct {
	Rows  []ResultMap
	Links []LinkResultMap
	Count int
}

func (qr QueryResult) Dump() {
	if len(qr.Rows) > 0 {
		for _, row := range qr.Rows {
			fmt.Println(row)
		}
		return
	}
	if len(qr.Links) > 0 {
		for _, link := range qr.Links {
			fmt.Println(link)
		}
		return
	}
	fmt.Println(qr.Count)
}

type ResultMap map[string]turtle.URI
type LinkResultMap map[turtle.URI]map[string]string

type ResultRow []turtle.URI

func (rr ResultRow) Less(than btree.Item) bool {
	row := than.(ResultRow)
	if len(rr) < len(row) {
		return true
	} else if len(row) < len(rr) {
		return false
	}
	before := false
	for idx, item := range rr {
		before = before || item.Value[0] < row[idx].Value[0]
	}
	return before
}
<commit_msg>fix regression for result rows<commit_after>package db

import (
	"fmt"
	"github.com/google/btree"
	turtle "github.com/gtfierro/hod/goraptor"
)

type QueryResult struct {
	Rows  []ResultMap
	Links []LinkResultMap
	Count int
}

func (qr QueryResult) Dump() {
	if len(qr.Rows) > 0 {
		for _, row := range qr.Rows {
			fmt.Println(row)
		}
		return
	}
	if len(qr.Links) > 0 {
		for _, link := range qr.Links {
			fmt.Println(link)
		}
		return
	}
	fmt.Println(qr.Count)
}

type ResultMap map[string]turtle.URI
type LinkResultMap map[turtle.URI]map[string]string

type ResultRow []turtle.URI

func (rr ResultRow) Less(than btree.Item) bool {
	row := than.(ResultRow)
	if len(rr) < len(row) {
		return true
	} else if len(row) < len(rr) {
		return false
	}
	before := false
	for idx, item := range rr {
		before = before || item.Value < row[idx].Value || item.Namespace < row[idx].Namespace
	}
	return before
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The cert-manager 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 listers

import (
	"runtime"
	"sync"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"k8s.io/apimachinery/pkg/labels"

	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
	cmlist "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1"
)

// MockCertificateRequestLister allows you to create a mock lister. This
// mock lister will make sure that the input parameters that the mock
// functions will be called with match the expected input parameters that
// you specified e.g., with CallList. The mock also makes sure the
// function(s) expected are actually called (or not called, depending).
//
// For example:
//
//   mock := MockCertificateRequestLister(t)
//   mock.
//       CallCertificateRequest("default").
//       CallGet("certificate-1").
//       ReturnGet(&cmapi.CertificateRequest{}, nil)
//
// will create a lister mock that expects the following call excatly once:
//
//   lister.CertificateRequest("default").Get("certificate-1")
//
// If you want to specify that no call should be made altogether, just give
// it the mock lister without any calls specified:
//
//   mock := MockCertificateRequestLister(t)
//
// Note that this mock lister is only able to account for either one or
// zero call to the Get and List functions, which is fine in our tests.
func MockCertificateRequestLister(t *testing.T) *CertificateRequestListerMock {
	return &CertificateRequestListerMock{t: t}
}

// The expectSelector is a label selector of the form:
//   "partition in (customerA, customerB),environment!=qa"
// as detailed in
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
func (mock *CertificateRequestListerMock) CallList(expectSelector string) *CertificateRequestListerMock {
	mock.t.Cleanup(func() {
		assert.True(mock.t, mock.gotListCalled, "lister.List was expected to be called but was not called")
	})
	mock.expectListCalled = true
	mock.expectListSelector = expectSelector
	return mock
}

func (mock *CertificateRequestListerMock) ReturnList(returnList []*cmapi.CertificateRequest, returnErr error) *CertificateRequestListerMock {
	mock.returnList = returnList
	mock.returnListErr = returnErr
	return mock
}

// This mock function does not have a matching ReturnCertificateRequests
// mock func. The return values of this mock function are already taken
// care of.
func (mock *CertificateRequestListerMock) CallCertificateRequests(expectNamespace string) *CertificateRequestListerNamespacedMock {
	mock.t.Cleanup(func() {
		assert.True(mock.t, mock.gotNamespaceCalled, "lister.CertificateRequests was expected to be called but was not called")
	})
	mock.expectNamespaceCalled = true
	mock.expectNamespace = expectNamespace
	mock.returnNamespaceLister = &CertificateRequestListerNamespacedMock{t: mock.t}
	return mock.returnNamespaceLister
}

// The expectSelector is a label selector of the form:
//   "partition in (customerA, customerB),environment!=qa"
// as detailed in
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
func (mock *CertificateRequestListerNamespacedMock) CallList(expectSelector string) *CertificateRequestListerNamespacedMock {
	mock.t.Cleanup(func() {
		assert.True(mock.t, mock.gotListCalled, "lister.CertificateRequest().List was expected to be called but was not called")
	})
	mock.expectListCalled = true
	mock.expectListSelector = expectSelector
	return mock
}

func (mock *CertificateRequestListerNamespacedMock) ReturnList(returnList []*cmapi.CertificateRequest, returnErr error) *CertificateRequestListerNamespacedMock {
	mock.returnList = returnList
	mock.returnListErr = returnErr
	return mock
}

func (mock *CertificateRequestListerNamespacedMock) CallGet(expectName string) *CertificateRequestListerNamespacedMock {
	mock.t.Cleanup(func() {
		assert.True(mock.t, mock.gotListCalled, "lister.CertificateRequest().Get was expected to be called but was not called")
	})
	mock.expectGetCalled = true
	mock.expectGetName = expectName
	return mock
}

func (mock *CertificateRequestListerNamespacedMock) ReturnGet(returnGet *cmapi.CertificateRequest, returnErr error) *CertificateRequestListerNamespacedMock {
	mock.returnGet = returnGet
	mock.returnGetErr = returnErr
	return mock
}

type CertificateRequestListerMock struct {
	t  *testing.T
	mu sync.Mutex

	expectNamespaceCalled, gotNamespaceCalled bool
	expectNamespace                           string
	returnNamespaceLister                     *CertificateRequestListerNamespacedMock

	expectListCalled, gotListCalled bool
	expectListSelector              string
	returnList                      []*cmapi.CertificateRequest
	returnListErr                   error
}

func (mock *CertificateRequestListerMock) CertificateRequests(gotNamespace string) cmlist.CertificateRequestNamespaceLister {
	mock.mu.Lock()
	defer mock.mu.Unlock()
	require.True(mock.t, mock.expectNamespaceCalled, curFuncName()+" not expected to be called")
	require.False(mock.t, mock.gotNamespaceCalled, curFuncName()+" already called once before")
	assert.Equal(mock.t, mock.expectNamespace, gotNamespace)
	mock.gotNamespaceCalled = true
	return mock.returnNamespaceLister
}

func (mock *CertificateRequestListerMock) List(gotLabel labels.Selector) (ret []*cmapi.CertificateRequest, err error) {
	mock.mu.Lock()
	defer mock.mu.Unlock()
	require.True(mock.t, mock.expectListCalled, curFuncName()+" not expected to be called")
	require.False(mock.t, mock.gotListCalled, curFuncName()+" already called once before")
	assert.Equal(mock.t, mock.expectListSelector, gotLabel.String())
	mock.gotListCalled = true
	return mock.returnList, mock.returnListErr
}

type CertificateRequestListerNamespacedMock struct {
	t  *testing.T
	mu sync.Mutex

	expectGetCalled, gotGetCalled bool
	expectGetName                 string
	returnGet                     *cmapi.CertificateRequest
	returnGetErr                  error

	expectListCalled, gotListCalled bool
	expectListSelector              string
	returnList                      []*cmapi.CertificateRequest
	returnListErr                   error
}

func (mock *CertificateRequestListerNamespacedMock) List(got labels.Selector) (ret []*cmapi.CertificateRequest, err error) {
	mock.mu.Lock()
	defer mock.mu.Unlock()
	require.NotNil(mock.t, mock.expectListCalled, curFuncName()+" not expected to be called")
	require.False(mock.t, mock.gotListCalled, curFuncName()+" already called once before")
	assert.Equal(mock.t, mock.expectListSelector, got.String())
	mock.gotListCalled = true
	return mock.returnList, mock.returnListErr
}

func (mock *CertificateRequestListerNamespacedMock) Get(gotName string) (cr *cmapi.CertificateRequest, e error) {
	mock.mu.Lock()
	defer mock.mu.Unlock()
	require.NotNil(mock.t, mock.expectGetCalled, curFuncName()+" not expected to be called")
	require.False(mock.t, mock.gotGetCalled, curFuncName()+" already called once before")
	assert.Equal(mock.t, mock.expectGetName, gotName)
	mock.gotGetCalled = true
	return nil, nil
}

func curFuncName() (fnName string) {
	pc, _, _, ok := runtime.Caller(1)
	if !ok {
		return "?"
	}

	fn := runtime.FuncForPC(pc)
	return fn.Name()
}
<commit_msg>DataForCertificate: tests: fix certificaterequest lister<commit_after>/*
Copyright 2020 The cert-manager 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 listers

import (
	"runtime"
	"sync"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"k8s.io/apimachinery/pkg/labels"

	cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
	cmlist "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1"
)

// MockCertificateRequestLister allows you to create a mock lister. This
// mock lister will make sure that the input parameters that the mock
// functions will be called with match the expected input parameters that
// you specified e.g., with CallList. The mock also makes sure the
// function(s) expected are actually called (or not called, depending).
//
// For example:
//
//   mock := MockCertificateRequestLister(t)
//   mock.
//       CallCertificateRequest("default").
//       CallGet("certificate-1").
//       ReturnGet(&cmapi.CertificateRequest{}, nil)
//
// will create a lister mock that expects the following call excatly once:
//
//   lister.CertificateRequest("default").Get("certificate-1")
//
// If you want to specify that no call should be made altogether, just give
// it the mock lister without any calls specified:
//
//   mock := MockCertificateRequestLister(t)
//
// Note that this mock lister is only able to account for either one or
// zero call to the Get and List functions, which is fine in our tests.
func MockCertificateRequestLister(t *testing.T) *CertificateRequestListerMock {
	return &CertificateRequestListerMock{t: t}
}

// The expectSelector is a label selector of the form:
//   "partition in (customerA, customerB),environment!=qa"
// as detailed in
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
func (mock *CertificateRequestListerMock) CallList(expectSelector string) *CertificateRequestListerMock {
	mock.t.Cleanup(func() {
		assert.True(mock.t, mock.gotListCalled, "lister.List was expected to be called but was not called")
	})
	mock.expectListCalled = true
	mock.expectListSelector = expectSelector
	return mock
}

func (mock *CertificateRequestListerMock) ReturnList(returnList []*cmapi.CertificateRequest, returnErr error) *CertificateRequestListerMock {
	mock.returnList = returnList
	mock.returnListErr = returnErr
	return mock
}

// This mock function does not have a matching ReturnCertificateRequests
// mock func. The return values of this mock function are already taken
// care of.
func (mock *CertificateRequestListerMock) CallCertificateRequests(expectNamespace string) *CertificateRequestListerNamespacedMock {
	mock.t.Cleanup(func() {
		assert.True(mock.t, mock.gotNamespaceCalled, "lister.CertificateRequests was expected to be called but was not called")
	})
	mock.expectNamespaceCalled = true
	mock.expectNamespace = expectNamespace
	mock.returnNamespaceLister = &CertificateRequestListerNamespacedMock{t: mock.t}
	return mock.returnNamespaceLister
}

// The expectSelector is a label selector of the form:
//   "partition in (customerA, customerB),environment!=qa"
// as detailed in
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
func (mock *CertificateRequestListerNamespacedMock) CallList(expectSelector string) *CertificateRequestListerNamespacedMock {
	mock.t.Cleanup(func() {
		assert.True(mock.t, mock.gotListCalled, "lister.CertificateRequest().List was expected to be called but was not called")
	})
	mock.expectListCalled = true
	mock.expectListSelector = expectSelector
	return mock
}

func (mock *CertificateRequestListerNamespacedMock) ReturnList(returnList []*cmapi.CertificateRequest, returnErr error) *CertificateRequestListerNamespacedMock {
	mock.returnList = returnList
	mock.returnListErr = returnErr
	return mock
}

func (mock *CertificateRequestListerNamespacedMock) CallGet(expectName string) *CertificateRequestListerNamespacedMock {
	mock.t.Cleanup(func() {
		assert.True(mock.t, mock.gotGetCalled, "lister.CertificateRequest().Get was expected to be called but was not called")
	})
	mock.expectGetCalled = true
	mock.expectGetName = expectName
	return mock
}

func (mock *CertificateRequestListerNamespacedMock) ReturnGet(returnGet *cmapi.CertificateRequest, returnErr error) *CertificateRequestListerNamespacedMock {
	mock.returnGet = returnGet
	mock.returnGetErr = returnErr
	return mock
}

type CertificateRequestListerMock struct {
	t  *testing.T
	mu sync.Mutex

	expectNamespaceCalled, gotNamespaceCalled bool
	expectNamespace                           string
	returnNamespaceLister                     *CertificateRequestListerNamespacedMock

	expectListCalled, gotListCalled bool
	expectListSelector              string
	returnList                      []*cmapi.CertificateRequest
	returnListErr                   error
}

func (mock *CertificateRequestListerMock) CertificateRequests(gotNamespace string) cmlist.CertificateRequestNamespaceLister {
	mock.mu.Lock()
	defer mock.mu.Unlock()
	require.True(mock.t, mock.expectNamespaceCalled, curFuncName()+" not expected to be called")
	require.False(mock.t, mock.gotNamespaceCalled, curFuncName()+" already called once before")
	assert.Equal(mock.t, mock.expectNamespace, gotNamespace)
	mock.gotNamespaceCalled = true
	return mock.returnNamespaceLister
}

func (mock *CertificateRequestListerMock) List(gotLabel labels.Selector) (ret []*cmapi.CertificateRequest, err error) {
	mock.mu.Lock()
	defer mock.mu.Unlock()
	require.True(mock.t, mock.expectListCalled, curFuncName()+" not expected to be called")
	require.False(mock.t, mock.gotListCalled, curFuncName()+" already called once before")
	assert.Equal(mock.t, mock.expectListSelector, gotLabel.String())
	mock.gotListCalled = true
	return mock.returnList, mock.returnListErr
}

type CertificateRequestListerNamespacedMock struct {
	t  *testing.T
	mu sync.Mutex

	expectGetCalled, gotGetCalled bool
	expectGetName                 string
	returnGet                     *cmapi.CertificateRequest
	returnGetErr                  error

	expectListCalled, gotListCalled bool
	expectListSelector              string
	returnList                      []*cmapi.CertificateRequest
	returnListErr                   error
}

func (mock *CertificateRequestListerNamespacedMock) List(got labels.Selector) (ret []*cmapi.CertificateRequest, err error) {
	mock.mu.Lock()
	defer mock.mu.Unlock()
	require.NotNil(mock.t, mock.expectListCalled, curFuncName()+" not expected to be called")
	require.False(mock.t, mock.gotListCalled, curFuncName()+" already called once before")
	assert.Equal(mock.t, mock.expectListSelector, got.String())
	mock.gotListCalled = true
	return mock.returnList, mock.returnListErr
}

func (mock *CertificateRequestListerNamespacedMock) Get(gotName string) (cr *cmapi.CertificateRequest, e error) {
	mock.mu.Lock()
	defer mock.mu.Unlock()
	require.NotNil(mock.t, mock.expectGetCalled, curFuncName()+" not expected to be called")
	require.False(mock.t, mock.gotGetCalled, curFuncName()+" already called once before")
	assert.Equal(mock.t, mock.expectGetName, gotName)
	mock.gotGetCalled = true
	return nil, nil
}

func curFuncName() (fnName string) {
	pc, _, _, ok := runtime.Caller(1)
	if !ok {
		return "?"
	}

	fn := runtime.FuncForPC(pc)
	return fn.Name()
}
<|endoftext|>