<commit_before>package toolbox_test

import (
	"os"
	"testing"

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

func TestOpenURL(t *testing.T) {
	fileName, _, _ := toolbox.CallerInfo(2)
	{
		file, err := toolbox.OpenURL(toolbox.FileSchema+fileName, os.O_RDONLY, 0644)
		assert.Nil(t, err)
		defer file.Close()
	}
	{
		_, err := toolbox.OpenURL(toolbox.FileSchema+fileName+"bleh_bleh", os.O_RDONLY, 0644)
		assert.NotNil(t, err)
	}

	{
		_, err := toolbox.OpenURL("https://github.com/viant/toolbox", os.O_RDONLY, 0644)
		assert.NotNil(t, err, "only file protocol is supported")
	}

}

func TestOpenReaderFromURL(t *testing.T) {
	fileName, _, _ := toolbox.CallerInfo(2)
	{
		file, _, err := toolbox.OpenReaderFromURL(toolbox.FileSchema + fileName)
		assert.Nil(t, err)
		defer file.Close()
	}
	{
		_, _, err := toolbox.OpenReaderFromURL(toolbox.FileSchema + fileName + "blahbla")
		assert.NotNil(t, err)
	}

	{
		file, _, err := toolbox.OpenReaderFromURL("https://github.com/viant/toolbox")
		assert.Nil(t, err)
		defer file.Close()
	}

	{
		_, _, err := toolbox.OpenReaderFromURL("abc://github.com/viant/toolbox")
		assert.NotNil(t, err)
	}
}
<commit_msg>added test for query value<commit_after>package toolbox_test

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/viant/toolbox"
	"net/url"
)

func TestOpenURL(t *testing.T) {
	fileName, _, _ := toolbox.CallerInfo(2)
	{
		file, err := toolbox.OpenURL(toolbox.FileSchema+fileName, os.O_RDONLY, 0644)
		assert.Nil(t, err)
		defer file.Close()
	}
	{
		_, err := toolbox.OpenURL(toolbox.FileSchema+fileName+"bleh_bleh", os.O_RDONLY, 0644)
		assert.NotNil(t, err)
	}

	{
		_, err := toolbox.OpenURL("https://github.com/viant/toolbox", os.O_RDONLY, 0644)
		assert.NotNil(t, err, "only file protocol is supported")
	}

}

func TestOpenReaderFromURL(t *testing.T) {
	fileName, _, _ := toolbox.CallerInfo(2)
	{
		file, _, err := toolbox.OpenReaderFromURL(toolbox.FileSchema + fileName)
		assert.Nil(t, err)
		defer file.Close()
	}
	{
		_, _, err := toolbox.OpenReaderFromURL(toolbox.FileSchema + fileName + "blahbla")
		assert.NotNil(t, err)
	}

	{
		file, _, err := toolbox.OpenReaderFromURL("https://github.com/viant/toolbox")
		assert.Nil(t, err)
		defer file.Close()
	}

	{
		_, _, err := toolbox.OpenReaderFromURL("abc://github.com/viant/toolbox")
		assert.NotNil(t, err)
	}
}

func Test_QueryValue(t *testing.T) {
	u, err := url.Parse("http://localhost/?k1=v1&k2=2&k3=false")
	assert.Nil(t, err)

	assert.Equal(t, "v1", toolbox.QueryValue(u, "k1", "default"))
	assert.Equal(t, "default", toolbox.QueryValue(u, "k10", "default"))

	assert.Equal(t, 2, toolbox.QueryIntValue(u, "k2", 3))
	assert.Equal(t, 3, toolbox.QueryIntValue(u, "k10", 3))

	assert.Equal(t, false, toolbox.QueryBoolValue(u, "k3", true))
	assert.Equal(t, true, toolbox.QueryBoolValue(u, "k10", true))

}
<|endoftext|>


<commit_before>/* walter: a deployment pipeline template
 * Copyright (C) 2014 Recruit Technologies Co., Ltd. and contributors
 * (see CONTRIBUTORS.md)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package messengers

import (
	"encoding/json"
	"github.com/recruit-tech/walter/log"
	"io/ioutil"
	"net/http"
	"net/url"
)

type Slack struct {
	Channel   string   `config:"channel" json:"channel"`
	UserName  string   `config:"username" json:"username"`
	IconEmoji string   `config:"icon" json:"icon_emoji,omitempty"`
	IconUrl   string   `config:"icon_url" json:"icon_url,omitempty"`
	IncomingUrl string `config:"url" json:"-"` // not map to json
}

// To avoid the infinite recursion
// (see http://stackoverflow.com/questions/23045884/can-i-use-marshaljson-to-add-arbitrary-fields-to-a-json-encoding-in-golang)
type FakeSlack Slack

func (self *Slack) Post(message string) bool {
	if self.Channel[0] != '#' {
		log.Infof("Add # to channel name: %s", self.Channel)
		self.Channel = "#" + self.Channel
	}

	params, _ := json.Marshal(struct {
		FakeSlack
		Text string `json:"text"`
	}{
		FakeSlack : FakeSlack(*self),
		Text:  message,
	})

	resp, err := http.PostForm(
		self.IncomingUrl,
		url.Values{"payload": {string(params)}},
	)
	defer resp.Body.Close()

	if err != nil {
		log.Errorf("Failed post message to Slack...: %s", message)
		return false
	}

	if body, err := ioutil.ReadAll(resp.Body); err == nil {
		log.Infof("Slack post result...: %s", body)
		return true
	}
	log.Errorf("Failed to read result from Slack...")
	return false
}
<commit_msg>Colorlize Slack notification<commit_after>/* walter: a deployment pipeline template
 * Copyright (C) 2014 Recruit Technologies Co., Ltd. and contributors
 * (see CONTRIBUTORS.md)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package messengers

import (
	"encoding/json"
	"github.com/recruit-tech/walter/log"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

type Slack struct {
	Channel   string   `config:"channel" json:"channel"`
	UserName  string   `config:"username" json:"username"`
	IconEmoji string   `config:"icon" json:"icon_emoji,omitempty"`
	IconUrl   string   `config:"icon_url" json:"icon_url,omitempty"`
	IncomingUrl string `config:"url" json:"-"` // not map to json
}

// To avoid the infinite recursion
// (see http://stackoverflow.com/questions/23045884/can-i-use-marshaljson-to-add-arbitrary-fields-to-a-json-encoding-in-golang)
type FakeSlack Slack

func (self *Slack) Post(message string) bool {
	if self.Channel[0] != '#' {
		log.Infof("Add # to channel name: %s", self.Channel)
		self.Channel = "#" + self.Channel
	}

	var color string

	if strings.Contains(message, ", true") {
		color = "good"
	} else if strings.Contains(message, ", skipped") {
		color = "warning"
	} else {
		color = "danger"
	}

	attachment := map[string]string{
		"text":  message,
		"color": color,
	}

	attachments := []map[string]string{attachment}

	params, _ := json.Marshal(struct {
		FakeSlack
		Attachments []map[string]string `json:"attachments"`
	}{
		FakeSlack:   FakeSlack(*self),
		Attachments: attachments,
	})

	resp, err := http.PostForm(
		self.IncomingUrl,
		url.Values{"payload": {string(params)}},
	)
	defer resp.Body.Close()

	if err != nil {
		log.Errorf("Failed post message to Slack...: %s", message)
		return false
	}

	if body, err := ioutil.ReadAll(resp.Body); err == nil {
		log.Infof("Slack post result...: %s", body)
		return true
	}
	log.Errorf("Failed to read result from Slack...")
	return false
}
<|endoftext|>


<commit_before>// offers api
// https://github.com/topfreegames/offers
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2017 Top Free Games <backend@tfgco.com>

package metadata

//Version of the Offers API
var Version = "1.0.0"
<commit_msg>Release v1.0.1.<commit_after>// offers api
// https://github.com/topfreegames/offers
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2017 Top Free Games <backend@tfgco.com>

package metadata

//Version of the Offers API
var Version = "1.0.1"
<|endoftext|>


<commit_before>package middleware

import (
	"github.com/gin-gonic/gin"
	"strings"

	"github.com/eirka/eirka-libs/redis"
)

var (
	RedisKeyIndex = make(map[string]RedisKey)
	RedisKeys     = []RedisKey{
		{base: "index", fieldcount: 1, hash: true, expire: false},
		{base: "image", fieldcount: 1, hash: true, expire: false},
		{base: "tags", fieldcount: 1, hash: true, expire: false},
		{base: "tag", fieldcount: 2, hash: true, expire: true},
		{base: "thread", fieldcount: 2, hash: true, expire: false},
		{base: "post", fieldcount: 2, hash: true, expire: false},
		{base: "directory", fieldcount: 1, hash: false, expire: false},
		{base: "favorited", fieldcount: 1, hash: false, expire: true},
		{base: "new", fieldcount: 1, hash: false, expire: true},
		{base: "popular", fieldcount: 1, hash: false, expire: true},
		{base: "imageboards", fieldcount: 1, hash: false, expire: true},
	}
)

func init() {
	// key index map
	for _, key := range RedisKeys {
		RedisKeyIndex[key.base] = key
	}
}

// Cache will check for the key in Redis and serve it. If not found, it will
// take the marshalled JSON from the controller and set it in Redis
func Cache() gin.HandlerFunc {
	return func(c *gin.Context) {
		var result []byte
		var err error

		// bool for analytics middleware
		c.Set("cached", false)

		// break cache if there is a query
		if c.Request.URL.RawQuery != "" {
			c.Next()
			return
		}

		// Trim leading / from path and split
		params := strings.Split(strings.Trim(c.Request.URL.Path, "/"), "/")

		// get the keyname
		key, ok := RedisKeyIndex[params[0]]
		if !ok {
			c.Next()
			return
		}

		// set the key minus the base
		key.SetKey(params[1:]...)

		result, err = key.Get()
		if err == redis.ErrCacheMiss {
			// go to the controller
			c.Next()

			// Check if there was an error from the controller
			_, controllerError := c.Get("controllerError")
			if controllerError {
				c.Abort()
				return
			}

			err = key.Set(c.MustGet("data").([]byte))
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

		} else if err != nil {
			c.Error(err)
			c.Abort()
			return
		}

		// if we made it this far then the page was cached
		c.Set("cached", true)

		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Write(result)
		c.Abort()
		return
	}

}

type RedisKey struct {
	base       string
	fieldcount int
	hash       bool
	expire     bool
	key        string
	hashid     string
}

func (r *RedisKey) SetKey(ids ...string) {

	// create our key
	r.key = strings.Join([]string{r.base, strings.Join(ids[:r.fieldcount], ":")}, ":")

	// get our hash id
	if r.hash {
		r.hashid = strings.Join(ids[r.fieldcount:], "")
	}

	return
}

func (r *RedisKey) Get() (result []byte, err error) {

	if r.hash {
		return redis.RedisCache.HGet(r.key, r.hashid)
	} else {
		return redis.RedisCache.Get(r.key)
	}

	return
}

func (r *RedisKey) Set(data []byte) (err error) {

	if r.hash {
		err = redis.RedisCache.HMSet(r.key, r.hashid, data)
	} else {
		err = redis.RedisCache.Set(r.key, data)
	}

	if r.expire {
		return redis.RedisCache.Expire(r.key, 600)
	}

	return
}
<commit_msg>use explicit keys<commit_after>package middleware

import (
	"github.com/gin-gonic/gin"
	"strings"

	"github.com/eirka/eirka-libs/redis"
)

var (
	RedisKeyIndex = make(map[string]RedisKey)
	RedisKeys     = []RedisKey{
		{base: "tag", fieldcount: 2, hash: true, expire: true},
		{base: "thread", fieldcount: 2, hash: true, expire: false},
		{base: "post", fieldcount: 2, hash: true, expire: false},
		{base: "directory", fieldcount: 1, hash: true, expire: false},
		{base: "index", fieldcount: 1, hash: true, expire: false},
		{base: "image", fieldcount: 1, hash: true, expire: false},
		{base: "tags", fieldcount: 1, hash: true, expire: false},
		{base: "favorited", fieldcount: 1, hash: false, expire: true},
		{base: "new", fieldcount: 1, hash: false, expire: true},
		{base: "popular", fieldcount: 1, hash: false, expire: true},
		{base: "imageboards", fieldcount: 1, hash: false, expire: true},
	}
)

func init() {
	// key index map
	for _, key := range RedisKeys {
		RedisKeyIndex[key.base] = key
	}
}

// Cache will check for the key in Redis and serve it. If not found, it will
// take the marshalled JSON from the controller and set it in Redis
func Cache() gin.HandlerFunc {
	return func(c *gin.Context) {
		var result []byte
		var err error

		// bool for analytics middleware
		c.Set("cached", false)

		// break cache if there is a query
		if c.Request.URL.RawQuery != "" {
			c.Next()
			return
		}

		// Trim leading / from path and split
		params := strings.Split(strings.Trim(c.Request.URL.Path, "/"), "/")

		// get the keyname
		key, ok := RedisKeyIndex[params[0]]
		if !ok {
			c.Next()
			return
		}

		// set the key minus the base
		key.SetKey(params[1:]...)

		result, err = key.Get()
		if err == redis.ErrCacheMiss {
			// go to the controller
			c.Next()

			// Check if there was an error from the controller
			_, controllerError := c.Get("controllerError")
			if controllerError {
				c.Abort()
				return
			}

			err = key.Set(c.MustGet("data").([]byte))
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

		} else if err != nil {
			c.Error(err)
			c.Abort()
			return
		}

		// if we made it this far then the page was cached
		c.Set("cached", true)

		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Write(result)
		c.Abort()
		return
	}

}

type RedisKey struct {
	base       string
	fieldcount int
	hash       bool
	expire     bool
	key        string
	hashid     string
}

func (r *RedisKey) SetKey(ids ...string) {

	// create our key
	r.key = strings.Join([]string{r.base, strings.Join(ids[:r.fieldcount], ":")}, ":")

	// get our hash id
	if r.hash {
		r.hashid = strings.Join(ids[r.fieldcount:], "")
	}

	return
}

func (r *RedisKey) Get() (result []byte, err error) {

	if r.hash {
		return redis.RedisCache.HGet(r.key, r.hashid)
	} else {
		return redis.RedisCache.Get(r.key)
	}

	return
}

func (r *RedisKey) Set(data []byte) (err error) {

	if r.hash {
		err = redis.RedisCache.HMSet(r.key, r.hashid, data)
	} else {
		err = redis.RedisCache.Set(r.key, data)
	}

	if r.expire {
		return redis.RedisCache.Expire(r.key, 600)
	}

	return
}
<|endoftext|>


<commit_before>package handler

import (
	"net/http"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"gopkg.in/macaron.v1"

	"github.com/containerops/vessel/models"
	"github.com/containerops/vessel/module/pipeline"
)

// type PipelinePOSTJSON struct {
// 	Kind       string `json:"kind"`
// 	ApiVersion string `json:"apiVersion"`
// 	MetaData   struct {
// 		Name              string `json:"name"`
// 		Workspace         string `json:"workspace"`
// 		Project           string `json:"project"`
// 		Namespace         string `json:"namespace"`
// 		SelfLink          string `json:"selfLink"`
// 		Uid               string `json:"uid"`
// 		CreateonTimestamp string `json:"createonTimestamp"`
// 		DeletionTimestamp string `json:"deletionTimestamp"`
// 		TimeoutDuration   string `json:"timeoutDuration"`
// 		Labels            string `json:"labels"`
// 		Annotations       string `json:"annotations"`
// 	} `json:"metadata"`
// 	Spec []struct {
// 		Name                string `json:"name"`
// 		Replicsa            int64  `json:"replicsa"`
// 		Dependence          string `json:"dependence"`
// 		Kind                string `json:"kind"`
// 		StatusCheckUrl      string `json:"statusCheckUrl"`
// 		StatusCheckInterval int64  `json:"statusCheckInterval"`
// 		StatusCheckCount    int64  `json:"statusCheckCount"`
// 		Image               string `json:"image"`
// 		Port                string `json:"port"`
// 	} `json:"spec"`
// }

func V1POSTPipelineHandler(ctx *macaron.Context, reqData models.PipelineSpecTemplate) (int, []byte) {
	/*
		etcd path /vessel/ws-xxx/pj-xxx/pl-xxx/plv-xxx/stage-xxx/

		plv-xxx  -> k8s namespace

		demo:
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/stage/stage1/...
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/stage/stage2...
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx2/stage/stage1/...
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx2/stage/stage2...
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/name
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/dependence/Dependence1ServicesName <--need watch
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/dependence/Dependence2ServicesName <--need watch
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/check/check_status_url
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/check/check_status_interval
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/check/check_status_count
	*/

	pl, err := createPipelineAndStage(reqData)
	if err != nil {
		return http.StatusOK, []byte(err.Error())
	}

	plv, err := pipeline.RunPipeline(pl)
	if err != nil {
		return http.StatusOK, []byte(err.Error())
	}

	result := pipeline.BootPipelineVersion(plv)

	return http.StatusOK, []byte(result)
}

