<commit_before>package main

import (
	"io/ioutil"
	"github.com/lonelycode/tykcommon"
	"code.google.com/p/go-uuid/uuid"
	"strings"
	"fmt"
	"encoding/json"
)

var CommandModeOptions = map[string]bool{
	"--import-blueprint": true,
	"--create-api": true,
	"--org-id": true,
	"--upstream-target": true,
	"--as-mock": true,
	"--for-api": true,
	"--as-version": true,
}

// ./tyk --import-blueprint=blueprint.json --create-api --org-id=<id> --upstream-target="http://widgets.com/api/"`
func HandleCommandModeArgs(arguments map[string]interface{}) {

	if arguments["--import-blueprint"] != nil {
		handleBluePrintMode(arguments)
	}

}

func handleBluePrintMode(arguments map[string]interface{}) {
	doCreate := arguments["--create-api"]
	inputFile := arguments["--import-blueprint"]
	if doCreate == true {
		upstreamVal := arguments["--upstream-target"]
		orgId := arguments["--org-id"]
		if upstreamVal != nil && orgId != nil {
			// Create the API with the blueprint
			bp, err := bluePrintLoadFile(inputFile.(string))
			if err != nil {
				log.Error("File load error: ", err)
				return
			}

			def, dErr := createDefFromBluePrint(bp, orgId.(string), upstreamVal.(string), arguments["--as-mock"].(bool))
			if dErr != nil {
				log.Error("Failed to create API Defintition from file")
				return
			}

			printDef(def)
			return
		}

		log.Error("No upstream target or org ID defined, these are both required")

	} else {
		// Different branch, here we need an API Definition to modify
		forApiPath := arguments["--for-api"]
		if forApiPath == nil {
			log.Error("If ading to an API, the path to the defintiton must be listed")
			return
		}

		versionName := arguments["--as-version"]
		if versionName == nil {
			log.Error("No version defined for this import operation, please set an import ID using the --as-version flag")
			return
		}

		thisDefFromFile, fileErr := apiDefLoadFile(forApiPath.(string))
		if fileErr != nil {
			log.Error("failed to load and decode file data for API Definition: ", fileErr)
			return
		}

		bp, err := bluePrintLoadFile(inputFile.(string))
		if err != nil {
			log.Error("File load error: ", err)
			return
		}

		versionData, err := bp.ConvertIntoApiVersion(arguments["--as-mock"].(bool))
		if err != nil {
			log.Error("onversion into API Def failed: ", err)
		}

		insertErr := bp.InsertIntoAPIDefinitionAsVersion(versionData, &thisDefFromFile, versionName.(string))
		if insertErr != nil {
			log.Error("Insertion failed: ", insertErr)
			return
		}

		printDef(&thisDefFromFile)

	}
}

func printDef(def *tykcommon.APIDefinition) {
	asJson, err := json.MarshalIndent(def, "", "    ")
	if err != nil {
		log.Error("Marshalling failed: ", err)
	}

	// The id attribute is for BSON only and breaks the parser if it's empty, cull it here.
	fixed := strings.Replace(string(asJson), "    \"id\": \"\",", "", 1)
	fmt.Printf(fixed)
}

func createDefFromBluePrint(bp *BluePrintAST, orgId, upstreamURL string, as_mock bool) (*tykcommon.APIDefinition, error) {
	thisAD := tykcommon.APIDefinition{}
	thisAD.Name = bp.Name
	thisAD.Active = true
	thisAD.UseKeylessAccess = true
	thisAD.APIID = uuid.NewUUID().String()
	thisAD.OrgID = orgId
	thisAD.VersionDefinition.Key = "version"
	thisAD.VersionDefinition.Location  ="header"
	thisAD.VersionData.Versions = make(map[string]tykcommon.VersionInfo)
	thisAD.Proxy.ListenPath = "/" + thisAD.APIID + "/"
	thisAD.Proxy.StripListenPath = true
	thisAD.Proxy.TargetURL = upstreamURL

	versionData, err := bp.ConvertIntoApiVersion(as_mock)
	if err != nil {
		log.Error("onversion into API Def failed: ", err)
	}

	bp.InsertIntoAPIDefinitionAsVersion(versionData, &thisAD, strings.Trim(bp.Name, " "))

	return &thisAD, nil
}

func bluePrintLoadFile(filePath string) (*BluePrintAST, error) {
	thisBlueprint, astErr := GetImporterForSource(ApiaryBluePrint)

	if astErr != nil {
		log.Error("Couldn't get blueprint importer: ", astErr)
		return thisBlueprint.(*BluePrintAST), astErr
	}

	bluePrintFileData, err := ioutil.ReadFile(filePath)

	if err != nil {
		log.Error("Couldn't load blueprint file: ", err)
		return thisBlueprint.(*BluePrintAST), err
	}

	readErr := thisBlueprint.ReadString(string(bluePrintFileData))
	if readErr != nil {
		log.Error("Failed to decode object")
		return thisBlueprint.(*BluePrintAST), readErr
	}

	return thisBlueprint.(*BluePrintAST), nil
}

func apiDefLoadFile(filePath string) (tykcommon.APIDefinition, error) {
	thisDef := tykcommon.APIDefinition{}

	defFileData, err := ioutil.ReadFile(filePath)

	if err != nil {
		log.Error("Couldn't load API Definition file: ", err)
		return thisDef, err
	}

	jsonErr := json.Unmarshal(defFileData, &thisDef)
	if jsonErr != nil {
		log.Error("Failed to unmarshal the JSON definition: ", jsonErr)
		return thisDef, jsonErr
	}

	return thisDef, nil
}
<commit_msg>Versioning forced on insert<commit_after>package main

import (
	"io/ioutil"
	"github.com/lonelycode/tykcommon"
	"code.google.com/p/go-uuid/uuid"
	"strings"
	"fmt"
	"encoding/json"
)

var CommandModeOptions = map[string]bool{
	"--import-blueprint": true,
	"--create-api": true,
	"--org-id": true,
	"--upstream-target": true,
	"--as-mock": true,
	"--for-api": true,
	"--as-version": true,
}

// ./tyk --import-blueprint=blueprint.json --create-api --org-id=<id> --upstream-target="http://widgets.com/api/"`
func HandleCommandModeArgs(arguments map[string]interface{}) {

	if arguments["--import-blueprint"] != nil {
		handleBluePrintMode(arguments)
	}

}

func handleBluePrintMode(arguments map[string]interface{}) {
	doCreate := arguments["--create-api"]
	inputFile := arguments["--import-blueprint"]
	if doCreate == true {
		upstreamVal := arguments["--upstream-target"]
		orgId := arguments["--org-id"]
		if upstreamVal != nil && orgId != nil {
			// Create the API with the blueprint
			bp, err := bluePrintLoadFile(inputFile.(string))
			if err != nil {
				log.Error("File load error: ", err)
				return
			}

			def, dErr := createDefFromBluePrint(bp, orgId.(string), upstreamVal.(string), arguments["--as-mock"].(bool))
			if dErr != nil {
				log.Error("Failed to create API Defintition from file")
				return
			}

			printDef(def)
			return
		}

		log.Error("No upstream target or org ID defined, these are both required")

	} else {
		// Different branch, here we need an API Definition to modify
		forApiPath := arguments["--for-api"]
		if forApiPath == nil {
			log.Error("If ading to an API, the path to the defintiton must be listed")
			return
		}

		versionName := arguments["--as-version"]
		if versionName == nil {
			log.Error("No version defined for this import operation, please set an import ID using the --as-version flag")
			return
		}

		thisDefFromFile, fileErr := apiDefLoadFile(forApiPath.(string))
		if fileErr != nil {
			log.Error("failed to load and decode file data for API Definition: ", fileErr)
			return
		}

		bp, err := bluePrintLoadFile(inputFile.(string))
		if err != nil {
			log.Error("File load error: ", err)
			return
		}

		versionData, err := bp.ConvertIntoApiVersion(arguments["--as-mock"].(bool))
		if err != nil {
			log.Error("onversion into API Def failed: ", err)
		}

		insertErr := bp.InsertIntoAPIDefinitionAsVersion(versionData, &thisDefFromFile, versionName.(string))
		if insertErr != nil {
			log.Error("Insertion failed: ", insertErr)
			return
		}

		printDef(&thisDefFromFile)

	}
}

func printDef(def *tykcommon.APIDefinition) {
	asJson, err := json.MarshalIndent(def, "", "    ")
	if err != nil {
		log.Error("Marshalling failed: ", err)
	}

	// The id attribute is for BSON only and breaks the parser if it's empty, cull it here.
	fixed := strings.Replace(string(asJson), "    \"id\": \"\",", "", 1)
	fmt.Printf(fixed)
}

func createDefFromBluePrint(bp *BluePrintAST, orgId, upstreamURL string, as_mock bool) (*tykcommon.APIDefinition, error) {
	thisAD := tykcommon.APIDefinition{}
	thisAD.Name = bp.Name
	thisAD.Active = true
	thisAD.UseKeylessAccess = true
	thisAD.APIID = uuid.NewUUID().String()
	thisAD.OrgID = orgId
	thisAD.VersionDefinition.Key = "version"
	thisAD.VersionDefinition.Location  ="header"
	thisAD.VersionData.Versions = make(map[string]tykcommon.VersionInfo)
	thisAD.VersionData.NotVersioned = false
	thisAD.Proxy.ListenPath = "/" + thisAD.APIID + "/"
	thisAD.Proxy.StripListenPath = true
	thisAD.Proxy.TargetURL = upstreamURL

	versionData, err := bp.ConvertIntoApiVersion(as_mock)
	if err != nil {
		log.Error("onversion into API Def failed: ", err)
	}

	bp.InsertIntoAPIDefinitionAsVersion(versionData, &thisAD, strings.Trim(bp.Name, " "))

	return &thisAD, nil
}

func bluePrintLoadFile(filePath string) (*BluePrintAST, error) {
	thisBlueprint, astErr := GetImporterForSource(ApiaryBluePrint)

	if astErr != nil {
		log.Error("Couldn't get blueprint importer: ", astErr)
		return thisBlueprint.(*BluePrintAST), astErr
	}

	bluePrintFileData, err := ioutil.ReadFile(filePath)

	if err != nil {
		log.Error("Couldn't load blueprint file: ", err)
		return thisBlueprint.(*BluePrintAST), err
	}

	readErr := thisBlueprint.ReadString(string(bluePrintFileData))
	if readErr != nil {
		log.Error("Failed to decode object")
		return thisBlueprint.(*BluePrintAST), readErr
	}

	return thisBlueprint.(*BluePrintAST), nil
}

func apiDefLoadFile(filePath string) (tykcommon.APIDefinition, error) {
	thisDef := tykcommon.APIDefinition{}

	defFileData, err := ioutil.ReadFile(filePath)

	if err != nil {
		log.Error("Couldn't load API Definition file: ", err)
		return thisDef, err
	}

	jsonErr := json.Unmarshal(defFileData, &thisDef)
	if jsonErr != nil {
		log.Error("Failed to unmarshal the JSON definition: ", jsonErr)
		return thisDef, jsonErr
	}

	return thisDef, nil
}
<|endoftext|>


<commit_before>package circuitry

import (
	"errors"
	"testing"
)

type alwaysFail struct{}

func (c *alwaysFail) Name() string {
	return "always-fail"
}

func (c *alwaysFail) Run() (interface{}, error) {
	return nil, errors.New("fail")
}

func (c *alwaysFail) Fallback() interface{} {
	return "fallback"
}

type alwaysSucceed struct{}

func (c *alwaysSucceed) Name() string {
	return "always-succeed"
}

func (c *alwaysSucceed) Run() (interface{}, error) {
	return "success", nil
}

func (c *alwaysSucceed) Fallback() interface{} {
	return "fallback"
}

func TestAlwaysFail(t *testing.T) {
	p := &Panel{}
	v := p.Execute(&alwaysFail{})
	if v != "fallback" {
		t.Error("didn't execute fallback")
	}
}

