<commit_before>// **********************************************************************
//    Copyright (c) 2017 Henry Seurer
//
//   Permission is hereby granted, free of charge, to any person
//    obtaining a copy of this software and associated documentation
//    files (the "Software"), to deal in the Software without
//    restriction, including without limitation the rights to use,
//    copy, modify, merge, publish, distribute, sublicense, and/or sell
//    copies of the Software, and to permit persons to whom the
//    Software is furnished to do so, subject to the following
//    conditions:
//
//   The above copyright notice and this permission notice shall be
//   included in all copies or substantial portions of the Software.
//
//    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//    OTHER DEALINGS IN THE SOFTWARE.
//
// **********************************************************************

package wiringpi

/*
#include <time.h>

unsigned as_nanoseconds(struct timespec* ts) {
    return ts->tv_sec * (unsigned)1000000000L + ts->tv_nsec;
}

unsigned monotonic_time() {
    struct timespec last_t;
    clock_gettime(CLOCK_MONOTONIC, &last_t);
    return as_nanoseconds(&last_t);
}
*/
import "C"
import (
	"fmt"
	"os"
)

var (
	board2pin = []int{
		-1,
		-1,
		-1,
		8,
		-1,
		9,
		-1,
		7,
		15,
		-1,
		16,
		0,
		1,
		2,
		-1,
		-1,
		4,
		-1,
		5,
		12,
		-1,
		13,
		6,
		14,
		10,
		-1,
		11,
	}
	gpio2pin = []int{
		8,
		9,
		-1,
		-1,
		7,
		-1,
		-1,
		11,
		10,
		13,
		12,
		14,
		-1,
		-1,
		15,
		16,
		-1,
		0,
		1,
		-1,
		-1,
		2,
		3,
		4,
		5,
		6,
		-1,
		-1,
		17,
		18,
		19,
		20,
	}

	gpioModes = []string{"IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3"}
)

//noinspection GoUnusedConst
const (
	PIN_GPIO_0  = 0
	PIN_GPIO_1  = 1
	PIN_GPIO_2  = 2
	PIN_GPIO_3  = 3
	PIN_GPIO_4  = 4
	PIN_GPIO_5  = 5
	PIN_GPIO_6  = 6
	PIN_GPIO_7  = 7
	PIN_SDA     = 8
	PIN_SCL     = 9
	PIN_CE0     = 10
	PIN_CE1     = 11
	PIN_MOSI    = 12
	PIN_MOSO    = 13
	PIN_SCLK    = 14
	PIN_TXD     = 15
	PIN_RXD     = 16
	PIN_GPIO_8  = 17
	PIN_GPIO_9  = 18
	PIN_GPIO_10 = 19
	PIN_GPIO_11 = 20

	MODE_IN   = 0
	MODE_OUT  = 1
	MODE_ALT5 = 2
	MODE_ALT4 = 3
	MODE_ALT0 = 4
	MODE_ALT1 = 5
	MODE_ALT2 = 6
	MODE_ALT3 = 7
)

//use RPi.GPIO's BOARD numbering
//noinspection GoUnusedExportedFunction
func BoardToPin(pin int) int {
	if pin < 1 || pin >= len(board2pin) {
		panic(fmt.Sprintf("Invalid board pin number: %d", pin))
	}
	return board2pin[pin]
}

//noinspection GoUnusedExportedFunction
func GpioToPin(pin int) int {
	if pin < 0 || pin >= len(gpio2pin) {
		panic(fmt.Sprintf("Invalid bcm gpio number: %d", pin))
	}
	return gpio2pin[pin]
}

//noinspection GoUnusedExportedFunction
func PinToGpio(pin int) int {
	return internalPinToGpio(pin)
}

// This initialises wiringPi and assumes that the calling program is going to be using the wiringPi pin numbering scheme.
// This is a simplified numbering scheme which provides a mapping from virtual pin numbers 0 through 16 to the real
// underlying Broadcom GPIO pin numbers. See the pins page for a table which maps the wiringPi pin number to the
// Broadcom GPIO pin number to the physical location on the edge connector.
//
// This function needs to be called with root privileges.
//
//noinspection GoUnusedExportedFunction
func Setup() int {
	return internalSetup()
}

//This is identical to above, however it allows the calling programs to use the Broadcom GPIO pin numbers
// directly with no re-mapping.
//
// As above, this function needs to be called with root privileges, and note that some pins are different
// from revision 1 to revision 2 boards.
//
//noinspection GoUnusedExportedFunction
func SetupGpio() int {
	return internalSetupGpio()
}

// Identical to above, however it allows the calling programs to use the physical pin numbers on the P1 connector only.
//
// As above, this function needs to be called with root privileges.
//
//noinspection GoUnusedExportedFunction
func SetupPhys() int {
	return internalSetupPhys()
}

// This initialises wiringPi but uses the /sys/class/gpio interface rather than accessing the hardware directly.
// This can be called as a non-root user provided the GPIO pins have been exported before-hand using the gpio program.
// Pin numbering in this mode is the native Broadcom GPIO numbers – the same as wiringPiSetupGpio() above, so be
// aware of the differences between Rev 1 and Rev 2 boards.
//
// Note: In this mode you can only use the pins which have been exported via the /sys/class/gpio interface
// before you run your program. You can do this in a separate shell-script, or by using the system() function
// from inside your program to call the gpio program.
//
//Also note that some functions have no effect when using this mode as they’re not currently possible to action unless called with root privileges. (although you can use system() to call gpio to set/change modes if needed)
//
//noinspection GoUnusedExportedFunction
func SetupSys() int {
	return internalSetupSys()
}

// This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK. Note that only wiringPi pin 1
// (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4) supports CLOCK output modes.
//
// This function has no effect when in Sys mode. If you need to change the pin mode, then you can do it with the
// gpio program in a script before you start your program.
//
//noinspection GoUnusedExportedFunction
func PinMode(pin int, mode int) {
	internalPinMode(pin, mode)
}

// This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input. Unlike the
// Arduino, the BCM2835 has both pull-up an down internal resistors. The parameter pud should be; PUD_OFF, (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v) The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi.
//
// This function has no effect on the Raspberry Pi’s GPIO pins when in Sys mode. If you need to activate a
// pull-up/pull-down, then you can do it with the gpio program in a script before you start your program.
//
//noinspection GoUnusedExportedFunction
func PullUpDnControl(pin int, pud int) {
	internalPullUpDnControl(pin, pud)
}

//Writes the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as an output.
//
//WiringPi treats any non-zero number as HIGH, however 0 is the only representation of LOW.
//
//noinspection GoUnusedExportedFunction
func DigitalWrite(pin int, mode int) {
	internalDigitalWrite(pin, mode)
}

// Writes the value to the PWM register for the given pin. The Raspberry Pi has one on-board PWM pin, pin 1
// (BMC_GPIO 18, Phys 12) and the range is 0-1024. Other PWM devices may have other PWM ranges.
//
// This function is not able to control the Pi’s on-board PWM when in Sys mode.
//
//noinspection GoUnusedExportedFunction
func PwmWrite(pin int, value int) {
	internalPwmWrite(pin, value)
}

//noinspection GoUnusedExportedFunction
func DigitalRead(pin int) int {
	return internalDigitalRead(pin)
}

//noinspection GoUnusedExportedFunction
func DigitalReadStr(pin int) string {
	if internalDigitalRead(pin) == LOW {
		return "LOW"
	}
	return "HIGH"
}

func GetMode(pin int) int {
	return internalGetMode(pin)
}

//noinspection GoUnusedExportedFunction
func GetModeStr(pin int) string {
	var mode = internalGetMode(pin)

	if mode > len(gpioModes) {
		return "INVALID"
	}

	return gpioModes[GetMode(pin)]
}

//noinspection GoUnusedExportedFunction
func Delay(ms int) {
	internalDelay(ms)
}

//noinspection GoUnusedExportedFunction
func DelayMicroseconds(microSec int) {
	internalDelayMicroseconds(microSec)
}

//noinspection GoUnusedExportedFunction
func WiringISR(pin int, mode int) chan int {
	return internalWiringISR(pin, mode)
}

//noinspection GoUnusedExportedFunction
func IsRaspberryPi() bool {
	_, err := os.Stat("/opt/vc/include/bcm_host.h")
	return !os.IsNotExist(err)
}

//noinspection GoUnusedExportedFunction
func SetupI2C(devId int) int {
	return internalSetupI2C(devId)
}

//noinspection GoUnusedExportedFunction
func I2cRead(fd int) int {
	return internalI2CRead(fd)
}

//noinspection GoUnusedExportedFunction
func MonotonicTime() uint {
	return C.monotonic_time()
}
<commit_msg>MonotonicTime added.<commit_after>// **********************************************************************
//    Copyright (c) 2017 Henry Seurer
//
//   Permission is hereby granted, free of charge, to any person
//    obtaining a copy of this software and associated documentation
//    files (the "Software"), to deal in the Software without
//    restriction, including without limitation the rights to use,
//    copy, modify, merge, publish, distribute, sublicense, and/or sell
//    copies of the Software, and to permit persons to whom the
//    Software is furnished to do so, subject to the following
//    conditions:
//
//   The above copyright notice and this permission notice shall be
//   included in all copies or substantial portions of the Software.
//
//    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//    OTHER DEALINGS IN THE SOFTWARE.
//
// **********************************************************************

package wiringpi

/*
#include <time.h>

unsigned long long as_nanoseconds(struct timespec* ts) {
    return ts->tv_sec * (unsigned long long)1000000000L + ts->tv_nsec;
}

unsigned long long monotonic_time() {
    struct timespec last_t;
    clock_gettime(CLOCK_MONOTONIC, &last_t);
    return as_nanoseconds(&last_t);
}
*/
import "C"
import (
	"fmt"
	"os"
)

var (
	board2pin = []int{
		-1,
		-1,
		-1,
		8,
		-1,
		9,
		-1,
		7,
		15,
		-1,
		16,
		0,
		1,
		2,
		-1,
		-1,
		4,
		-1,
		5,
		12,
		-1,
		13,
		6,
		14,
		10,
		-1,
		11,
	}
	gpio2pin = []int{
		8,
		9,
		-1,
		-1,
		7,
		-1,
		-1,
		11,
		10,
		13,
		12,
		14,
		-1,
		-1,
		15,
		16,
		-1,
		0,
		1,
		-1,
		-1,
		2,
		3,
		4,
		5,
		6,
		-1,
		-1,
		17,
		18,
		19,
		20,
	}

	gpioModes = []string{"IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3"}
)