func createPipelineAndStage(pst models.PipelineSpecTemplate) (*models.Pipeline, error) {
	var plInfo *models.Pipeline = &models.Pipeline{}
	plInfo.Id = time.Now().UnixNano()
	//ignore workspace & project
	plInfo.WorkspaceId = 10000
	plInfo.ProjectId = 20000
	plInfo.Name = pst.MetaData.Name
	plInfo.Created = time.Now().Unix()
	plInfo.Updated = time.Now().Unix()
	plInfo.Labels = pst.MetaData.Labels
	plInfo.Annotations = pst.MetaData.Annotations
	//ignore plJson Detail
	plInfo.Detail = ""

	for _, value := range pst.Spec {
		var sInfo *models.Stage = &models.Stage{}
		sInfo.Id = time.Now().Unix()
		sInfo.WorkspaceId = plInfo.WorkspaceId
		sInfo.ProjectId = plInfo.ProjectId
		sInfo.PipelineId = plInfo.Id
		sInfo.Created = time.Now().Unix()
		sInfo.Updated = time.Now().Unix()
		sInfo.Name = value.Name
		//ignore Stage Detail
		//StatusCheckUrl to Detail
		//StatusCheckInterval to Detail
		//StatusCheckCount to Detail
		sInfo.Detail = ""
		sInfo.From = strings.Split(value.Dependence, ",")
		if len(sInfo.From) == 1 && sInfo.From[0] == "" {
			sInfo.From = make([]string, 0)
		}
		plInfo.Stages = append(plInfo.Stages, sInfo)
	}

	log.Error(plInfo)
	for _, value := range plInfo.Stages {
		log.Error(value)
	}

	return plInfo, nil
}

func V1PUTPipelineHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}

func V1GETPipelineHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}

func V1DELETEPipelineHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}

func V1RunPipelineHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}

func V1StatusGETHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}
<commit_msg>modify spec<commit_after>package handler

import (
	"net/http"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"gopkg.in/macaron.v1"

	"github.com/containerops/vessel/models"
	"github.com/containerops/vessel/module/pipeline"
)

// type PipelinePOSTJSON struct {
// 	Kind       string `json:"kind"`
// 	ApiVersion string `json:"apiVersion"`
// 	MetaData   struct {
// 		Name              string `json:"name"`
// 		Workspace         string `json:"workspace"`
// 		Project           string `json:"project"`
// 		Namespace         string `json:"namespace"`
// 		SelfLink          string `json:"selfLink"`
// 		Uid               string `json:"uid"`
// 		CreateonTimestamp string `json:"createonTimestamp"`
// 		DeletionTimestamp string `json:"deletionTimestamp"`
// 		TimeoutDuration   string `json:"timeoutDuration"`
// 		Labels            string `json:"labels"`
// 		Annotations       string `json:"annotations"`
// 	} `json:"metadata"`
// 	Spec []struct {
// 		Name                string `json:"name"`
// 		Replicsa            int64  `json:"replicsa"`
// 		Dependence          string `json:"dependence"`
// 		Kind                string `json:"kind"`
// 		StatusCheckUrl      string `json:"statusCheckUrl"`
// 		StatusCheckInterval int64  `json:"statusCheckInterval"`
// 		StatusCheckCount    int64  `json:"statusCheckCount"`
// 		Image               string `json:"image"`
// 		Port                string `json:"port"`
// 	} `json:"spec"`
// }

func V1POSTPipelineHandler(ctx *macaron.Context, reqData models.PipelineSpecTemplate) (int, []byte) {
	/*
		etcd path /vessel/ws-xxx/pj-xxx/pl-xxx/plv-xxx/stage-xxx/

		plv-xxx  -> k8s namespace

		demo:
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/stage/stage1/...
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/stage/stage2...
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx2/stage/stage1/...
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx2/stage/stage2...
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/name
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/dependence/Dependence1ServicesName <--need watch
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/dependence/Dependence2ServicesName <--need watch
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/check/check_status_url
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/check/check_status_interval
		/containerops/vessel/ws-xxx/pj-xxx/pl-xxx1/plv-xxx/stagev-xxx/check/check_status_count
	*/

	pl, err := createPipelineAndStage(reqData)
	if err != nil {
		return http.StatusOK, []byte(err.Error())
	}

	plv, err := pipeline.RunPipeline(pl)
	if err != nil {
		return http.StatusOK, []byte(err.Error())
	}

	result := pipeline.BootPipelineVersion(plv)

	return http.StatusOK, []byte(result)
}