func TestAlwaysSucceed(t *testing.T) {
	p := &Panel{}
	v := p.Execute(&alwaysSucceed{})
	if v != "success" {
		t.Error("the fallback was executed")
	}
}
<commit_msg>proper command tests<commit_after>package circuitry

import (
	"errors"
	"testing"
	"time"
)

type alwaysFail struct{}

func (c *alwaysFail) Name() string {
	return "always-fail"
}

func (c *alwaysFail) Run() (interface{}, error) {
	return nil, errors.New("fail")
}

func (c *alwaysFail) Fallback() interface{} {
	return "fallback"
}

type alwaysSucceed struct{}

func (c *alwaysSucceed) Name() string {
	return "always-succeed"
}

func (c *alwaysSucceed) Run() (interface{}, error) {
	return "success", nil
}

func (c *alwaysSucceed) Fallback() interface{} {
	return "fallback"
}

func TestAlwaysFail(t *testing.T) {
	b := NewBreaker(40, 0, time.Minute, window())
	v := Execute(&alwaysFail{}, b)
	if v != "fallback" {
		t.Error("didn't execute fallback")
	}
}

func TestAlwaysSucceed(t *testing.T) {
	b := NewBreaker(40, 0, time.Minute, window())
	v := Execute(&alwaysSucceed{}, b)
	if v != "success" {
		t.Error("the fallback was executed")
	}
}
<|endoftext|>


<commit_before>package commands

import (
	"log"
	"os"
)

func ConfigEnvVars(direction string) {
	if os.Getenv("CONSUL_SERVER") != "" {
		ConsulServer = os.Getenv("CONSUL_SERVER")
		log.Print(direction, ": Using CONSUL_SERVER ENV variable.")
	}
	if os.Getenv("CONSUL_TOKEN") != "" {
		Token = os.Getenv("CONSUL_TOKEN")
		log.Print(direction, ": Using CONSUL_TOKEN ENV variable.")
	}
	if os.Getenv("DATADOG_HOST") != "" {
		DatadogHost = os.Getenv("DATADOG_HOST")
		log.Print(direction, ": Using DATADOG_HOST ENV variable.")
	}
}
<commit_msg>Add DATADOG keys as env vars if you use -E true<commit_after>package commands

import (
	"log"
	"os"
)

func ConfigEnvVars(direction string) {
	if os.Getenv("CONSUL_SERVER") != "" {
		ConsulServer = os.Getenv("CONSUL_SERVER")
		log.Print(direction, ": Using CONSUL_SERVER ENV variable.")
	}
	if os.Getenv("CONSUL_TOKEN") != "" {
		Token = os.Getenv("CONSUL_TOKEN")
		log.Print(direction, ": Using CONSUL_TOKEN ENV variable.")
	}
	if os.Getenv("DATADOG_HOST") != "" {
		DatadogHost = os.Getenv("DATADOG_HOST")
		log.Print(direction, ": Using DATADOG_HOST ENV variable.")
	}
	if os.Getenv("DATADOG_API_KEY") != "" {
		DatadogAPIKey = os.Getenv("DATADOG_API_KEY")
		log.Print(direction, ": Using DATADOG_API_KEY ENV variable.")
	}
	if os.Getenv("DATADOG_APP_KEY") != "" {
		DatadogAPPKey = os.Getenv("DATADOG_APP_KEY")
		log.Print(direction, ": Using DATADOG_APP_KEY ENV variable.")
	}
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"os"
	"strings"

	"rollcage/core"

	"github.com/cactus/cobra"
	"github.com/cactus/gologit"
)

var force bool = false

func destroyCmdRun(cmd *cobra.Command, args []string) {
	// requires root
	if !core.IsRoot() {
		gologit.Fatalf("Must be root to destroy\n")
	}

	jailUUID := core.GetJailUUIDByTagOrUUID(args[0])
	if jailUUID == "" {
		gologit.Fatalf("No jail found by '%s'\n", args[0])
	}

	jailpath := core.GetJailByTagOrUUID(jailUUID)
	if jailpath == "" {
		gologit.Fatalf("No jail found by '%s'\n", args[0])
	}

	jid := string(core.JlsMust("-j", fmt.Sprintf("ioc-%s", jailUUID), "jid"))
	if jid != "" {
		gologit.Fatalf("Jail is running. Shutdown first.\n")
	}

	propertyList := []string{
		"mountpoint",
		"org.freebsd.iocage:type",
		"org.freebsd.iocage:tag",
	}

	lines := core.SplitOutput(core.ZFSMust("list", "-H", "-o", strings.Join(propertyList, ","), jailpath))
	if len(lines) < 1 {
		gologit.Fatalf("No output from property fetch\n")
	}

	prop_mountpoint := removeDash(lines[0][0])
	prop_type := removeDash(lines[0][1])
	prop_tag := removeDash(lines[0][2])

	if prop_type != "thickjail" {
		gologit.Fatalf("Type is not thickjail.\nI don't know how to handle this yet.\nGiving up!")
	}

	fmt.Print("Are you sure [yN]? :")
	var response string
	_, err := fmt.Scanln(&response)
	if err != nil {
		gologit.Fatalf("%s", err)
	}

	if !force {
		response = strings.ToLower(strings.TrimSpace(response))
		if len(response) != 1 || response[0] != 'y' {
			return
		}
	}

	fmt.Printf("Destroying: %s (%s)\n", jailUUID, prop_tag)
	core.ZFSMust("destroy", "-fr", jailpath)
	os.RemoveAll(prop_mountpoint)
}

func init() {
	cmd := &cobra.Command{
		Use:   "destroy UUID|TAG",
		Short: "destroy jail",
		Long:  "destroy jail identified by UUID or TAG.",
		Run:   destroyCmdRun,
		PreRun: func(cmd *cobra.Command, args []string) {
			if len(args) == 0 {
				gologit.Fatalln("Required UUID|TAG not provided")
			}
		},
	}
	cmd.Flags().BoolVarP(
		&force, "force", "f",
		false, "attempt to remove jail without prompting for confirmation")
	RootCmd.AddCommand(cmd)
}
<commit_msg>fixes<commit_after>package commands

import (
	"bytes"
	"fmt"
	"os"
	"strings"

	"rollcage/core"

	"github.com/cactus/cobra"
	"github.com/cactus/gologit"
)

var force bool = false

func destroyCmdRun(cmd *cobra.Command, args []string) {
	// requires root
	if !core.IsRoot() {
		gologit.Fatalf("Must be root to destroy\n")
	}

	var jailpath, jailUUID string
	for _, line := range core.SplitOutput(core.ZFSMust(
		"list", "-H", "-d", "1",
		"-o", "name,org.freebsd.iocage:host_hostuuid,org.freebsd.iocage:tag",
		core.GetJailsPath())) {
		if line[2] == args[0] || strings.HasPrefix(line[1], args[0]) {
			jailpath = line[0]
			jailUUID = line[1]
			break
		}
	}
	if jailpath == "" {
		gologit.Fatalf("Jail '%s' not found!\n", args[0])
	}

	out, err := core.Jls("-j", fmt.Sprintf("ioc-%s", jailUUID), "jid")
	if err == nil && !bytes.Contains(out, []byte("not found")) {
		gologit.Fatalf("Jail is running. Shutdown first.\n")
	}

	propertyList := []string{
		"mountpoint",
		"org.freebsd.iocage:type",
		"org.freebsd.iocage:tag",
	}

	lines := core.SplitOutput(core.ZFSMust("list", "-H", "-o", strings.Join(propertyList, ","), jailpath))
	if len(lines) < 1 {
		gologit.Fatalf("No output from property fetch\n")
	}

	prop_mountpoint := removeDash(lines[0][0])
	prop_type := removeDash(lines[0][1])
	prop_tag := removeDash(lines[0][2])

	if prop_type != "thickjail" {
		gologit.Fatalf("Type is not thickjail.\nI don't know how to handle this yet.\nGiving up!")
	}

	fmt.Print("Are you sure [yN]? :")
	var response string
	_, err = fmt.Scanln(&response)
	if err != nil {
		gologit.Fatalf("%s", err)
	}

	if !force {
		response = strings.ToLower(strings.TrimSpace(response))
		if len(response) != 1 || response[0] != 'y' {
			return
		}
	}

	fmt.Printf("Destroying: %s (%s)\n", jailUUID, prop_tag)
	core.ZFSMust("destroy", "-fr", jailpath)
	os.RemoveAll(prop_mountpoint)
}

func init() {
	cmd := &cobra.Command{
		Use:   "destroy UUID|TAG",
		Short: "destroy jail",
		Long:  "destroy jail identified by UUID or TAG.",
		Run:   destroyCmdRun,
		PreRun: func(cmd *cobra.Command, args []string) {
			if len(args) == 0 {
				gologit.Fatalln("Required UUID|TAG not provided")
			}
		},
	}
	cmd.Flags().BoolVarP(
		&force, "force", "f",
		false, "attempt to remove jail without prompting for confirmation")
	RootCmd.AddCommand(cmd)
}
<|endoftext|>


<commit_before>package encoders

import (
	"code.cloudfoundry.org/lager"
	"github.com/snickers/hls/segmenter"
	"github.com/snickers/snickers/db"
	"github.com/snickers/snickers/types"
)

// HLSEncode function is responsible for encoding adaptive bitrate outputs
func HLSEncode(logger lager.Logger, dbInstance db.Storage, jobID string) error {
	log := logger.Session("hls-encode")
	log.Info("started", lager.Data{"job": jobID})
	defer log.Info("finished")

	job, err := dbInstance.RetrieveJob(jobID)
	if err != nil {
		return err
	}

	job.Details = "0%"
	job.Status = types.JobEncoding
	dbInstance.UpdateJob(job.ID, job)

	hlsConfig := buildHLSConfig(job)
	return segmenter.Segment(hlsConfig)
}

func buildHLSConfig(job types.Job) segmenter.HLSConfig {
	return segmenter.HLSConfig{
		SourceFile:      job.LocalSource,
		FileBase:        job.LocalDestination,
		SegmentDuration: 10,
	}
}
<commit_msg>encoders/hls: set job progress to 100% after segmenting<commit_after>package encoders

import (
	"code.cloudfoundry.org/lager"
	"github.com/snickers/hls/segmenter"
	"github.com/snickers/snickers/db"
	"github.com/snickers/snickers/types"
)

// HLSEncode function is responsible for encoding adaptive bitrate outputs
func HLSEncode(logger lager.Logger, dbInstance db.Storage, jobID string) error {
	log := logger.Session("hls-encode")
	log.Info("started", lager.Data{"job": jobID})
	defer log.Info("finished")

	job, err := dbInstance.RetrieveJob(jobID)
	if err != nil {
		return err
	}

	job.Details = "0%"
	job.Status = types.JobEncoding
	dbInstance.UpdateJob(job.ID, job)

	hlsConfig := buildHLSConfig(job)
	err = segmenter.Segment(hlsConfig)
	job.Details = "100%"
	job.Status = types.JobFinished
	return err
}

func buildHLSConfig(job types.Job) segmenter.HLSConfig {
	return segmenter.HLSConfig{
		SourceFile:      job.LocalSource,
		FileBase:        job.LocalDestination,
		SegmentDuration: 10,
	}
}
<|endoftext|>


<commit_before>package engine

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	sm "github.com/Ariemeth/frame-assault-2/engine/shaderManager"
	tm "github.com/Ariemeth/frame-assault-2/engine/textureManager"
	"github.com/go-gl/gl/v4.1-core/gl"
	"github.com/go-gl/mathgl/mgl32"
)

const (
	// ModelSrcDir is the expected location of textures
	ModelSrcDir = "assets/models/"
)

// Model represents a physical entity
type Model struct {
	id                string
	data              vertexData
	shaders           sm.ShaderManager
	textures          tm.TextureManager
	angle             float64
	model             mgl32.Mat4
	camera            mgl32.Mat4
	projection        mgl32.Mat4
	modelUniform      int32
	projectionUniform int32
	cameraUniform     int32
	textureUniform    int32
	vao               uint32
	currentProgram    uint32
	currentTexture    uint32
}