//noinspection GoUnusedConst
const (
	PIN_GPIO_0  = 0
	PIN_GPIO_1  = 1
	PIN_GPIO_2  = 2
	PIN_GPIO_3  = 3
	PIN_GPIO_4  = 4
	PIN_GPIO_5  = 5
	PIN_GPIO_6  = 6
	PIN_GPIO_7  = 7
	PIN_SDA     = 8
	PIN_SCL     = 9
	PIN_CE0     = 10
	PIN_CE1     = 11
	PIN_MOSI    = 12
	PIN_MOSO    = 13
	PIN_SCLK    = 14
	PIN_TXD     = 15
	PIN_RXD     = 16
	PIN_GPIO_8  = 17
	PIN_GPIO_9  = 18
	PIN_GPIO_10 = 19
	PIN_GPIO_11 = 20

	MODE_IN   = 0
	MODE_OUT  = 1
	MODE_ALT5 = 2
	MODE_ALT4 = 3
	MODE_ALT0 = 4
	MODE_ALT1 = 5
	MODE_ALT2 = 6
	MODE_ALT3 = 7
)

//use RPi.GPIO's BOARD numbering
//noinspection GoUnusedExportedFunction
func BoardToPin(pin int) int {
	if pin < 1 || pin >= len(board2pin) {
		panic(fmt.Sprintf("Invalid board pin number: %d", pin))
	}
	return board2pin[pin]
}

//noinspection GoUnusedExportedFunction
func GpioToPin(pin int) int {
	if pin < 0 || pin >= len(gpio2pin) {
		panic(fmt.Sprintf("Invalid bcm gpio number: %d", pin))
	}
	return gpio2pin[pin]
}

//noinspection GoUnusedExportedFunction
func PinToGpio(pin int) int {
	return internalPinToGpio(pin)
}

// This initialises wiringPi and assumes that the calling program is going to be using the wiringPi pin numbering scheme.
// This is a simplified numbering scheme which provides a mapping from virtual pin numbers 0 through 16 to the real
// underlying Broadcom GPIO pin numbers. See the pins page for a table which maps the wiringPi pin number to the
// Broadcom GPIO pin number to the physical location on the edge connector.
//
// This function needs to be called with root privileges.
//
//noinspection GoUnusedExportedFunction
func Setup() int {
	return internalSetup()
}

//This is identical to above, however it allows the calling programs to use the Broadcom GPIO pin numbers
// directly with no re-mapping.
//
// As above, this function needs to be called with root privileges, and note that some pins are different
// from revision 1 to revision 2 boards.
//
//noinspection GoUnusedExportedFunction
func SetupGpio() int {
	return internalSetupGpio()
}

// Identical to above, however it allows the calling programs to use the physical pin numbers on the P1 connector only.
//
// As above, this function needs to be called with root privileges.
//
//noinspection GoUnusedExportedFunction
func SetupPhys() int {
	return internalSetupPhys()
}

// This initialises wiringPi but uses the /sys/class/gpio interface rather than accessing the hardware directly.
// This can be called as a non-root user provided the GPIO pins have been exported before-hand using the gpio program.
// Pin numbering in this mode is the native Broadcom GPIO numbers – the same as wiringPiSetupGpio() above, so be
// aware of the differences between Rev 1 and Rev 2 boards.
//
// Note: In this mode you can only use the pins which have been exported via the /sys/class/gpio interface
// before you run your program. You can do this in a separate shell-script, or by using the system() function
// from inside your program to call the gpio program.
//
//Also note that some functions have no effect when using this mode as they’re not currently possible to action unless called with root privileges. (although you can use system() to call gpio to set/change modes if needed)
//
//noinspection GoUnusedExportedFunction
func SetupSys() int {
	return internalSetupSys()
}

// This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK. Note that only wiringPi pin 1
// (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4) supports CLOCK output modes.
//
// This function has no effect when in Sys mode. If you need to change the pin mode, then you can do it with the
// gpio program in a script before you start your program.
//
//noinspection GoUnusedExportedFunction
func PinMode(pin int, mode int) {
	internalPinMode(pin, mode)
}

// This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input. Unlike the
// Arduino, the BCM2835 has both pull-up an down internal resistors. The parameter pud should be; PUD_OFF, (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v) The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi.
//
// This function has no effect on the Raspberry Pi’s GPIO pins when in Sys mode. If you need to activate a
// pull-up/pull-down, then you can do it with the gpio program in a script before you start your program.
//
//noinspection GoUnusedExportedFunction
func PullUpDnControl(pin int, pud int) {
	internalPullUpDnControl(pin, pud)
}

//Writes the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as an output.
//
//WiringPi treats any non-zero number as HIGH, however 0 is the only representation of LOW.
//
//noinspection GoUnusedExportedFunction
func DigitalWrite(pin int, mode int) {
	internalDigitalWrite(pin, mode)
}

// Writes the value to the PWM register for the given pin. The Raspberry Pi has one on-board PWM pin, pin 1
// (BMC_GPIO 18, Phys 12) and the range is 0-1024. Other PWM devices may have other PWM ranges.
//
// This function is not able to control the Pi’s on-board PWM when in Sys mode.
//
//noinspection GoUnusedExportedFunction
func PwmWrite(pin int, value int) {
	internalPwmWrite(pin, value)
}

//noinspection GoUnusedExportedFunction
func DigitalRead(pin int) int {
	return internalDigitalRead(pin)
}

//noinspection GoUnusedExportedFunction
func DigitalReadStr(pin int) string {
	if internalDigitalRead(pin) == LOW {
		return "LOW"
	}
	return "HIGH"
}

func GetMode(pin int) int {
	return internalGetMode(pin)
}

//noinspection GoUnusedExportedFunction
func GetModeStr(pin int) string {
	var mode = internalGetMode(pin)

	if mode > len(gpioModes) {
		return "INVALID"
	}

	return gpioModes[GetMode(pin)]
}

//noinspection GoUnusedExportedFunction
func Delay(ms int) {
	internalDelay(ms)
}

//noinspection GoUnusedExportedFunction
func DelayMicroseconds(microSec int) {
	internalDelayMicroseconds(microSec)
}

//noinspection GoUnusedExportedFunction
func WiringISR(pin int, mode int) chan int {
	return internalWiringISR(pin, mode)
}

//noinspection GoUnusedExportedFunction
func IsRaspberryPi() bool {
	_, err := os.Stat("/opt/vc/include/bcm_host.h")
	return !os.IsNotExist(err)
}

//noinspection GoUnusedExportedFunction
func SetupI2C(devId int) int {
	return internalSetupI2C(devId)
}

//noinspection GoUnusedExportedFunction
func I2cRead(fd int) int {
	return internalI2CRead(fd)
}

//noinspection GoUnusedExportedFunction
func MonotonicTime() uint64 {
	var nanoseconds C.ulonglong
	nanoseconds = C.monotonic_time()
	return nanoseconds
}
<|endoftext|>


<commit_before>/*
	ToDD API - manages testruns

	Copyright 2016 Matt Oswalt. Use or modification of this
	source code is governed by the license provided here:
	https://github.com/Mierdin/todd/blob/master/LICENSE
*/

package api

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

	log "github.com/Sirupsen/logrus"

	"github.com/Mierdin/todd/server/objects"
	"github.com/Mierdin/todd/server/testrun"
)

// Run will activate an existing testrun
func (tapi ToDDApi) Run(w http.ResponseWriter, r *http.Request) {

	// Defer the closing of the body
	defer r.Body.Close()

	// Read the content into a byte array
	// (we're doing this so we can access the JSON contents more than once)
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	// anonymous struct to hold our testRun info
	testRunInfo := struct {
		TestRunName string `json:"testRunName"`
		SourceGroup string `json:"sourceGroup"`
		SourceApp   string `json:"sourceApp"`
		SourceArgs  string `json:"sourceArgs"`
	}{}

	// Marshal API data into our struct
	err = json.Unmarshal(body, &testRunInfo)
	if err != nil {
		panic(err)
	}

	// Retrieve list of existing testrun objects
	objectList, err := tapi.tdb.GetObjects("testrun")
	if err != nil {
		http.Error(w, "Internal Error", 500)
		return
	}

	// See if the requested object name exists within the current object store
	testRunExists := false
	var finalObj objects.ToddObject
	for i := range objectList {
		if objectList[i].GetLabel() == testRunInfo.TestRunName {
			testRunExists = true
			finalObj = objectList[i]
			break
		}
	}

	// If testrun object doesn't exist, send error message back to client. Otherwise, proceed with testrun.
	if !testRunExists {
		log.Warnf("Client requested run of testrun object, but %s was not found.", testRunInfo.TestRunName)
		fmt.Fprint(w, "notfound")
	}

	// Populate sourceOverrideMap dict
	sourceOverrideMap := map[string]string{
		"SourceGroup": testRunInfo.SourceGroup,
		"SourceApp":   testRunInfo.SourceApp,
		"SourceArgs":  testRunInfo.SourceArgs,
	}

	// Send back the testrun UUID
	testUUID := testrun.Start(tapi.cfg, finalObj.(objects.TestRunObject), sourceOverrideMap)
	fmt.Fprint(w, testUUID)
}

// TestData will retrieve clean test data by test UUID
func (tapi ToDDApi) TestData(w http.ResponseWriter, r *http.Request) {
	// Make sure UUID string is provided
	uuid := r.URL.Query().Get("uuid")
	if uuid == "" {
		fmt.Fprint(w, "Error, test UUID not provided.")
		return
	}

	testData, err := tapi.tdb.GetCleanTestData(uuid)
	if err != nil {
		fmt.Fprint(w, "Error, test UUID not found.")
		return
	}

	fmt.Fprint(w, testData)
}
<commit_msg>correct uuid back to testUuid<commit_after>/*
	ToDD API - manages testruns

	Copyright 2016 Matt Oswalt. Use or modification of this
	source code is governed by the license provided here:
	https://github.com/Mierdin/todd/blob/master/LICENSE
*/