func createPipelineAndStage(pst models.PipelineSpecTemplate) (*models.Pipeline, error) {
	var plInfo *models.Pipeline = &models.Pipeline{}
	plInfo.Id = time.Now().UnixNano()
	//ignore workspace & project
	plInfo.WorkspaceId = 10000
	plInfo.ProjectId = 20000
	plInfo.Name = pst.MetaData.Name
	plInfo.Created = time.Now().Unix()
	plInfo.Updated = time.Now().Unix()
	plInfo.Labels = pst.MetaData.Labels
	plInfo.Annotations = pst.MetaData.Annotations
	//ignore plJson Detail
	plInfo.Detail = ""
	plInfo.MetaData = pst.MetaData
	plInfo.StageSpecs = pst.Spec

	for _, value := range pst.Spec {
		var sInfo *models.Stage = &models.Stage{}
		sInfo.Id = time.Now().Unix()
		sInfo.WorkspaceId = plInfo.WorkspaceId
		sInfo.ProjectId = plInfo.ProjectId
		sInfo.PipelineId = plInfo.Id
		sInfo.Created = time.Now().Unix()
		sInfo.Updated = time.Now().Unix()
		sInfo.Name = value.Name
		//ignore Stage Detail
		//StatusCheckUrl to Detail
		//StatusCheckInterval to Detail
		//StatusCheckCount to Detail
		sInfo.Detail = ""
		sInfo.From = strings.Split(value.Dependence, ",")
		if len(sInfo.From) == 1 && sInfo.From[0] == "" {
			sInfo.From = make([]string, 0)
		}
		sInfo.MetaData = plInfo.MetaData
		sInfo.StageSpec = value

		plInfo.Stages = append(plInfo.Stages, sInfo)
	}

	log.Error(plInfo)
	for _, value := range plInfo.Stages {
		log.Error(value)
	}

	return plInfo, nil
}

func V1PUTPipelineHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}

func V1GETPipelineHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}

func V1DELETEPipelineHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}

func V1RunPipelineHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}

func V1StatusGETHandler(ctx *macaron.Context) (int, []byte) {
	return http.StatusOK, []byte("")
}
<|endoftext|>


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

package create

import (
	"bytes"
	"fmt"
	"strings"
	"time"

	"github.com/gohugoio/hugo/helpers"
	"github.com/gohugoio/hugo/source"

	"github.com/gohugoio/hugo/hugolib"
	"github.com/gohugoio/hugo/tpl"
	"github.com/spf13/afero"
)

// ArchetypeFileData represents the data available to an archetype template.
type ArchetypeFileData struct {
	// The archetype content type, either given as --kind option or extracted
	// from the target path's section, i.e. "blog/mypost.md" will resolve to
	// "blog".
	Type string

	// The current date and time as a RFC3339 formatted string, suitable for use in front matter.
	Date string

	// The Site, fully equipped with all the pages etc. Note: This will only be set if it is actually
	// used in the archetype template. Also, if this is a multilingual setup,
	// this site is the site that best matches the target content file, based
	// on the presence of language code in the filename.
	Site *hugolib.Site

	// The target content file. Note that the .Content will be empty, as that
	// has not been created yet.
	source.File
}

const (
	// ArchetypeTemplateTemplate is used as initial template when adding an archetype template.
	ArchetypeTemplateTemplate = `---
title: "{{ replace .TranslationBaseName "-" " " | title }}"
date: {{ .Date }}
draft: true
---

`
)

var (
	archetypeShortcodeReplacementsPre = strings.NewReplacer(
		"{{<", "{x{<",
		"{{%", "{x{%",
		">}}", ">}x}",
		"%}}", "%}x}")

	archetypeShortcodeReplacementsPost = strings.NewReplacer(
		"{x{<", "{{<",
		"{x{%", "{{%",
		">}x}", ">}}",
		"%}x}", "%}}")
)

func executeArcheTypeAsTemplate(s *hugolib.Site, kind, targetPath, archetypeFilename string) ([]byte, error) {

	var (
		archetypeContent  []byte
		archetypeTemplate []byte
		err               error
	)

	sp := source.NewSourceSpec(s.Deps.Cfg, s.Deps.Fs)
	f := sp.NewFileInfo("", targetPath, false, nil)

	data := ArchetypeFileData{
		Type: kind,
		Date: time.Now().Format(time.RFC3339),
		File: f,
		Site: s,
	}

	if archetypeFilename == "" {
		// TODO(bep) archetype revive the issue about wrong tpl funcs arg order
		archetypeTemplate = []byte(ArchetypeTemplateTemplate)
	} else {
		archetypeTemplate, err = afero.ReadFile(s.Fs.Source, archetypeFilename)
		if err != nil {
			return nil, fmt.Errorf("Failed to read archetype file %q: %s", archetypeFilename, err)
		}

	}

	// The archetype template may contain shortcodes, and these does not play well
	// with the Go templates. Need to set some temporary delimiters.
	archetypeTemplate = []byte(archetypeShortcodeReplacementsPre.Replace(string(archetypeTemplate)))

	// Reuse the Hugo template setup to get the template funcs properly set up.
	templateHandler := s.Deps.Tmpl.(tpl.TemplateHandler)
	templateName := "_text/" + helpers.Filename(archetypeFilename)
	if err := templateHandler.AddTemplate(templateName, string(archetypeTemplate)); err != nil {
		return nil, fmt.Errorf("Failed to parse archetype file %q: %s", archetypeFilename, err)
	}

	templ := templateHandler.Lookup(templateName)

	var buff bytes.Buffer
	if err := templ.Execute(&buff, data); err != nil {
		return nil, fmt.Errorf("Failed to process archetype file %q: %s", archetypeFilename, err)
	}

	archetypeContent = []byte(archetypeShortcodeReplacementsPost.Replace(buff.String()))

	if !bytes.Contains(archetypeContent, []byte("date")) || !bytes.Contains(archetypeContent, []byte("title")) {
		// TODO(bep) remove some time in the future.
		s.Log.FEEDBACK.Println(fmt.Sprintf(`WARNING: date and/or title missing from archetype file %q.
From Hugo 0.24 this must be provided in the archetype file itself, if needed. Example:
%s
`, archetypeFilename, ArchetypeTemplateTemplate))

	}

	return archetypeContent, nil

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

package create

import (
	"bytes"
	"fmt"
	"path/filepath"
	"strings"
	"time"

	"github.com/gohugoio/hugo/helpers"
	"github.com/gohugoio/hugo/source"

	"github.com/gohugoio/hugo/hugolib"
	"github.com/gohugoio/hugo/tpl"
	"github.com/spf13/afero"
)

// ArchetypeFileData represents the data available to an archetype template.
type ArchetypeFileData struct {
	// The archetype content type, either given as --kind option or extracted
	// from the target path's section, i.e. "blog/mypost.md" will resolve to
	// "blog".
	Type string

	// The current date and time as a RFC3339 formatted string, suitable for use in front matter.
	Date string

	// The Site, fully equipped with all the pages etc. Note: This will only be set if it is actually
	// used in the archetype template. Also, if this is a multilingual setup,
	// this site is the site that best matches the target content file, based
	// on the presence of language code in the filename.
	Site *hugolib.Site

	// Name will in most cases be the same as TranslationBaseName, e.g. "my-post".
	// But if that value is "index" (bundles), the Name is instead the owning folder.
	// This is the value you in most cases would want to use to construct the title in your
	// archetype template.
	Name string

	// The target content file. Note that the .Content will be empty, as that
	// has not been created yet.
	source.File
}

const (
	// ArchetypeTemplateTemplate is used as initial template when adding an archetype template.
	ArchetypeTemplateTemplate = `---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

`
)

var (
	archetypeShortcodeReplacementsPre = strings.NewReplacer(
		"{{<", "{x{<",
		"{{%", "{x{%",
		">}}", ">}x}",
		"%}}", "%}x}")

	archetypeShortcodeReplacementsPost = strings.NewReplacer(
		"{x{<", "{{<",
		"{x{%", "{{%",
		">}x}", ">}}",
		"%}x}", "%}}")
)

func executeArcheTypeAsTemplate(s *hugolib.Site, kind, targetPath, archetypeFilename string) ([]byte, error) {

	var (
		archetypeContent  []byte
		archetypeTemplate []byte
		err               error
	)

	sp := source.NewSourceSpec(s.Deps.Cfg, s.Deps.Fs)
	f := sp.NewFileInfo("", targetPath, false, nil)

	name := f.TranslationBaseName()
	if name == "index" || name == "_index" {
		// Page bundles; the directory name will hopefully have a better name.
		dir := strings.TrimSuffix(f.Dir(), helpers.FilePathSeparator)
		_, name = filepath.Split(dir)
	}

	data := ArchetypeFileData{
		Type: kind,
		Date: time.Now().Format(time.RFC3339),
		Name: name,
		File: f,
		Site: s,
	}

	if archetypeFilename == "" {
		// TODO(bep) archetype revive the issue about wrong tpl funcs arg order
		archetypeTemplate = []byte(ArchetypeTemplateTemplate)
	} else {
		archetypeTemplate, err = afero.ReadFile(s.Fs.Source, archetypeFilename)
		if err != nil {
			return nil, fmt.Errorf("Failed to read archetype file %q: %s", archetypeFilename, err)
		}

	}

	// The archetype template may contain shortcodes, and these does not play well
	// with the Go templates. Need to set some temporary delimiters.
	archetypeTemplate = []byte(archetypeShortcodeReplacementsPre.Replace(string(archetypeTemplate)))

	// Reuse the Hugo template setup to get the template funcs properly set up.
	templateHandler := s.Deps.Tmpl.(tpl.TemplateHandler)
	templateName := "_text/" + helpers.Filename(archetypeFilename)
	if err := templateHandler.AddTemplate(templateName, string(archetypeTemplate)); err != nil {
		return nil, fmt.Errorf("Failed to parse archetype file %q: %s", archetypeFilename, err)
	}

	templ := templateHandler.Lookup(templateName)

	var buff bytes.Buffer
	if err := templ.Execute(&buff, data); err != nil {
		return nil, fmt.Errorf("Failed to process archetype file %q: %s", archetypeFilename, err)
	}

	archetypeContent = []byte(archetypeShortcodeReplacementsPost.Replace(buff.String()))

	if !bytes.Contains(archetypeContent, []byte("date")) || !bytes.Contains(archetypeContent, []byte("title")) {
		// TODO(bep) remove some time in the future.
		s.Log.FEEDBACK.Println(fmt.Sprintf(`WARNING: date and/or title missing from archetype file %q.
From Hugo 0.24 this must be provided in the archetype file itself, if needed. Example:
%s
`, archetypeFilename, ArchetypeTemplateTemplate))

	}

	return archetypeContent, nil

}
<|endoftext|>


<commit_before>package pkgs

import (
	"context"
	"encoding/json"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/arduino/arduino-create-agent/gen/indexes"
	"github.com/sirupsen/logrus"
	"go.bug.st/downloader"
)

// Indexes is a client that implements github.com/arduino/arduino-create-agent/gen/indexes.Service interface
type Indexes struct {
	Log    *logrus.Logger
	Folder string
}

// Add downloads the index file found at the url contained in the payload, and saves it in the Indexes Folder.
// If called with an already existing index, it overwrites the file.
// It can fail if the payload is not defined, if it contains an invalid url.
func (c *Indexes) Add(ctx context.Context, payload *indexes.IndexPayload) (*indexes.Operation, error) {
	// Parse url
	indexURL, err := url.Parse(payload.URL)
	if err != nil {
		return nil, indexes.MakeInvalidURL(err)
	}

	// Download tmp file
	filename := url.PathEscape(payload.URL)
	path := filepath.Join(c.Folder, filename+".tmp")
	d, err := downloader.Download(path, indexURL.String())
	if err != nil {
		return nil, err
	}
	err = d.Run()
	if err != nil {
		return nil, err
	}

	// Move tmp file
	err = os.Rename(path, filepath.Join(c.Folder, filename))
	if err != nil {
		return nil, err
	}

	return &indexes.Operation{Status: "ok"}, nil
}

// Get reads the index file from the Indexes Folder, unmarshaling it
func (c *Indexes) Get(ctx context.Context, uri string) (index Index, err error) {
	filename := url.PathEscape(uri)
	path := filepath.Join(c.Folder, filename)
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return index, err
	}

	err = json.Unmarshal(data, &index)
	if err != nil {
		return index, err
	}

	return index, nil
}