// NewModel creates a new model.
func NewModel(id string, shaders sm.ShaderManager, textures tm.TextureManager, shader string) *Model {
	m := Model{
		id:         id,
		shaders:    shaders,
		textures:   textures,
		angle:      0.0,
		model:      mgl32.Ident4(),
		camera:     mgl32.Ident4(),
		projection: mgl32.Ident4(),
	}

	return &m
}

// ID returns the id of the model.
func (m Model) ID() string {
	return m.id
}

// Update updates the model
func (m *Model) Update(elapsed float64) {
	m.angle += elapsed
	m.model = mgl32.HomogRotate3D(float32(m.angle), mgl32.Vec3{0, 1, 0})
}

// Render renders the model
func (m *Model) Render() {

	gl.UseProgram(m.currentProgram)
	gl.UniformMatrix4fv(m.modelUniform, 1, false, &m.model[0])

	gl.BindVertexArray(m.vao)

	gl.ActiveTexture(gl.TEXTURE0)

	texture, isLoaded := m.textures.GetTexture(m.data.TextureFile)

	if isLoaded {
		gl.BindTexture(gl.TEXTURE_2D, texture)
	} else {
		if m.data.TextureFile != "" {
			fmt.Printf("Unable to load texture %s", m.data.TextureFile)
		}
	}

	if m.data.Indexed {
		gl.DrawElements(gl.TRIANGLE_FAN, int32(len(m.data.Indices)), gl.UNSIGNED_INT, gl.PtrOffset(0))
	} else {
		gl.DrawArrays(gl.TRIANGLES, 0, int32(len(m.data.Verts))/m.data.VertSize)
	}

	gl.BindVertexArray(0)
}

// Load loads and sets up the model
func (m *Model) Load(fileName string) {

	m.LoadFile(fileName)

	shader := sm.Shader{VertSrcFile: m.data.VertShaderFile, FragSrcFile: m.data.FragShaderFile, Name: fmt.Sprintf("%s:%s", m.data.VertShaderFile, m.data.FragShaderFile)}
	program, err := m.shaders.LoadProgram(shader, false)
	if err != nil {
		return
	}
	m.currentProgram = program

	gl.UseProgram(m.currentProgram)

	m.projection = mgl32.Perspective(mgl32.DegToRad(45.0), float32(windowWidth)/windowHeight, 0.1, 10.0)
	m.projectionUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("projection\x00"))
	gl.UniformMatrix4fv(m.projectionUniform, 1, false, &m.projection[0])

	m.camera = mgl32.LookAtV(mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0})
	m.cameraUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("camera\x00"))
	gl.UniformMatrix4fv(m.cameraUniform, 1, false, &m.camera[0])

	m.modelUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("model\x00"))
	gl.UniformMatrix4fv(m.modelUniform, 1, false, &m.model[0])

	m.textureUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("tex\x00"))
	gl.Uniform1i(m.textureUniform, 0)

	gl.BindFragDataLocation(m.currentProgram, 0, gl.Str("outputColor\x00"))

	// Load the texture
	m.textures.LoadTexture(m.data.TextureFile, m.data.TextureFile)

	// Configure the vertex data
	gl.GenVertexArrays(1, &m.vao)
	gl.BindVertexArray(m.vao)

	var vbo uint32
	gl.GenBuffers(1, &vbo)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(m.data.Verts)*4, gl.Ptr(m.data.Verts), gl.STATIC_DRAW)

	vertAttrib := uint32(gl.GetAttribLocation(m.currentProgram, gl.Str("vert\x00")))
	gl.EnableVertexAttribArray(vertAttrib)
	gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, m.data.VertSize*4, gl.PtrOffset(0)) // 4:number of bytes in a float32

	texCoordAttrib := uint32(gl.GetAttribLocation(m.currentProgram, gl.Str("vertTexCoord\x00")))
	gl.EnableVertexAttribArray(texCoordAttrib)
	gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, true, m.data.VertSize*4, gl.PtrOffset(3*4)) // 4:number of bytes in a float32

	if m.data.Indexed {
		var indices uint32
		gl.GenBuffers(1, &indices)
		gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices)
		gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(m.data.Indices)*4, gl.Ptr(m.data.Indices), gl.STATIC_DRAW)
	}

	gl.BindVertexArray(0)
}

// LoadFile loads a model's data from a json file.
func (m *Model) LoadFile(fileName string) {
	data, err := ioutil.ReadFile(fmt.Sprintf("%s%s", ModelSrcDir, fileName))
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	json.Unmarshal(data, &m.data)
}

type vertexData struct {
	Indexed        bool      `json:"indexed"`
	Verts          []float32 `json:"verts"`
	Indices        []uint32  `json:"indices"`
	VertSize       int32     `json:"vertSize"`
	TextureFile    string    `json:"textureFile"`
	FragShaderFile string    `json:"fragShaderFile"`
	VertShaderFile string    `json:"vertShaderFile"`
}
<commit_msg>put the log output from failing to load the texture into a go routine<commit_after>package engine

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	sm "github.com/Ariemeth/frame-assault-2/engine/shaderManager"
	tm "github.com/Ariemeth/frame-assault-2/engine/textureManager"
	"github.com/go-gl/gl/v4.1-core/gl"
	"github.com/go-gl/mathgl/mgl32"
)

const (
	// ModelSrcDir is the expected location of textures
	ModelSrcDir = "assets/models/"
)

// Model represents a physical entity
type Model struct {
	id                string
	data              vertexData
	shaders           sm.ShaderManager
	textures          tm.TextureManager
	angle             float64
	model             mgl32.Mat4
	camera            mgl32.Mat4
	projection        mgl32.Mat4
	modelUniform      int32
	projectionUniform int32
	cameraUniform     int32
	textureUniform    int32
	vao               uint32
	currentProgram    uint32
	currentTexture    uint32
}

// NewModel creates a new model.
func NewModel(id string, shaders sm.ShaderManager, textures tm.TextureManager, shader string) *Model {
	m := Model{
		id:         id,
		shaders:    shaders,
		textures:   textures,
		angle:      0.0,
		model:      mgl32.Ident4(),
		camera:     mgl32.Ident4(),
		projection: mgl32.Ident4(),
	}

	return &m
}

// ID returns the id of the model.
func (m Model) ID() string {
	return m.id
}

// Update updates the model
func (m *Model) Update(elapsed float64) {
	m.angle += elapsed
	m.model = mgl32.HomogRotate3D(float32(m.angle), mgl32.Vec3{0, 1, 0})
}

// Render renders the model
func (m *Model) Render() {

	gl.UseProgram(m.currentProgram)
	gl.UniformMatrix4fv(m.modelUniform, 1, false, &m.model[0])

	gl.BindVertexArray(m.vao)

	gl.ActiveTexture(gl.TEXTURE0)

	texture, isLoaded := m.textures.GetTexture(m.data.TextureFile)

	if isLoaded {
		gl.BindTexture(gl.TEXTURE_2D, texture)
	} else {
		if m.data.TextureFile != "" {
			go fmt.Printf("Unable to load texture %s", m.data.TextureFile)
		}
	}

	if m.data.Indexed {
		gl.DrawElements(gl.TRIANGLE_FAN, int32(len(m.data.Indices)), gl.UNSIGNED_INT, gl.PtrOffset(0))
	} else {
		gl.DrawArrays(gl.TRIANGLES, 0, int32(len(m.data.Verts))/m.data.VertSize)
	}

	gl.BindVertexArray(0)
}

// Load loads and sets up the model
func (m *Model) Load(fileName string) {

	m.LoadFile(fileName)

	shader := sm.Shader{VertSrcFile: m.data.VertShaderFile, FragSrcFile: m.data.FragShaderFile, Name: fmt.Sprintf("%s:%s", m.data.VertShaderFile, m.data.FragShaderFile)}
	program, err := m.shaders.LoadProgram(shader, false)
	if err != nil {
		return
	}
	m.currentProgram = program

	gl.UseProgram(m.currentProgram)

	m.projection = mgl32.Perspective(mgl32.DegToRad(45.0), float32(windowWidth)/windowHeight, 0.1, 10.0)
	m.projectionUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("projection\x00"))
	gl.UniformMatrix4fv(m.projectionUniform, 1, false, &m.projection[0])

	m.camera = mgl32.LookAtV(mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0})
	m.cameraUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("camera\x00"))
	gl.UniformMatrix4fv(m.cameraUniform, 1, false, &m.camera[0])

	m.modelUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("model\x00"))
	gl.UniformMatrix4fv(m.modelUniform, 1, false, &m.model[0])

	m.textureUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("tex\x00"))
	gl.Uniform1i(m.textureUniform, 0)

	gl.BindFragDataLocation(m.currentProgram, 0, gl.Str("outputColor\x00"))

	// Load the texture
	m.textures.LoadTexture(m.data.TextureFile, m.data.TextureFile)

	// Configure the vertex data
	gl.GenVertexArrays(1, &m.vao)
	gl.BindVertexArray(m.vao)

	var vbo uint32
	gl.GenBuffers(1, &vbo)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(m.data.Verts)*4, gl.Ptr(m.data.Verts), gl.STATIC_DRAW)

	vertAttrib := uint32(gl.GetAttribLocation(m.currentProgram, gl.Str("vert\x00")))
	gl.EnableVertexAttribArray(vertAttrib)
	gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, m.data.VertSize*4, gl.PtrOffset(0)) // 4:number of bytes in a float32

	texCoordAttrib := uint32(gl.GetAttribLocation(m.currentProgram, gl.Str("vertTexCoord\x00")))
	gl.EnableVertexAttribArray(texCoordAttrib)
	gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, true, m.data.VertSize*4, gl.PtrOffset(3*4)) // 4:number of bytes in a float32

	if m.data.Indexed {
		var indices uint32
		gl.GenBuffers(1, &indices)
		gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices)
		gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(m.data.Indices)*4, gl.Ptr(m.data.Indices), gl.STATIC_DRAW)
	}

	gl.BindVertexArray(0)
}

// LoadFile loads a model's data from a json file.
func (m *Model) LoadFile(fileName string) {
	data, err := ioutil.ReadFile(fmt.Sprintf("%s%s", ModelSrcDir, fileName))
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	json.Unmarshal(data, &m.data)
}

type vertexData struct {
	Indexed        bool      `json:"indexed"`
	Verts          []float32 `json:"verts"`
	Indices        []uint32  `json:"indices"`
	VertSize       int32     `json:"vertSize"`
	TextureFile    string    `json:"textureFile"`
	FragShaderFile string    `json:"fragShaderFile"`
	VertShaderFile string    `json:"vertShaderFile"`
}
<|endoftext|>


<commit_before>package metrics

import (
	"testing"

	types "github.com/openfaas/faas-provider/types"
	"github.com/prometheus/client_golang/prometheus"
	dto "github.com/prometheus/client_model/go"
)

type metricResult struct {
	value  float64
	labels map[string]string
}

func labels2Map(labels []*dto.LabelPair) map[string]string {
	res := map[string]string{}
	for _, l := range labels {
		res[l.GetName()] = l.GetValue()
	}
	return res
}

func readGauge(g prometheus.Metric) metricResult {
	m := &dto.Metric{}
	g.Write(m)

	return metricResult{
		value:  m.GetGauge().GetValue(),
		labels: labels2Map(m.GetLabel()),
	}
}