package api

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

	log "github.com/Sirupsen/logrus"

	"github.com/Mierdin/todd/server/objects"
	"github.com/Mierdin/todd/server/testrun"
)

// Run will activate an existing testrun
func (tapi ToDDApi) Run(w http.ResponseWriter, r *http.Request) {

	// Defer the closing of the body
	defer r.Body.Close()

	// Read the content into a byte array
	// (we're doing this so we can access the JSON contents more than once)
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	// anonymous struct to hold our testRun info
	testRunInfo := struct {
		TestRunName string `json:"testRunName"`
		SourceGroup string `json:"sourceGroup"`
		SourceApp   string `json:"sourceApp"`
		SourceArgs  string `json:"sourceArgs"`
	}{}

	// Marshal API data into our struct
	err = json.Unmarshal(body, &testRunInfo)
	if err != nil {
		panic(err)
	}

	// Retrieve list of existing testrun objects
	objectList, err := tapi.tdb.GetObjects("testrun")
	if err != nil {
		http.Error(w, "Internal Error", 500)
		return
	}

	// See if the requested object name exists within the current object store
	testRunExists := false
	var finalObj objects.ToddObject
	for i := range objectList {
		if objectList[i].GetLabel() == testRunInfo.TestRunName {
			testRunExists = true
			finalObj = objectList[i]
			break
		}
	}

	// If testrun object doesn't exist, send error message back to client. Otherwise, proceed with testrun.
	if !testRunExists {
		log.Warnf("Client requested run of testrun object, but %s was not found.", testRunInfo.TestRunName)
		fmt.Fprint(w, "notfound")
	}

	// Populate sourceOverrideMap dict
	sourceOverrideMap := map[string]string{
		"SourceGroup": testRunInfo.SourceGroup,
		"SourceApp":   testRunInfo.SourceApp,
		"SourceArgs":  testRunInfo.SourceArgs,
	}

	// Send back the testrun UUID
	testUUID := testrun.Start(tapi.cfg, finalObj.(objects.TestRunObject), sourceOverrideMap)
	fmt.Fprint(w, testUUID)
}

// TestData will retrieve clean test data by test UUID
func (tapi ToDDApi) TestData(w http.ResponseWriter, r *http.Request) {
	// Make sure UUID string is provided
	uuid := r.URL.Query().Get("testUuid")
	if uuid == "" {
		fmt.Fprint(w, "Error, test UUID not provided.")
		return
	}

	testData, err := tapi.tdb.GetCleanTestData(uuid)
	if err != nil {
		fmt.Fprint(w, "Error, test UUID not found.")
		return
	}

	fmt.Fprint(w, testData)
}
<|endoftext|>


<commit_before>package models

import (
	"strings"
	"testing"

	"math/rand"

	"github.com/koding/bongo"
	"github.com/koding/runner"
	"labix.org/v2/mgo/bson"

	. "github.com/smartystreets/goconvey/convey"
)

func TestAccountNewAccount(t *testing.T) {
	Convey("while testing new account", t, func() {
		Convey("Function call should return account", func() {
			So(NewAccount(), ShouldNotBeNil)
		})
	})
}

func TestAccountGetId(t *testing.T) {
	Convey("while testing get id", t, func() {
		Convey("Initialized struct ", func() {
			Convey("should return given id", func() {
				a := Account{Id: 42}
				So(a.GetId(), ShouldEqual, 42)
			})

			Convey("Uninitialized struct ", func() {
				Convey("should return 0", func() {
					So(NewAccount().GetId(), ShouldEqual, 0)
				})
				So(NewAccount(), ShouldNotBeNil)
			})
		})
	})
}

func TestAccountFetchOrCreate(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while fetching or creating account", t, func() {
		Convey("it should have old id", func() {
			a := NewAccount()
			err := a.FetchOrCreate()
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, ErrOldIdIsNotSet)
		})

		Convey("it should have error if nick contains guest-", func() {
			a := NewAccount()
			a.OldId = "oldestId"
			a.Nick = "guest-test"
			err := a.FetchOrCreate()
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, ErrGuestsAreNotAllowed)
		})

		Convey("it should not have error if required fields are exist", func() {
			a := NewAccount()
			a.OldId = "oldIdOfAccount"
			a.Nick = "WhatANick"
			err := a.FetchOrCreate()
			So(err, ShouldBeNil)
		})

	})
}

func TestAccountFetchAccountById(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while fetching an account by id", t, func() {
		Convey("it should not have error while fething", func() {
			// create account
			acc := CreateAccountWithTest()
			So(acc.Create(), ShouldBeNil)

			// fetch the account by id of account
			fa, err := FetchAccountById(acc.Id)
			// error should be nil
			// means that fetching is done successfully
			So(err, ShouldBeNil)
			// account in the db should equal to fetched account
			So(fa.Id, ShouldEqual, acc.Id)
			So(fa.OldId, ShouldEqual, acc.OldId)
			So(fa.Nick, ShouldEqual, acc.Nick)
		})

		Convey("it should have error if record is not found", func() {
			// init account
			a := NewAccount()
			a.Id = 12345
			a.OldId = "oldIdOfAccount"
			a.Nick = "WhatANick"

			// this account id is not exist
			_, err := FetchAccountById(a.Id)
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, bongo.RecordNotFound)

		})

	})
}

func TestAccountByNick(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while fetching an account by nick", t, func() {
		Convey("it should not have error while fething", func() {
			// create account
			acc := CreateAccountWithTest()
			So(acc.Create(), ShouldBeNil)

			fa := NewAccount()

			// fetch the account by nick of account
			err := fa.ByNick(acc.Nick)
			// error should be nil
			// means that fetching is done successfully
			So(err, ShouldBeNil)
			// account in the db should be equal to fetched account
			So(fa.Id, ShouldEqual, acc.Id)
			So(fa.OldId, ShouldEqual, acc.OldId)
			So(fa.Nick, ShouldEqual, acc.Nick)
		})

		Convey("it should have error if nick is not set", func() {
			fa := NewAccount()
			err := fa.ByNick("")
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, ErrNickIsNotSet)
		})

		Convey("it should have error if record is not found", func() {
			fa := NewAccount()
			err := fa.ByNick("foobarzaa")
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, bongo.RecordNotFound)
		})

	})
}

func TestAccountFetchOldIdsByAccountIds(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while fetching Old Ids by account ids", t, func() {
		Convey("it should have account id (ids of length) more than zero", func() {
			acc := []int64{}
			foi, err := FetchOldIdsByAccountIds(acc)
			So(err, ShouldBeNil)
			So(foi, ShouldBeEmpty)
		})

		Convey("it should not have error if account is exist in db", func() {
			// create account
			acc := CreateAccountWithTest()
			So(acc.Create(), ShouldBeNil)
			// we created slice to send to FetchOldIdsByAccountIds as argument
			idd := []int64{acc.Id}

			// FetchOldIdsByAccountIds returns as slice
			foi, err := FetchOldIdsByAccountIds(idd)
			So(err, ShouldBeNil)
			// used shouldcontain because foi is a slice
			So(foi, ShouldContain, acc.OldId)

		})

		Convey("it should append successfully", func() {
			acc1 := NewAccount()
			acc1.OldId = bson.NewObjectId().Hex()
			acc1.Nick = bson.NewObjectId().Hex()
			So(acc1.Create(), ShouldBeNil)

			acc2 := NewAccount()
			acc2.OldId = bson.NewObjectId().Hex()
			acc2.Nick = bson.NewObjectId().Hex()
			So(acc2.Create(), ShouldBeNil)

			idd := []int64{acc1.Id, acc2.Id}
			old := []string{acc1.OldId, acc2.OldId}

			foi, err := FetchOldIdsByAccountIds(idd)
			So(err, ShouldBeNil)
			So(foi[1], ShouldEqual, old[1])

		})

	})
}

func TestAccountCreateFollowingFeedChannel(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while creating feed channel", t, func() {
		Convey("it should have account id", func() {
			// create account
			acc := NewAccount()

			_, err := acc.CreateFollowingFeedChannel()
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, ErrAccountIdIsNotSet)
		})

		Convey("it should have creator id as account id", func() {
			// create account
			acc := CreateAccountWithTest()
			So(acc.Create(), ShouldBeNil)

			cff, err := acc.CreateFollowingFeedChannel()
			So(err, ShouldBeNil)
			So(cff.CreatorId, ShouldEqual, acc.Id)
		})

		Convey("it should have channel name as required", func() {
			// create account
			acc := NewAccount()
			acc.OldId = bson.NewObjectId().Hex()
			acc.Nick = bson.NewObjectId().Hex()
			So(acc.Create(), ShouldBeNil)

			cff, err := acc.CreateFollowingFeedChannel()
			So(err, ShouldBeNil)
			So(strings.HasSuffix(cff.Name, "-FollowingFeedChannel"), ShouldBeTrue)
		})

		Convey("it should have group name as Channel_KODING_NAME", func() {
			// create account
			acc := CreateAccountWithTest()
			So(acc.Create(), ShouldBeNil)

			cff, err := acc.CreateFollowingFeedChannel()
			So(err, ShouldBeNil)
			So(cff.GroupName, ShouldEqual, Channel_KODING_NAME)
		})

		Convey("it should have purpose as Following Feed for me", func() {
			// create account
			acc := CreateAccountWithTest()
			So(acc.Create(), ShouldBeNil)

			cff, err := acc.CreateFollowingFeedChannel()
			So(err, ShouldBeNil)
			So(cff.Purpose, ShouldEqual, "Following Feed for Me")
		})

		Convey("it should have type constant as Channel_TYPE_FOLLOWERS", func() {
			// create account
			acc := CreateAccountWithTest()
			So(acc.Create(), ShouldBeNil)

			cff, err := acc.CreateFollowingFeedChannel()
			So(err, ShouldBeNil)
			So(cff.TypeConstant, ShouldEqual, Channel_TYPE_FOLLOWERS)
		})

	})
}