// List reads from the Indexes Folder and returns the indexes that have been downloaded
func (c *Indexes) List(context.Context) ([]string, error) {
	// Create folder if it doesn't exist
	_ = os.MkdirAll(c.Folder, 0755)
	// Read files
	files, err := ioutil.ReadDir(c.Folder)
	if err != nil {
		return nil, err
	}

	res := []string{}
	for _, file := range files {
		// Select only files that begin with http
		if !strings.HasPrefix(file.Name(), "http") {
			continue
		}
		path, err := url.PathUnescape(file.Name())
		if err != nil {
			c.Log.Warn(err)
		}
		res = append(res, path)
	}

	return res, nil
}

// Remove deletes the index file from the Indexes Folder
func (c *Indexes) Remove(ctx context.Context, payload *indexes.IndexPayload) (*indexes.Operation, error) {
	filename := url.PathEscape(payload.URL)
	err := os.RemoveAll(filepath.Join(c.Folder, filename))
	if err != nil {
		return nil, err
	}
	return &indexes.Operation{Status: "ok"}, nil
}
<commit_msg>replace PathEscaping with encoding in base64 for downloaded index filenames in order to be compatible on windows FS<commit_after>package pkgs

import (
	"context"
	b64 "encoding/base64"
	"encoding/json"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/arduino/arduino-create-agent/gen/indexes"
	"github.com/sirupsen/logrus"
	"go.bug.st/downloader"
)

// Indexes is a client that implements github.com/arduino/arduino-create-agent/gen/indexes.Service interface
type Indexes struct {
	Log    *logrus.Logger
	Folder string
}

// Add downloads the index file found at the url contained in the payload, and saves it in the Indexes Folder.
// If called with an already existing index, it overwrites the file.
// It can fail if the payload is not defined, if it contains an invalid url.
func (c *Indexes) Add(ctx context.Context, payload *indexes.IndexPayload) (*indexes.Operation, error) {
	// Parse url
	indexURL, err := url.Parse(payload.URL)
	if err != nil {
		return nil, indexes.MakeInvalidURL(err)
	}

	// Download tmp file
	filename := b64.StdEncoding.EncodeToString([]byte(url.PathEscape(payload.URL)))
	path := filepath.Join(c.Folder, filename+".tmp")
	d, err := downloader.Download(path, indexURL.String())
	if err != nil {
		return nil, err
	}
	err = d.Run()
	if err != nil {
		return nil, err
	}

	// Move tmp file
	err = os.Rename(path, filepath.Join(c.Folder, filename))
	if err != nil {
		return nil, err
	}

	return &indexes.Operation{Status: "ok"}, nil
}

// Get reads the index file from the Indexes Folder, unmarshaling it
func (c *Indexes) Get(ctx context.Context, uri string) (index Index, err error) {
	filename := b64.StdEncoding.EncodeToString([]byte(url.PathEscape(uri)))
	path := filepath.Join(c.Folder, filename)
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return index, err
	}

	err = json.Unmarshal(data, &index)
	if err != nil {
		return index, err
	}

	return index, nil
}

// List reads from the Indexes Folder and returns the indexes that have been downloaded
func (c *Indexes) List(context.Context) ([]string, error) {
	// Create folder if it doesn't exist
	_ = os.MkdirAll(c.Folder, 0755)
	// Read files
	files, err := ioutil.ReadDir(c.Folder)

	if err != nil {
		return nil, err
	}

	res := []string{}
	for _, file := range files {
		// Select only files that begin with http
		decodedFileName, _ := b64.URLEncoding.DecodeString(file.Name())
		fileName:=string(decodedFileName)
		if !strings.HasPrefix(fileName, "http") {
			continue
		}
		path, err := url.PathUnescape(fileName)
		if err != nil {
			c.Log.Warn(err)
		}
		res = append(res, path)
	}

	return res, nil
}

// Remove deletes the index file from the Indexes Folder
func (c *Indexes) Remove(ctx context.Context, payload *indexes.IndexPayload) (*indexes.Operation, error) {
	filename := b64.StdEncoding.EncodeToString([]byte(url.PathEscape(payload.URL)))
	err := os.RemoveAll(filepath.Join(c.Folder, filename))
	if err != nil {
		return nil, err
	}
	return &indexes.Operation{Status: "ok"}, nil
}
<|endoftext|>


<commit_before>package version

import (
	"bytes"
	"fmt"
)

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string

// The main version number that is being run at the moment.
const Version = "1.0.2"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""

func FormattedVersion() string {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "%s", Version)
	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, "-%s", VersionPrerelease)

		if GitCommit != "" {
			fmt.Fprintf(&versionString, " (%s)", GitCommit)
		}
	}

	return versionString.String()
}
<commit_msg>next version is 1.0.3<commit_after>package version

import (
	"bytes"
	"fmt"
)

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string

// The main version number that is being run at the moment.
const Version = "1.0.3"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "dev"

func FormattedVersion() string {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "%s", Version)
	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, "-%s", VersionPrerelease)

		if GitCommit != "" {
			fmt.Fprintf(&versionString, " (%s)", GitCommit)
		}
	}

	return versionString.String()
}
<|endoftext|>


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

package version

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

package version

var (
	Version         = "2.0.2"
	InternalVersion = "2"
)
<|endoftext|>


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

package vertical