func Test_Describe_DescribesThePrometheusMetrics(t *testing.T) {
	metricsOptions := BuildMetricsOptions()
	exporter := NewExporter(metricsOptions, nil, "openfaas-fn")

	ch := make(chan *prometheus.Desc)
	// defer close(ch)

	go exporter.Describe(ch)

	d := <-ch
	expectedGatewayFunctionInvocationDesc := `Desc{fqName: "gateway_function_invocation_total", help: "Function metrics", constLabels: {}, variableLabels: [function_name code]}`
	actualGatewayFunctionInvocationDesc := d.String()
	if expectedGatewayFunctionInvocationDesc != actualGatewayFunctionInvocationDesc {
		t.Errorf("Want\n%s\ngot\n%s", expectedGatewayFunctionInvocationDesc, actualGatewayFunctionInvocationDesc)
	}

	d = <-ch
	expectedGatewayFunctionsHistogramDesc := `Desc{fqName: "gateway_functions_seconds", help: "Function time taken", constLabels: {}, variableLabels: [function_name]}`
	actualGatewayFunctionsHistogramDesc := d.String()
	if expectedGatewayFunctionsHistogramDesc != actualGatewayFunctionsHistogramDesc {
		t.Errorf("Want\n%s\ngot\n%s", expectedGatewayFunctionsHistogramDesc, actualGatewayFunctionsHistogramDesc)
	}

	d = <-ch
	expectedServiceReplicasGaugeDesc := `Desc{fqName: "gateway_service_count", help: "Current count of replicas for function", constLabels: {}, variableLabels: [function_name]}`
	actualServiceReplicasGaugeDesc := d.String()
	if expectedServiceReplicasGaugeDesc != actualServiceReplicasGaugeDesc {
		t.Errorf("Want\n%s\ngot\n%s", expectedServiceReplicasGaugeDesc, actualServiceReplicasGaugeDesc)
	}

}

func Test_Collect_CollectsTheNumberOfReplicasOfAService(t *testing.T) {
	metricsOptions := BuildMetricsOptions()
	exporter := NewExporter(metricsOptions, nil, "openfaas-fn")

	expectedService := types.FunctionStatus{
		Name:     "function_with_two_replica",
		Replicas: 2,
	}

	exporter.services = []types.FunctionStatus{expectedService}

	ch := make(chan prometheus.Metric)
	defer close(ch)

	go exporter.Collect(ch)

	g := (<-ch).(prometheus.Gauge)
	result := readGauge(g)
	if expectedService.Name != result.labels["function_name"] {
		t.Errorf("Want %s, got %s", expectedService.Name, result.labels["function_name"])
	}
	expectedReplicas := float64(expectedService.Replicas)
	if expectedReplicas != result.value {
		t.Errorf("Want %f, got %f", expectedReplicas, result.value)
	}
}
<commit_msg>Deference channel<commit_after>package metrics

import (
	"testing"

	types "github.com/openfaas/faas-provider/types"
	"github.com/prometheus/client_golang/prometheus"
	dto "github.com/prometheus/client_model/go"
)

type metricResult struct {
	value  float64
	labels map[string]string
}

func labels2Map(labels []*dto.LabelPair) map[string]string {
	res := map[string]string{}
	for _, l := range labels {
		res[l.GetName()] = l.GetValue()
	}
	return res
}

func readGauge(g prometheus.Metric) metricResult {
	m := &dto.Metric{}
	g.Write(m)

	return metricResult{
		value:  m.GetGauge().GetValue(),
		labels: labels2Map(m.GetLabel()),
	}
}

func Test_Describe_DescribesThePrometheusMetrics(t *testing.T) {
	metricsOptions := BuildMetricsOptions()
	exporter := NewExporter(metricsOptions, nil, "openfaas-fn")

	ch := make(chan *prometheus.Desc)
	// defer close(ch)

	go exporter.Describe(ch)

	d := <-ch
	expectedGatewayFunctionInvocationDesc := `Desc{fqName: "gateway_function_invocation_total", help: "Function metrics", constLabels: {}, variableLabels: [function_name code]}`
	actualGatewayFunctionInvocationDesc := d.String()
	if expectedGatewayFunctionInvocationDesc != actualGatewayFunctionInvocationDesc {
		t.Errorf("Want\n%s\ngot\n%s", expectedGatewayFunctionInvocationDesc, actualGatewayFunctionInvocationDesc)
	}

	d = <-ch
	expectedGatewayFunctionsHistogramDesc := `Desc{fqName: "gateway_functions_seconds", help: "Function time taken", constLabels: {}, variableLabels: [function_name]}`
	actualGatewayFunctionsHistogramDesc := d.String()
	if expectedGatewayFunctionsHistogramDesc != actualGatewayFunctionsHistogramDesc {
		t.Errorf("Want\n%s\ngot\n%s", expectedGatewayFunctionsHistogramDesc, actualGatewayFunctionsHistogramDesc)
	}

	d = <-ch
	expectedServiceReplicasGaugeDesc := `Desc{fqName: "gateway_service_count", help: "Current count of replicas for function", constLabels: {}, variableLabels: [function_name]}`
	actualServiceReplicasGaugeDesc := d.String()
	if expectedServiceReplicasGaugeDesc != actualServiceReplicasGaugeDesc {
		t.Errorf("Want\n%s\ngot\n%s", expectedServiceReplicasGaugeDesc, actualServiceReplicasGaugeDesc)
	}

}

func Test_Collect_CollectsTheNumberOfReplicasOfAService(t *testing.T) {
	metricsOptions := BuildMetricsOptions()
	exporter := NewExporter(metricsOptions, nil, "openfaas-fn")

	expectedService := types.FunctionStatus{
		Name:     "function_with_two_replica",
		Replicas: 2,
	}

	exporter.services = []types.FunctionStatus{expectedService}

	ch := make(chan prometheus.Metric)

	go exporter.Collect(ch)

	g := (<-ch).(prometheus.Gauge)
	result := readGauge(g)
	if expectedService.Name != result.labels["function_name"] {
		t.Errorf("Want %s, got %s", expectedService.Name, result.labels["function_name"])
	}
	expectedReplicas := float64(expectedService.Replicas)
	if expectedReplicas != result.value {
		t.Errorf("Want %f, got %f", expectedReplicas, result.value)
	}
	ch = nil

}
<|endoftext|>


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

package core

import (
	"bytes"
	"sync"

	"github.com/pingcap/kvproto/pkg/metapb"
	"github.com/pingcap/log"
	"github.com/pingcap/pd/v4/pkg/slice"
	"github.com/pingcap/pd/v4/server/schedule/storelimit"
	"go.uber.org/zap"
)

// BasicCluster provides basic data member and interface for a tikv cluster.
type BasicCluster struct {
	sync.RWMutex
	Stores  *StoresInfo
	Regions *RegionsInfo
}

// NewBasicCluster creates a BasicCluster.
func NewBasicCluster() *BasicCluster {
	return &BasicCluster{
		Stores:  NewStoresInfo(),
		Regions: NewRegionsInfo(),
	}
}

// GetStores returns all Stores in the cluster.
func (bc *BasicCluster) GetStores() []*StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetStores()
}

// GetMetaStores gets a complete set of metapb.Store.
func (bc *BasicCluster) GetMetaStores() []*metapb.Store {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetMetaStores()
}

// GetStore searches for a store by ID.
func (bc *BasicCluster) GetStore(storeID uint64) *StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetStore(storeID)
}

// GetRegion searches for a region by ID.
func (bc *BasicCluster) GetRegion(regionID uint64) *RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetRegion(regionID)
}

// GetRegions gets all RegionInfo from regionMap.
func (bc *BasicCluster) GetRegions() []*RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetRegions()
}

// GetMetaRegions gets a set of metapb.Region from regionMap.
func (bc *BasicCluster) GetMetaRegions() []*metapb.Region {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetMetaRegions()
}

// GetStoreRegions gets all RegionInfo with a given storeID.
func (bc *BasicCluster) GetStoreRegions(storeID uint64) []*RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreRegions(storeID)
}

// GetRegionStores returns all Stores that contains the region's peer.
func (bc *BasicCluster) GetRegionStores(region *RegionInfo) []*StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	var Stores []*StoreInfo
	for id := range region.GetStoreIds() {
		if store := bc.Stores.GetStore(id); store != nil {
			Stores = append(Stores, store)
		}
	}
	return Stores
}

// GetFollowerStores returns all Stores that contains the region's follower peer.
func (bc *BasicCluster) GetFollowerStores(region *RegionInfo) []*StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	var Stores []*StoreInfo
	for id := range region.GetFollowers() {
		if store := bc.Stores.GetStore(id); store != nil {
			Stores = append(Stores, store)
		}
	}
	return Stores
}

// GetLeaderStore returns all Stores that contains the region's leader peer.
func (bc *BasicCluster) GetLeaderStore(region *RegionInfo) *StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetStore(region.GetLeader().GetStoreId())
}

// GetAdjacentRegions returns region's info that is adjacent with specific region.
func (bc *BasicCluster) GetAdjacentRegions(region *RegionInfo) (*RegionInfo, *RegionInfo) {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetAdjacentRegions(region)
}

// BlockStore stops balancer from selecting the store.
func (bc *BasicCluster) BlockStore(storeID uint64) error {
	bc.Lock()
	defer bc.Unlock()
	return bc.Stores.BlockStore(storeID)
}

// UnblockStore allows balancer to select the store.
func (bc *BasicCluster) UnblockStore(storeID uint64) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.UnblockStore(storeID)
}

// AttachAvailableFunc attaches an available function to a specific store.
func (bc *BasicCluster) AttachAvailableFunc(storeID uint64, limitType storelimit.Type, f func() bool) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.AttachAvailableFunc(storeID, limitType, f)
}

// UpdateStoreStatus updates the information of the store.
func (bc *BasicCluster) UpdateStoreStatus(storeID uint64, leaderCount int, regionCount int, pendingPeerCount int, leaderSize int64, regionSize int64) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.UpdateStoreStatus(storeID, leaderCount, regionCount, pendingPeerCount, leaderSize, regionSize)
}

const randomRegionMaxRetry = 10

// RandFollowerRegion returns a random region that has a follower on the store.
func (bc *BasicCluster) RandFollowerRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo {
	bc.RLock()
	regions := bc.Regions.RandFollowerRegions(storeID, ranges, randomRegionMaxRetry)
	bc.RUnlock()
	return bc.selectRegion(regions, opts...)
}

// RandLeaderRegion returns a random region that has leader on the store.
func (bc *BasicCluster) RandLeaderRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo {
	bc.RLock()
	regions := bc.Regions.RandLeaderRegions(storeID, ranges, randomRegionMaxRetry)
	bc.RUnlock()
	return bc.selectRegion(regions, opts...)
}

// RandPendingRegion returns a random region that has a pending peer on the store.
func (bc *BasicCluster) RandPendingRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo {
	bc.RLock()
	regions := bc.Regions.RandPendingRegions(storeID, ranges, randomRegionMaxRetry)
	bc.RUnlock()
	return bc.selectRegion(regions, opts...)
}

// RandLearnerRegion returns a random region that has a learner peer on the store.
func (bc *BasicCluster) RandLearnerRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo {
	bc.RLock()
	regions := bc.Regions.RandLearnerRegions(storeID, ranges, randomRegionMaxRetry)
	bc.RUnlock()
	return bc.selectRegion(regions, opts...)
}

func (bc *BasicCluster) selectRegion(regions []*RegionInfo, opts ...RegionOption) *RegionInfo {
	for _, r := range regions {
		if r == nil {
			break
		}
		if slice.AllOf(opts, func(i int) bool { return opts[i](r) }) {
			return r
		}
	}
	return nil
}

// GetRegionCount gets the total count of RegionInfo of regionMap.
func (bc *BasicCluster) GetRegionCount() int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetRegionCount()
}

// GetStoreCount returns the total count of storeInfo.
func (bc *BasicCluster) GetStoreCount() int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetStoreCount()
}

// GetStoreRegionCount gets the total count of a store's leader and follower RegionInfo by storeID.
func (bc *BasicCluster) GetStoreRegionCount(storeID uint64) int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreLeaderCount(storeID) + bc.Regions.GetStoreFollowerCount(storeID) + bc.Regions.GetStoreLearnerCount(storeID)
}