func TestAccountUnMarkAsTroll(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while unmarking as troll", t, func() {
		Convey("it should have account id", func() {
			acc := NewAccount()

			err := acc.UnMarkAsTroll()
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, ErrAccountIdIsNotSet)
		})

		Convey("it should have account in db", func() {
			acc := NewAccount()
			acc.Id = rand.Int63()
			err := acc.UnMarkAsTroll()
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, bongo.RecordNotFound)
		})

		// Convey("it should have error if not troll", func() {
		// 	// create account
		// 	acc := CreateAccountWithTest()
		// 	So(acc.Create(), ShouldBeNil)

		// 	err := acc.UnMarkAsTroll()
		// 	So(err, ShouldNotBeNil)
		// 	So(err.Error(), ShouldContainSubstring, "account is not a troll")
		// })

		Convey("it should not have error if troll is mark as not a troll", func() {
			// create account
			acc := CreateAccountWithTest()
			acc.IsTroll = true
			So(acc.Create(), ShouldBeNil)

			err := acc.UnMarkAsTroll()
			So(err, ShouldBeNil)
		})
	})
}

func TestAccountMarkAsTroll(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while marking account as troll", t, func() {
		Convey("it should have account id", func() {
			acc := NewAccount()

			err := acc.MarkAsTroll()
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, ErrAccountIdIsNotSet)
		})

		Convey("it should have account in db", func() {
			acc := NewAccount()
			acc.Id = 1122312

			err := acc.MarkAsTroll()
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, bongo.RecordNotFound)
		})

		// Convey("it should have error if account is already troll", func() {
		// 	// create account
		// 	acc := CreateAccountWithTest()
		// 	acc.IsTroll = true
		// 	So(acc.Create(), ShouldBeNil)

		// 	err := acc.MarkAsTroll()
		// 	So(err, ShouldNotBeNil)
		// 	So(err.Error(), ShouldContainSubstring, "account is already a troll")
		// })

		Convey("it should not have error if non-troll account is marked as troll", func() {
			// create account
			acc := CreateAccountWithTest()
			acc.IsTroll = false
			So(acc.Create(), ShouldBeNil)

			err := acc.MarkAsTroll()
			So(err, ShouldBeNil)
			So(acc.IsTroll, ShouldEqual, true)
		})

	})
}

func TestAccountFetchChannel(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while fetching channel", t, func() {
		Convey("it should have account id", func() {
			acc := NewAccount()

			_, err := acc.FetchChannel("ChannelType")
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, ErrAccountIdIsNotSet)
		})

		Convey("it should have error if channel is not exist", func() {
			acc := NewAccount()
			acc.Id = 35135

			_, err := acc.FetchChannel(Channel_TYPE_GROUP)
			So(err, ShouldNotBeNil)
			So(err, ShouldEqual, bongo.RecordNotFound)
		})

		Convey("it should not have error if channel type is exist", func() {

			// create account
			acc := CreateAccountWithTest()
			So(acc.Create(), ShouldBeNil)

			// create channel
			c := createNewChannelWithTest()
			c.CreatorId = acc.Id
			c.TypeConstant = Channel_TYPE_TOPIC
			So(c.Create(), ShouldBeNil)

			cha, err := acc.FetchChannel(Channel_TYPE_TOPIC)
			So(err, ShouldBeNil)
			So(cha.TypeConstant, ShouldEqual, c.TypeConstant)
		})

	})
}

func TestAccountsByNick(t *testing.T) {
	r := runner.New("test")
	if err := r.Init(); err != nil {
		t.Fatalf("couldnt start bongo %s", err.Error())
	}
	defer r.Close()

	Convey("while fetching account ids by nicknames", t, func() {
		Convey("it should not fetch any accounts when nicknames are empty", func() {
			nicknames := make([]string, 0)

			accounts, err := FetchAccountsByNicks(nicknames)
			So(err, ShouldBeNil)
			So(len(accounts), ShouldEqual, 0)
		})

		Convey("it should fetch accounts by nicknames", func() {
			acc1 := CreateAccountWithTest()
			acc2 := CreateAccountWithTest()
			nicknames := make([]string, 0)
			nicknames = append(nicknames, acc1.Nick, acc2.Nick)
			accounts, err := FetchAccountsByNicks(nicknames)
			So(err, ShouldBeNil)
			So(accounts, ShouldNotBeNil)
			So(len(accounts), ShouldEqual, 2)
		})
	})

}
<commit_msg>Socialapi: more clean up in account test file<commit_after>package models

import (
	"socialapi/workers/common/tests"
	"strings"
	"testing"

	"math/rand"

	"github.com/koding/bongo"
	"github.com/koding/runner"
	"labix.org/v2/mgo/bson"

	. "github.com/smartystreets/goconvey/convey"
)

func TestAccountNewAccount(t *testing.T) {
	Convey("while testing new account", t, func() {
		Convey("Function call should return account", func() {
			So(NewAccount(), ShouldNotBeNil)
		})
	})
}

func TestAccountGetId(t *testing.T) {
	Convey("while testing get id", t, func() {
		Convey("Initialized struct ", func() {
			Convey("should return given id", func() {
				a := Account{Id: 42}
				So(a.GetId(), ShouldEqual, 42)
			})

			Convey("Uninitialized struct ", func() {
				Convey("should return 0", func() {
					So(NewAccount().GetId(), ShouldEqual, 0)
				})
				So(NewAccount(), ShouldNotBeNil)
			})
		})
	})
}

func TestAccountFetchOrCreate(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {

		Convey("while fetching or creating account", t, func() {
			Convey("it should have old id", func() {
				a := NewAccount()
				err := a.FetchOrCreate()
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, ErrOldIdIsNotSet)
			})

			Convey("it should have error if nick contains guest-", func() {
				a := NewAccount()
				a.OldId = "oldestId"
				a.Nick = "guest-test"
				err := a.FetchOrCreate()
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, ErrGuestsAreNotAllowed)
			})

			Convey("it should not have error if required fields are exist", func() {
				a := NewAccount()
				a.OldId = "oldIdOfAccount"
				a.Nick = "WhatANick"
				err := a.FetchOrCreate()
				So(err, ShouldBeNil)
			})

		})
	})
}

func TestAccountFetchAccountById(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {

		Convey("while fetching an account by id", t, func() {
			Convey("it should not have error while fething", func() {
				// create account
				acc := CreateAccountWithTest()
				So(acc.Create(), ShouldBeNil)

				// fetch the account by id of account
				fa, err := FetchAccountById(acc.Id)
				// error should be nil
				// means that fetching is done successfully
				So(err, ShouldBeNil)
				// account in the db should equal to fetched account
				So(fa.Id, ShouldEqual, acc.Id)
				So(fa.OldId, ShouldEqual, acc.OldId)
				So(fa.Nick, ShouldEqual, acc.Nick)
			})

			Convey("it should have error if record is not found", func() {
				// init account
				a := NewAccount()
				a.Id = 12345
				a.OldId = "oldIdOfAccount"
				a.Nick = "WhatANick"

				// this account id is not exist
				_, err := FetchAccountById(a.Id)
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, bongo.RecordNotFound)

			})
		})
	})
}

func TestAccountByNick(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {

		Convey("while fetching an account by nick", t, func() {
			Convey("it should not have error while fething", func() {
				// create account
				acc := CreateAccountWithTest()
				So(acc.Create(), ShouldBeNil)

				fa := NewAccount()

				// fetch the account by nick of account
				err := fa.ByNick(acc.Nick)
				// error should be nil
				// means that fetching is done successfully
				So(err, ShouldBeNil)
				// account in the db should be equal to fetched account
				So(fa.Id, ShouldEqual, acc.Id)
				So(fa.OldId, ShouldEqual, acc.OldId)
				So(fa.Nick, ShouldEqual, acc.Nick)
			})

			Convey("it should have error if nick is not set", func() {
				fa := NewAccount()
				err := fa.ByNick("")
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, ErrNickIsNotSet)
			})

			Convey("it should have error if record is not found", func() {
				fa := NewAccount()
				err := fa.ByNick("foobarzaa")
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, bongo.RecordNotFound)
			})
		})
	})
}

func TestAccountFetchOldIdsByAccountIds(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {

		Convey("while fetching Old Ids by account ids", t, func() {
			Convey("it should have account id (ids of length) more than zero", func() {
				acc := []int64{}
				foi, err := FetchOldIdsByAccountIds(acc)
				So(err, ShouldBeNil)
				So(foi, ShouldBeEmpty)
			})

			Convey("it should not have error if account is exist in db", func() {
				// create account
				acc := CreateAccountWithTest()
				So(acc.Create(), ShouldBeNil)
				// we created slice to send to FetchOldIdsByAccountIds as argument
				idd := []int64{acc.Id}

				// FetchOldIdsByAccountIds returns as slice
				foi, err := FetchOldIdsByAccountIds(idd)
				So(err, ShouldBeNil)
				// used shouldcontain because foi is a slice
				So(foi, ShouldContain, acc.OldId)

			})

			Convey("it should append successfully", func() {
				acc1 := NewAccount()
				acc1.OldId = bson.NewObjectId().Hex()
				acc1.Nick = bson.NewObjectId().Hex()
				So(acc1.Create(), ShouldBeNil)

				acc2 := NewAccount()
				acc2.OldId = bson.NewObjectId().Hex()
				acc2.Nick = bson.NewObjectId().Hex()
				So(acc2.Create(), ShouldBeNil)

				idd := []int64{acc1.Id, acc2.Id}
				old := []string{acc1.OldId, acc2.OldId}

				foi, err := FetchOldIdsByAccountIds(idd)
				So(err, ShouldBeNil)
				So(foi[1], ShouldEqual, old[1])

			})
		})
	})
}