import (
	"bufio"
	"compress/gzip"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

const (
	channelChunkSize = 30000 // please note that this affects the performance quite a lot
)

// --------------------------------------------------------

// ParserConf contains configuration parameters for
// vertical file parser
type ParserConf struct {

	// Source vertical file (either a plain text file or a gzip one)
	VerticalFilePath string `json:"verticalFilePath"`

	FilterArgs map[string]string `json:"filterArgs"`

	NgramIgnoreStructs []string `json:"ngramIgnoreStructs"`

	OutDirectory string `json:"outDirectory"`

	NgramStopStrings []string `json:"ngramStopStrings"`

	NgramIgnoreStrings []string `json:"ngramIgnoreStrings"`
}

// LoadConfig loads the configuration from a JSON file.
// In case of an error the program exits with panic.
func LoadConfig(path string) *ParserConf {
	rawData, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	var conf ParserConf
	err = json.Unmarshal(rawData, &conf)
	if err != nil {
		panic(err)
	}
	return &conf
}

// --------------------------------------------------------

// Token is a representation of
// a parsed line. It connects both, positional attributes
// and currently accumulated structural attributes.
type Token struct {
	Word        string
	Attrs       []string
	StructAttrs map[string]string
}

func (v *Token) WordLC() string {
	return strings.ToLower(v.Word)
}

// --------------------------------------------------------

type VerticalMetaLine struct {
	Name  string
	Attrs map[string]string
}

// --------------------------------------------------------

type LineProcessor interface {
	ProcessLine(vline *Token)
}

// --------------------------------------------------------

func isOpenElement(tagSrc string) bool {
	return strings.HasPrefix(tagSrc, "<") && !strings.HasPrefix(tagSrc, "</") &&
		!strings.HasSuffix(tagSrc, "/>")
}

func isCloseElement(tagSrc string) bool {
	return strings.HasPrefix(tagSrc, "</")
}

func isSelfCloseElement(tagSrc string) bool {
	return strings.HasPrefix(tagSrc, "<") && strings.HasSuffix(tagSrc, "/>")
}

func parseAttrVal(src string) map[string]string {
	ans := make(map[string]string)
	rg := regexp.MustCompile("(\\w+)=\"([^\"]+)\"")
	srch := rg.FindAllStringSubmatch(src, -1)
	for i := 0; i < len(srch); i++ {
		ans[srch[i][1]] = srch[i][2]
	}
	return ans
}

func parseLine(line string, elmStack *Stack) *Token {
	var meta *VerticalMetaLine
	rg := regexp.MustCompile("<([\\w]+)(\\s*[^>]*)|>")
	srch := rg.FindStringSubmatch(line)

	switch {
	case isOpenElement(line):
		meta = &VerticalMetaLine{Name: srch[1], Attrs: parseAttrVal(srch[2])}
		elmStack.Push(meta)
	case isCloseElement(line):
		elmStack.Pop()
	case isSelfCloseElement(line):
		meta = &VerticalMetaLine{Name: srch[1], Attrs: parseAttrVal(srch[2])}
	default:
		items := strings.Split(line, "\t")
		return &Token{
			Word:        items[0],
			Attrs:       items[1:],
			StructAttrs: elmStack.GetAttrs(),
		}
	}
	return nil
}

// ParseVerticalFile processes a corpus vertical file
// line by line and applies a custom LineProcessor on
// them. The processing is parallelized in the sense
// that reading a file into lines and processing of
// the lines runs in different goroutines. To reduce
// overhead, the data are passed between goroutines
// in chunks.
func ParseVerticalFile(conf *ParserConf, lproc LineProcessor) {
	f, err := os.Open(conf.VerticalFilePath)
	if err != nil {
		panic(err)
	}

	var rd io.Reader
	if strings.HasSuffix(conf.VerticalFilePath, ".gz") {
		rd, err = gzip.NewReader(f)
		if err != nil {
			panic(err)
		}

	} else {
		rd = f
	}
	brd := bufio.NewScanner(rd)

	stack := NewStack()

	ch := make(chan []*Token)
	chunk := make([]*Token, channelChunkSize)
	go func() {
		i := 0
		for brd.Scan() {
			line := parseLine(brd.Text(), stack)
			chunk[i] = line
			i++
			if i == channelChunkSize {
				i = 0
				ch <- chunk
			}
		}
		if i > 0 {
			ch <- chunk[:i]
		}
		close(ch)
	}()

	for items := range ch {
		for _, item := range items {
			lproc.ProcessLine(item)
		}
	}

	fmt.Println("DONE: stack size: ", stack.Size())
}

//ParseVerticalFileNoGoRo is just for benchmarking purposes
func ParseVerticalFileNoGoRo(conf *ParserConf, lproc LineProcessor) {
	f, err := os.Open(conf.VerticalFilePath)
	if err != nil {
		panic(err)
	}
	rd := bufio.NewScanner(f)
	stack := NewStack()

	for rd.Scan() {
		line := parseLine(rd.Text(), stack)
		lproc.ProcessLine(line)
	}

	fmt.Println("DONE: stack size: ", stack.Size())
}
<commit_msg>Status logging<commit_after>// Copyright 2017 Tomas Machalek <tomas.machalek@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package vertical

import (
	"bufio"
	"compress/gzip"
	"encoding/json"
	"io"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
)

const (
	channelChunkSize = 30000 // please note that this affects the performance quite a lot
	logProgressEach  = 1000000
)

// --------------------------------------------------------

// ParserConf contains configuration parameters for
// vertical file parser
type ParserConf struct {

	// Source vertical file (either a plain text file or a gzip one)
	VerticalFilePath string `json:"verticalFilePath"`

	FilterArgs map[string]string `json:"filterArgs"`

	NgramIgnoreStructs []string `json:"ngramIgnoreStructs"`

	OutDirectory string `json:"outDirectory"`

	NgramStopStrings []string `json:"ngramStopStrings"`

	NgramIgnoreStrings []string `json:"ngramIgnoreStrings"`
}

// LoadConfig loads the configuration from a JSON file.
// In case of an error the program exits with panic.
func LoadConfig(path string) *ParserConf {
	rawData, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	var conf ParserConf
	err = json.Unmarshal(rawData, &conf)
	if err != nil {
		panic(err)
	}
	return &conf
}

// --------------------------------------------------------

// Token is a representation of
// a parsed line. It connects both, positional attributes
// and currently accumulated structural attributes.
type Token struct {
	Word        string
	Attrs       []string
	StructAttrs map[string]string
}

func (v *Token) WordLC() string {
	return strings.ToLower(v.Word)
}

// --------------------------------------------------------

type VerticalMetaLine struct {
	Name  string
	Attrs map[string]string
}

// --------------------------------------------------------

type LineProcessor interface {
	ProcessLine(vline *Token)
}

// --------------------------------------------------------

func isOpenElement(tagSrc string) bool {
	return strings.HasPrefix(tagSrc, "<") && !strings.HasPrefix(tagSrc, "</") &&
		!strings.HasSuffix(tagSrc, "/>")
}

func isCloseElement(tagSrc string) bool {
	return strings.HasPrefix(tagSrc, "</")
}

func isSelfCloseElement(tagSrc string) bool {
	return strings.HasPrefix(tagSrc, "<") && strings.HasSuffix(tagSrc, "/>")
}

func parseAttrVal(src string) map[string]string {
	ans := make(map[string]string)
	rg := regexp.MustCompile("(\\w+)=\"([^\"]+)\"")
	srch := rg.FindAllStringSubmatch(src, -1)
	for i := 0; i < len(srch); i++ {
		ans[srch[i][1]] = srch[i][2]
	}
	return ans
}

func parseLine(line string, elmStack *Stack) *Token {
	var meta *VerticalMetaLine
	rg := regexp.MustCompile("<([\\w]+)(\\s*[^>]*)|>")
	srch := rg.FindStringSubmatch(line)

	switch {
	case isOpenElement(line):
		meta = &VerticalMetaLine{Name: srch[1], Attrs: parseAttrVal(srch[2])}
		elmStack.Push(meta)
	case isCloseElement(line):
		elmStack.Pop()
	case isSelfCloseElement(line):
		meta = &VerticalMetaLine{Name: srch[1], Attrs: parseAttrVal(srch[2])}
	default:
		items := strings.Split(line, "\t")
		return &Token{
			Word:        items[0],
			Attrs:       items[1:],
			StructAttrs: elmStack.GetAttrs(),
		}
	}
	return nil
}

// ParseVerticalFile processes a corpus vertical file
// line by line and applies a custom LineProcessor on
// them. The processing is parallelized in the sense
// that reading a file into lines and processing of
// the lines runs in different goroutines. To reduce
// overhead, the data are passed between goroutines
// in chunks.
func ParseVerticalFile(conf *ParserConf, lproc LineProcessor) {
	f, err := os.Open(conf.VerticalFilePath)
	if err != nil {
		panic(err)
	}

	var rd io.Reader
	if strings.HasSuffix(conf.VerticalFilePath, ".gz") {
		rd, err = gzip.NewReader(f)
		if err != nil {
			panic(err)
		}

	} else {
		rd = f
	}
	brd := bufio.NewScanner(rd)

	stack := NewStack()

	ch := make(chan []*Token)
	chunk := make([]*Token, channelChunkSize)
	go func() {
		i := 0
		progress := 0
		for brd.Scan() {
			line := parseLine(brd.Text(), stack)
			chunk[i] = line
			i++
			if i == channelChunkSize {
				i = 0
				ch <- chunk
			}
			progress++
			if progress%logProgressEach == 0 {
				log.Printf("...processed %d lines.\n", progress)
			}
		}
		if i > 0 {
			ch <- chunk[:i]
		}
		close(ch)
	}()

	for items := range ch {
		for _, item := range items {
			lproc.ProcessLine(item)
		}
	}

	log.Println("DONE: stack size: ", stack.Size())
}

//ParseVerticalFileNoGoRo is just for benchmarking purposes
func ParseVerticalFileNoGoRo(conf *ParserConf, lproc LineProcessor) {
	f, err := os.Open(conf.VerticalFilePath)
	if err != nil {
		panic(err)
	}
	rd := bufio.NewScanner(f)
	stack := NewStack()

	for rd.Scan() {
		line := parseLine(rd.Text(), stack)
		lproc.ProcessLine(line)
	}

	log.Println("DONE: stack size: ", stack.Size())
}
<|endoftext|>


<commit_before>package video

import "github.com/32bitkid/bitreader"
import "errors"

type ExtensionID uint32

const (
	_                                  ExtensionID = iota // reserved
	SequenceExtensionID                                   //
	SequenceDisplayExtensionID                            //
	QuantMatrixExtensionID                                //
	CopyrightExtensionID                                  //
	SequenceScalableExtensionID                           //
	_                                                     // reserved
	PictureDisplayExtensionID                             //
	PictureCodingExtensionID                              //
	PictureSpatialScalableExtensionID                     //
	PictureTemporalScalableExtensionID                    //
	_                                                     // reserved
	_                                                     // reserved
	_                                                     // reserved
	_                                                     // reserved
)

var ErrUnexpectedSequenceExtensionID = errors.New("unexpected sequence extension id")

func (expected ExtensionID) check(br bitreader.BitReader) (bool, error) {
	if nextbits, err := br.Peek32(4); err != nil {
		return false, err
	} else {
		return ExtensionID(nextbits) == expected, nil
	}
}

func (expected ExtensionID) assert(br bitreader.BitReader) error {
	if test, err := expected.check(br); err != nil {
		return err
	} else if test != true {
		return ErrUnexpectedSequenceExtensionID
	}
	if err := br.Trash(4); err != nil {
		return err
	}
	return nil
}
<commit_msg>cleaning up some stray comments that made the documentation look funny.<commit_after>package video

import "github.com/32bitkid/bitreader"
import "errors"

type ExtensionID uint32

const (
	_ ExtensionID = iota // reserved
	SequenceExtensionID
	SequenceDisplayExtensionID
	QuantMatrixExtensionID
	CopyrightExtensionID
	SequenceScalableExtensionID
	_ // reserved
	PictureDisplayExtensionID
	PictureCodingExtensionID
	PictureSpatialScalableExtensionID
	PictureTemporalScalableExtensionID
	_ // reserved
	_ // reserved
	_ // reserved
	_ // reserved
)

var ErrUnexpectedSequenceExtensionID = errors.New("unexpected sequence extension id")

func (expected ExtensionID) check(br bitreader.BitReader) (bool, error) {
	if nextbits, err := br.Peek32(4); err != nil {
		return false, err
	} else {
		return ExtensionID(nextbits) == expected, nil
	}
}

func (expected ExtensionID) assert(br bitreader.BitReader) error {
	if test, err := expected.check(br); err != nil {
		return err
	} else if test != true {
		return ErrUnexpectedSequenceExtensionID
	}
	if err := br.Trash(4); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package agent

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

)

// Returns a complete list of all nodes
func (s *HTTPServer) Nodes(w http.ResponseWriter, req *http.Request) {
	instructions := []Machine{}

	// Fetch all the items from the database
	rows, err := r.Table(tableIpxe).OrderBy(r.Asc("Created")).Run(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Scan each row into a TodoItem instance and then add this to the list
	for rows.Next() {
		var instruction Machine

		err := rows.Scan(&instruction)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		instructions = append(instructions, instruction)
	}

	renderHtml(w, "enforcer", instructions)
}

func (s *HTTPServer) ToggleNode(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	if id == "" {
		http.NotFound(w, req)
		return
	}

	// Check that the item exists
	res, err := r.Table(tableIpxe).Get(id).RunRow(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if res.IsNil() {
		http.NotFound(w, req)
		return
	}

	_, err = r.Table(tableIpxe).Get(id).Update(map[string]interface{}{"Status": r.Branch(
		r.Row.Field("Status").Eq("AVAILABLE"),
		"UNAVAILABLE",
		"AVAILABLE",
	)}).RunWrite(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	http.Redirect(w, req, "/", http.StatusFound)
}

func (s *HTTPServer) DeleteNode(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	if id == "" {
		http.NotFound(w, req)
		return
	}

	// Check that the item exists
	res, err := r.Table(tableIpxe).Get(id).RunRow(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if res.IsNil() {
		http.NotFound(w, req)
		return
	}

	// Delete the item
	_, err = r.Table(tableIpxe).Get(id).Delete().RunWrite(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	http.Redirect(w, req, "/", http.StatusFound)
}

func (s *HTTPServer) NodeIpxe(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	if id == "" {
		http.NotFound(w, req)
		return
	}

	// Check that the item exists
	queryExistance := r.Table(tableIpxe)
	queryExistance = queryExistance.Filter(r.Row.Field("id").Eq(id)).Filter(r.Row.Field("Status").Eq("AVAILABLE"))
	res, err := queryExistance.RunRow(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if res.IsNil() {
		http.NotFound(w, req)
		return
	}

	instructions := []Machine{}

	var instruction Machine
	err = res.Scan(&instruction)
	if err != nil {
		fmt.Println(err)
		return
	}

	instructions = append(instructions, instruction)

	// Render template
	renderTemplate(w, instruction.Template, instructions)

	// Set status to installed
	_, err = r.Table(tableIpxe).Get(id).Update(map[string]interface{}{"Status": "INSTALLED"}).RunWrite(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

}
<commit_msg>disable some imports<commit_after>package agent

import (
//	"fmt"
//	"log"
	"net/http"
	"os"
	r "github.com/dancannon/gorethink"
//	"time"

)

// Returns a complete list of all nodes
func (s *HTTPServer) Nodes(w http.ResponseWriter, req *http.Request) {
	instructions := []Machine{}

	// Fetch all the items from the database
	rows, err := r.Table(tableIpxe).OrderBy(r.Asc("Created")).Run(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Scan each row into a TodoItem instance and then add this to the list
	for rows.Next() {
		var instruction Machine

		err := rows.Scan(&instruction)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		instructions = append(instructions, instruction)
	}

	renderHtml(w, "enforcer", instructions)
}

func (s *HTTPServer) ToggleNode(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	if id == "" {
		http.NotFound(w, req)
		return
	}

	// Check that the item exists
	res, err := r.Table(tableIpxe).Get(id).RunRow(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if res.IsNil() {
		http.NotFound(w, req)
		return
	}

	_, err = r.Table(tableIpxe).Get(id).Update(map[string]interface{}{"Status": r.Branch(
		r.Row.Field("Status").Eq("AVAILABLE"),
		"UNAVAILABLE",
		"AVAILABLE",
	)}).RunWrite(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	http.Redirect(w, req, "/", http.StatusFound)
}

func (s *HTTPServer) DeleteNode(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	if id == "" {
		http.NotFound(w, req)
		return
	}

	// Check that the item exists
	res, err := r.Table(tableIpxe).Get(id).RunRow(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if res.IsNil() {
		http.NotFound(w, req)
		return
	}

	// Delete the item
	_, err = r.Table(tableIpxe).Get(id).Delete().RunWrite(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	http.Redirect(w, req, "/", http.StatusFound)
}

func (s *HTTPServer) NodeIpxe(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	if id == "" {
		http.NotFound(w, req)
		return
	}

	// Check that the item exists
	queryExistance := r.Table(tableIpxe)
	queryExistance = queryExistance.Filter(r.Row.Field("id").Eq(id)).Filter(r.Row.Field("Status").Eq("AVAILABLE"))
	res, err := queryExistance.RunRow(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if res.IsNil() {
		http.NotFound(w, req)
		return
	}

	instructions := []Machine{}

	var instruction Machine
	err = res.Scan(&instruction)
	if err != nil {
		fmt.Println(err)
		return
	}

	instructions = append(instructions, instruction)

	// Render template
	renderTemplate(w, instruction.Template, instructions)

	// Set status to installed
	_, err = r.Table(tableIpxe).Get(id).Update(map[string]interface{}{"Status": "INSTALLED"}).RunWrite(session)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

}
<|endoftext|>


<commit_before>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package index

import (
	"reflect"
	"testing"
)

type testCol struct {
	name string
	keys []Key
	grps map[Key]Group
	flds map[string]interface{}
}

func (c testCol) Keys() []Key                    { return c.keys }
func (c testCol) Name() string                   { return c.name }
func (c testCol) Get(k Key) Group                { return c.grps[k] }
func (c testCol) Field(field string) interface{} { return c.flds[field] }

func (c testCol) Tracks() []Track {
	return collectionTracks(c)
}

func TestSumGroupIntAttr(t *testing.T) {
	table := []struct {
		in    Group
		field string
		total int
	}{
		// One group with one track
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Duration: 1,
					},
				},
			},
			field: "Duration",
			total: 1,
		},

		// One group, two tracks
		{
			in: group{
				name: "Group Two",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Duration: 1,
					},
					testTrack{
						Name:     "Track Two",
						Duration: 2,
					},
				},
			},
			field: "Duration",
			total: 3,
		},

		// One collection, one group, three tracks
		{
			in: testCol{
				name: "Group Three (collection)",
				keys: []Key{"Group-Three-One"},
				grps: map[Key]Group{
					"Group-Three-One": group{
						name: "Group One (Three)",
						tracks: []Track{
							testTrack{
								Name:     "Track One",
								Duration: 1,
							},
							testTrack{
								Name:     "Track Two",
								Duration: 2,
							},
							testTrack{
								Name:     "Track One",
								Duration: 4,
							},
						},
					},
				},
			},
			field: "Duration",
			total: 7,
		},

		// One collection, three groups, many tracks!
		{
			in: testCol{
				name: "Root",
				keys: []Key{"Group-One", "Group-Two", "Group-Three"},
				grps: map[Key]Group{
					"Group-One": group{
						name: "Group One",
						tracks: []Track{
							testTrack{
								Name:     "Track One",
								Duration: 1,
							},
						},
					},
					"Group-Two": group{
						name: "Group Two",
						tracks: []Track{
							testTrack{
								Name:     "Track One",
								Duration: 10,
							},
							testTrack{
								Name:     "Track Two",
								Duration: 20,
							},
						},
					},
					"Group-Three": testCol{
						name: "Group Three (collection)",
						keys: []Key{"Group-Three-One"},
						grps: map[Key]Group{
							"Group-Three-One": group{
								name: "Group One (Three)",
								tracks: []Track{
									testTrack{
										Name:     "Track One",
										Duration: 100,
									},
									testTrack{
										Name:     "Track Two",
										Duration: 200,
									},
									testTrack{
										Name:     "Track One",
										Duration: 400,
									},
								},
							},
						},
					},
				},
			},
			field: "Duration",
			total: 731,
		},
	}

	for ii, tt := range table {
		g := SumGroupIntAttr(tt.field, tt.in)
		got := g.Field(tt.field)
		if got != tt.total {
			t.Errorf("[%d] Fields()['%v'] = %d, expected %d", ii, tt.field, got, tt.total)
		}
	}
}

func TestCommonGroupAttr(t *testing.T) {
	table := []struct {
		in     Group
		fields []Attr
		out    []interface{}
	}{
		// One group with one track, unset common field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			fields: []Attr{StringAttr("Artist")},
			out:    []interface{}{nil},
		},

		// One group with one track, unset common int field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Empty common field",
					},
				},
			},
			fields: []Attr{IntAttr("Year")},
			out:    []interface{}{nil},
		},

		// One group with one track, unset common (string) and (int) fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), IntAttr("Year")},
			out:    []interface{}{nil, nil},
		},

		// One group with two tracks, empty first string & int fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
					testTrack{
						Name:   "Track Two",
						Artist: "Artist One",
						Year:   1984,
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), IntAttr("Year")},
			out:    []interface{}{nil, nil},
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
					testTrack{
						Name: "Track Two",
						Year: 1985,
					},
				},
			},
			fields: []Attr{IntAttr("Year")},
			out:    []interface{}{nil},
		},

		// One group with one track, common string/int fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
						Year:     1984,
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), IntAttr("Year")},
			out:    []interface{}{"Artist One", 1984},
		},

		// One group with one track, common string fields for Artist and Composer
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), StringAttr("Composer")},
			out:    []interface{}{"Artist One", "Composer One"},
		},

		// One group with two tracks, common fields across pairs
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
					},
					testTrack{
						Name:     "Track Two",
						Artist:   "Artist Two",
						Composer: "Composer One",
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), StringAttr("Composer")},
			out:    []interface{}{nil, "Composer One"},
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group Three (collection)",
				keys: []Key{"Group-Three-One"},
				grps: map[Key]Group{
					"Group-Three-One": group{
						name: "Group One (Three)",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
							},
						},
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), StringAttr("Composer")},
			out:    []interface{}{"Artist One", nil},
		},

		// One collection, three groups, many tracks!
		{
			in: testCol{
				name: "Root",
				keys: []Key{"Group-One", "Group-Two", "Group-Three"},
				grps: map[Key]Group{
					"Group-One": group{
						name: "Group One",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
								Year:   1984,
							},
						},
					},
					"Group-Two": group{
						name: "Group Two",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
								Year:   1984,
							},
							testTrack{
								Name:   "Track Two",
								Artist: "Artist One",
								Year:   1984,
							},
						},
					},
					"Group-Three": testCol{
						name: "Group Three (collection)",
						keys: []Key{"Group-Three-One"},
						grps: map[Key]Group{
							"Group-Three-One": group{
								name: "Group One (Three)",
								tracks: []Track{
									testTrack{
										Name:   "Track One",
										Artist: "Artist One",
										Year:   1984,
									},
									testTrack{
										Name:   "Track Two",
										Artist: "Artist One",
										Year:   2000,
									},
									testTrack{
										Name:   "Track One",
										Artist: "Artist One",
										Year:   1984,
									},
								},
							},
						},
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), IntAttr("Year")},
			out:    []interface{}{"Artist One", nil},
		},
	}

	for ii, tt := range table {
		g := CommonGroupAttr(tt.fields, tt.in)
		got := make([]interface{}, len(tt.out))
		for i, f := range tt.fields {
			got[i] = g.Field(f.Field())
		}

		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected %#v", ii, got, tt.out)
		}
	}
}