// GetStoreLeaderCount get the total count of a store's leader RegionInfo.
func (bc *BasicCluster) GetStoreLeaderCount(storeID uint64) int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreLeaderCount(storeID)
}

// GetStoreFollowerCount get the total count of a store's follower RegionInfo.
func (bc *BasicCluster) GetStoreFollowerCount(storeID uint64) int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreFollowerCount(storeID)
}

// GetStorePendingPeerCount gets the total count of a store's region that includes pending peer.
func (bc *BasicCluster) GetStorePendingPeerCount(storeID uint64) int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStorePendingPeerCount(storeID)
}

// GetStoreLeaderRegionSize get total size of store's leader regions.
func (bc *BasicCluster) GetStoreLeaderRegionSize(storeID uint64) int64 {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreLeaderRegionSize(storeID)
}

// GetStoreRegionSize get total size of store's regions.
func (bc *BasicCluster) GetStoreRegionSize(storeID uint64) int64 {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreLeaderRegionSize(storeID) + bc.Regions.GetStoreFollowerRegionSize(storeID) + bc.Regions.GetStoreLearnerRegionSize(storeID)
}

// GetAverageRegionSize returns the average region approximate size.
func (bc *BasicCluster) GetAverageRegionSize() int64 {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetAverageRegionSize()
}

// PutStore put a store.
func (bc *BasicCluster) PutStore(store *StoreInfo) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.SetStore(store)
}

// DeleteStore deletes a store.
func (bc *BasicCluster) DeleteStore(store *StoreInfo) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.DeleteStore(store)
}

// TakeStore returns the point of the origin StoreInfo with the specified storeID.
func (bc *BasicCluster) TakeStore(storeID uint64) *StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.TakeStore(storeID)
}

// PreCheckPutRegion checks if the region is valid to put.
func (bc *BasicCluster) PreCheckPutRegion(region *RegionInfo) (*RegionInfo, error) {
	bc.RLock()
	origin := bc.Regions.GetRegion(region.GetID())
	if origin == nil || !bytes.Equal(origin.GetStartKey(), region.GetStartKey()) || !bytes.Equal(origin.GetEndKey(), region.GetEndKey()) {
		for _, item := range bc.Regions.GetOverlaps(region) {
			if region.GetRegionEpoch().GetVersion() < item.GetRegionEpoch().GetVersion() {
				bc.RUnlock()
				return nil, ErrRegionIsStale(region.GetMeta(), item.GetMeta())
			}
		}
	}
	bc.RUnlock()
	if origin == nil {
		return nil, nil
	}
	r := region.GetRegionEpoch()
	o := origin.GetRegionEpoch()
	// Region meta is stale, return an error.
	if r.GetVersion() < o.GetVersion() || r.GetConfVer() < o.GetConfVer() {
		return origin, ErrRegionIsStale(region.GetMeta(), origin.GetMeta())
	}
	return origin, nil
}

// PutRegion put a region.
func (bc *BasicCluster) PutRegion(region *RegionInfo) []*RegionInfo {
	bc.Lock()
	defer bc.Unlock()
	return bc.Regions.SetRegion(region)
}

// CheckAndPutRegion checks if the region is valid to put,if valid then put.
func (bc *BasicCluster) CheckAndPutRegion(region *RegionInfo) []*RegionInfo {
	origin, err := bc.PreCheckPutRegion(region)
	if err != nil {
		log.Warn("region is stale", zap.Error(err), zap.Stringer("origin", origin.GetMeta()))
		// return the state region to delete.
		return []*RegionInfo{region}
	}
	return bc.PutRegion(region)
}

// RemoveRegion removes RegionInfo from regionTree and regionMap.
func (bc *BasicCluster) RemoveRegion(region *RegionInfo) {
	bc.Lock()
	defer bc.Unlock()
	bc.Regions.RemoveRegion(region)
}

// SearchRegion searches RegionInfo from regionTree.
func (bc *BasicCluster) SearchRegion(regionKey []byte) *RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.SearchRegion(regionKey)
}

// SearchPrevRegion searches previous RegionInfo from regionTree.
func (bc *BasicCluster) SearchPrevRegion(regionKey []byte) *RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.SearchPrevRegion(regionKey)
}

// ScanRange scans regions intersecting [start key, end key), returns at most
// `limit` regions. limit <= 0 means no limit.
func (bc *BasicCluster) ScanRange(startKey, endKey []byte, limit int) []*RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.ScanRange(startKey, endKey, limit)
}

// GetOverlaps returns the regions which are overlapped with the specified region range.
func (bc *BasicCluster) GetOverlaps(region *RegionInfo) []*RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetOverlaps(region)
}

// RegionSetInformer provides access to a shared informer of regions.
type RegionSetInformer interface {
	GetRegionCount() int
	RandFollowerRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo
	RandLeaderRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo
	RandLearnerRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo
	RandPendingRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo
	GetAverageRegionSize() int64
	GetStoreRegionCount(storeID uint64) int
	GetRegion(id uint64) *RegionInfo
	GetAdjacentRegions(region *RegionInfo) (*RegionInfo, *RegionInfo)
	ScanRegions(startKey, endKey []byte, limit int) []*RegionInfo
}

// StoreSetInformer provides access to a shared informer of stores.
type StoreSetInformer interface {
	GetStores() []*StoreInfo
	GetStore(id uint64) *StoreInfo

	GetRegionStores(region *RegionInfo) []*StoreInfo
	GetFollowerStores(region *RegionInfo) []*StoreInfo
	GetLeaderStore(region *RegionInfo) *StoreInfo
}

// StoreSetController is used to control stores' status.
type StoreSetController interface {
	BlockStore(id uint64) error
	UnblockStore(id uint64)

	AttachAvailableFunc(id uint64, limitType storelimit.Type, f func() bool)
}

// KeyRange is a key range.
type KeyRange struct {
	StartKey []byte `json:"start-key"`
	EndKey   []byte `json:"end-key"`
}

// NewKeyRange create a KeyRange with the given start key and end key.
func NewKeyRange(startKey, endKey string) KeyRange {
	return KeyRange{
		StartKey: []byte(startKey),
		EndKey:   []byte(endKey),
	}
}
<commit_msg>core: adjust log level (#2456)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package core

import (
	"bytes"
	"sync"

	"github.com/pingcap/kvproto/pkg/metapb"
	"github.com/pingcap/log"
	"github.com/pingcap/pd/v4/pkg/slice"
	"github.com/pingcap/pd/v4/server/schedule/storelimit"
	"go.uber.org/zap"
)

// BasicCluster provides basic data member and interface for a tikv cluster.
type BasicCluster struct {
	sync.RWMutex
	Stores  *StoresInfo
	Regions *RegionsInfo
}

// NewBasicCluster creates a BasicCluster.
func NewBasicCluster() *BasicCluster {
	return &BasicCluster{
		Stores:  NewStoresInfo(),
		Regions: NewRegionsInfo(),
	}
}

// GetStores returns all Stores in the cluster.
func (bc *BasicCluster) GetStores() []*StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetStores()
}

// GetMetaStores gets a complete set of metapb.Store.
func (bc *BasicCluster) GetMetaStores() []*metapb.Store {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetMetaStores()
}

// GetStore searches for a store by ID.
func (bc *BasicCluster) GetStore(storeID uint64) *StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetStore(storeID)
}

// GetRegion searches for a region by ID.
func (bc *BasicCluster) GetRegion(regionID uint64) *RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetRegion(regionID)
}

// GetRegions gets all RegionInfo from regionMap.
func (bc *BasicCluster) GetRegions() []*RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetRegions()
}

// GetMetaRegions gets a set of metapb.Region from regionMap.
func (bc *BasicCluster) GetMetaRegions() []*metapb.Region {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetMetaRegions()
}

// GetStoreRegions gets all RegionInfo with a given storeID.
func (bc *BasicCluster) GetStoreRegions(storeID uint64) []*RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreRegions(storeID)
}

// GetRegionStores returns all Stores that contains the region's peer.
func (bc *BasicCluster) GetRegionStores(region *RegionInfo) []*StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	var Stores []*StoreInfo
	for id := range region.GetStoreIds() {
		if store := bc.Stores.GetStore(id); store != nil {
			Stores = append(Stores, store)
		}
	}
	return Stores
}

// GetFollowerStores returns all Stores that contains the region's follower peer.
func (bc *BasicCluster) GetFollowerStores(region *RegionInfo) []*StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	var Stores []*StoreInfo
	for id := range region.GetFollowers() {
		if store := bc.Stores.GetStore(id); store != nil {
			Stores = append(Stores, store)
		}
	}
	return Stores
}

// GetLeaderStore returns all Stores that contains the region's leader peer.
func (bc *BasicCluster) GetLeaderStore(region *RegionInfo) *StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetStore(region.GetLeader().GetStoreId())
}

// GetAdjacentRegions returns region's info that is adjacent with specific region.
func (bc *BasicCluster) GetAdjacentRegions(region *RegionInfo) (*RegionInfo, *RegionInfo) {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetAdjacentRegions(region)
}

// BlockStore stops balancer from selecting the store.
func (bc *BasicCluster) BlockStore(storeID uint64) error {
	bc.Lock()
	defer bc.Unlock()
	return bc.Stores.BlockStore(storeID)
}

// UnblockStore allows balancer to select the store.
func (bc *BasicCluster) UnblockStore(storeID uint64) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.UnblockStore(storeID)
}

// AttachAvailableFunc attaches an available function to a specific store.
func (bc *BasicCluster) AttachAvailableFunc(storeID uint64, limitType storelimit.Type, f func() bool) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.AttachAvailableFunc(storeID, limitType, f)
}

// UpdateStoreStatus updates the information of the store.
func (bc *BasicCluster) UpdateStoreStatus(storeID uint64, leaderCount int, regionCount int, pendingPeerCount int, leaderSize int64, regionSize int64) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.UpdateStoreStatus(storeID, leaderCount, regionCount, pendingPeerCount, leaderSize, regionSize)
}

const randomRegionMaxRetry = 10

// RandFollowerRegion returns a random region that has a follower on the store.
func (bc *BasicCluster) RandFollowerRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo {
	bc.RLock()
	regions := bc.Regions.RandFollowerRegions(storeID, ranges, randomRegionMaxRetry)
	bc.RUnlock()
	return bc.selectRegion(regions, opts...)
}

// RandLeaderRegion returns a random region that has leader on the store.
func (bc *BasicCluster) RandLeaderRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo {
	bc.RLock()
	regions := bc.Regions.RandLeaderRegions(storeID, ranges, randomRegionMaxRetry)
	bc.RUnlock()
	return bc.selectRegion(regions, opts...)
}

// RandPendingRegion returns a random region that has a pending peer on the store.
func (bc *BasicCluster) RandPendingRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo {
	bc.RLock()
	regions := bc.Regions.RandPendingRegions(storeID, ranges, randomRegionMaxRetry)
	bc.RUnlock()
	return bc.selectRegion(regions, opts...)
}

// RandLearnerRegion returns a random region that has a learner peer on the store.
func (bc *BasicCluster) RandLearnerRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo {
	bc.RLock()
	regions := bc.Regions.RandLearnerRegions(storeID, ranges, randomRegionMaxRetry)
	bc.RUnlock()
	return bc.selectRegion(regions, opts...)
}

func (bc *BasicCluster) selectRegion(regions []*RegionInfo, opts ...RegionOption) *RegionInfo {
	for _, r := range regions {
		if r == nil {
			break
		}
		if slice.AllOf(opts, func(i int) bool { return opts[i](r) }) {
			return r
		}
	}
	return nil
}

// GetRegionCount gets the total count of RegionInfo of regionMap.
func (bc *BasicCluster) GetRegionCount() int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetRegionCount()
}

// GetStoreCount returns the total count of storeInfo.
func (bc *BasicCluster) GetStoreCount() int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.GetStoreCount()
}