func TestAccountCreateFollowingFeedChannel(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {

		Convey("while creating feed channel", t, func() {
			Convey("it should have account id", func() {
				// create account
				acc := NewAccount()

				_, err := acc.CreateFollowingFeedChannel()
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, ErrAccountIdIsNotSet)
			})

			Convey("it should have creator id as account id", func() {
				// create account
				acc := CreateAccountWithTest()
				So(acc.Create(), ShouldBeNil)

				cff, err := acc.CreateFollowingFeedChannel()
				So(err, ShouldBeNil)
				So(cff.CreatorId, ShouldEqual, acc.Id)
			})

			Convey("it should have channel name as required", func() {
				// create account
				acc := NewAccount()
				acc.OldId = bson.NewObjectId().Hex()
				acc.Nick = bson.NewObjectId().Hex()
				So(acc.Create(), ShouldBeNil)

				cff, err := acc.CreateFollowingFeedChannel()
				So(err, ShouldBeNil)
				So(strings.HasSuffix(cff.Name, "-FollowingFeedChannel"), ShouldBeTrue)
			})

			Convey("it should have group name as Channel_KODING_NAME", func() {
				// create account
				acc := CreateAccountWithTest()
				So(acc.Create(), ShouldBeNil)

				cff, err := acc.CreateFollowingFeedChannel()
				So(err, ShouldBeNil)
				So(cff.GroupName, ShouldEqual, Channel_KODING_NAME)
			})

			Convey("it should have purpose as Following Feed for me", func() {
				// create account
				acc := CreateAccountWithTest()
				So(acc.Create(), ShouldBeNil)

				cff, err := acc.CreateFollowingFeedChannel()
				So(err, ShouldBeNil)
				So(cff.Purpose, ShouldEqual, "Following Feed for Me")
			})

			Convey("it should have type constant as Channel_TYPE_FOLLOWERS", func() {
				// create account
				acc := CreateAccountWithTest()
				So(acc.Create(), ShouldBeNil)

				cff, err := acc.CreateFollowingFeedChannel()
				So(err, ShouldBeNil)
				So(cff.TypeConstant, ShouldEqual, Channel_TYPE_FOLLOWERS)
			})
		})
	})
}

func TestAccountUnMarkAsTroll(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {

		Convey("while unmarking as troll", t, func() {
			Convey("it should have account id", func() {
				acc := NewAccount()

				err := acc.UnMarkAsTroll()
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, ErrAccountIdIsNotSet)
			})

			Convey("it should have account in db", func() {
				acc := NewAccount()
				acc.Id = rand.Int63()
				err := acc.UnMarkAsTroll()
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, bongo.RecordNotFound)
			})

			// Convey("it should have error if not troll", func() {
			// 	// create account
			// 	acc := CreateAccountWithTest()
			// 	So(acc.Create(), ShouldBeNil)

			// 	err := acc.UnMarkAsTroll()
			// 	So(err, ShouldNotBeNil)
			// 	So(err.Error(), ShouldContainSubstring, "account is not a troll")
			// })

			Convey("it should not have error if troll is mark as not a troll", func() {
				// create account
				acc := CreateAccountWithTest()
				acc.IsTroll = true
				So(acc.Create(), ShouldBeNil)

				err := acc.UnMarkAsTroll()
				So(err, ShouldBeNil)
			})
		})
	})
}

func TestAccountMarkAsTroll(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {
		Convey("while marking account as troll", t, func() {
			Convey("it should have account id", func() {
				acc := NewAccount()

				err := acc.MarkAsTroll()
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, ErrAccountIdIsNotSet)
			})

			Convey("it should have account in db", func() {
				acc := NewAccount()
				acc.Id = 1122312

				err := acc.MarkAsTroll()
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, bongo.RecordNotFound)
			})

			// Convey("it should have error if account is already troll", func() {
			// 	// create account
			// 	acc := CreateAccountWithTest()
			// 	acc.IsTroll = true
			// 	So(acc.Create(), ShouldBeNil)

			// 	err := acc.MarkAsTroll()
			// 	So(err, ShouldNotBeNil)
			// 	So(err.Error(), ShouldContainSubstring, "account is already a troll")
			// })

			Convey("it should not have error if non-troll account is marked as troll", func() {
				// create account
				acc := CreateAccountWithTest()
				acc.IsTroll = false
				So(acc.Create(), ShouldBeNil)

				err := acc.MarkAsTroll()
				So(err, ShouldBeNil)
				So(acc.IsTroll, ShouldEqual, true)
			})
		})
	})
}

func TestAccountFetchChannel(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {

		Convey("while fetching channel", t, func() {
			Convey("it should have account id", func() {
				acc := NewAccount()

				_, err := acc.FetchChannel("ChannelType")
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, ErrAccountIdIsNotSet)
			})

			Convey("it should have error if channel is not exist", func() {
				acc := NewAccount()
				acc.Id = 35135

				_, err := acc.FetchChannel(Channel_TYPE_GROUP)
				So(err, ShouldNotBeNil)
				So(err, ShouldEqual, bongo.RecordNotFound)
			})

			Convey("it should not have error if channel type is exist", func() {
				acc := CreateAccountWithTest()
				c := CreateTypedChannelWithTest(acc.Id, Channel_TYPE_TOPIC)

				cha, err := acc.FetchChannel(Channel_TYPE_TOPIC)
				So(err, ShouldBeNil)
				So(cha.TypeConstant, ShouldEqual, c.TypeConstant)
			})
		})
	})
}

func TestAccountsByNick(t *testing.T) {
	tests.WithRunner(t, func(r *runner.Runner) {

		Convey("while fetching account ids by nicknames", t, func() {
			Convey("it should not fetch any accounts when nicknames are empty", func() {
				nicknames := make([]string, 0)

				accounts, err := FetchAccountsByNicks(nicknames)
				So(err, ShouldBeNil)
				So(len(accounts), ShouldEqual, 0)
			})

			Convey("it should fetch accounts by nicknames", func() {
				acc1 := CreateAccountWithTest()
				acc2 := CreateAccountWithTest()
				nicknames := make([]string, 0)
				nicknames = append(nicknames, acc1.Nick, acc2.Nick)
				accounts, err := FetchAccountsByNicks(nicknames)
				So(err, ShouldBeNil)
				So(accounts, ShouldNotBeNil)
				So(len(accounts), ShouldEqual, 2)
			})
		})
	})
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"sync"

	"github.com/joho/godotenv"
)

func init() {
	log.Println("Starting RFC-Bot")
	if err := godotenv.Load(); err != nil {
		log.Fatal("Error loading .env file")
	}
}

func main() {
	log.Println("Initialising Writers")
	writer := NewWriter()

	log.Println("Initialising Twitter")
	twitter, err := NewTwitter(os.Getenv("TWITTER_CONSUMER_KEY"), os.Getenv("TWITTER_CONSUMER_SECRET"), os.Getenv("TWITTER_ACCESS_TOKEN"), os.Getenv("TWITTER_ACCESS_TOKEN_SECRET"))
	if err != nil {
		log.Fatal("Could not authenticate to twitter:", err)
	}
	writer.AddWriter(twitter)

	log.Println("Initialising Readers")
	var wg sync.WaitGroup
	wg.Add(2)
	go ietfRFC(writer.Wchan)
	go ietfDraftRFC(writer.Wchan)

	log.Println("Initialised")
	wg.Wait()
}
<commit_msg>Switch to runtime.Goexit instead of sync.WaitGroup as goroutines run forever<commit_after>package main

import (
	"log"
	"os"
	"runtime"

	"github.com/joho/godotenv"
)

func init() {
	log.Println("Starting RFC-Bot")
	if err := godotenv.Load(); err != nil {
		log.Fatal("Error loading .env file")
	}
}

func main() {
	log.Println("Initialising Writers")
	writer := NewWriter()

	log.Println("Initialising Twitter")
	twitter, err := NewTwitter(os.Getenv("TWITTER_CONSUMER_KEY"), os.Getenv("TWITTER_CONSUMER_SECRET"), os.Getenv("TWITTER_ACCESS_TOKEN"), os.Getenv("TWITTER_ACCESS_TOKEN_SECRET"))
	if err != nil {
		log.Fatal("Could not authenticate to twitter:", err)
	}
	writer.AddWriter(twitter)

	log.Println("Initialising Readers")
	go ietfRFC(writer.Wchan)
	go ietfDraftRFC(writer.Wchan)

	log.Println("Initialised")
	runtime.Goexit()
}
<|endoftext|>


<commit_before>package clideployment