func TestFirstTrackAttr(t *testing.T) {
	table := []struct {
		in    Group
		field Attr
		out   interface{}
	}{
		// One group with no tracks
		{
			in: group{
				name: "Group One",
			},
			field: StringAttr("Name"),
			out:   nil,
		},

		{
			in: group{
				name: "Group One",
			},
			field: StringsAttr("Artist"),
			out:   nil,
		},

		// One group with one track
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			field: StringAttr("Name"),
			out:   "Track One",
		},

		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Artist: "Track One",
					},
				},
			},
			field: StringsAttr("Artist"),
			out:   []string{"Track One"},
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{},
					testTrack{
						Name:   "Track Two",
						Artist: "Artist One",
					},
				},
			},
			field: StringAttr("Artist"),
			out:   nil,
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group One (collection)",
				keys: []Key{"Group-One-One"},
				grps: map[Key]Group{
					"Group-One-One": group{
						name: "Group One (One)",
						tracks: []Track{
							testTrack{
								Name: "Track One",
							},
						},
					},
				},
			},
			field: StringAttr("Name"),
			out:   "Track One",
		},

		// One group with one track
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Duration: 1234,
					},
				},
			},
			field: IntAttr("Duration"),
			out:   1234,
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{},
					testTrack{
						Duration: 1234,
						Artist:   "Artist One",
					},
				},
			},
			field: IntAttr("Duration"),
			out:   nil,
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group One (collection)",
				keys: []Key{"Group-One-One"},
				grps: map[Key]Group{
					"Group-One-One": group{
						name: "Group One (One)",
						tracks: []Track{
							testTrack{
								Duration: 1234,
							},
						},
					},
				},
			},
			field: IntAttr("Duration"),
			out:   1234,
		},
	}

	for ii, tt := range table {
		g := FirstTrackAttr(tt.field, tt.in)
		got := g.Field(tt.field.Field())

		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected %#v", ii, got, tt.out)
		}
	}
}
<commit_msg>Added another StringsAttr test.<commit_after>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package index