// GetStoreRegionCount gets the total count of a store's leader and follower RegionInfo by storeID.
func (bc *BasicCluster) GetStoreRegionCount(storeID uint64) int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreLeaderCount(storeID) + bc.Regions.GetStoreFollowerCount(storeID) + bc.Regions.GetStoreLearnerCount(storeID)
}

// GetStoreLeaderCount get the total count of a store's leader RegionInfo.
func (bc *BasicCluster) GetStoreLeaderCount(storeID uint64) int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreLeaderCount(storeID)
}

// GetStoreFollowerCount get the total count of a store's follower RegionInfo.
func (bc *BasicCluster) GetStoreFollowerCount(storeID uint64) int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreFollowerCount(storeID)
}

// GetStorePendingPeerCount gets the total count of a store's region that includes pending peer.
func (bc *BasicCluster) GetStorePendingPeerCount(storeID uint64) int {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStorePendingPeerCount(storeID)
}

// GetStoreLeaderRegionSize get total size of store's leader regions.
func (bc *BasicCluster) GetStoreLeaderRegionSize(storeID uint64) int64 {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreLeaderRegionSize(storeID)
}

// GetStoreRegionSize get total size of store's regions.
func (bc *BasicCluster) GetStoreRegionSize(storeID uint64) int64 {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetStoreLeaderRegionSize(storeID) + bc.Regions.GetStoreFollowerRegionSize(storeID) + bc.Regions.GetStoreLearnerRegionSize(storeID)
}

// GetAverageRegionSize returns the average region approximate size.
func (bc *BasicCluster) GetAverageRegionSize() int64 {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetAverageRegionSize()
}

// PutStore put a store.
func (bc *BasicCluster) PutStore(store *StoreInfo) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.SetStore(store)
}

// DeleteStore deletes a store.
func (bc *BasicCluster) DeleteStore(store *StoreInfo) {
	bc.Lock()
	defer bc.Unlock()
	bc.Stores.DeleteStore(store)
}

// TakeStore returns the point of the origin StoreInfo with the specified storeID.
func (bc *BasicCluster) TakeStore(storeID uint64) *StoreInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Stores.TakeStore(storeID)
}

// PreCheckPutRegion checks if the region is valid to put.
func (bc *BasicCluster) PreCheckPutRegion(region *RegionInfo) (*RegionInfo, error) {
	bc.RLock()
	origin := bc.Regions.GetRegion(region.GetID())
	if origin == nil || !bytes.Equal(origin.GetStartKey(), region.GetStartKey()) || !bytes.Equal(origin.GetEndKey(), region.GetEndKey()) {
		for _, item := range bc.Regions.GetOverlaps(region) {
			if region.GetRegionEpoch().GetVersion() < item.GetRegionEpoch().GetVersion() {
				bc.RUnlock()
				return nil, ErrRegionIsStale(region.GetMeta(), item.GetMeta())
			}
		}
	}
	bc.RUnlock()
	if origin == nil {
		return nil, nil
	}
	r := region.GetRegionEpoch()
	o := origin.GetRegionEpoch()
	// Region meta is stale, return an error.
	if r.GetVersion() < o.GetVersion() || r.GetConfVer() < o.GetConfVer() {
		return origin, ErrRegionIsStale(region.GetMeta(), origin.GetMeta())
	}
	return origin, nil
}

// PutRegion put a region.
func (bc *BasicCluster) PutRegion(region *RegionInfo) []*RegionInfo {
	bc.Lock()
	defer bc.Unlock()
	return bc.Regions.SetRegion(region)
}

// CheckAndPutRegion checks if the region is valid to put,if valid then put.
func (bc *BasicCluster) CheckAndPutRegion(region *RegionInfo) []*RegionInfo {
	origin, err := bc.PreCheckPutRegion(region)
	if err != nil {
		log.Debug("region is stale", zap.Error(err), zap.Stringer("origin", origin.GetMeta()))
		// return the state region to delete.
		return []*RegionInfo{region}
	}
	return bc.PutRegion(region)
}

// RemoveRegion removes RegionInfo from regionTree and regionMap.
func (bc *BasicCluster) RemoveRegion(region *RegionInfo) {
	bc.Lock()
	defer bc.Unlock()
	bc.Regions.RemoveRegion(region)
}

// SearchRegion searches RegionInfo from regionTree.
func (bc *BasicCluster) SearchRegion(regionKey []byte) *RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.SearchRegion(regionKey)
}

// SearchPrevRegion searches previous RegionInfo from regionTree.
func (bc *BasicCluster) SearchPrevRegion(regionKey []byte) *RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.SearchPrevRegion(regionKey)
}

// ScanRange scans regions intersecting [start key, end key), returns at most
// `limit` regions. limit <= 0 means no limit.
func (bc *BasicCluster) ScanRange(startKey, endKey []byte, limit int) []*RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.ScanRange(startKey, endKey, limit)
}

// GetOverlaps returns the regions which are overlapped with the specified region range.
func (bc *BasicCluster) GetOverlaps(region *RegionInfo) []*RegionInfo {
	bc.RLock()
	defer bc.RUnlock()
	return bc.Regions.GetOverlaps(region)
}

// RegionSetInformer provides access to a shared informer of regions.
type RegionSetInformer interface {
	GetRegionCount() int
	RandFollowerRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo
	RandLeaderRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo
	RandLearnerRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo
	RandPendingRegion(storeID uint64, ranges []KeyRange, opts ...RegionOption) *RegionInfo
	GetAverageRegionSize() int64
	GetStoreRegionCount(storeID uint64) int
	GetRegion(id uint64) *RegionInfo
	GetAdjacentRegions(region *RegionInfo) (*RegionInfo, *RegionInfo)
	ScanRegions(startKey, endKey []byte, limit int) []*RegionInfo
}

// StoreSetInformer provides access to a shared informer of stores.
type StoreSetInformer interface {
	GetStores() []*StoreInfo
	GetStore(id uint64) *StoreInfo

	GetRegionStores(region *RegionInfo) []*StoreInfo
	GetFollowerStores(region *RegionInfo) []*StoreInfo
	GetLeaderStore(region *RegionInfo) *StoreInfo
}

// StoreSetController is used to control stores' status.
type StoreSetController interface {
	BlockStore(id uint64) error
	UnblockStore(id uint64)

	AttachAvailableFunc(id uint64, limitType storelimit.Type, f func() bool)
}

// KeyRange is a key range.
type KeyRange struct {
	StartKey []byte `json:"start-key"`
	EndKey   []byte `json:"end-key"`
}

// NewKeyRange create a KeyRange with the given start key and end key.
func NewKeyRange(startKey, endKey string) KeyRange {
	return KeyRange{
		StartKey: []byte(startKey),
		EndKey:   []byte(endKey),
	}
}
<|endoftext|>


<commit_before>package models

import (
	"encoding/json"
	"strings"

	"testing"

	"github.com/cihangir/gene/generators/common"
	"github.com/cihangir/gene/generators/folders"
	"github.com/cihangir/gene/generators/validators"
	"github.com/cihangir/gene/testdata"
	"github.com/cihangir/schema"

	"github.com/cihangir/gene/writers"
)

func TestGenerateModel(t *testing.T) {
	var s schema.Schema
	err := json.Unmarshal([]byte(testdata.JSON1), &s)
	common.TestEquals(t, nil, err)

	model, err := GenerateModel(&s)
	common.TestEquals(t, nil, err)

	folders.EnsureFolders("/tmp/", folders.FolderStucture)
	fileName := "/tmp/models/" + s.Title + ".go"

	err = writers.WriteFormattedFile(fileName, model)
	common.TestEquals(t, nil, err)

}

func TestGenerateSchema(t *testing.T) {
	s := &schema.Schema{}
	err := json.Unmarshal([]byte(testdata.JSON1), s)
	common.TestEquals(t, nil, err)

	// replace "~" with "`"
	result := strings.Replace(`
// Account represents a registered User
type Account struct {
	CreatedAt              time.Time ~json:"createdAt,omitempty"~              // Profile's creation time
	EmailAddress           string    ~json:"emailAddress"~                     // Email Address of the Account
	EmailStatusConstant    string    ~json:"emailStatusConstant,omitempty"~    // Status of the Account's Email
	ID                     int64     ~json:"id,omitempty,string"~              // The unique identifier for a Account's Profile
	Password               string    ~json:"password"~                         // Salted Password of the Account
	PasswordStatusConstant string    ~json:"passwordStatusConstant,omitempty"~ // Status of the Account's Password
	ProfileID              int64     ~json:"profileId,omitempty,string"~       // The unique identifier for a Account's Profile
	Salt                   string    ~json:"salt,omitempty"~                   // Salt used to hash Password of the Account
	StatusConstant         string    ~json:"statusConstant,omitempty"~         // Status of the Account
	URL                    string    ~json:"url,omitempty"~                    // Salted Password of the Account
	URLName                string    ~json:"urlName,omitempty"~                // Salted Password of the Account
}`, "~", "`", -1)

	code, err := GenerateSchema(s.Definitions["Account"])
	common.TestEquals(t, nil, err)
	common.TestEquals(t, result, string(code))
}

func TestGenerateValidators(t *testing.T) {
	s := &schema.Schema{}
	err := json.Unmarshal([]byte(testdata.JSON1), s)
	common.TestEquals(t, nil, err)

	result := `
// Validate validates the Account struct
func (a *Account) Validate() error {
	return govalidator.NewMulti(govalidator.Date(a.CreatedAt),
		govalidator.MaxLength(a.Salt, 255),
		govalidator.Min(float64(a.ID), 1.000000),
		govalidator.Min(float64(a.ProfileID), 1.000000),
		govalidator.MinLength(a.Password, 6),
		govalidator.MinLength(a.URL, 6),
		govalidator.MinLength(a.URLName, 6),
		govalidator.OneOf(a.EmailStatusConstant, []string{
			AccountEmailStatusConstant.Verified,
			AccountEmailStatusConstant.NotVerified,
		}),
		govalidator.OneOf(a.PasswordStatusConstant, []string{
			AccountPasswordStatusConstant.Valid,
			AccountPasswordStatusConstant.NeedsReset,
			AccountPasswordStatusConstant.Generated,
		}),
		govalidator.OneOf(a.StatusConstant, []string{
			AccountStatusConstant.Registered,
			AccountStatusConstant.Unregistered,
			AccountStatusConstant.NeedsManualVerification,
		})).Validate()
}`

	code, err := validators.Generate(s.Definitions["Account"])
	common.TestEquals(t, nil, err)
	common.TestEquals(t, result, string(code))
}

func TestGenerateFunctions(t *testing.T) {
	s := &schema.Schema{}
	err := json.Unmarshal([]byte(testdata.JSON1), s)
	common.TestEquals(t, nil, err)

	_, err = GenerateFunctions(s)
	common.TestEquals(t, nil, err)
}
<commit_msg>Gene: do not create folder and file while testing model generation<commit_after>package models

import (
	"encoding/json"
	"strings"

	"testing"

	"github.com/cihangir/gene/generators/common"
	"github.com/cihangir/gene/generators/validators"
	"github.com/cihangir/gene/testdata"
	"github.com/cihangir/schema"
)

func TestGenerateModel(t *testing.T) {
	var s schema.Schema
	err := json.Unmarshal([]byte(testdata.JSON1), &s)
	common.TestEquals(t, nil, err)

	_, err = GenerateModel(&s)
	common.TestEquals(t, nil, err)
}