import (
	"fmt"

	"github.com/containerum/chkit/pkg/configuration"

	"github.com/containerum/chkit/pkg/chkitErrors"
	"github.com/containerum/chkit/pkg/context"
	"github.com/containerum/chkit/pkg/model"
	"github.com/containerum/chkit/pkg/model/deployment"
	"github.com/containerum/chkit/pkg/util/angel"
	"github.com/containerum/chkit/pkg/util/strset"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

const (
	ErrNoNamespaceSpecified chkitErrors.Err = "no namespace specified"
)

var aliases = []string{"depl", "deployments", "deploy"}

func Get(ctx *context.Context) *cobra.Command {
	var getDeplDataConfig = struct {
		configuration.ExportConfig
	}{
		configuration.ExportConfig{
			Format: configuration.PRETTY,
		},
	}
	command := &cobra.Command{
		Use:     "deployment",
		Short:   "show deployment data",
		Long:    "Print deployment data.",
		Example: "namespace deployment_names... [-n namespace_label]",
		Aliases: aliases,
		Run: func(command *cobra.Command, args []string) {
			deplData, err := func() (model.Renderer, error) {
				switch len(args) {
				case 0:
					logrus.Debugf("getting deployment from %q", ctx.Namespace)
					list, err := ctx.Client.GetDeploymentList(ctx.Namespace.ID)
					if err != nil {
						return nil, err
					}
					return list, nil
				default:
					deplNames := strset.NewSet(args)
					var showList deployment.DeploymentList = make([]deployment.Deployment, 0) // prevents panic
					list, err := ctx.Client.GetDeploymentList(ctx.Namespace.ID)
					if err != nil {
						return nil, err
					}
					for _, depl := range list {
						if deplNames.Have(depl.Name) {
							showList = append(showList, depl)
						}
					}
					return showList, nil
				}
			}()
			if err != nil {
				logrus.WithError(err).Errorf("unable to get deployment data")
				fmt.Printf("%v :(\n", err)
				return
			}
			if err := configuration.ExportData(deplData, getDeplDataConfig.ExportConfig); err != nil {
				logrus.WithError(err).Errorf("unable to export data")
				angel.Angel(ctx, err)
			}
		},
	}

	command.PersistentFlags().
		StringVarP((*string)(&getDeplDataConfig.Format), "output", "o", "", "output format (yaml/json)")
	command.PersistentFlags().
		StringVarP(&getDeplDataConfig.Filename, "file", "f", "", "output file")

	return command
}
<commit_msg>refactor get deployment command<commit_after>package clideployment

import (
	"os"

	"github.com/containerum/chkit/pkg/chkitErrors"
	"github.com/containerum/chkit/pkg/configuration"
	"github.com/containerum/chkit/pkg/context"
	"github.com/containerum/chkit/pkg/model"
	"github.com/containerum/chkit/pkg/model/deployment"
	"github.com/containerum/chkit/pkg/util/angel"
	"github.com/containerum/chkit/pkg/util/ferr"
	"github.com/ninedraft/boxofstuff/strset"
	"github.com/octago/sflags/gen/gpflag"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

const (
	ErrNoNamespaceSpecified chkitErrors.Err = "no namespace specified"
)

var aliases = []string{"depl", "deployments", "deploy"}

func Get(ctx *context.Context) *cobra.Command {
	var flags struct {
		File   string `desc:"output file, STDOUT by default"`
		Output string `flag:"output o" desc:"output format, json/yaml"`
	}
	command := &cobra.Command{
		Use:     "deployment",
		Short:   "show deployment data",
		Long:    "Print deployment data.",
		Example: "namespace deployment_names... [-n namespace_label]",
		Aliases: aliases,
		Run: func(command *cobra.Command, args []string) {
			var logger = ctx.Log.Command("get deployment")
			logger.Debugf("START")
			defer logrus.Debugf("END")
			var deplData model.Renderer
			if len(args) == 1 {
				var depl, err = ctx.Client.GetDeployment(ctx.Namespace.ID, args[0])
				if err != nil {
					ferr.Println(err)
					os.Exit(1)
				}
				deplData = depl
			} else {
				var list, err = ctx.Client.GetDeploymentList(ctx.Namespace.ID)
				if err != nil {
					ferr.Println(err)
					os.Exit(1)
				}
				var names = strset.NewSet(args)
				list = list.Filter(func(depl deployment.Deployment) bool {
					return names.Have(depl.Name)
				})
				deplData = list
			}
			if err := configuration.ExportData(deplData, configuration.ExportConfig{
				Format:   configuration.ExportFormat(flags.Output),
				Filename: flags.File,
			}); err != nil {
				logrus.WithError(err).Errorf("unable to export data")
				angel.Angel(ctx, err)
			}
		},
	}
	if err := gpflag.ParseTo(&flags, command.PersistentFlags()); err != nil {
		panic(err)
	}
	return command
}
<|endoftext|>


<commit_before>package quic

import (
	"context"
	"errors"
	"io"
	"net"
	"time"

	"github.com/lucas-clemente/quic-go/internal/handshake"
	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/logging"
)

// The StreamID is the ID of a QUIC stream.
type StreamID = protocol.StreamID

// A VersionNumber is a QUIC version number.
type VersionNumber = protocol.VersionNumber

const (
	// VersionDraft29 is IETF QUIC draft-29
	VersionDraft29 = protocol.VersionDraft29
	// Version1 is RFC 9000
	Version1 = protocol.Version1
)

// A Token can be used to verify the ownership of the client address.
type Token struct {
	// IsRetryToken encodes how the client received the token. There are two ways:
	// * In a Retry packet sent when trying to establish a new connection.
	// * In a NEW_TOKEN frame on a previous connection.
	IsRetryToken bool
	RemoteAddr   string
	SentTime     time.Time
}

// A ClientToken is a token received by the client.
// It can be used to skip address validation on future connection attempts.
type ClientToken struct {
	data []byte
}

type TokenStore interface {
	// Pop searches for a ClientToken associated with the given key.
	// Since tokens are not supposed to be reused, it must remove the token from the cache.
	// It returns nil when no token is found.
	Pop(key string) (token *ClientToken)

	// Put adds a token to the cache with the given key. It might get called
	// multiple times in a connection.
	Put(key string, token *ClientToken)
}

// Err0RTTRejected is the returned from:
// * Open{Uni}Stream{Sync}
// * Accept{Uni}Stream
// * Stream.Read and Stream.Write
// when the server rejects a 0-RTT connection attempt.
var Err0RTTRejected = errors.New("0-RTT rejected")

// ConnectionTracingKey can be used to associate a ConnectionTracer with a Connection.
// It is set on the Connection.Context() context,
// as well as on the context passed to logging.Tracer.NewConnectionTracer.
var ConnectionTracingKey = connTracingCtxKey{}

type connTracingCtxKey struct{}

// Stream is the interface implemented by QUIC streams
// In addition to the errors listed on the Connection,
// calls to stream functions can return a StreamError if the stream is canceled.
type Stream interface {
	ReceiveStream
	SendStream
	// SetDeadline sets the read and write deadlines associated
	// with the connection. It is equivalent to calling both
	// SetReadDeadline and SetWriteDeadline.
	SetDeadline(t time.Time) error
}

// A ReceiveStream is a unidirectional Receive Stream.
type ReceiveStream interface {
	// StreamID returns the stream ID.
	StreamID() StreamID
	// Read reads data from the stream.
	// Read can be made to time out and return a net.Error with Timeout() == true
	// after a fixed time limit; see SetDeadline and SetReadDeadline.
	// If the stream was canceled by the peer, the error implements the StreamError
	// interface, and Canceled() == true.
	// If the connection was closed due to a timeout, the error satisfies
	// the net.Error interface, and Timeout() will be true.
	io.Reader
	// CancelRead aborts receiving on this stream.
	// It will ask the peer to stop transmitting stream data.
	// Read will unblock immediately, and future Read calls will fail.
	// When called multiple times or after reading the io.EOF it is a no-op.
	CancelRead(StreamErrorCode)
	// SetReadDeadline sets the deadline for future Read calls and
	// any currently-blocked Read call.
	// A zero value for t means Read will not time out.

	SetReadDeadline(t time.Time) error
}

// A SendStream is a unidirectional Send Stream.
type SendStream interface {
	// StreamID returns the stream ID.
	StreamID() StreamID
	// Write writes data to the stream.
	// Write can be made to time out and return a net.Error with Timeout() == true
	// after a fixed time limit; see SetDeadline and SetWriteDeadline.
	// If the stream was canceled by the peer, the error implements the StreamError
	// interface, and Canceled() == true.
	// If the connection was closed due to a timeout, the error satisfies
	// the net.Error interface, and Timeout() will be true.
	io.Writer
	// Close closes the write-direction of the stream.
	// Future calls to Write are not permitted after calling Close.
	// It must not be called concurrently with Write.
	// It must not be called after calling CancelWrite.
	io.Closer
	// CancelWrite aborts sending on this stream.
	// Data already written, but not yet delivered to the peer is not guaranteed to be delivered reliably.
	// Write will unblock immediately, and future calls to Write will fail.
	// When called multiple times or after closing the stream it is a no-op.
	CancelWrite(StreamErrorCode)
	// The Context is canceled as soon as the write-side of the stream is closed.
	// This happens when Close() or CancelWrite() is called, or when the peer
	// cancels the read-side of their stream.
	Context() context.Context
	// SetWriteDeadline sets the deadline for future Write calls
	// and any currently-blocked Write call.
	// Even if write times out, it may return n > 0, indicating that
	// some data was successfully written.
	// A zero value for t means Write will not time out.
	SetWriteDeadline(t time.Time) error
}

// A Connection is a QUIC connection between two peers.
// Calls to the connection (and to streams) can return the following types of errors:
// * ApplicationError: for errors triggered by the application running on top of QUIC
// * TransportError: for errors triggered by the QUIC transport (in many cases a misbehaving peer)
// * IdleTimeoutError: when the peer goes away unexpectedly (this is a net.Error timeout error)
// * HandshakeTimeoutError: when the cryptographic handshake takes too long (this is a net.Error timeout error)
// * StatelessResetError: when we receive a stateless reset (this is a net.Error temporary error)
// * VersionNegotiationError: returned by the client, when there's no version overlap between the peers
type Connection interface {
	// AcceptStream returns the next stream opened by the peer, blocking until one is available.
	// If the connection was closed due to a timeout, the error satisfies
	// the net.Error interface, and Timeout() will be true.
	AcceptStream(context.Context) (Stream, error)
	// AcceptUniStream returns the next unidirectional stream opened by the peer, blocking until one is available.
	// If the connection was closed due to a timeout, the error satisfies
	// the net.Error interface, and Timeout() will be true.
	AcceptUniStream(context.Context) (ReceiveStream, error)
	// OpenStream opens a new bidirectional QUIC stream.
	// There is no signaling to the peer about new streams:
	// The peer can only accept the stream after data has been sent on the stream.
	// If the error is non-nil, it satisfies the net.Error interface.
	// When reaching the peer's stream limit, err.Temporary() will be true.
	// If the connection was closed due to a timeout, Timeout() will be true.
	OpenStream() (Stream, error)
	// OpenStreamSync opens a new bidirectional QUIC stream.
	// It blocks until a new stream can be opened.
	// If the error is non-nil, it satisfies the net.Error interface.
	// If the connection was closed due to a timeout, Timeout() will be true.
	OpenStreamSync(context.Context) (Stream, error)
	// OpenUniStream opens a new outgoing unidirectional QUIC stream.
	// If the error is non-nil, it satisfies the net.Error interface.
	// When reaching the peer's stream limit, Temporary() will be true.
	// If the connection was closed due to a timeout, Timeout() will be true.
	OpenUniStream() (SendStream, error)
	// OpenUniStreamSync opens a new outgoing unidirectional QUIC stream.
	// It blocks until a new stream can be opened.
	// If the error is non-nil, it satisfies the net.Error interface.
	// If the connection was closed due to a timeout, Timeout() will be true.
	OpenUniStreamSync(context.Context) (SendStream, error)
	// LocalAddr returns the local address.
	LocalAddr() net.Addr
	// RemoteAddr returns the address of the peer.
	RemoteAddr() net.Addr
	// CloseWithError closes the connection with an error.
	// The error string will be sent to the peer.
	CloseWithError(ApplicationErrorCode, string) error
	// The context is cancelled when the connection is closed.
	Context() context.Context
	// ConnectionState returns basic details about the QUIC connection.
	// It blocks until the handshake completes.
	// Warning: This API should not be considered stable and might change soon.
	ConnectionState() ConnectionState

	// SendMessage sends a message as a datagram, as specified in RFC 9221.
	SendMessage([]byte) error
	// ReceiveMessage gets a message received in a datagram, as specified in RFC 9221.
	ReceiveMessage() ([]byte, error)
}

// An EarlyConnection is a connection that is handshaking.
// Data sent during the handshake is encrypted using the forward secure keys.
// When using client certificates, the client's identity is only verified
// after completion of the handshake.
type EarlyConnection interface {
	Connection

	// HandshakeComplete blocks until the handshake completes (or fails).
	// Data sent before completion of the handshake is encrypted with 1-RTT keys.
	// Note that the client's identity hasn't been verified yet.
	HandshakeComplete() context.Context

	NextConnection() Connection
}

// Config contains all configuration data needed for a QUIC server or client.
type Config struct {
	// The QUIC versions that can be negotiated.
	// If not set, it uses all versions available.
	Versions []VersionNumber
	// The length of the connection ID in bytes.
	// It can be 0, or any value between 4 and 18.
	// If not set, the interpretation depends on where the Config is used:
	// If used for dialing an address, a 0 byte connection ID will be used.
	// If used for a server, or dialing on a packet conn, a 4 byte connection ID will be used.
	// When dialing on a packet conn, the ConnectionIDLength value must be the same for every Dial call.
	ConnectionIDLength int
	// HandshakeIdleTimeout is the idle timeout before completion of the handshake.
	// Specifically, if we don't receive any packet from the peer within this time, the connection attempt is aborted.
	// If this value is zero, the timeout is set to 5 seconds.
	HandshakeIdleTimeout time.Duration
	// MaxIdleTimeout is the maximum duration that may pass without any incoming network activity.
	// The actual value for the idle timeout is the minimum of this value and the peer's.
	// This value only applies after the handshake has completed.
	// If the timeout is exceeded, the connection is closed.
	// If this value is zero, the timeout is set to 30 seconds.
	MaxIdleTimeout time.Duration
	// AcceptToken determines if a Token is accepted.
	// It is called with token = nil if the client didn't send a token.
	// If not set, a default verification function is used:
	// * it verifies that the address matches, and
	//   * if the token is a retry token, that it was issued within the last 5 seconds
	//   * else, that it was issued within the last 24 hours.
	// This option is only valid for the server.
	AcceptToken func(clientAddr net.Addr, token *Token) bool
	// The TokenStore stores tokens received from the server.
	// Tokens are used to skip address validation on future connection attempts.
	// The key used to store tokens is the ServerName from the tls.Config, if set
	// otherwise the token is associated with the server's IP address.
	TokenStore TokenStore
	// InitialStreamReceiveWindow is the initial size of the stream-level flow control window for receiving data.
	// If the application is consuming data quickly enough, the flow control auto-tuning algorithm
	// will increase the window up to MaxStreamReceiveWindow.
	// If this value is zero, it will default to 512 KB.
	InitialStreamReceiveWindow uint64
	// MaxStreamReceiveWindow is the maximum stream-level flow control window for receiving data.
	// If this value is zero, it will default to 6 MB.
	MaxStreamReceiveWindow uint64
	// InitialConnectionReceiveWindow is the initial size of the stream-level flow control window for receiving data.
	// If the application is consuming data quickly enough, the flow control auto-tuning algorithm
	// will increase the window up to MaxConnectionReceiveWindow.
	// If this value is zero, it will default to 512 KB.
	InitialConnectionReceiveWindow uint64
	// MaxConnectionReceiveWindow is the connection-level flow control window for receiving data.
	// If this value is zero, it will default to 15 MB.
	MaxConnectionReceiveWindow uint64
	// AllowConnectionWindowIncrease is called every time the connection flow controller attempts
	// to increase the connection flow control window.
	// If set, the caller can prevent an increase of the window. Typically, it would do so to
	// limit the memory usage.
	// To avoid deadlocks, it is not valid to call other functions on the connection or on streams
	// in this callback.
	AllowConnectionWindowIncrease func(sess Connection, delta uint64) bool
	// MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open.
	// Values above 2^60 are invalid.
	// If not set, it will default to 100.
	// If set to a negative value, it doesn't allow any bidirectional streams.
	MaxIncomingStreams int64
	// MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open.
	// Values above 2^60 are invalid.
	// If not set, it will default to 100.
	// If set to a negative value, it doesn't allow any unidirectional streams.
	MaxIncomingUniStreams int64
	// The StatelessResetKey is used to generate stateless reset tokens.
	// If no key is configured, sending of stateless resets is disabled.
	StatelessResetKey []byte
	// KeepAlive defines whether this peer will periodically send a packet to keep the connection alive.
	KeepAlive bool
	// DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899).
	// Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.
	// Note that if Path MTU discovery is causing issues on your system, please open a new issue
	DisablePathMTUDiscovery bool
	// DisableVersionNegotiationPackets disables the sending of Version Negotiation packets.
	// This can be useful if version information is exchanged out-of-band.
	// It has no effect for a client.
	DisableVersionNegotiationPackets bool
	// See https://datatracker.ietf.org/doc/draft-ietf-quic-datagram/.
	// Datagrams will only be available when both peers enable datagram support.
	EnableDatagrams bool
	Tracer          logging.Tracer
}

// ConnectionState records basic details about a QUIC connection
type ConnectionState struct {
	TLS               handshake.ConnectionState
	SupportsDatagrams bool
}

// A Listener for incoming QUIC connections
type Listener interface {
	// Close the server. All active connections will be closed.
	Close() error
	// Addr returns the local network addr that the server is listening on.
	Addr() net.Addr
	// Accept returns new connections. It should be called in a loop.
	Accept(context.Context) (Connection, error)
}

// An EarlyListener listens for incoming QUIC connections,
// and returns them before the handshake completes.
type EarlyListener interface {
	// Close the server. All active connections will be closed.
	Close() error
	// Addr returns the local network addr that the server is listening on.
	Addr() net.Addr
	// Accept returns new early connections. It should be called in a loop.
	Accept(context.Context) (EarlyConnection, error)
}
<commit_msg>export quic.Version2<commit_after>package quic

import (
	"context"
	"errors"
	"io"
	"net"
	"time"

	"github.com/lucas-clemente/quic-go/internal/handshake"
	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/logging"
)

// The StreamID is the ID of a QUIC stream.
type StreamID = protocol.StreamID

// A VersionNumber is a QUIC version number.
type VersionNumber = protocol.VersionNumber

const (
	// VersionDraft29 is IETF QUIC draft-29
	VersionDraft29 = protocol.VersionDraft29
	// Version1 is RFC 9000
	Version1 = protocol.Version1
	Version2 = protocol.Version2
)

// A Token can be used to verify the ownership of the client address.
type Token struct {
	// IsRetryToken encodes how the client received the token. There are two ways:
	// * In a Retry packet sent when trying to establish a new connection.
	// * In a NEW_TOKEN frame on a previous connection.
	IsRetryToken bool
	RemoteAddr   string
	SentTime     time.Time
}

// A ClientToken is a token received by the client.
// It can be used to skip address validation on future connection attempts.
type ClientToken struct {
	data []byte
}

type TokenStore interface {
	// Pop searches for a ClientToken associated with the given key.
	// Since tokens are not supposed to be reused, it must remove the token from the cache.
	// It returns nil when no token is found.
	Pop(key string) (token *ClientToken)

	// Put adds a token to the cache with the given key. It might get called
	// multiple times in a connection.
	Put(key string, token *ClientToken)
}

// Err0RTTRejected is the returned from:
// * Open{Uni}Stream{Sync}
// * Accept{Uni}Stream
// * Stream.Read and Stream.Write
// when the server rejects a 0-RTT connection attempt.
var Err0RTTRejected = errors.New("0-RTT rejected")

// ConnectionTracingKey can be used to associate a ConnectionTracer with a Connection.
// It is set on the Connection.Context() context,
// as well as on the context passed to logging.Tracer.NewConnectionTracer.
var ConnectionTracingKey = connTracingCtxKey{}

type connTracingCtxKey struct{}

// Stream is the interface implemented by QUIC streams
// In addition to the errors listed on the Connection,
// calls to stream functions can return a StreamError if the stream is canceled.
type Stream interface {
	ReceiveStream
	SendStream
	// SetDeadline sets the read and write deadlines associated
	// with the connection. It is equivalent to calling both
	// SetReadDeadline and SetWriteDeadline.
	SetDeadline(t time.Time) error
}

// A ReceiveStream is a unidirectional Receive Stream.
type ReceiveStream interface {
	// StreamID returns the stream ID.
	StreamID() StreamID
	// Read reads data from the stream.
	// Read can be made to time out and return a net.Error with Timeout() == true
	// after a fixed time limit; see SetDeadline and SetReadDeadline.
	// If the stream was canceled by the peer, the error implements the StreamError
	// interface, and Canceled() == true.
	// If the connection was closed due to a timeout, the error satisfies
	// the net.Error interface, and Timeout() will be true.
	io.Reader
	// CancelRead aborts receiving on this stream.
	// It will ask the peer to stop transmitting stream data.
	// Read will unblock immediately, and future Read calls will fail.
	// When called multiple times or after reading the io.EOF it is a no-op.
	CancelRead(StreamErrorCode)
	// SetReadDeadline sets the deadline for future Read calls and
	// any currently-blocked Read call.
	// A zero value for t means Read will not time out.

	SetReadDeadline(t time.Time) error
}

// A SendStream is a unidirectional Send Stream.
type SendStream interface {
	// StreamID returns the stream ID.
	StreamID() StreamID
	// Write writes data to the stream.
	// Write can be made to time out and return a net.Error with Timeout() == true
	// after a fixed time limit; see SetDeadline and SetWriteDeadline.
	// If the stream was canceled by the peer, the error implements the StreamError
	// interface, and Canceled() == true.
	// If the connection was closed due to a timeout, the error satisfies
	// the net.Error interface, and Timeout() will be true.
	io.Writer
	// Close closes the write-direction of the stream.
	// Future calls to Write are not permitted after calling Close.
	// It must not be called concurrently with Write.
	// It must not be called after calling CancelWrite.
	io.Closer
	// CancelWrite aborts sending on this stream.
	// Data already written, but not yet delivered to the peer is not guaranteed to be delivered reliably.
	// Write will unblock immediately, and future calls to Write will fail.
	// When called multiple times or after closing the stream it is a no-op.
	CancelWrite(StreamErrorCode)
	// The Context is canceled as soon as the write-side of the stream is closed.
	// This happens when Close() or CancelWrite() is called, or when the peer
	// cancels the read-side of their stream.
	Context() context.Context
	// SetWriteDeadline sets the deadline for future Write calls
	// and any currently-blocked Write call.
	// Even if write times out, it may return n > 0, indicating that
	// some data was successfully written.
	// A zero value for t means Write will not time out.
	SetWriteDeadline(t time.Time) error
}

// A Connection is a QUIC connection between two peers.
// Calls to the connection (and to streams) can return the following types of errors:
// * ApplicationError: for errors triggered by the application running on top of QUIC
// * TransportError: for errors triggered by the QUIC transport (in many cases a misbehaving peer)
// * IdleTimeoutError: when the peer goes away unexpectedly (this is a net.Error timeout error)
// * HandshakeTimeoutError: when the cryptographic handshake takes too long (this is a net.Error timeout error)
// * StatelessResetError: when we receive a stateless reset (this is a net.Error temporary error)
// * VersionNegotiationError: returned by the client, when there's no version overlap between the peers
type Connection interface {
	// AcceptStream returns the next stream opened by the peer, blocking until one is available.
	// If the connection was closed due to a timeout, the error satisfies
	// the net.Error interface, and Timeout() will be true.
	AcceptStream(context.Context) (Stream, error)
	// AcceptUniStream returns the next unidirectional stream opened by the peer, blocking until one is available.
	// If the connection was closed due to a timeout, the error satisfies
	// the net.Error interface, and Timeout() will be true.
	AcceptUniStream(context.Context) (ReceiveStream, error)
	// OpenStream opens a new bidirectional QUIC stream.
	// There is no signaling to the peer about new streams:
	// The peer can only accept the stream after data has been sent on the stream.
	// If the error is non-nil, it satisfies the net.Error interface.
	// When reaching the peer's stream limit, err.Temporary() will be true.
	// If the connection was closed due to a timeout, Timeout() will be true.
	OpenStream() (Stream, error)
	// OpenStreamSync opens a new bidirectional QUIC stream.
	// It blocks until a new stream can be opened.
	// If the error is non-nil, it satisfies the net.Error interface.
	// If the connection was closed due to a timeout, Timeout() will be true.
	OpenStreamSync(context.Context) (Stream, error)
	// OpenUniStream opens a new outgoing unidirectional QUIC stream.
	// If the error is non-nil, it satisfies the net.Error interface.
	// When reaching the peer's stream limit, Temporary() will be true.
	// If the connection was closed due to a timeout, Timeout() will be true.
	OpenUniStream() (SendStream, error)
	// OpenUniStreamSync opens a new outgoing unidirectional QUIC stream.
	// It blocks until a new stream can be opened.
	// If the error is non-nil, it satisfies the net.Error interface.
	// If the connection was closed due to a timeout, Timeout() will be true.
	OpenUniStreamSync(context.Context) (SendStream, error)
	// LocalAddr returns the local address.
	LocalAddr() net.Addr
	// RemoteAddr returns the address of the peer.
	RemoteAddr() net.Addr
	// CloseWithError closes the connection with an error.
	// The error string will be sent to the peer.
	CloseWithError(ApplicationErrorCode, string) error
	// The context is cancelled when the connection is closed.
	Context() context.Context
	// ConnectionState returns basic details about the QUIC connection.
	// It blocks until the handshake completes.
	// Warning: This API should not be considered stable and might change soon.
	ConnectionState() ConnectionState

	// SendMessage sends a message as a datagram, as specified in RFC 9221.
	SendMessage([]byte) error
	// ReceiveMessage gets a message received in a datagram, as specified in RFC 9221.
	ReceiveMessage() ([]byte, error)
}

// An EarlyConnection is a connection that is handshaking.
// Data sent during the handshake is encrypted using the forward secure keys.
// When using client certificates, the client's identity is only verified
// after completion of the handshake.
type EarlyConnection interface {
	Connection

	// HandshakeComplete blocks until the handshake completes (or fails).
	// Data sent before completion of the handshake is encrypted with 1-RTT keys.
	// Note that the client's identity hasn't been verified yet.
	HandshakeComplete() context.Context

	NextConnection() Connection
}

// Config contains all configuration data needed for a QUIC server or client.
type Config struct {
	// The QUIC versions that can be negotiated.
	// If not set, it uses all versions available.
	Versions []VersionNumber
	// The length of the connection ID in bytes.
	// It can be 0, or any value between 4 and 18.
	// If not set, the interpretation depends on where the Config is used:
	// If used for dialing an address, a 0 byte connection ID will be used.
	// If used for a server, or dialing on a packet conn, a 4 byte connection ID will be used.
	// When dialing on a packet conn, the ConnectionIDLength value must be the same for every Dial call.
	ConnectionIDLength int
	// HandshakeIdleTimeout is the idle timeout before completion of the handshake.
	// Specifically, if we don't receive any packet from the peer within this time, the connection attempt is aborted.
	// If this value is zero, the timeout is set to 5 seconds.
	HandshakeIdleTimeout time.Duration
	// MaxIdleTimeout is the maximum duration that may pass without any incoming network activity.
	// The actual value for the idle timeout is the minimum of this value and the peer's.
	// This value only applies after the handshake has completed.
	// If the timeout is exceeded, the connection is closed.
	// If this value is zero, the timeout is set to 30 seconds.
	MaxIdleTimeout time.Duration
	// AcceptToken determines if a Token is accepted.
	// It is called with token = nil if the client didn't send a token.
	// If not set, a default verification function is used:
	// * it verifies that the address matches, and
	//   * if the token is a retry token, that it was issued within the last 5 seconds
	//   * else, that it was issued within the last 24 hours.
	// This option is only valid for the server.
	AcceptToken func(clientAddr net.Addr, token *Token) bool
	// The TokenStore stores tokens received from the server.
	// Tokens are used to skip address validation on future connection attempts.
	// The key used to store tokens is the ServerName from the tls.Config, if set
	// otherwise the token is associated with the server's IP address.
	TokenStore TokenStore
	// InitialStreamReceiveWindow is the initial size of the stream-level flow control window for receiving data.
	// If the application is consuming data quickly enough, the flow control auto-tuning algorithm
	// will increase the window up to MaxStreamReceiveWindow.
	// If this value is zero, it will default to 512 KB.
	InitialStreamReceiveWindow uint64
	// MaxStreamReceiveWindow is the maximum stream-level flow control window for receiving data.
	// If this value is zero, it will default to 6 MB.
	MaxStreamReceiveWindow uint64
	// InitialConnectionReceiveWindow is the initial size of the stream-level flow control window for receiving data.
	// If the application is consuming data quickly enough, the flow control auto-tuning algorithm
	// will increase the window up to MaxConnectionReceiveWindow.
	// If this value is zero, it will default to 512 KB.
	InitialConnectionReceiveWindow uint64
	// MaxConnectionReceiveWindow is the connection-level flow control window for receiving data.
	// If this value is zero, it will default to 15 MB.
	MaxConnectionReceiveWindow uint64
	// AllowConnectionWindowIncrease is called every time the connection flow controller attempts
	// to increase the connection flow control window.
	// If set, the caller can prevent an increase of the window. Typically, it would do so to
	// limit the memory usage.
	// To avoid deadlocks, it is not valid to call other functions on the connection or on streams
	// in this callback.
	AllowConnectionWindowIncrease func(sess Connection, delta uint64) bool
	// MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open.
	// Values above 2^60 are invalid.
	// If not set, it will default to 100.
	// If set to a negative value, it doesn't allow any bidirectional streams.
	MaxIncomingStreams int64
	// MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open.
	// Values above 2^60 are invalid.
	// If not set, it will default to 100.
	// If set to a negative value, it doesn't allow any unidirectional streams.
	MaxIncomingUniStreams int64
	// The StatelessResetKey is used to generate stateless reset tokens.
	// If no key is configured, sending of stateless resets is disabled.
	StatelessResetKey []byte
	// KeepAlive defines whether this peer will periodically send a packet to keep the connection alive.
	KeepAlive bool
	// DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899).
	// Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.
	// Note that if Path MTU discovery is causing issues on your system, please open a new issue
	DisablePathMTUDiscovery bool
	// DisableVersionNegotiationPackets disables the sending of Version Negotiation packets.
	// This can be useful if version information is exchanged out-of-band.
	// It has no effect for a client.
	DisableVersionNegotiationPackets bool
	// See https://datatracker.ietf.org/doc/draft-ietf-quic-datagram/.
	// Datagrams will only be available when both peers enable datagram support.
	EnableDatagrams bool
	Tracer          logging.Tracer
}

// ConnectionState records basic details about a QUIC connection
type ConnectionState struct {
	TLS               handshake.ConnectionState
	SupportsDatagrams bool
}

// A Listener for incoming QUIC connections
type Listener interface {
	// Close the server. All active connections will be closed.
	Close() error
	// Addr returns the local network addr that the server is listening on.
	Addr() net.Addr
	// Accept returns new connections. It should be called in a loop.
	Accept(context.Context) (Connection, error)
}

// An EarlyListener listens for incoming QUIC connections,
// and returns them before the handshake completes.
type EarlyListener interface {
	// Close the server. All active connections will be closed.
	Close() error
	// Addr returns the local network addr that the server is listening on.
	Addr() net.Addr
	// Accept returns new early connections. It should be called in a loop.
	Accept(context.Context) (EarlyConnection, error)
}
<|endoftext|>


<commit_before>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.0.61"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<commit_msg>functions: 0.0.62 release [skip ci]<commit_after>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.0.62"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<|endoftext|>