import (
	"reflect"
	"testing"
)

type testCol struct {
	name string
	keys []Key
	grps map[Key]Group
	flds map[string]interface{}
}

func (c testCol) Keys() []Key                    { return c.keys }
func (c testCol) Name() string                   { return c.name }
func (c testCol) Get(k Key) Group                { return c.grps[k] }
func (c testCol) Field(field string) interface{} { return c.flds[field] }

func (c testCol) Tracks() []Track {
	return collectionTracks(c)
}

func TestSumGroupIntAttr(t *testing.T) {
	table := []struct {
		in    Group
		field string
		total int
	}{
		// One group with one track
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Duration: 1,
					},
				},
			},
			field: "Duration",
			total: 1,
		},

		// One group, two tracks
		{
			in: group{
				name: "Group Two",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Duration: 1,
					},
					testTrack{
						Name:     "Track Two",
						Duration: 2,
					},
				},
			},
			field: "Duration",
			total: 3,
		},

		// One collection, one group, three tracks
		{
			in: testCol{
				name: "Group Three (collection)",
				keys: []Key{"Group-Three-One"},
				grps: map[Key]Group{
					"Group-Three-One": group{
						name: "Group One (Three)",
						tracks: []Track{
							testTrack{
								Name:     "Track One",
								Duration: 1,
							},
							testTrack{
								Name:     "Track Two",
								Duration: 2,
							},
							testTrack{
								Name:     "Track One",
								Duration: 4,
							},
						},
					},
				},
			},
			field: "Duration",
			total: 7,
		},

		// One collection, three groups, many tracks!
		{
			in: testCol{
				name: "Root",
				keys: []Key{"Group-One", "Group-Two", "Group-Three"},
				grps: map[Key]Group{
					"Group-One": group{
						name: "Group One",
						tracks: []Track{
							testTrack{
								Name:     "Track One",
								Duration: 1,
							},
						},
					},
					"Group-Two": group{
						name: "Group Two",
						tracks: []Track{
							testTrack{
								Name:     "Track One",
								Duration: 10,
							},
							testTrack{
								Name:     "Track Two",
								Duration: 20,
							},
						},
					},
					"Group-Three": testCol{
						name: "Group Three (collection)",
						keys: []Key{"Group-Three-One"},
						grps: map[Key]Group{
							"Group-Three-One": group{
								name: "Group One (Three)",
								tracks: []Track{
									testTrack{
										Name:     "Track One",
										Duration: 100,
									},
									testTrack{
										Name:     "Track Two",
										Duration: 200,
									},
									testTrack{
										Name:     "Track One",
										Duration: 400,
									},
								},
							},
						},
					},
				},
			},
			field: "Duration",
			total: 731,
		},
	}

	for ii, tt := range table {
		g := SumGroupIntAttr(tt.field, tt.in)
		got := g.Field(tt.field)
		if got != tt.total {
			t.Errorf("[%d] Fields()['%v'] = %d, expected %d", ii, tt.field, got, tt.total)
		}
	}
}

func TestCommonGroupAttr(t *testing.T) {
	table := []struct {
		in     Group
		fields []Attr
		out    []interface{}
	}{
		// One group with one track, unset common field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			fields: []Attr{StringAttr("Artist")},
			out:    []interface{}{nil},
		},

		// One group with one track, unset common int field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Empty common field",
					},
				},
			},
			fields: []Attr{IntAttr("Year")},
			out:    []interface{}{nil},
		},

		// One group with one track, unset common (string) and (int) fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), IntAttr("Year")},
			out:    []interface{}{nil, nil},
		},

		// One group with two tracks, empty first string & int fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
					testTrack{
						Name:   "Track Two",
						Artist: "Artist One",
						Year:   1984,
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), IntAttr("Year")},
			out:    []interface{}{nil, nil},
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
					testTrack{
						Name: "Track Two",
						Year: 1985,
					},
				},
			},
			fields: []Attr{IntAttr("Year")},
			out:    []interface{}{nil},
		},

		// One group with one track, common string/int fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
						Year:     1984,
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), IntAttr("Year")},
			out:    []interface{}{"Artist One", 1984},
		},

		// One group with one track, common string fields for Artist and Composer
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), StringAttr("Composer")},
			out:    []interface{}{"Artist One", "Composer One"},
		},

		// One group with two tracks, common fields across pairs
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
					},
					testTrack{
						Name:     "Track Two",
						Artist:   "Artist Two",
						Composer: "Composer One",
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), StringAttr("Composer")},
			out:    []interface{}{nil, "Composer One"},
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group Three (collection)",
				keys: []Key{"Group-Three-One"},
				grps: map[Key]Group{
					"Group-Three-One": group{
						name: "Group One (Three)",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
							},
						},
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), StringAttr("Composer")},
			out:    []interface{}{"Artist One", nil},
		},

		// One collection, three groups, many tracks!
		{
			in: testCol{
				name: "Root",
				keys: []Key{"Group-One", "Group-Two", "Group-Three"},
				grps: map[Key]Group{
					"Group-One": group{
						name: "Group One",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
								Year:   1984,
							},
						},
					},
					"Group-Two": group{
						name: "Group Two",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
								Year:   1984,
							},
							testTrack{
								Name:   "Track Two",
								Artist: "Artist One",
								Year:   1984,
							},
						},
					},
					"Group-Three": testCol{
						name: "Group Three (collection)",
						keys: []Key{"Group-Three-One"},
						grps: map[Key]Group{
							"Group-Three-One": group{
								name: "Group One (Three)",
								tracks: []Track{
									testTrack{
										Name:   "Track One",
										Artist: "Artist One",
										Year:   1984,
									},
									testTrack{
										Name:   "Track Two",
										Artist: "Artist One",
										Year:   2000,
									},
									testTrack{
										Name:   "Track One",
										Artist: "Artist One",
										Year:   1984,
									},
								},
							},
						},
					},
				},
			},
			fields: []Attr{StringAttr("Artist"), IntAttr("Year")},
			out:    []interface{}{"Artist One", nil},
		},
	}

	for ii, tt := range table {
		g := CommonGroupAttr(tt.fields, tt.in)
		got := make([]interface{}, len(tt.out))
		for i, f := range tt.fields {
			got[i] = g.Field(f.Field())
		}

		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected %#v", ii, got, tt.out)
		}
	}
}

func TestFirstTrackAttr(t *testing.T) {
	table := []struct {
		in    Group
		field Attr
		out   interface{}
	}{
		// One group with no tracks
		{
			in: group{
				name: "Group One",
			},
			field: StringAttr("Name"),
			out:   nil,
		},

		{
			in: group{
				name: "Group One",
			},
			field: StringsAttr("Artist"),
			out:   nil,
		},

		// One group with one track
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			field: StringAttr("Name"),
			out:   "Track One",
		},

		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Artist: "Track One",
					},
				},
			},
			field: StringsAttr("Artist"),
			out:   []string{"Track One"},
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{},
					testTrack{
						Name:   "Track Two",
						Artist: "Artist One",
					},
				},
			},
			field: StringAttr("Artist"),
			out:   nil,
		},

		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{},
					testTrack{
						Name:   "Track Two",
						Artist: "Artist One",
					},
				},
			},
			field: StringsAttr("Artist"),
			out:   []string(nil),
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group One (collection)",
				keys: []Key{"Group-One-One"},
				grps: map[Key]Group{
					"Group-One-One": group{
						name: "Group One (One)",
						tracks: []Track{
							testTrack{
								Name: "Track One",
							},
						},
					},
				},
			},
			field: StringAttr("Name"),
			out:   "Track One",
		},

		// One group with one track
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Duration: 1234,
					},
				},
			},
			field: IntAttr("Duration"),
			out:   1234,
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{},
					testTrack{
						Duration: 1234,
						Artist:   "Artist One",
					},
				},
			},
			field: IntAttr("Duration"),
			out:   nil,
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group One (collection)",
				keys: []Key{"Group-One-One"},
				grps: map[Key]Group{
					"Group-One-One": group{
						name: "Group One (One)",
						tracks: []Track{
							testTrack{
								Duration: 1234,
							},
						},
					},
				},
			},
			field: IntAttr("Duration"),
			out:   1234,
		},
	}

	for ii, tt := range table {
		g := FirstTrackAttr(tt.field, tt.in)
		got := g.Field(tt.field.Field())

		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected %#v", ii, got, tt.out)
		}
	}
}
<|endoftext|>


<commit_before>package reflect

import (
	"reflect"

	. "./types"
	ocheck "github.com/Cepave/open-falcon-backend/common/testing/check"
	. "gopkg.in/check.v1"
)

type TestReflectSuite struct{}

var _ = Suite(&TestReflectSuite{})

// Tests the getting value of field by strings
func (suite *TestReflectSuite) TestGetValueOfField(c *C) {
	type sampleBox struct {
		Age        int
		Name       string
		ChildBox   *sampleBox
		ChildBoxL2 **sampleBox
	}

	box1 := sampleBox{Age: 30, Name: "b1"}
	box2 := &sampleBox{Age: 33, ChildBox: &box1}
	box3 := &sampleBox{ChildBoxL2: &box2}

	c.Assert(GetValueOfField(box1, "Age"), Equals, 30)

	c.Assert(GetValueOfField(box2, "Age"), Equals, 33)
	c.Assert(GetValueOfField(box2, "ChildBox", "Age"), Equals, 30)

	c.Assert(GetValueOfField(box3, "ChildBoxL2", "Age"), Equals, 33)
	c.Assert(GetValueOfField(box3, "ChildBox"), IsNil)
}