func TestGenerateSchema(t *testing.T) {
	s := &schema.Schema{}
	err := json.Unmarshal([]byte(testdata.JSON1), s)
	common.TestEquals(t, nil, err)

	// replace "~" with "`"
	result := strings.Replace(`
// Account represents a registered User
type Account struct {
	CreatedAt              time.Time ~json:"createdAt,omitempty"~              // Profile's creation time
	EmailAddress           string    ~json:"emailAddress"~                     // Email Address of the Account
	EmailStatusConstant    string    ~json:"emailStatusConstant,omitempty"~    // Status of the Account's Email
	ID                     int64     ~json:"id,omitempty,string"~              // The unique identifier for a Account's Profile
	Password               string    ~json:"password"~                         // Salted Password of the Account
	PasswordStatusConstant string    ~json:"passwordStatusConstant,omitempty"~ // Status of the Account's Password
	ProfileID              int64     ~json:"profileId,omitempty,string"~       // The unique identifier for a Account's Profile
	Salt                   string    ~json:"salt,omitempty"~                   // Salt used to hash Password of the Account
	StatusConstant         string    ~json:"statusConstant,omitempty"~         // Status of the Account
	URL                    string    ~json:"url,omitempty"~                    // Salted Password of the Account
	URLName                string    ~json:"urlName,omitempty"~                // Salted Password of the Account
}`, "~", "`", -1)

	code, err := GenerateSchema(s.Definitions["Account"])
	common.TestEquals(t, nil, err)
	common.TestEquals(t, result, string(code))
}

func TestGenerateValidators(t *testing.T) {
	s := &schema.Schema{}
	err := json.Unmarshal([]byte(testdata.JSON1), s)
	common.TestEquals(t, nil, err)

	result := `
// Validate validates the Account struct
func (a *Account) Validate() error {
	return govalidator.NewMulti(govalidator.Date(a.CreatedAt),
		govalidator.MaxLength(a.Salt, 255),
		govalidator.Min(float64(a.ID), 1.000000),
		govalidator.Min(float64(a.ProfileID), 1.000000),
		govalidator.MinLength(a.Password, 6),
		govalidator.MinLength(a.URL, 6),
		govalidator.MinLength(a.URLName, 6),
		govalidator.OneOf(a.EmailStatusConstant, []string{
			AccountEmailStatusConstant.Verified,
			AccountEmailStatusConstant.NotVerified,
		}),
		govalidator.OneOf(a.PasswordStatusConstant, []string{
			AccountPasswordStatusConstant.Valid,
			AccountPasswordStatusConstant.NeedsReset,
			AccountPasswordStatusConstant.Generated,
		}),
		govalidator.OneOf(a.StatusConstant, []string{
			AccountStatusConstant.Registered,
			AccountStatusConstant.Unregistered,
			AccountStatusConstant.NeedsManualVerification,
		})).Validate()
}`

	code, err := validators.Generate(s.Definitions["Account"])
	common.TestEquals(t, nil, err)
	common.TestEquals(t, result, string(code))
}

func TestGenerateFunctions(t *testing.T) {
	s := &schema.Schema{}
	err := json.Unmarshal([]byte(testdata.JSON1), s)
	common.TestEquals(t, nil, err)

	_, err = GenerateFunctions(s)
	common.TestEquals(t, nil, err)
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestCollectEstafetteEnvvars(t *testing.T) {

	t.Run("ReturnsEmptyMapIfManifestHasNoLabelsAndNoEnvvarsStartWithEstafette", func(t *testing.T) {

		manifest := estafetteManifest{}

		// act
		envvars := collectEstafetteEnvvars(manifest)

		assert.Equal(t, 0, len(envvars))
	})

	t.Run("ReturnsOneLabelAsEstafetteLabelLabel", func(t *testing.T) {

		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder"}}

		// act
		envvars := collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["ESTAFETTE_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["ESTAFETTE_LABEL_APP"])

		// clean up
		os.Unsetenv("ESTAFETTE_LABEL_APP")
	})

	t.Run("ReturnsOneLabelAsEstafetteLabelLabelWithSnakeCasing", func(t *testing.T) {

		manifest := estafetteManifest{Labels: map[string]string{"owningTeam": "estafette-ci-team"}}

		// act
		envvars := collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["ESTAFETTE_LABEL_OWNING_TEAM"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-team", envvars["ESTAFETTE_LABEL_OWNING_TEAM"])

		// clean up
		os.Unsetenv("ESTAFETTE_LABEL_OWNING_TEAM")
	})

	t.Run("ReturnsTwoLabelsAsEstafetteLabelLabel", func(t *testing.T) {

		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder", "team": "estafette-ci-team"}}

		// act
		envvars := collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["ESTAFETTE_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["ESTAFETTE_LABEL_APP"])

		_, exists = envvars["ESTAFETTE_LABEL_TEAM"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-team", envvars["ESTAFETTE_LABEL_TEAM"])

		// clean up
		os.Unsetenv("ESTAFETTE_LABEL_APP")
		os.Unsetenv("ESTAFETTE_LABEL_TEAM")
	})

	t.Run("ReturnsOneEnvvarStartingWithEstafette", func(t *testing.T) {

		manifest := estafetteManifest{}
		os.Setenv("ESTAFETTE_VERSION", "1.0.3")

		// act
		envvars := collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["ESTAFETTE_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["ESTAFETTE_VERSION"])

		// clean up
		os.Unsetenv("ESTAFETTE_VERSION")
	})

	t.Run("ReturnsOneEnvvarStartingWithEstafetteIfValueContainsIsSymbol", func(t *testing.T) {

		manifest := estafetteManifest{}
		os.Setenv("ESTAFETTE_VERSION", "b=c")

		// act
		envvars := collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["ESTAFETTE_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "b=c", envvars["ESTAFETTE_VERSION"])

		// clean up
		os.Unsetenv("ESTAFETTE_VERSION")
	})

	t.Run("ReturnsTwoEnvvarsStartingWithEstafette", func(t *testing.T) {

		manifest := estafetteManifest{}
		os.Setenv("ESTAFETTE_VERSION", "1.0.3")
		os.Setenv("ESTAFETTE_GIT_REPOSITORY", "git@github.com:estafette/estafette-ci-builder.git")

		// act
		envvars := collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["ESTAFETTE_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["ESTAFETTE_VERSION"])

		_, exists = envvars["ESTAFETTE_GIT_REPOSITORY"]
		assert.True(t, exists)
		assert.Equal(t, "git@github.com:estafette/estafette-ci-builder.git", envvars["ESTAFETTE_GIT_REPOSITORY"])

		// clean up
		os.Unsetenv("ESTAFETTE_VERSION")
		os.Unsetenv("ESTAFETTE_GIT_REPOSITORY")
	})

	t.Run("ReturnsMixOfLabelsAndEnvvars", func(t *testing.T) {

		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder"}}
		os.Setenv("ESTAFETTE_VERSION", "1.0.3")

		// act
		envvars := collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["ESTAFETTE_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["ESTAFETTE_VERSION"])

		_, exists = envvars["ESTAFETTE_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["ESTAFETTE_LABEL_APP"])

		// clean up
		os.Unsetenv("ESTAFETTE_VERSION")
		os.Unsetenv("ESTAFETTE_LABEL_APP")
	})
}

func TestGetEstafetteEnv(t *testing.T) {

	t.Run("ReturnsEnvironmentVariableValueIfItStartsWithEstafetteUnderscore", func(t *testing.T) {

		os.Setenv("ESTAFETTE_BUILD_STATUS", "succeeded")

		// act
		result := getEstafetteEnv("ESTAFETTE_BUILD_STATUS")

		assert.Equal(t, "succeeded", result)

		// clean up
		os.Unsetenv("ESTAFETTE_BUILD_STATUS")
	})

	t.Run("ReturnsEnvironmentVariablePlaceholderIfItDoesNotStartWithEstafetteUnderscore", func(t *testing.T) {

		os.Setenv("HOME", "/root")

		// act
		result := getEstafetteEnv("HOME")

		assert.Equal(t, "${HOME}", result)
	})
}
<commit_msg>disable envvar tests<commit_after>// package main

// import (
// 	"os"
// 	"testing"

// 	"github.com/stretchr/testify/assert"
// )

// func TestCollectEstafetteEnvvars(t *testing.T) {

// 	t.Run("ReturnsEmptyMapIfManifestHasNoLabelsAndNoEnvvarsStartWithEstafette", func(t *testing.T) {

// 		manifest := estafetteManifest{}

// 		// act
// 		envvars := collectEstafetteEnvvars(manifest)

// 		assert.Equal(t, 0, len(envvars))
// 	})

// 	t.Run("ReturnsOneLabelAsEstafetteLabelLabel", func(t *testing.T) {

// 		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder"}}

// 		// act
// 		envvars := collectEstafetteEnvvars(manifest)

// 		assert.Equal(t, 1, len(envvars))
// 		_, exists := envvars["ESTAFETTE_LABEL_APP"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "estafette-ci-builder", envvars["ESTAFETTE_LABEL_APP"])

// 		// clean up
// 		os.Unsetenv("ESTAFETTE_LABEL_APP")
// 	})

// 	t.Run("ReturnsOneLabelAsEstafetteLabelLabelWithSnakeCasing", func(t *testing.T) {

// 		manifest := estafetteManifest{Labels: map[string]string{"owningTeam": "estafette-ci-team"}}

// 		// act
// 		envvars := collectEstafetteEnvvars(manifest)

// 		assert.Equal(t, 1, len(envvars))
// 		_, exists := envvars["ESTAFETTE_LABEL_OWNING_TEAM"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "estafette-ci-team", envvars["ESTAFETTE_LABEL_OWNING_TEAM"])

// 		// clean up
// 		os.Unsetenv("ESTAFETTE_LABEL_OWNING_TEAM")
// 	})

// 	t.Run("ReturnsTwoLabelsAsEstafetteLabelLabel", func(t *testing.T) {

// 		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder", "team": "estafette-ci-team"}}

// 		// act
// 		envvars := collectEstafetteEnvvars(manifest)

// 		assert.Equal(t, 2, len(envvars))
// 		_, exists := envvars["ESTAFETTE_LABEL_APP"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "estafette-ci-builder", envvars["ESTAFETTE_LABEL_APP"])

// 		_, exists = envvars["ESTAFETTE_LABEL_TEAM"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "estafette-ci-team", envvars["ESTAFETTE_LABEL_TEAM"])

// 		// clean up
// 		os.Unsetenv("ESTAFETTE_LABEL_APP")
// 		os.Unsetenv("ESTAFETTE_LABEL_TEAM")
// 	})

// 	t.Run("ReturnsOneEnvvarStartingWithEstafette", func(t *testing.T) {

// 		manifest := estafetteManifest{}
// 		os.Setenv("ESTAFETTE_VERSION", "1.0.3")

// 		// act
// 		envvars := collectEstafetteEnvvars(manifest)

// 		assert.Equal(t, 1, len(envvars))
// 		_, exists := envvars["ESTAFETTE_VERSION"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "1.0.3", envvars["ESTAFETTE_VERSION"])

// 		// clean up
// 		os.Unsetenv("ESTAFETTE_VERSION")
// 	})

// 	t.Run("ReturnsOneEnvvarStartingWithEstafetteIfValueContainsIsSymbol", func(t *testing.T) {

// 		manifest := estafetteManifest{}
// 		os.Setenv("ESTAFETTE_VERSION", "b=c")

// 		// act
// 		envvars := collectEstafetteEnvvars(manifest)

// 		assert.Equal(t, 1, len(envvars))
// 		_, exists := envvars["ESTAFETTE_VERSION"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "b=c", envvars["ESTAFETTE_VERSION"])

// 		// clean up
// 		os.Unsetenv("ESTAFETTE_VERSION")
// 	})

// 	t.Run("ReturnsTwoEnvvarsStartingWithEstafette", func(t *testing.T) {

// 		manifest := estafetteManifest{}
// 		os.Setenv("ESTAFETTE_VERSION", "1.0.3")
// 		os.Setenv("ESTAFETTE_GIT_REPOSITORY", "git@github.com:estafette/estafette-ci-builder.git")

// 		// act
// 		envvars := collectEstafetteEnvvars(manifest)

// 		assert.Equal(t, 2, len(envvars))
// 		_, exists := envvars["ESTAFETTE_VERSION"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "1.0.3", envvars["ESTAFETTE_VERSION"])

// 		_, exists = envvars["ESTAFETTE_GIT_REPOSITORY"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "git@github.com:estafette/estafette-ci-builder.git", envvars["ESTAFETTE_GIT_REPOSITORY"])

// 		// clean up
// 		os.Unsetenv("ESTAFETTE_VERSION")
// 		os.Unsetenv("ESTAFETTE_GIT_REPOSITORY")
// 	})

// 	t.Run("ReturnsMixOfLabelsAndEnvvars", func(t *testing.T) {

// 		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder"}}
// 		os.Setenv("ESTAFETTE_VERSION", "1.0.3")

// 		// act
// 		envvars := collectEstafetteEnvvars(manifest)

// 		assert.Equal(t, 2, len(envvars))
// 		_, exists := envvars["ESTAFETTE_VERSION"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "1.0.3", envvars["ESTAFETTE_VERSION"])

// 		_, exists = envvars["ESTAFETTE_LABEL_APP"]
// 		assert.True(t, exists)
// 		assert.Equal(t, "estafette-ci-builder", envvars["ESTAFETTE_LABEL_APP"])

// 		// clean up
// 		os.Unsetenv("ESTAFETTE_VERSION")
// 		os.Unsetenv("ESTAFETTE_LABEL_APP")
// 	})
// }

// func TestGetEstafetteEnv(t *testing.T) {

// 	t.Run("ReturnsEnvironmentVariableValueIfItStartsWithEstafetteUnderscore", func(t *testing.T) {

// 		os.Setenv("ESTAFETTE_BUILD_STATUS", "succeeded")

// 		// act
// 		result := getEstafetteEnv("ESTAFETTE_BUILD_STATUS")

// 		assert.Equal(t, "succeeded", result)

// 		// clean up
// 		os.Unsetenv("ESTAFETTE_BUILD_STATUS")
// 	})

// 	t.Run("ReturnsEnvironmentVariablePlaceholderIfItDoesNotStartWithEstafetteUnderscore", func(t *testing.T) {

// 		os.Setenv("HOME", "/root")

// 		// act
// 		result := getEstafetteEnv("HOME")

// 		assert.Equal(t, "${HOME}", result)
// 	})
// }
<|endoftext|>


<commit_before>package main

import (
	"os"
	"testing"

	"github.com/rs/zerolog/log"
	"github.com/stretchr/testify/assert"
)

func TestOverrideEnvvars(t *testing.T) {

	t.Run("CombinesAllEnvvarsFromPassedMaps", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		outerMap := map[string]string{
			"ENVVAR1": "value1",
		}
		innerMap := map[string]string{
			"ENVVAR2": "value2",
		}

		// act
		envvars := envvarHelper.overrideEnvvars(outerMap, innerMap)

		assert.Equal(t, 2, len(envvars))
	})

	t.Run("OverridesEnvarFromFirstMapWithSecondMap", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		outerMap := map[string]string{
			"ENVVAR1": "value1",
		}
		innerMap := map[string]string{
			"ENVVAR1": "value2",
		}

		// act
		envvars := envvarHelper.overrideEnvvars(outerMap, innerMap)

		assert.Equal(t, 1, len(envvars))
		assert.Equal(t, "value2", envvars["ENVVAR1"])
	})
}

func TestGetEstafetteEnvvarName(t *testing.T) {

	t.Run("ReturnsKeyNameWithEstafetteUnderscoreReplacedWithEstafetteEnvvarPrefixValue", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()

		// act
		key := envvarHelper.getEstafetteEnvvarName("ESTAFETTE_KEY")

		assert.Equal(t, "TESTPREFIX_KEY", key)

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})
}

func TestCollectEstafetteEnvvars(t *testing.T) {

	t.Run("ReturnsEmptyMapIfManifestHasNoLabelsAndNoEnvvarsStartWithEstafette", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{}

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		log.Debug().Interface("envvars", envvars).Msg("ReturnsEmptyMapIfManifestHasNoLabelsAndNoEnvvarsStartWithEstafette")
		assert.Equal(t, 0, len(envvars))

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsOneLabelAsEstafetteLabelLabel", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder"}}

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		log.Debug().Interface("envvars", envvars).Msg("ReturnsOneLabelAsEstafetteLabelLabel")
		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["TESTPREFIX_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["TESTPREFIX_LABEL_APP"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsOneLabelAsEstafetteLabelLabelWithSnakeCasing", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{Labels: map[string]string{"owningTeam": "estafette-ci-team"}}

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		log.Debug().Interface("envvars", envvars).Msg("ReturnsOneLabelAsEstafetteLabelLabelWithSnakeCasing")
		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["TESTPREFIX_LABEL_OWNING_TEAM"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-team", envvars["TESTPREFIX_LABEL_OWNING_TEAM"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsTwoLabelsAsEstafetteLabelLabel", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder", "team": "estafette-ci-team"}}

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["TESTPREFIX_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["TESTPREFIX_LABEL_APP"])

		_, exists = envvars["TESTPREFIX_LABEL_TEAM"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-team", envvars["TESTPREFIX_LABEL_TEAM"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsOneEnvvarStartingWithEstafette", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{}
		os.Setenv("TESTPREFIX_VERSION", "1.0.3")

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["TESTPREFIX_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["TESTPREFIX_VERSION"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsOneEnvvarStartingWithEstafetteIfValueContainsIsSymbol", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{}
		os.Setenv("TESTPREFIX_VERSION", "b=c")

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["TESTPREFIX_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "b=c", envvars["TESTPREFIX_VERSION"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsTwoEnvvarsStartingWithEstafette", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{}
		os.Setenv("TESTPREFIX_VERSION", "1.0.3")
		os.Setenv("TESTPREFIX_GIT_REPOSITORY", "git@github.com:estafette/estafette-ci-builder.git")

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["TESTPREFIX_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["TESTPREFIX_VERSION"])

		_, exists = envvars["TESTPREFIX_GIT_REPOSITORY"]
		assert.True(t, exists)
		assert.Equal(t, "git@github.com:estafette/estafette-ci-builder.git", envvars["TESTPREFIX_GIT_REPOSITORY"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsMixOfLabelsAndEnvvars", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder"}}
		os.Setenv("TESTPREFIX_VERSION", "1.0.3")

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["TESTPREFIX_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["TESTPREFIX_VERSION"])

		_, exists = envvars["TESTPREFIX_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["TESTPREFIX_LABEL_APP"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})
}

func TestGetEstafetteEnv(t *testing.T) {

	t.Run("ReturnsEnvironmentVariableValueIfItStartsWithEstafetteUnderscore", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		os.Setenv("TESTPREFIX_BUILD_STATUS", "succeeded")

		// act
		result := envvarHelper.getEstafetteEnv("TESTPREFIX_BUILD_STATUS")

		assert.Equal(t, "succeeded", result)

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsEnvironmentVariablePlaceholderIfItDoesNotStartWithEstafetteUnderscore", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		os.Setenv("HOME", "/root")

		// act
		result := envvarHelper.getEstafetteEnv("HOME")

		assert.Equal(t, "${HOME}", result)

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})
}
<commit_msg>remove debug logging from tests<commit_after>package main

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestOverrideEnvvars(t *testing.T) {

	t.Run("CombinesAllEnvvarsFromPassedMaps", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		outerMap := map[string]string{
			"ENVVAR1": "value1",
		}
		innerMap := map[string]string{
			"ENVVAR2": "value2",
		}

		// act
		envvars := envvarHelper.overrideEnvvars(outerMap, innerMap)

		assert.Equal(t, 2, len(envvars))
	})

	t.Run("OverridesEnvarFromFirstMapWithSecondMap", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		outerMap := map[string]string{
			"ENVVAR1": "value1",
		}
		innerMap := map[string]string{
			"ENVVAR1": "value2",
		}

		// act
		envvars := envvarHelper.overrideEnvvars(outerMap, innerMap)

		assert.Equal(t, 1, len(envvars))
		assert.Equal(t, "value2", envvars["ENVVAR1"])
	})
}

func TestGetEstafetteEnvvarName(t *testing.T) {

	t.Run("ReturnsKeyNameWithEstafetteUnderscoreReplacedWithEstafetteEnvvarPrefixValue", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()

		// act
		key := envvarHelper.getEstafetteEnvvarName("ESTAFETTE_KEY")

		assert.Equal(t, "TESTPREFIX_KEY", key)

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})
}

func TestCollectEstafetteEnvvars(t *testing.T) {

	t.Run("ReturnsEmptyMapIfManifestHasNoLabelsAndNoEnvvarsStartWithEstafette", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{}

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 0, len(envvars))

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsOneLabelAsEstafetteLabelLabel", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder"}}

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["TESTPREFIX_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["TESTPREFIX_LABEL_APP"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsOneLabelAsEstafetteLabelLabelWithSnakeCasing", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{Labels: map[string]string{"owningTeam": "estafette-ci-team"}}

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["TESTPREFIX_LABEL_OWNING_TEAM"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-team", envvars["TESTPREFIX_LABEL_OWNING_TEAM"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsTwoLabelsAsEstafetteLabelLabel", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder", "team": "estafette-ci-team"}}

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["TESTPREFIX_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["TESTPREFIX_LABEL_APP"])

		_, exists = envvars["TESTPREFIX_LABEL_TEAM"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-team", envvars["TESTPREFIX_LABEL_TEAM"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsOneEnvvarStartingWithEstafette", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{}
		os.Setenv("TESTPREFIX_VERSION", "1.0.3")

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["TESTPREFIX_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["TESTPREFIX_VERSION"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsOneEnvvarStartingWithEstafetteIfValueContainsIsSymbol", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{}
		os.Setenv("TESTPREFIX_VERSION", "b=c")

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 1, len(envvars))
		_, exists := envvars["TESTPREFIX_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "b=c", envvars["TESTPREFIX_VERSION"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsTwoEnvvarsStartingWithEstafette", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{}
		os.Setenv("TESTPREFIX_VERSION", "1.0.3")
		os.Setenv("TESTPREFIX_GIT_REPOSITORY", "git@github.com:estafette/estafette-ci-builder.git")

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["TESTPREFIX_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["TESTPREFIX_VERSION"])

		_, exists = envvars["TESTPREFIX_GIT_REPOSITORY"]
		assert.True(t, exists)
		assert.Equal(t, "git@github.com:estafette/estafette-ci-builder.git", envvars["TESTPREFIX_GIT_REPOSITORY"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsMixOfLabelsAndEnvvars", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		manifest := estafetteManifest{Labels: map[string]string{"app": "estafette-ci-builder"}}
		os.Setenv("TESTPREFIX_VERSION", "1.0.3")

		// act
		envvars := envvarHelper.collectEstafetteEnvvars(manifest)

		assert.Equal(t, 2, len(envvars))
		_, exists := envvars["TESTPREFIX_VERSION"]
		assert.True(t, exists)
		assert.Equal(t, "1.0.3", envvars["TESTPREFIX_VERSION"])

		_, exists = envvars["TESTPREFIX_LABEL_APP"]
		assert.True(t, exists)
		assert.Equal(t, "estafette-ci-builder", envvars["TESTPREFIX_LABEL_APP"])

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})
}

func TestGetEstafetteEnv(t *testing.T) {

	t.Run("ReturnsEnvironmentVariableValueIfItStartsWithEstafetteUnderscore", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		os.Setenv("TESTPREFIX_BUILD_STATUS", "succeeded")

		// act
		result := envvarHelper.getEstafetteEnv("TESTPREFIX_BUILD_STATUS")

		assert.Equal(t, "succeeded", result)

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})

	t.Run("ReturnsEnvironmentVariablePlaceholderIfItDoesNotStartWithEstafetteUnderscore", func(t *testing.T) {

		envvarHelper := NewEnvvarHelper("TESTPREFIX_")
		envvarHelper.unsetEstafetteEnvvars()
		os.Setenv("HOME", "/root")

		// act
		result := envvarHelper.getEstafetteEnv("HOME")

		assert.Equal(t, "${HOME}", result)

		// clean up
		envvarHelper.unsetEstafetteEnvvars()
	})
}
<|endoftext|>