// Tests the getting value of field by strings
func (suite *TestReflectSuite) TestSetValueOfField(c *C) {
	type blueBox struct {
		Age int
	}
	type sampleBox struct {
		Age        int
		Name       string
		ChildBox   *sampleBox
		ChildBoxL2 **sampleBox

		BlueBox blueBox
	}

	box1 := &sampleBox{Age: 35}
	box2 := &sampleBox{Age: 77}
	box3 := &sampleBox{Age: 491}

	/**
	 * Sets the field value by pointer
	 */
	SetValueOfField(box1, 77, "Age")
	c.Assert(box1.Age, Equals, 77)

	SetValueOfField(box1, blueBox{Age: 62}, "BlueBox")
	c.Assert(box1.BlueBox.Age, Equals, 62)

	SetValueOfField(box1, 53, "BlueBox", "Age")
	c.Assert(box1.BlueBox.Age, Equals, 53)

	SetValueOfField(box1, box2, "ChildBox")
	c.Assert(box1.ChildBox.Age, Equals, 77)

	SetValueOfField(box1, &box3, "ChildBoxL2")
	c.Assert((*(box1.ChildBoxL2)).Age, Equals, 491)
	// :~)
}

// Test the extraction for final pointed type
func (suite *TestReflectSuite) TestFinalPointedType(c *C) {
	testCases := []*struct {
		sampleType   interface{}
		expectedType reflect.Type
	}{
		{int32(45), TypeOfInt32},
		{new(**int32), TypeOfInt32},
		{new(****int32), TypeOfInt32},
	}

	for i, testCase := range testCases {
		comment := ocheck.TestCaseComment(i)
		ocheck.LogTestCase(c, testCase)

		testedType := FinalPointedType(reflect.TypeOf(testCase.sampleType))

		c.Assert(testedType, DeepEquals, testCase.expectedType, comment)
	}
}

// Tests the getting of final value from pointed value
func (suite *TestReflectSuite) TestGetPointedValue(c *C) {
	v := int(77)
	v1 := &v
	v2 := &v1

	testCases := []*struct {
		sampleValue   interface{}
		expectedValue interface{}
	}{
		{&v, v},
		{v1, v},
		{v2, v},
		{(*uint16)(nil), (*uint16)(nil)},
		{(**uint16)(nil), (**uint16)(nil)},
		{(****uint16)(nil), (****uint16)(nil)},
	}

	for i, testCase := range testCases {
		comment := ocheck.TestCaseComment(i)
		ocheck.LogTestCase(c, testCase)

		testedResult := FinalPointedValue(
			reflect.ValueOf(testCase.sampleValue),
		)

		c.Assert(testedResult.Interface(), Equals, testCase.expectedValue, comment)
	}
}

// Tests the new() of final value from pointer type
func (suite *TestReflectSuite) TestNewFinalValue(c *C) {
	testCases := []*struct {
		sampleType    reflect.Type
		expectedValue interface{}
	}{
		{TypeOfInt8, int8(0)},
		{reflect.TypeOf(new(**string)), ""},
	}

	for i, testCase := range testCases {
		comment := ocheck.TestCaseComment(i)
		ocheck.LogTestCase(c, testCase)

		testedValue := NewFinalValue(testCase.sampleType).Interface()

		c.Assert(testedValue, Equals, testCase.expectedValue, comment)
	}
}

// Tests the new() of final value from any type to its pointer type(multi-layer)
func (suite *TestReflectSuite) TestNewFinalValueFrom(c *C) {
	v := int32(97)
	v1 := &v
	v2 := &v1
	v3 := &v2

	testCases := []*struct {
		sampleValue    interface{}
		finalType      reflect.Type
		expectedResult interface{}
	}{
		{int64(99), TypeOfInt64, int64(99)},
		{v, reflect.TypeOf(new(*int32)), v2},
		{v, reflect.TypeOf(new(**int32)), v3},
	}

	for i, testCase := range testCases {
		comment := ocheck.TestCaseComment(i)
		ocheck.LogTestCase(c, testCase)

		testedValue := NewFinalValueFrom(
			reflect.ValueOf(testCase.sampleValue),
			testCase.finalType,
		)

		c.Logf("New type[%v]. Result type[%v]", testedValue.Type(), reflect.TypeOf(testCase.expectedResult))
		c.Assert(testedValue.Type().String(), Equals, reflect.TypeOf(testCase.expectedResult).String(), comment)

		testedFinalValue := FinalPointedValue(testedValue)
		expectedFinalValue := FinalPointedValue(reflect.ValueOf(testCase.expectedResult))

		c.Assert(testedFinalValue.Interface(), Equals, expectedFinalValue.Interface(), comment)
	}
}
<commit_msg>refector import.<commit_after>package reflect

import (
	"reflect"

	. "github.com/Cepave/open-falcon-backend/common/reflect/types"
	ocheck "github.com/Cepave/open-falcon-backend/common/testing/check"
	. "gopkg.in/check.v1"
)

type TestReflectSuite struct{}

var _ = Suite(&TestReflectSuite{})

// Tests the getting value of field by strings
func (suite *TestReflectSuite) TestGetValueOfField(c *C) {
	type sampleBox struct {
		Age        int
		Name       string
		ChildBox   *sampleBox
		ChildBoxL2 **sampleBox
	}

	box1 := sampleBox{Age: 30, Name: "b1"}
	box2 := &sampleBox{Age: 33, ChildBox: &box1}
	box3 := &sampleBox{ChildBoxL2: &box2}

	c.Assert(GetValueOfField(box1, "Age"), Equals, 30)

	c.Assert(GetValueOfField(box2, "Age"), Equals, 33)
	c.Assert(GetValueOfField(box2, "ChildBox", "Age"), Equals, 30)

	c.Assert(GetValueOfField(box3, "ChildBoxL2", "Age"), Equals, 33)
	c.Assert(GetValueOfField(box3, "ChildBox"), IsNil)
}

// Tests the getting value of field by strings
func (suite *TestReflectSuite) TestSetValueOfField(c *C) {
	type blueBox struct {
		Age int
	}
	type sampleBox struct {
		Age        int
		Name       string
		ChildBox   *sampleBox
		ChildBoxL2 **sampleBox

		BlueBox blueBox
	}

	box1 := &sampleBox{Age: 35}
	box2 := &sampleBox{Age: 77}
	box3 := &sampleBox{Age: 491}

	/**
	 * Sets the field value by pointer
	 */
	SetValueOfField(box1, 77, "Age")
	c.Assert(box1.Age, Equals, 77)

	SetValueOfField(box1, blueBox{Age: 62}, "BlueBox")
	c.Assert(box1.BlueBox.Age, Equals, 62)

	SetValueOfField(box1, 53, "BlueBox", "Age")
	c.Assert(box1.BlueBox.Age, Equals, 53)

	SetValueOfField(box1, box2, "ChildBox")
	c.Assert(box1.ChildBox.Age, Equals, 77)

	SetValueOfField(box1, &box3, "ChildBoxL2")
	c.Assert((*(box1.ChildBoxL2)).Age, Equals, 491)
	// :~)
}

// Test the extraction for final pointed type
func (suite *TestReflectSuite) TestFinalPointedType(c *C) {
	testCases := []*struct {
		sampleType   interface{}
		expectedType reflect.Type
	}{
		{int32(45), TypeOfInt32},
		{new(**int32), TypeOfInt32},
		{new(****int32), TypeOfInt32},
	}

	for i, testCase := range testCases {
		comment := ocheck.TestCaseComment(i)
		ocheck.LogTestCase(c, testCase)

		testedType := FinalPointedType(reflect.TypeOf(testCase.sampleType))

		c.Assert(testedType, DeepEquals, testCase.expectedType, comment)
	}
}

// Tests the getting of final value from pointed value
func (suite *TestReflectSuite) TestGetPointedValue(c *C) {
	v := int(77)
	v1 := &v
	v2 := &v1

	testCases := []*struct {
		sampleValue   interface{}
		expectedValue interface{}
	}{
		{&v, v},
		{v1, v},
		{v2, v},
		{(*uint16)(nil), (*uint16)(nil)},
		{(**uint16)(nil), (**uint16)(nil)},
		{(****uint16)(nil), (****uint16)(nil)},
	}

	for i, testCase := range testCases {
		comment := ocheck.TestCaseComment(i)
		ocheck.LogTestCase(c, testCase)

		testedResult := FinalPointedValue(
			reflect.ValueOf(testCase.sampleValue),
		)

		c.Assert(testedResult.Interface(), Equals, testCase.expectedValue, comment)
	}
}

// Tests the new() of final value from pointer type
func (suite *TestReflectSuite) TestNewFinalValue(c *C) {
	testCases := []*struct {
		sampleType    reflect.Type
		expectedValue interface{}
	}{
		{TypeOfInt8, int8(0)},
		{reflect.TypeOf(new(**string)), ""},
	}

	for i, testCase := range testCases {
		comment := ocheck.TestCaseComment(i)
		ocheck.LogTestCase(c, testCase)

		testedValue := NewFinalValue(testCase.sampleType).Interface()

		c.Assert(testedValue, Equals, testCase.expectedValue, comment)
	}
}

// Tests the new() of final value from any type to its pointer type(multi-layer)
func (suite *TestReflectSuite) TestNewFinalValueFrom(c *C) {
	v := int32(97)
	v1 := &v
	v2 := &v1
	v3 := &v2

	testCases := []*struct {
		sampleValue    interface{}
		finalType      reflect.Type
		expectedResult interface{}
	}{
		{int64(99), TypeOfInt64, int64(99)},
		{v, reflect.TypeOf(new(*int32)), v2},
		{v, reflect.TypeOf(new(**int32)), v3},
	}

	for i, testCase := range testCases {
		comment := ocheck.TestCaseComment(i)
		ocheck.LogTestCase(c, testCase)

		testedValue := NewFinalValueFrom(
			reflect.ValueOf(testCase.sampleValue),
			testCase.finalType,
		)

		c.Logf("New type[%v]. Result type[%v]", testedValue.Type(), reflect.TypeOf(testCase.expectedResult))
		c.Assert(testedValue.Type().String(), Equals, reflect.TypeOf(testCase.expectedResult).String(), comment)

		testedFinalValue := FinalPointedValue(testedValue)
		expectedFinalValue := FinalPointedValue(reflect.ValueOf(testCase.expectedResult))

		c.Assert(testedFinalValue.Interface(), Equals, expectedFinalValue.Interface(), comment)
	}
}
<|endoftext|>