<commit_before>package main

import (
	"net/http"
	"fmt"
)

// http://qiita.com/taizo/items/bf1ec35a65ad5f608d45
// https://golang.org/pkg/net/http/

type String string

func (s String) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, s)
}

func main() {

	// handlerを定義する場合.
	http.HandleFunc("/a", handler)

	// クロージャー的なのでもOK.
	http.HandleFunc("/b", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Hello from Closure")
	})

	// DuckTyping的に、ServeHTTP関数があれば良い.
	http.Handle("/c", String("Duck Typing!!!"))

	// 例えばPOSTのみ.
	http.HandleFunc("/onlyPost", handleOnlyPost)

	// パラメータ受け取り
	http.HandleFunc("/params", handleParams)

	// 静的ファイル配信.
	http.Handle("/contents/", http.FileServer(http.Dir("./")))
	http.Handle("/mysecret/", http.StripPrefix("/mysecret/", http.FileServer(http.Dir("./contents"))))

	// basic認証.
	http.HandleFunc("/basicAuth", handleBasicAuth)

	http.ListenAndServe(":8080", nil)
	//http.ListenAndServe(":8080", String("Other Handler"))
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello World from Go.")
}

func handleOnlyPost(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusMethodNotAllowed) // 405
		w.Write([]byte("POSTだけだよー"))
		return
	}

	w.Write([]byte("OK"))
}

func handleParams(w http.ResponseWriter, r *http.Request) {

	// https://golang.org/pkg/net/http/#Request
	// https://golang.org/pkg/net/url/#URL

	// クエリパラメータ取得してみる
	fmt.Fprintf(w, "クエリ：%s\n", r.URL.RawQuery)

	// ボディを受け取ってみる
	//if r.Method == http.MethodPost {

		r.ParseForm()
		form := r.PostForm
		fmt.Fprintf(w, "フォーム：\n%v\n", form)

		// または、クエリパラメータも含めて全部.
		params := r.Form
		fmt.Fprintf(w, "フォーム2：\n%v\n", params)
	//}
}

func handleBasicAuth(w http.ResponseWriter, r *http.Request) {

	username, password, ok := r.BasicAuth()
	if ok == false {
		w.Header().Set("WWW-Authenticate", `Basic realm="SECRET AREA"`)
		w.WriteHeader(http.StatusUnauthorized) // 401
		fmt.Fprintf(w, "%d Not authorized.", http.StatusUnauthorized)
		return
	}

	// 認証チェック
	if username != "my" || password != "secret" {
		w.Header().Set("WWW-Authenticate", `Basic realm="SECRET AREA"`)
		w.WriteHeader(http.StatusUnauthorized) // 401
		fmt.Fprintf(w, "%d Not authorized.", http.StatusUnauthorized)
		return
	}

	// OK
	fmt.Fprint(w, "OK")

}<commit_msg>Refactoring<commit_after>package main

import (
	"net/http"
	"fmt"
)

// https://golang.org/pkg/net/http/

type String string

func (s String) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, s)
}

func main() {

	// handlerを定義する場合.
	http.HandleFunc("/a", handler)

	// クロージャー的なのでもOK.
	http.HandleFunc("/b", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Hello from Closure")
	})

	// DuckTyping的に、ServeHTTP関数があれば良い.
	http.Handle("/c", String("Duck Typing!!!"))

	// 例えばPOSTのみ.
	http.HandleFunc("/onlyPost", handleOnlyPost)

	// パラメータ受け取り
	http.HandleFunc("/params", handleParams)

	// 静的ファイル配信.
	http.Handle("/contents/", http.FileServer(http.Dir("./")))
	http.Handle("/mysecret/", http.StripPrefix("/mysecret/", http.FileServer(http.Dir("./contents"))))

	// basic認証.
	http.HandleFunc("/basicAuth", handleBasicAuth)

	http.ListenAndServe(":8080", nil)
	//http.ListenAndServe(":8080", String("Other Handler"))
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello World from Go.")
}

func handleOnlyPost(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusMethodNotAllowed) // 405
		w.Write([]byte("POSTだけだよー"))
		return
	}

	w.Write([]byte("OK"))
}

func handleParams(w http.ResponseWriter, r *http.Request) {

	// https://golang.org/pkg/net/http/#Request
	// https://golang.org/pkg/net/url/#URL

	// クエリパラメータ取得してみる
	fmt.Fprintf(w, "クエリ：%s\n", r.URL.RawQuery)

	r.ParseForm()
	form := r.PostForm
	fmt.Fprintf(w, "フォーム：\n%v\n", form)

	// または、クエリパラメータも含めて全部.
	params := r.Form
	fmt.Fprintf(w, "フォーム2：\n%v\n", params)
}

func handleBasicAuth(w http.ResponseWriter, r *http.Request) {

	username, password, ok := r.BasicAuth()
	if ok == false {
		w.Header().Set("WWW-Authenticate", `Basic realm="SECRET AREA"`)
		w.WriteHeader(http.StatusUnauthorized) // 401
		fmt.Fprintf(w, "%d Not authorized.", http.StatusUnauthorized)
		return
	}

	// 認証チェック
	if username != "my" || password != "secret" {
		w.Header().Set("WWW-Authenticate", `Basic realm="SECRET AREA"`)
		w.WriteHeader(http.StatusUnauthorized) // 401
		fmt.Fprintf(w, "%d Not authorized.", http.StatusUnauthorized)
		return
	}

	// OK
	fmt.Fprint(w, "OK")

}<|endoftext|>


<commit_before>package instance

import (
	"context"

	"github.com/giantswarm/azure-operator/service/controller/v13/resource/instance/internal/state"
)

func (r *Resource) provisioningSuccessfulTransition(ctx context.Context, obj interface{}, currentState state.State) (state.State, error) {
	r.logger.LogCtx(ctx, "level", "debug", "message", "VMSS deployment successfully provisioned")
	return MasterInstancesUpgrading, nil
}
<commit_msg>Ensure that scaling shortcut is active (#650)<commit_after>package instance

import (
	"context"

	"github.com/giantswarm/azure-operator/service/controller/v13/resource/instance/internal/state"
)

func (r *Resource) provisioningSuccessfulTransition(ctx context.Context, obj interface{}, currentState state.State) (state.State, error) {
	r.logger.LogCtx(ctx, "level", "debug", "message", "VMSS deployment successfully provisioned")
	return ClusterUpgradeRequirementCheck, nil
}
<|endoftext|>


<commit_before>package svnwatch

import (
	"encoding/xml"

	"github.com/jackwilsdon/svnwatch/svn"
	"github.com/pkg/errors"
)

type Repositories struct {
	XMLName      xml.Name     `xml:"repositories"`
	Repositories []Repository `xml:"repository"`
}

func (r *Repositories) ForURL(url string) *Repository {
	for i, _ := range r.Repositories {
		if url == r.Repositories[i].URL {
			return &r.Repositories[i]
		}
	}

	r.Repositories = append(r.Repositories, Repository{
		Revision: 0,
		URL:      url,
	})

	return &r.Repositories[len(r.Repositories)-1]
}

type Repository struct {
	XMLName  xml.Name `xml:"repository"`
	URL      string   `xml:"url,attr"`
	Revision int      `xml:",chardata"`
}

func (r *Repository) Update() (bool, error) {
	info, err := svn.GetInfo(r.URL)

	if err != nil {
		return false, errors.Wrapf(err, "failed to update %s", r.URL)
	}

	if len(info.Entries) == 0 {
		return false, errors.New("no entries in info")
	}

	revision := info.Entries[0].Revision

	if revision > r.Revision {
		r.Revision = revision
		return true, nil
	}

	return false, nil
}

func (r *Repository) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	repo := struct {
		URL *string `xml:"url,attr"`
	}{}

	if err := d.DecodeElement(&repo, &start); err != nil {
		return err
	}

	if repo.URL == nil {
		return errors.New("missing URL from watch")
	}

	r.URL = *repo.URL

	return nil
}
<commit_msg>Use log instead of info for repo update<commit_after>package svnwatch

import (
	"encoding/xml"

	"github.com/jackwilsdon/svnwatch/svn"
	"github.com/pkg/errors"
)

type Repositories struct {
	XMLName      xml.Name     `xml:"repositories"`
	Repositories []Repository `xml:"repository"`
}

func (r *Repositories) ForURL(url string) *Repository {
	for i, _ := range r.Repositories {
		if url == r.Repositories[i].URL {
			return &r.Repositories[i]
		}
	}

	r.Repositories = append(r.Repositories, Repository{
		Revision: 0,
		URL:      url,
	})

	return &r.Repositories[len(r.Repositories)-1]
}

type Repository struct {
	XMLName  xml.Name `xml:"repository"`
	URL      string   `xml:"url,attr"`
	Revision int      `xml:",chardata"`
}

func (r *Repository) Update() (bool, error) {
	revision, err := svn.GetLatestRevision(r.URL)

	if err != nil {
		return false, errors.Wrapf(err, "failed to update %s", r.URL)
	}

	if revision.Revision > r.Revision {
		r.Revision = revision.Revision
		return true, nil
	}

	return false, nil
}

func (r *Repository) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	repo := struct {
		URL *string `xml:"url,attr"`
	}{}

	if err := d.DecodeElement(&repo, &start); err != nil {
		return err
	}

	if repo.URL == nil {
		return errors.New("missing URL from watch")
	}

	r.URL = *repo.URL

	return nil
}
<|endoftext|>


<commit_before>package tap

import (
	"V-switch/conf"
	"V-switch/plane"
	"V-switch/tools"
	"fmt"
	"log"
	"net"
	"strconv"
	"strings"
)

type Vswitchdevice struct {
	devicename string
	mtu        int
	frame      []byte
	Realif     Interface
	err        error
	mac        string
}

//This will represent the tap device when exported.
var VDev Vswitchdevice

func init() {

	VDev.SetDeviceConf()
	go VDev.ReadFrameThread()  //this is blocking so it must be a new thread
	go VDev.WriteFrameThread() //thread which writes frames into the interface
}

func (vd *Vswitchdevice) SetDeviceConf() {

	if vd.mtu, vd.err = strconv.Atoi(conf.GetConfigItem("MTU")); vd.err != nil {
		log.Printf("[TAP] Cannot get MTU from conf: <%s>", vd.err)
		vd.mtu = 1500
		vd.frame = make([]byte, vd.mtu+42)
		log.Printf("[TAP] Using the default of 1500. Hope is fine.")
	} else {
		vd.frame = make([]byte, vd.mtu+42)
		log.Printf("[TAP] MTU SET TO: %v", vd.mtu)
	}

	vd.devicename = conf.GetConfigItem("DEVICENAME")
	log.Printf("[TAP] Devicename in conf is: %v", vd.devicename)

	vd.Realif, vd.err = newTAP(vd.devicename)

	if vd.err != nil {
		log.Printf("[TAP][ERROR] Error creating tap: <%s>", vd.err)
		log.Println("[TAP][ERROR] Are you ROOT?")
	} else {
		tmp_if, _ := net.InterfaceByName(vd.devicename)
		vd.mac = strings.ToUpper(tmp_if.HardwareAddr.String())
		plane.VSwitch.HAddr = vd.mac
		log.Printf("[TAP] Success creating tap: <%s> at mac [%s] ", vd.devicename, vd.mac)
	}

}

//creates a TAP device with name specified as argument
// just do ;
//sudo ip addr add 10.1.0.10/24 dev <tapname>
//sudo ip link set dev <tapname> up
//ping -c1 -b 10.1.0.255
func (vd *Vswitchdevice) ReadFrameThread() {

	defer func() {
		if e := recover(); e != nil {
			log.Println("[TAP][EXCEPTION] OH, SHIT.")
			err, ok := e.(error)
			if !ok {
				err = fmt.Errorf("[TAP][DRV]: %v", e)
			}
			log.Printf("[TAP][EXCEPTION] Error: <%s>", err)

		}
	}()

	for {

		vd.ReadFrame()

	}

}

//returns mac address of the device we created
func (vd *Vswitchdevice) GetTapMac() string {

	macc, _ := net.ParseMAC(vd.mac)
	if macc != nil {
		log.Printf("[TAP] GetTapMac: %s", vd.mac)
		return strings.ToUpper(vd.mac)

	}

	log.Printf("[TAP] GetTapMac: mac address is empty, using default one")
	return "00:00:00:00:00:00"

}

func (vd *Vswitchdevice) ReadFrame() {

	var n int

	n, vd.err = vd.Realif.Read(vd.frame)

	if vd.err != nil {
		log.Printf("[TAP] Error reading tap: <%s>", vd.err)

	} else {

		//log.Printf("Src: %s , Broadcast :%t\n", vd.frame.Source(), tools.IsMacBcast(vd.frame.Source().String()))
		//log.Printf("Dst: %s , Broadcast :%t\n", vd.frame.Destination(), tools.IsMacBcast(vd.frame.Destination().String()))
		//log.Printf("Ethertype: % x\n", vd.frame.Ethertype())
		//log.Printf("Payload: % x\n", vd.frame.Payload())
		log.Printf("Size: %d\n", n)
		log.Printf("Frame(%d): % x\n", len(vd.frame), vd.frame)

		vd.frame = vd.frame[:n]

		plane.TapToPlane <- vd.frame

	}

}

func (vd *Vswitchdevice) WriteFrameThread() {

	var n_frame []byte

	log.Printf("[TAP][WRITE] Tap writing thread started")

	for {

		n_frame = <-plane.PlaneToTap

		n, err := vd.Realif.Write(n_frame)
		if err != nil {
			log.Printf("[TAP][WRITE][ERROR] Error writing %d bytes to %s : %s", len(n_frame), vd.devicename, err.Error())
		} else {
			log.Printf("[TAP][WRITE] %d long frame of %d , from %s -> %s  to dev %s", n, len(n_frame), tools.MACSource(n_frame).String(), tools.MACDestination(n_frame).String(), vd.devicename)
		}

	}

}

//EngineStart triggers the init function in the package tap
func EngineStart() {

	log.Println("[TAP] Tap Engine Init")

}
<commit_msg>Using raw frames: who cares<commit_after>package tap

import (
	"V-switch/conf"
	"V-switch/plane"
	"V-switch/tools"
	"fmt"
	"log"
	"net"
	"strconv"
	"strings"
)

type Vswitchdevice struct {
	devicename string
	mtu        int
	frame      []byte
	Realif     Interface
	err        error
	mac        string
}

//This will represent the tap device when exported.
var VDev Vswitchdevice

func init() {

	VDev.SetDeviceConf()
	go VDev.ReadFrameThread()  //this is blocking so it must be a new thread
	go VDev.WriteFrameThread() //thread which writes frames into the interface
}

func (vd *Vswitchdevice) SetDeviceConf() {

	if vd.mtu, vd.err = strconv.Atoi(conf.GetConfigItem("MTU")); vd.err != nil {
		log.Printf("[TAP] Cannot get MTU from conf: <%s>", vd.err)
		vd.mtu = 1500
		vd.frame = make([]byte, vd.mtu+42)
		log.Printf("[TAP] Using the default of 1500. Hope is fine.")
	} else {
		vd.frame = make([]byte, vd.mtu+42)
		log.Printf("[TAP] MTU SET TO: %v", vd.mtu)
	}

	vd.devicename = conf.GetConfigItem("DEVICENAME")
	log.Printf("[TAP] Devicename in conf is: %v", vd.devicename)

	vd.Realif, vd.err = newTAP(vd.devicename)

	if vd.err != nil {
		log.Printf("[TAP][ERROR] Error creating tap: <%s>", vd.err)
		log.Println("[TAP][ERROR] Are you ROOT?")
	} else {
		tmp_if, _ := net.InterfaceByName(vd.devicename)
		vd.mac = strings.ToUpper(tmp_if.HardwareAddr.String())
		plane.VSwitch.HAddr = vd.mac
		log.Printf("[TAP] Success creating tap: <%s> at mac [%s] ", vd.devicename, vd.mac)
	}

}

//creates a TAP device with name specified as argument
// just do ;
//sudo ip addr add 10.1.0.10/24 dev <tapname>
//sudo ip link set dev <tapname> up
//ping -c1 -b 10.1.0.255
func (vd *Vswitchdevice) ReadFrameThread() {

	defer func() {
		if e := recover(); e != nil {
			log.Println("[TAP][EXCEPTION] OH, SHIT.")
			err, ok := e.(error)
			if !ok {
				err = fmt.Errorf("[TAP][DRV]: %v", e)
			}
			log.Printf("[TAP][EXCEPTION] Error: <%s>", err)

		}
	}()

	for {

		vd.ReadFrame()

	}

}

//returns mac address of the device we created
func (vd *Vswitchdevice) GetTapMac() string {

	macc, _ := net.ParseMAC(vd.mac)
	if macc != nil {
		log.Printf("[TAP] GetTapMac: %s", vd.mac)
		return strings.ToUpper(vd.mac)

	}

	log.Printf("[TAP] GetTapMac: mac address is empty, using default one")
	return "00:00:00:00:00:00"

}

func (vd *Vswitchdevice) ReadFrame() {

	var n int

	n, vd.err = vd.Realif.Read(vd.frame)

	if vd.err != nil {
		log.Printf("[TAP] Error reading tap: <%s>", vd.err)

	} else {

		//log.Printf("Src: %s , Broadcast :%t\n", vd.frame.Source(), tools.IsMacBcast(vd.frame.Source().String()))
		//log.Printf("Dst: %s , Broadcast :%t\n", vd.frame.Destination(), tools.IsMacBcast(vd.frame.Destination().String()))
		//log.Printf("Ethertype: % x\n", vd.frame.Ethertype())
		//log.Printf("Payload: % x\n", vd.frame.Payload())
		log.Printf("Size: %d\n", n)
		log.Printf("Frame(%d): % x\n", len(vd.frame), vd.frame)

		plane.TapToPlane <- vd.frame

	}

}

func (vd *Vswitchdevice) WriteFrameThread() {

	var n_frame []byte

	log.Printf("[TAP][WRITE] Tap writing thread started")

	for {

		n_frame = <-plane.PlaneToTap

		n, err := vd.Realif.Write(n_frame)
		if err != nil {
			log.Printf("[TAP][WRITE][ERROR] Error writing %d bytes to %s : %s", len(n_frame), vd.devicename, err.Error())
		} else {
			log.Printf("[TAP][WRITE] %d long frame of %d , from %s -> %s  to dev %s", n, len(n_frame), tools.MACSource(n_frame).String(), tools.MACDestination(n_frame).String(), vd.devicename)
		}

	}

}

//EngineStart triggers the init function in the package tap
func EngineStart() {

	log.Println("[TAP] Tap Engine Init")

}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"launchpad.net/tomb"
	"log"
	"strconv"
	"sync"
)

const (
	DEFAULT_LATENCY_EVENT_CHANNEL_SIZE = 0 // Unbuffered
)

type LatencyEmitter interface {
	PublishResponseTime(clientId int, latency int64, res WorkResult)
}

type LatencyEvent struct {
	id   int
	usec int64
}

type LatencyEventsChannel <-chan *LatencyEvent

type TaskMasterInfo struct {
	WaitGroup  *sync.WaitGroup
	Properties map[string]string
}

type taskmaster struct {
	t      tomb.Tomb
	ch     chan *LatencyEvent
	wg     *sync.WaitGroup
	props  map[string]string
	chSize int
}

func NewTaskMaster(info *TaskMasterInfo) *taskmaster {
	return &taskmaster{
		wg:     info.WaitGroup,
		props:  info.Properties,
		ch:     nil,
		chSize: DEFAULT_LATENCY_EVENT_CHANNEL_SIZE,
	}
}

func (this *taskmaster) Start() {
	go this.loop()
}

func (this *taskmaster) Stop() (err error) {
	this.t.Kill(nil)
	return this.t.Wait()
}

func (this *taskmaster) ResponseTimes() LatencyEventsChannel {
	return this.ch
}

func (this *taskmaster) PublishResponseTime(clientId int, latency int64, res WorkResult) {
	this.ch <- &LatencyEvent{clientId, latency}
}

func (this *taskmaster) loop() {
	defer this.t.Done()

	this.setup()

	for {
		select {
		case <-this.t.Dying():
			this.shutdown()
			return
		default:
			this.wg.Wait()
			this.t.Kill(nil)
		}
	}
}

func (this *taskmaster) setup() {
	err := this.parseProperties(this.props)
	if err != nil {
		log.Fatal(err)
	}

	if this.chSize == 0 {
		this.ch = make(chan *LatencyEvent)
	} else {
		this.ch = make(chan *LatencyEvent, this.chSize)
	}
}

func (this *taskmaster) shutdown() {
	close(this.ch)
}

func (this *taskmaster) parseProperties(props map[string]string) (err error) {
	if v, ok := props["internals.LatencyEventChannelSize"]; ok {
		w, err := strconv.Atoi(v)
		if err != nil || w < 0 {
			return errors.New("internals.LatencyEventChannelSize must be >= 0")
		}

		this.chSize = w
	} else {
		this.chSize = DEFAULT_LATENCY_EVENT_CHANNEL_SIZE
	}

	return
}
<commit_msg>fix a race condition in the taskmaster caused by moving the channel initialization into the taskmaster goroutine which allowed master to slip forward into capture on a nil channel leading to a hang<commit_after>package main

import (
	"errors"
	"launchpad.net/tomb"
	"log"
	"strconv"
	"sync"
)

const (
	DEFAULT_LATENCY_EVENT_CHANNEL_SIZE = 0 // Unbuffered
)

type LatencyEmitter interface {
	PublishResponseTime(clientId int, latency int64, res WorkResult)
}

type LatencyEvent struct {
	id   int
	usec int64
}

type LatencyEventsChannel <-chan *LatencyEvent

type TaskMasterInfo struct {
	WaitGroup  *sync.WaitGroup
	Properties map[string]string
}

type taskmaster struct {
	t      tomb.Tomb
	ch     chan *LatencyEvent
	wg     *sync.WaitGroup
	props  map[string]string
	chSize int
}

func NewTaskMaster(info *TaskMasterInfo) *taskmaster {
	tm := &taskmaster{
		wg:     info.WaitGroup,
		props:  info.Properties,
		ch:     nil,
		chSize: DEFAULT_LATENCY_EVENT_CHANNEL_SIZE,
	}

	err := tm.parseProperties(tm.props)
	if err != nil {
		log.Fatal(err)
	}

	if tm.chSize == 0 {
		tm.ch = make(chan *LatencyEvent)
	} else {
		tm.ch = make(chan *LatencyEvent, tm.chSize)
	}

	return tm
}

func (this *taskmaster) Start() {
	go this.loop()
}

func (this *taskmaster) Stop() (err error) {
	this.t.Kill(nil)
	return this.t.Wait()
}

func (this *taskmaster) ResponseTimes() LatencyEventsChannel {
	return this.ch
}

func (this *taskmaster) PublishResponseTime(clientId int, latency int64, res WorkResult) {
	this.ch <- &LatencyEvent{clientId, latency}
}

func (this *taskmaster) loop() {
	defer this.t.Done()

	for {
		select {
		case <-this.t.Dying():
			this.shutdown()
			return
		default:
			this.wg.Wait()
			this.t.Kill(nil)
		}
	}
}

func (this *taskmaster) shutdown() {
	close(this.ch)
}

func (this *taskmaster) parseProperties(props map[string]string) (err error) {
	if v, ok := props["internals.LatencyEventChannelSize"]; ok {
		w, err := strconv.Atoi(v)
		if err != nil || w < 0 {
			return errors.New("internals.LatencyEventChannelSize must be >= 0")
		}

		this.chSize = w
	} else {
		this.chSize = DEFAULT_LATENCY_EVENT_CHANNEL_SIZE
	}

	return
}
<|endoftext|>


<commit_before>// Copyright 2018 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package sqlbuilder

import (
	"context"
	"database/sql"
)

// DropTableStmt 删除表语句
type DropTableStmt struct {
	engine Engine
	table  string
}

// DropTable 声明一条删除表的语句
func DropTable(e Engine) *DropTableStmt {
	return &DropTableStmt{
		engine: e,
	}
}

// Table 指定表名。
// 重复指定，会覆盖之前的。
func (stmt *DropTableStmt) Table(table string) *DropTableStmt {
	stmt.table = table
	return stmt
}

// DDLSQL 获取 SQL 语句以及对应的参数
func (stmt *DropTableStmt) DDLSQL() ([]string, error) {
	if stmt.table == "" {
		return nil, ErrTableIsEmpty
	}

	buf := New("DROP TABLE IF EXISTS {")
	buf.WriteString(stmt.table)
	return []string{buf.String()}, nil
}

// Reset 重置
func (stmt *DropTableStmt) Reset() {
	stmt.table = ""
}

// Exec 执行 SQL 语句
func (stmt *DropTableStmt) Exec() error {
	return stmt.ExecContext(context.Background())
}

// ExecContext 执行 SQL 语句
func (stmt *DropTableStmt) ExecContext(ctx context.Context) error {
	return ddlExecContext(ctx, stmt.engine, stmt)
}

// DropConstraintStmt 删除约束
type DropConstraintStmt struct {
	engine     Engine
	table      string
	constraint string
}

// DropConstraint 声明一条删除表约束的语句
func DropConstraint(e Engine) *DropConstraintStmt {
	return &DropConstraintStmt{
		engine: e,
	}
}

// Table 指定表名。
// 重复指定，会覆盖之前的。
func (stmt *DropConstraintStmt) Table(table string) *DropConstraintStmt {
	stmt.table = table
	return stmt
}

// Constraint 指定需要删除的列
func (stmt *DropConstraintStmt) Constraint(cont string) *DropConstraintStmt {
	stmt.constraint = cont
	return stmt
}

// SQL 获取 SQL 语句以及对应的参数
func (stmt *DropConstraintStmt) SQL() (string, []interface{}, error) {
	if stmt.table == "" {
		return "", nil, ErrTableIsEmpty
	}

	buf := New("ALTER TABLE {")
	buf.WriteString(stmt.table)
	buf.WriteString("} DROP CONSTRAINT {")
	buf.WriteString(stmt.constraint)
	buf.WriteString("};")
	return buf.String(), nil, nil
}

// Reset 重置
func (stmt *DropConstraintStmt) Reset() {
	stmt.table = ""
	stmt.constraint = ""
}

// Exec 执行 SQL 语句
func (stmt *DropConstraintStmt) Exec() (sql.Result, error) {
	return stmt.ExecContext(context.Background())
}

// ExecContext 执行 SQL 语句
func (stmt *DropConstraintStmt) ExecContext(ctx context.Context) (sql.Result, error) {
	return execContext(ctx, stmt.engine, stmt)
}
<commit_msg>修正测试错误<commit_after>// Copyright 2018 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package sqlbuilder

import (
	"context"
	"database/sql"
)

// DropTableStmt 删除表语句
type DropTableStmt struct {
	engine Engine
	table  string
}

// DropTable 声明一条删除表的语句
func DropTable(e Engine) *DropTableStmt {
	return &DropTableStmt{
		engine: e,
	}
}

// Table 指定表名。
// 重复指定，会覆盖之前的。
func (stmt *DropTableStmt) Table(table string) *DropTableStmt {
	stmt.table = table
	return stmt
}

// DDLSQL 获取 SQL 语句以及对应的参数
func (stmt *DropTableStmt) DDLSQL() ([]string, error) {
	if stmt.table == "" {
		return nil, ErrTableIsEmpty
	}

	buf := New("DROP TABLE IF EXISTS ")
	buf.WriteString(stmt.table)
	return []string{buf.String()}, nil
}

// Reset 重置
func (stmt *DropTableStmt) Reset() {
	stmt.table = ""
}

// Exec 执行 SQL 语句
func (stmt *DropTableStmt) Exec() error {
	return stmt.ExecContext(context.Background())
}

// ExecContext 执行 SQL 语句
func (stmt *DropTableStmt) ExecContext(ctx context.Context) error {
	return ddlExecContext(ctx, stmt.engine, stmt)
}

// DropConstraintStmt 删除约束
type DropConstraintStmt struct {
	engine     Engine
	table      string
	constraint string
}

// DropConstraint 声明一条删除表约束的语句
func DropConstraint(e Engine) *DropConstraintStmt {
	return &DropConstraintStmt{
		engine: e,
	}
}

// Table 指定表名。
// 重复指定，会覆盖之前的。
func (stmt *DropConstraintStmt) Table(table string) *DropConstraintStmt {
	stmt.table = table
	return stmt
}

// Constraint 指定需要删除的列
func (stmt *DropConstraintStmt) Constraint(cont string) *DropConstraintStmt {
	stmt.constraint = cont
	return stmt
}

// SQL 获取 SQL 语句以及对应的参数
func (stmt *DropConstraintStmt) SQL() (string, []interface{}, error) {
	if stmt.table == "" {
		return "", nil, ErrTableIsEmpty
	}

	buf := New("ALTER TABLE {")
	buf.WriteString(stmt.table)
	buf.WriteString("} DROP CONSTRAINT {")
	buf.WriteString(stmt.constraint)
	buf.WriteString("};")
	return buf.String(), nil, nil
}

// Reset 重置
func (stmt *DropConstraintStmt) Reset() {
	stmt.table = ""
	stmt.constraint = ""
}

// Exec 执行 SQL 语句
func (stmt *DropConstraintStmt) Exec() (sql.Result, error) {
	return stmt.ExecContext(context.Background())
}

// ExecContext 执行 SQL 语句
func (stmt *DropConstraintStmt) ExecContext(ctx context.Context) (sql.Result, error) {
	return execContext(ctx, stmt.engine, stmt)
}
<|endoftext|>


<commit_before>package brain

import (
	"github.com/BytemarkHosting/bytemark-client/lib/prettyprint"
	"io"
)

// Disc is a representation of a VM's disc.
type Disc struct {
	Label        string `json:"label"`
	StorageGrade string `json:"storage_grade"`
	Size         int    `json:"size"`

	ID               int    `json:"id,omitempty"`
	VirtualMachineID int    `json:"virtual_machine_id,omitempty"`
	StoragePool      string `json:"storage_pool,omitempty"`
}

func (d Disc) PrettyPrint(wr io.Writer, detail prettyprint.DetailLevel) error {
	tmpl := `{{ define "disc_sgl" }}{{ .Label }} - {{ gibtib .Size }}, {{ .StorageGrade }} grade{{ end }}
{{ define "disc_medium" }}{{ template "_sgl" . }}{{ end }}
{{ define "disc_full" }}{{ template "_medium" . }}{{ end }}`
	return prettyprint.Run(wr, tmpl, "disc"+string(detail), d)
}

// Validate makes sure the disc has a storage grade. Doesn't modify the origin disc.
func (disc Disc) Validate() (*Disc, error) {
	if disc.StorageGrade == "" {
		newDisc := disc
		newDisc.StorageGrade = "sata"
		return &newDisc, nil
	}
	return &disc, nil
}
<commit_msg>Keep receiver name the same throughout disc.go<commit_after>package brain

import (
	"github.com/BytemarkHosting/bytemark-client/lib/prettyprint"
	"io"
)

// Disc is a representation of a VM's disc.
type Disc struct {
	Label        string `json:"label"`
	StorageGrade string `json:"storage_grade"`
	Size         int    `json:"size"`

	ID               int    `json:"id,omitempty"`
	VirtualMachineID int    `json:"virtual_machine_id,omitempty"`
	StoragePool      string `json:"storage_pool,omitempty"`
}

// PrettyPrint outputs the disc nicely-formatted to the writer.
func (d Disc) PrettyPrint(wr io.Writer, detail prettyprint.DetailLevel) error {
	tmpl := `{{ define "disc_sgl" }}{{ .Label }} - {{ gibtib .Size }}, {{ .StorageGrade }} grade{{ end }}
{{ define "disc_medium" }}{{ template "_sgl" . }}{{ end }}
{{ define "disc_full" }}{{ template "_medium" . }}{{ end }}`
	return prettyprint.Run(wr, tmpl, "disc"+string(detail), d)
}

// Validate makes sure the disc has a storage grade. Doesn't modify the origin disc.
func (d Disc) Validate() (*Disc, error) {
	if d.StorageGrade == "" {
		newDisc := d
		newDisc.StorageGrade = "sata"
		return &newDisc, nil
	}
	return &d, nil
}
<|endoftext|>


<commit_before>package htm

import (
	//"fmt"
	"github.com/zacg/testify/assert"
	"sort"
	"testing"
)

func TestPickCellsToLearnOnAvoidDuplicates(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.MaxNewSynapseCount = 1000
	tm := NewTemporalMemory(tmp)

	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)

	winnerCells := []int{233, 144}

	// Ensure that no additional (duplicate) cells were picked
	assert.Equal(t, winnerCells, tm.pickCellsToLearnOn(2, 0, winnerCells, connections))

}

func TestPickCellsToLearnOn(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)

	winnerCells := []int{4, 47, 58, 93}

	result := tm.pickCellsToLearnOn(100, 0, winnerCells, connections)
	sort.Ints(result)
	assert.Equal(t, []int{4, 47, 58, 93}, result)
	assert.Equal(t, []int{}, tm.pickCellsToLearnOn(0, 0, winnerCells, connections))
	assert.Equal(t, []int{4, 58}, tm.pickCellsToLearnOn(2, 0, winnerCells, connections))
}
<commit_msg>adding least used cell unit test<commit_after>package htm

import (
	//"fmt"
	"github.com/zacg/testify/assert"
	"sort"
	"testing"
)

func TestPickCellsToLearnOnAvoidDuplicates(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.MaxNewSynapseCount = 1000
	tm := NewTemporalMemory(tmp)

	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)

	winnerCells := []int{233, 144}

	// Ensure that no additional (duplicate) cells were picked
	assert.Equal(t, winnerCells, tm.pickCellsToLearnOn(2, 0, winnerCells, connections))

}

func TestPickCellsToLearnOn(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)

	winnerCells := []int{4, 47, 58, 93}

	result := tm.pickCellsToLearnOn(100, 0, winnerCells, connections)
	sort.Ints(result)
	assert.Equal(t, []int{4, 47, 58, 93}, result)
	assert.Equal(t, []int{}, tm.pickCellsToLearnOn(0, 0, winnerCells, connections))
	assert.Equal(t, []int{4, 58}, tm.pickCellsToLearnOn(2, 0, winnerCells, connections))
}

func TestLeastUsedCell(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.ColumnDimensions = []int{2}
	tmp.CellsPerColumn = 2

	tm := NewTemporalMemory(tmp)

	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 3, 0.3)

	for i := 0; i < 100; i++ {
		assert.Equal(t, 1, tm.getLeastUsedCell(0, connections))
	}

}
<|endoftext|>


<commit_before>package htm

import (
	//"fmt"
	"github.com/stretchr/testify/assert"
	"sort"
	"testing"
)

func TestPickCellsToLearnOnAvoidDuplicates(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.MaxNewSynapseCount = 1000
	tm := NewTemporalMemory(tmp)

	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)

	winnerCells := []int{233, 144}

	// Ensure that no additional (duplicate) cells were picked
	assert.Equal(t, winnerCells, tm.pickCellsToLearnOn(2, 0, winnerCells, connections))

}

func TestPickCellsToLearnOn(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)

	winnerCells := []int{4, 47, 58, 93}

	result := tm.pickCellsToLearnOn(100, 0, winnerCells, connections)
	sort.Ints(result)
	assert.Equal(t, []int{4, 47, 58, 93}, result)
	assert.Equal(t, []int{}, tm.pickCellsToLearnOn(0, 0, winnerCells, connections))
	assert.Equal(t, []int{4, 58}, tm.pickCellsToLearnOn(2, 0, winnerCells, connections))
}

func TestAdaptSegmentToMin(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.1)

	tm.adaptSegment(0, []int{}, connections)
	assert.Equal(t, 0.0, connections.DataForSynapse(0).Permanence)

	// // Now permanence should be at min
	tm.adaptSegment(0, []int{}, connections)
	assert.Equal(t, 0.0, connections.DataForSynapse(0).Permanence)

}

func TestAdaptSegmentToMax(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.9)

	tm.adaptSegment(0, []int{0}, connections)
	assert.Equal(t, 1.0, connections.DataForSynapse(0).Permanence)

	// Now permanence should be at max
	tm.adaptSegment(0, []int{0}, connections)
	assert.Equal(t, 1.0, connections.DataForSynapse(0).Permanence)

}

func TestLeastUsedCell(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.ColumnDimensions = []int{2}
	tmp.CellsPerColumn = 2

	tm := NewTemporalMemory(tmp)

	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 3, 0.3)

	for i := 0; i < 100; i++ {
		assert.Equal(t, 1, tm.getLeastUsedCell(0, connections))
	}

}

func TestAdaptSegment(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	tm.adaptSegment(0, []int{0, 1}, connections)

	assert.Equal(t, 0.7, connections.DataForSynapse(0).Permanence)
	assert.Equal(t, 0.5, connections.DataForSynapse(1).Permanence)
	assert.Equal(t, 0.8, connections.DataForSynapse(2).Permanence)

}

func TestGetConnectedActiveSynapsesForSegment(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(2, 486, 0.9)

	activeSynapsesForSegment := map[int][]int{
		0: {0, 1},
		1: {3},
	}

	assert.Equal(t, []int{0}, tm.getConnectedActiveSynapsesForSegment(0,
		activeSynapsesForSegment,
		0.5,
		connections))

	assert.Equal(t, []int{3}, tm.getConnectedActiveSynapsesForSegment(1,
		activeSynapsesForSegment,
		0.5,
		connections))

}

func TestComputeActiveSynapsesNoActivity(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(2, 486, 0.9)
	activeCells := []int{}
	assert.Equal(t, map[int][]int{}, tm.computeActiveSynapses(activeCells, connections))

}

func TestGetBestMatchingSegment(t *testing.T) {

	tmp := NewTemporalMemoryParams()
	tmp.MinThreshold = 1
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(0)
	connections.CreateSynapse(1, 49, 0.9)
	connections.CreateSynapse(1, 3, 0.8)
	connections.CreateSegment(1)
	connections.CreateSynapse(2, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(3, 486, 0.9)

	activeSynapsesForSegment := map[int][]int{
		0: []int{0, 1},
		1: []int{3},
		2: []int{5},
	}

	bestCell, connectedSyns := tm.getBestMatchingSegment(0, activeSynapsesForSegment, connections)
	assert.Equal(t, 0, bestCell)
	assert.Equal(t, []int{0, 1}, connectedSyns)

	bestCell, connectedSyns = tm.getBestMatchingSegment(1, activeSynapsesForSegment, connections)
	assert.Equal(t, 2, bestCell)
	assert.Equal(t, []int{5}, connectedSyns)

	bestCell, connectedSyns = tm.getBestMatchingSegment(8, activeSynapsesForSegment, connections)
	assert.Equal(t, -1, bestCell)
	assert.Equal(t, []int(nil), connectedSyns)

	bestCell, connectedSyns = tm.getBestMatchingSegment(100, activeSynapsesForSegment, connections)
	assert.Equal(t, -1, bestCell)
	assert.Equal(t, []int(nil), connectedSyns)

}

func TestGetBestMatchingCellFewestSegments(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.ColumnDimensions = []int{2}
	tmp.CellsPerColumn = 2
	tmp.MinThreshold = 1
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 3, 0.3)
	activeSynapsesForSegment := map[int][]int{}

	for i := 0; i < 100; i++ {
		// Never pick cell 0, always pick cell 1
		cell, _ := tm.getBestMatchingCell(0, activeSynapsesForSegment, connections)
		assert.Equal(t, 1, cell)
	}

}

func TestGetBestMatchingCell(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.MinThreshold = 1
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(0)
	connections.CreateSynapse(1, 49, 0.9)
	connections.CreateSynapse(1, 3, 0.8)
	connections.CreateSegment(1)
	connections.CreateSynapse(2, 733, 0.7)
	connections.CreateSegment(108)
	connections.CreateSynapse(3, 486, 0.9)

	activeSynapsesForSegment := map[int][]int{
		0: []int{0, 1},
		1: []int{3},
		2: []int{5},
	}

	bestCell, bestSeg := tm.getBestMatchingCell(0, activeSynapsesForSegment, connections)
	assert.Equal(t, 0, bestCell)
	assert.Equal(t, 0, bestSeg)

	//randomly picked
	bestCell, bestSeg = tm.getBestMatchingCell(3, activeSynapsesForSegment, connections)
	assert.Equal(t, 98, bestCell)
	assert.Equal(t, -1, bestSeg)

	//randomly picked
	bestCell, bestSeg = tm.getBestMatchingCell(999, activeSynapsesForSegment, connections)
	assert.Equal(t, 31970, bestCell)
	assert.Equal(t, -1, bestSeg)

}

func TestComputeActiveSynapses(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	//tmp.MinThreshold = 1
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(2, 486, 0.9)
	activeCells := []int{23, 37, 733, 4973}

	expected := map[int][]int{
		0: []int{0, 1},
		1: []int{3},
	}
	assert.Equal(t, expected, tm.computeActiveSynapses(activeCells, connections))

}

func TestComputePredictiveCells(t *testing.T) {

	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.5)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSynapse(1, 733, 0.4)
	connections.CreateSegment(1)
	connections.CreateSynapse(2, 974, 0.9)
	connections.CreateSegment(8)
	connections.CreateSynapse(3, 486, 0.9)
	connections.CreateSegment(100)

	activeSynapsesForSegment := map[int][]int{
		0: []int{0, 1},
		1: []int{3, 4},
		2: []int{5},
	}

	activeSegments, predictiveCells := tm.computePredictiveCells(activeSynapsesForSegment, connections)
	//TODO: numentas returns [0]
	assert.Equal(t, []int(nil), activeSegments)
	assert.Equal(t, []int(nil), predictiveCells)

}

func TestLearnOnSegments(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(2, 486, 0.9)
	connections.CreateSegment(100)

	prevActiveSegments := []int{0, 2}
	learningSegments := []int{1, 3}

	prevActiveSynapsesForSegment := map[int][]int{
		0: []int{0, 1},
		1: []int{3},
	}

	winnerCells := []int{0}

	prevWinnerCells := []int{10, 11, 12, 13, 14}

	tm.learnOnSegments(prevActiveSegments,
		learningSegments,
		prevActiveSynapsesForSegment,
		winnerCells,
		prevWinnerCells,
		connections)

	//Check segment 0
	assert.Equal(t, 0.7, connections.DataForSynapse(0).Permanence)
	assert.Equal(t, 0.5, connections.DataForSynapse(1).Permanence)
	assert.Equal(t, 0.8, connections.DataForSynapse(2).Permanence)

	//Check segment 1
	assert.InEpsilon(t, 0.8, connections.DataForSynapse(3).Permanence, 0.1)
	assert.Equal(t, 2, len(connections.synapsesForSegment[1]))

	//Check segment 2
	assert.Equal(t, 0.9, connections.DataForSynapse(4).Permanence)
	assert.Equal(t, 1, len(connections.synapsesForSegment[2]))

	// Check segment 3
	assert.Equal(t, 1, len(connections.synapsesForSegment[3]))

}
<commit_msg>add burst cols empty unit test<commit_after>package htm

import (
	//"fmt"
	"github.com/stretchr/testify/assert"
	"sort"
	"testing"
)

func TestPickCellsToLearnOnAvoidDuplicates(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.MaxNewSynapseCount = 1000
	tm := NewTemporalMemory(tmp)

	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)

	winnerCells := []int{233, 144}

	// Ensure that no additional (duplicate) cells were picked
	assert.Equal(t, winnerCells, tm.pickCellsToLearnOn(2, 0, winnerCells, connections))

}

func TestPickCellsToLearnOn(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)

	winnerCells := []int{4, 47, 58, 93}

	result := tm.pickCellsToLearnOn(100, 0, winnerCells, connections)
	sort.Ints(result)
	assert.Equal(t, []int{4, 47, 58, 93}, result)
	assert.Equal(t, []int{}, tm.pickCellsToLearnOn(0, 0, winnerCells, connections))
	assert.Equal(t, []int{4, 58}, tm.pickCellsToLearnOn(2, 0, winnerCells, connections))
}

func TestAdaptSegmentToMin(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.1)

	tm.adaptSegment(0, []int{}, connections)
	assert.Equal(t, 0.0, connections.DataForSynapse(0).Permanence)

	// // Now permanence should be at min
	tm.adaptSegment(0, []int{}, connections)
	assert.Equal(t, 0.0, connections.DataForSynapse(0).Permanence)

}

func TestAdaptSegmentToMax(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.9)

	tm.adaptSegment(0, []int{0}, connections)
	assert.Equal(t, 1.0, connections.DataForSynapse(0).Permanence)

	// Now permanence should be at max
	tm.adaptSegment(0, []int{0}, connections)
	assert.Equal(t, 1.0, connections.DataForSynapse(0).Permanence)

}

func TestLeastUsedCell(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.ColumnDimensions = []int{2}
	tmp.CellsPerColumn = 2

	tm := NewTemporalMemory(tmp)

	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 3, 0.3)

	for i := 0; i < 100; i++ {
		assert.Equal(t, 1, tm.getLeastUsedCell(0, connections))
	}

}

func TestAdaptSegment(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	tm.adaptSegment(0, []int{0, 1}, connections)

	assert.Equal(t, 0.7, connections.DataForSynapse(0).Permanence)
	assert.Equal(t, 0.5, connections.DataForSynapse(1).Permanence)
	assert.Equal(t, 0.8, connections.DataForSynapse(2).Permanence)

}

func TestGetConnectedActiveSynapsesForSegment(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(2, 486, 0.9)

	activeSynapsesForSegment := map[int][]int{
		0: {0, 1},
		1: {3},
	}

	assert.Equal(t, []int{0}, tm.getConnectedActiveSynapsesForSegment(0,
		activeSynapsesForSegment,
		0.5,
		connections))

	assert.Equal(t, []int{3}, tm.getConnectedActiveSynapsesForSegment(1,
		activeSynapsesForSegment,
		0.5,
		connections))

}

func TestComputeActiveSynapsesNoActivity(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(2, 486, 0.9)
	activeCells := []int{}
	assert.Equal(t, map[int][]int{}, tm.computeActiveSynapses(activeCells, connections))

}

func TestGetBestMatchingSegment(t *testing.T) {

	tmp := NewTemporalMemoryParams()
	tmp.MinThreshold = 1
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(0)
	connections.CreateSynapse(1, 49, 0.9)
	connections.CreateSynapse(1, 3, 0.8)
	connections.CreateSegment(1)
	connections.CreateSynapse(2, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(3, 486, 0.9)

	activeSynapsesForSegment := map[int][]int{
		0: []int{0, 1},
		1: []int{3},
		2: []int{5},
	}

	bestCell, connectedSyns := tm.getBestMatchingSegment(0, activeSynapsesForSegment, connections)
	assert.Equal(t, 0, bestCell)
	assert.Equal(t, []int{0, 1}, connectedSyns)

	bestCell, connectedSyns = tm.getBestMatchingSegment(1, activeSynapsesForSegment, connections)
	assert.Equal(t, 2, bestCell)
	assert.Equal(t, []int{5}, connectedSyns)

	bestCell, connectedSyns = tm.getBestMatchingSegment(8, activeSynapsesForSegment, connections)
	assert.Equal(t, -1, bestCell)
	assert.Equal(t, []int(nil), connectedSyns)

	bestCell, connectedSyns = tm.getBestMatchingSegment(100, activeSynapsesForSegment, connections)
	assert.Equal(t, -1, bestCell)
	assert.Equal(t, []int(nil), connectedSyns)

}

func TestGetBestMatchingCellFewestSegments(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.ColumnDimensions = []int{2}
	tmp.CellsPerColumn = 2
	tmp.MinThreshold = 1
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 3, 0.3)
	activeSynapsesForSegment := map[int][]int{}

	for i := 0; i < 100; i++ {
		// Never pick cell 0, always pick cell 1
		cell, _ := tm.getBestMatchingCell(0, activeSynapsesForSegment, connections)
		assert.Equal(t, 1, cell)
	}

}

func TestGetBestMatchingCell(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tmp.MinThreshold = 1
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(0)
	connections.CreateSynapse(1, 49, 0.9)
	connections.CreateSynapse(1, 3, 0.8)
	connections.CreateSegment(1)
	connections.CreateSynapse(2, 733, 0.7)
	connections.CreateSegment(108)
	connections.CreateSynapse(3, 486, 0.9)

	activeSynapsesForSegment := map[int][]int{
		0: []int{0, 1},
		1: []int{3},
		2: []int{5},
	}

	bestCell, bestSeg := tm.getBestMatchingCell(0, activeSynapsesForSegment, connections)
	assert.Equal(t, 0, bestCell)
	assert.Equal(t, 0, bestSeg)

	//randomly picked
	bestCell, bestSeg = tm.getBestMatchingCell(3, activeSynapsesForSegment, connections)
	assert.Equal(t, 98, bestCell)
	assert.Equal(t, -1, bestSeg)

	//randomly picked
	bestCell, bestSeg = tm.getBestMatchingCell(999, activeSynapsesForSegment, connections)
	assert.Equal(t, 31970, bestCell)
	assert.Equal(t, -1, bestSeg)

}

func TestComputeActiveSynapses(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	//tmp.MinThreshold = 1
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(2, 486, 0.9)
	activeCells := []int{23, 37, 733, 4973}

	expected := map[int][]int{
		0: []int{0, 1},
		1: []int{3},
	}
	assert.Equal(t, expected, tm.computeActiveSynapses(activeCells, connections))

}

func TestComputePredictiveCells(t *testing.T) {

	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections

	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.5)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSynapse(1, 733, 0.4)
	connections.CreateSegment(1)
	connections.CreateSynapse(2, 974, 0.9)
	connections.CreateSegment(8)
	connections.CreateSynapse(3, 486, 0.9)
	connections.CreateSegment(100)

	activeSynapsesForSegment := map[int][]int{
		0: []int{0, 1},
		1: []int{3, 4},
		2: []int{5},
	}

	activeSegments, predictiveCells := tm.computePredictiveCells(activeSynapsesForSegment, connections)
	//TODO: numentas returns [0]
	assert.Equal(t, []int(nil), activeSegments)
	assert.Equal(t, []int(nil), predictiveCells)

}

func TestLearnOnSegments(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	connections.CreateSegment(0)
	connections.CreateSynapse(0, 23, 0.6)
	connections.CreateSynapse(0, 37, 0.4)
	connections.CreateSynapse(0, 477, 0.9)
	connections.CreateSegment(1)
	connections.CreateSynapse(1, 733, 0.7)
	connections.CreateSegment(8)
	connections.CreateSynapse(2, 486, 0.9)
	connections.CreateSegment(100)

	prevActiveSegments := []int{0, 2}
	learningSegments := []int{1, 3}

	prevActiveSynapsesForSegment := map[int][]int{
		0: []int{0, 1},
		1: []int{3},
	}

	winnerCells := []int{0}

	prevWinnerCells := []int{10, 11, 12, 13, 14}

	tm.learnOnSegments(prevActiveSegments,
		learningSegments,
		prevActiveSynapsesForSegment,
		winnerCells,
		prevWinnerCells,
		connections)

	//Check segment 0
	assert.Equal(t, 0.7, connections.DataForSynapse(0).Permanence)
	assert.Equal(t, 0.5, connections.DataForSynapse(1).Permanence)
	assert.Equal(t, 0.8, connections.DataForSynapse(2).Permanence)

	//Check segment 1
	assert.InEpsilon(t, 0.8, connections.DataForSynapse(3).Permanence, 0.1)
	assert.Equal(t, 2, len(connections.synapsesForSegment[1]))

	//Check segment 2
	assert.Equal(t, 0.9, connections.DataForSynapse(4).Permanence)
	assert.Equal(t, 1, len(connections.synapsesForSegment[2]))

	// Check segment 3
	assert.Equal(t, 1, len(connections.synapsesForSegment[3]))

}

func testBurstColumnsEmpty(t *testing.T) {
	tmp := NewTemporalMemoryParams()
	tm := NewTemporalMemory(tmp)
	connections := tm.Connections
	activeColumns := []int{}
	predictedColumns := []int{}
	prevActiveSynapsesForSegment := make(map[int][]int)

	activeCells, winnerCells, learningSegments := tm.burstColumns(activeColumns,
		predictedColumns,
		prevActiveSynapsesForSegment,
		connections)

	assert.Equal(t, []int{}, activeCells)
	assert.Equal(t, []int{}, winnerCells)
	assert.Equal(t, []int{}, learningSegments)

}
<|endoftext|>


<commit_before>package pipeline

import (
	"errors"
	"io"
	"os"
	"path/filepath"
	"strings"

	"github.com/fsouza/go-dockerclient"
)

const defaultDockerHost = "unix:///var/run/docker.sock"

var DefaultConfig = docker.Config{
	AttachStdin:  true,
	AttachStdout: true,
	AttachStderr: true,
	OpenStdin:    true,
	StdinOnce:    true,
}

func startContainer(opts docker.CreateContainerOptions) (string, error) {
	client, err := newDockerClientFromEnv()
	if err != nil {
		return "", err
	}
	container, err := client.CreateContainer(opts)
	if err != nil {
		return "", err
	}
	err = client.StartContainer(container.ID, opts.HostConfig)
	if err != nil {
		return "", err
	}

	return container.ID, nil
}

func stopContainer(id string) error {
	client, err := newDockerClientFromEnv()
	if err != nil {
		return err
	}
	return client.StopContainer(id, 5)
}

func pullImage(image string) error {
	repo_tag := strings.Split(image, ":")
	client, err := newDockerClientFromEnv()
	if err != nil {
		return err
	}
	opts := docker.PullImageOptions{Repository: repo_tag[0], Tag: "latest"}
	if len(repo_tag) == 2 {
		opts.Tag = repo_tag[1]
	}
	return client.PullImage(opts, docker.AuthConfiguration{})
}

func pipeToStdin(id string, in io.Reader) error {
	client, err := newDockerClientFromEnv()
	if err != nil {
		return err
	}
	return client.AttachToContainer(docker.AttachToContainerOptions{
		Container:   id,
		InputStream: in,
		Stdin:       true,
		Stream:      true,
	})
}

func containerLogs(id string, out io.Writer) error {
	client, err := newDockerClientFromEnv()
	if err != nil {
		return err
	}
	return client.AttachToContainer(docker.AttachToContainerOptions{
		Container:    id,
		OutputStream: out,
		ErrorStream:  out,
		Stdout:       true,
		Stderr:       true,
		Logs:         true,
	})
}

func waitContainer(id string) (int, error) {
	client, err := newDockerClientFromEnv()
	if err != nil {
		return 0, err
	}

	return client.WaitContainer(id)
}

func newDockerClientFromEnv() (*docker.Client, error) {
	host := os.Getenv("DOCKER_HOST")

	if host == "" {
		host = defaultDockerHost
	}

	if os.Getenv("DOCKER_TLS_VERIFY") != "" {
		path := os.Getenv("DOCKER_CERT_PATH")

		if path == "" {
			path = os.Getenv("HOME")

			if path == "" {
				return nil, errors.New("pfs: environment variable HOME must be set if DOCKER_CERT_PATH is not set")
			}

			var err error

			path = filepath.Join(path, ".docker")
			path, err = filepath.Abs(path)

			if err != nil {
				return nil, err
			}
		}

		return docker.NewTLSClient(
			host,
			path+"/cert.pem",
			path+"/key.pem",
			path+"/ca.pem",
		)
	}

	return docker.NewClient(host)
}
<commit_msg>use docker.NewClientFromEnv<commit_after>package pipeline

import (
	"io"
	"strings"

	"github.com/fsouza/go-dockerclient"
)

var DefaultConfig = docker.Config{
	AttachStdin:  true,
	AttachStdout: true,
	AttachStderr: true,
	OpenStdin:    true,
	StdinOnce:    true,
}

func startContainer(opts docker.CreateContainerOptions) (string, error) {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		return "", err
	}
	container, err := client.CreateContainer(opts)
	if err != nil {
		return "", err
	}
	err = client.StartContainer(container.ID, opts.HostConfig)
	if err != nil {
		return "", err
	}

	return container.ID, nil
}

func stopContainer(id string) error {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		return err
	}
	return client.StopContainer(id, 5)
}

func pullImage(image string) error {
	repo_tag := strings.Split(image, ":")
	client, err := docker.NewClientFromEnv()
	if err != nil {
		return err
	}
	opts := docker.PullImageOptions{Repository: repo_tag[0], Tag: "latest"}
	if len(repo_tag) == 2 {
		opts.Tag = repo_tag[1]
	}
	return client.PullImage(opts, docker.AuthConfiguration{})
}

func pipeToStdin(id string, in io.Reader) error {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		return err
	}
	return client.AttachToContainer(docker.AttachToContainerOptions{
		Container:   id,
		InputStream: in,
		Stdin:       true,
		Stream:      true,
	})
}

func containerLogs(id string, out io.Writer) error {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		return err
	}
	return client.AttachToContainer(docker.AttachToContainerOptions{
		Container:    id,
		OutputStream: out,
		ErrorStream:  out,
		Stdout:       true,
		Stderr:       true,
		Logs:         true,
	})
}

func waitContainer(id string) (int, error) {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		return 0, err
	}

	return client.WaitContainer(id)
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements the Check function, which typechecks a package.

package types

import (
	"fmt"
	"go/ast"
	"go/scanner"
	"go/token"
	"sort"
)

// enable for debugging
const trace = false

type checker struct {
	ctxt  *Context
	fset  *token.FileSet
	files []*ast.File

	// lazily initialized
	pkgscope *ast.Scope
	firsterr error
	initspec map[*ast.ValueSpec]*ast.ValueSpec // "inherited" type and initialization expressions for constant declarations
	funclist []function                        // list of functions/methods with correct signatures and non-empty bodies
	funcsig  *Signature                        // signature of currently typechecked function
	pos      []token.Pos                       // stack of expr positions; debugging support, used if trace is set
}

type function struct {
	obj  *ast.Object // for debugging/tracing only
	sig  *Signature
	body *ast.BlockStmt
}

// later adds a function with non-empty body to the list of functions
// that need to be processed after all package-level declarations
// are typechecked.
//
func (check *checker) later(obj *ast.Object, sig *Signature, body *ast.BlockStmt) {
	// functions implemented elsewhere (say in assembly) have no body
	if body != nil {
		check.funclist = append(check.funclist, function{obj, sig, body})
	}
}

// declare declares an object of the given kind and name (ident) in scope;
// decl is the corresponding declaration in the AST. An error is reported
// if the object was declared before.
//
// TODO(gri) This is very similar to the declare function in go/parser; it
// is only used to associate methods with their respective receiver base types.
// In a future version, it might be simpler and cleaner to do all the resolution
// in the type-checking phase. It would simplify the parser, AST, and also
// reduce some amount of code duplication.
//
func (check *checker) declare(scope *ast.Scope, kind ast.ObjKind, ident *ast.Ident, decl ast.Decl) {
	assert(ident.Obj == nil) // identifier already declared or resolved
	obj := ast.NewObj(kind, ident.Name)
	obj.Decl = decl
	ident.Obj = obj
	if ident.Name != "_" {
		if alt := scope.Insert(obj); alt != nil {
			prevDecl := ""
			if pos := alt.Pos(); pos.IsValid() {
				prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", check.fset.Position(pos))
			}
			check.errorf(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
		}
	}
}

func (check *checker) valueSpec(pos token.Pos, obj *ast.Object, lhs []*ast.Ident, typ ast.Expr, rhs []ast.Expr, iota int) {
	if len(lhs) == 0 {
		check.invalidAST(pos, "missing lhs in declaration")
		return
	}

	// determine type for all of lhs, if any
	// (but only set it for the object we typecheck!)
	var t Type
	if typ != nil {
		t = check.typ(typ, false)
	}

	// len(lhs) > 0
	if len(lhs) == len(rhs) {
		// check only lhs and rhs corresponding to obj
		var l, r ast.Expr
		for i, name := range lhs {
			if name.Obj == obj {
				l = lhs[i]
				r = rhs[i]
				break
			}
		}
		assert(l != nil)
		obj.Type = t
		check.assign1to1(l, r, nil, true, iota)
		return
	}

	// there must be a type or initialization expressions
	if t == nil && len(rhs) == 0 {
		check.invalidAST(pos, "missing type or initialization expression")
		t = Typ[Invalid]
	}

	// if we have a type, mark all of lhs
	if t != nil {
		for _, name := range lhs {
			name.Obj.Type = t
		}
	}

	// check initial values, if any
	if len(rhs) > 0 {
		// TODO(gri) should try to avoid this conversion
		lhx := make([]ast.Expr, len(lhs))
		for i, e := range lhs {
			lhx[i] = e
		}
		check.assignNtoM(lhx, rhs, true, iota)
	}
}

// object typechecks an object by assigning it a type; obj.Type must be nil.
// Callers must check obj.Type before calling object; this eliminates a call
// for each identifier that has been typechecked already, a common scenario.
//
func (check *checker) object(obj *ast.Object, cycleOk bool) {
	assert(obj.Type == nil)

	switch obj.Kind {
	case ast.Bad, ast.Pkg:
		// nothing to do

	case ast.Con, ast.Var:
		// The obj.Data field for constants and variables is initialized
		// to the respective (hypothetical, for variables) iota value by
		// the parser. The object's fields can be in one of the following
		// states:
		// Type != nil  =>  the constant value is Data
		// Type == nil  =>  the object is not typechecked yet, and Data can be:
		// Data is int  =>  Data is the value of iota for this declaration
		// Data == nil  =>  the object's expression is being evaluated
		if obj.Data == nil {
			check.errorf(obj.Pos(), "illegal cycle in initialization of %s", obj.Name)
			obj.Type = Typ[Invalid]
			return
		}
		spec := obj.Decl.(*ast.ValueSpec)
		iota := obj.Data.(int)
		obj.Data = nil
		// determine spec for type and initialization expressions
		init := spec
		if len(init.Values) == 0 && obj.Kind == ast.Con {
			init = check.initspec[spec]
		}
		check.valueSpec(spec.Pos(), obj, spec.Names, init.Type, init.Values, iota)

	case ast.Typ:
		typ := &NamedType{Obj: obj}
		obj.Type = typ // "mark" object so recursion terminates
		typ.Underlying = underlying(check.typ(obj.Decl.(*ast.TypeSpec).Type, cycleOk))
		// typecheck associated method signatures
		if obj.Data != nil {
			scope := obj.Data.(*ast.Scope)
			switch t := typ.Underlying.(type) {
			case *Struct:
				// struct fields must not conflict with methods
				for _, f := range t.Fields {
					if m := scope.Lookup(f.Name); m != nil {
						check.errorf(m.Pos(), "type %s has both field and method named %s", obj.Name, f.Name)
						// ok to continue
					}
				}
			case *Interface:
				// methods cannot be associated with an interface type
				for _, m := range scope.Objects {
					recv := m.Decl.(*ast.FuncDecl).Recv.List[0].Type
					check.errorf(recv.Pos(), "invalid receiver type %s (%s is an interface type)", obj.Name, obj.Name)
					// ok to continue
				}
			}
			// typecheck method signatures
			for _, obj := range scope.Objects {
				mdecl := obj.Decl.(*ast.FuncDecl)
				sig := check.typ(mdecl.Type, cycleOk).(*Signature)
				params, _ := check.collectParams(mdecl.Recv, false)
				sig.Recv = params[0] // the parser/assocMethod ensure there is exactly one parameter
				obj.Type = sig
				check.later(obj, sig, mdecl.Body)
			}
		}

	case ast.Fun:
		fdecl := obj.Decl.(*ast.FuncDecl)
		// methods are typechecked when their receivers are typechecked
		if fdecl.Recv == nil {
			sig := check.typ(fdecl.Type, cycleOk).(*Signature)
			if obj.Name == "init" && (len(sig.Params) != 0 || len(sig.Results) != 0) {
				check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
				// ok to continue
			}
			obj.Type = sig
			check.later(obj, sig, fdecl.Body)
		}

	default:
		panic("unreachable")
	}
}

// assocInitvals associates "inherited" initialization expressions
// with the corresponding *ast.ValueSpec in the check.initspec map
// for constant declarations without explicit initialization expressions.
//
func (check *checker) assocInitvals(decl *ast.GenDecl) {
	var last *ast.ValueSpec
	for _, s := range decl.Specs {
		if s, ok := s.(*ast.ValueSpec); ok {
			if len(s.Values) > 0 {
				last = s
			} else {
				check.initspec[s] = last
			}
		}
	}
	if last == nil {
		check.invalidAST(decl.Pos(), "no initialization values provided")
	}
}

// assocMethod associates a method declaration with the respective
// receiver base type. meth.Recv must exist.
//
func (check *checker) assocMethod(meth *ast.FuncDecl) {
	// The receiver type is one of the following (enforced by parser):
	// - *ast.Ident
	// - *ast.StarExpr{*ast.Ident}
	// - *ast.BadExpr (parser error)
	typ := meth.Recv.List[0].Type
	if ptr, ok := typ.(*ast.StarExpr); ok {
		typ = ptr.X
	}
	// determine receiver base type object
	var obj *ast.Object
	if ident, ok := typ.(*ast.Ident); ok && ident.Obj != nil {
		obj = ident.Obj
		if obj.Kind != ast.Typ {
			check.errorf(ident.Pos(), "%s is not a type", ident.Name)
			return // ignore this method
		}
		// TODO(gri) determine if obj was defined in this package
		/*
			if check.notLocal(obj) {
				check.errorf(ident.Pos(), "cannot define methods on non-local type %s", ident.Name)
				return // ignore this method
			}
		*/
	} else {
		// If it's not an identifier or the identifier wasn't declared/resolved,
		// the parser/resolver already reported an error. Nothing to do here.
		return // ignore this method
	}
	// declare method in receiver base type scope
	var scope *ast.Scope
	if obj.Data != nil {
		scope = obj.Data.(*ast.Scope)
	} else {
		scope = ast.NewScope(nil)
		obj.Data = scope
	}
	check.declare(scope, ast.Fun, meth.Name, meth)
}

func (check *checker) assocInitvalsOrMethod(decl ast.Decl) {
	switch d := decl.(type) {
	case *ast.GenDecl:
		if d.Tok == token.CONST {
			check.assocInitvals(d)
		}
	case *ast.FuncDecl:
		if d.Recv != nil {
			check.assocMethod(d)
		}
	}
}

func (check *checker) decl(decl ast.Decl) {
	switch d := decl.(type) {
	case *ast.BadDecl:
		// ignore
	case *ast.GenDecl:
		for _, spec := range d.Specs {
			switch s := spec.(type) {
			case *ast.ImportSpec:
				// nothing to do (handled by ast.NewPackage)
			case *ast.ValueSpec:
				for _, name := range s.Names {
					if obj := name.Obj; obj.Type == nil {
						check.object(obj, false)
					}
				}
			case *ast.TypeSpec:
				if obj := s.Name.Obj; obj.Type == nil {
					check.object(obj, false)
				}
			default:
				check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
			}
		}
	case *ast.FuncDecl:
		// methods are checked when their respective base types are checked
		if d.Recv != nil {
			return
		}
		obj := d.Name.Obj
		// Initialization functions don't have an object associated with them
		// since they are not in any scope. Create a dummy object for them.
		if d.Name.Name == "init" {
			assert(obj == nil) // all other functions should have an object
			obj = ast.NewObj(ast.Fun, d.Name.Name)
			obj.Decl = d
			d.Name.Obj = obj
		}
		if obj.Type == nil {
			check.object(obj, false)
		}
	default:
		check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
	}
}

// iterate calls f for each package-level declaration.
func (check *checker) iterate(f func(*checker, ast.Decl)) {
	for _, file := range check.files {
		for _, decl := range file.Decls {
			f(check, decl)
		}
	}
}

// sortedFiles returns the sorted list of package files given a package file map.
func sortedFiles(m map[string]*ast.File) []*ast.File {
	keys := make([]string, len(m))
	i := 0
	for k, _ := range m {
		keys[i] = k
		i++
	}
	sort.Strings(keys)

	files := make([]*ast.File, len(m))
	for i, k := range keys {
		files[i] = m[k]
	}

	return files
}

// A bailout panic is raised to indicate early termination.
type bailout struct{}

func check(ctxt *Context, fset *token.FileSet, files map[string]*ast.File) (pkg *ast.Package, err error) {
	// initialize checker
	check := checker{
		ctxt:     ctxt,
		fset:     fset,
		files:    sortedFiles(files),
		initspec: make(map[*ast.ValueSpec]*ast.ValueSpec),
	}

	// handle panics
	defer func() {
		switch p := recover().(type) {
		case nil, bailout:
			// normal return or early exit
			err = check.firsterr
		default:
			// unexpected panic: don't crash clients
			// panic(p) // enable for debugging
			// TODO(gri) add a test case for this scenario
			err = fmt.Errorf("types internal error: %v", p)
		}
	}()

	// resolve identifiers
	imp := ctxt.Import
	if imp == nil {
		imp = GcImport
	}
	pkg, err = ast.NewPackage(fset, files, imp, Universe)
	if err != nil {
		if list, _ := err.(scanner.ErrorList); len(list) > 0 {
			for _, err := range list {
				check.err(err)
			}
		} else {
			check.err(err)
		}
	}
	check.pkgscope = pkg.Scope

	// determine missing constant initialization expressions
	// and associate methods with types
	check.iterate((*checker).assocInitvalsOrMethod)

	// typecheck all declarations
	check.iterate((*checker).decl)

	// typecheck all function/method bodies
	// (funclist may grow when checking statements - do not use range clause!)
	for i := 0; i < len(check.funclist); i++ {
		f := check.funclist[i]
		if trace {
			s := "<function literal>"
			if f.obj != nil {
				s = f.obj.Name
			}
			fmt.Println("---", s)
		}
		check.funcsig = f.sig
		check.stmtList(f.body.List)
	}

	return
}
<commit_msg>go/types: don't parse imported packages multiple times.<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements the Check function, which typechecks a package.

package types

import (
	"fmt"
	"go/ast"
	"go/scanner"
	"go/token"
	"sort"
)

// enable for debugging
const trace = false

type checker struct {
	ctxt  *Context
	fset  *token.FileSet
	files []*ast.File

	// lazily initialized
	pkgscope *ast.Scope
	firsterr error
	initspec map[*ast.ValueSpec]*ast.ValueSpec // "inherited" type and initialization expressions for constant declarations
	funclist []function                        // list of functions/methods with correct signatures and non-empty bodies
	funcsig  *Signature                        // signature of currently typechecked function
	pos      []token.Pos                       // stack of expr positions; debugging support, used if trace is set
}

type function struct {
	obj  *ast.Object // for debugging/tracing only
	sig  *Signature
	body *ast.BlockStmt
}

// later adds a function with non-empty body to the list of functions
// that need to be processed after all package-level declarations
// are typechecked.
//
func (check *checker) later(obj *ast.Object, sig *Signature, body *ast.BlockStmt) {
	// functions implemented elsewhere (say in assembly) have no body
	if body != nil {
		check.funclist = append(check.funclist, function{obj, sig, body})
	}
}

// declare declares an object of the given kind and name (ident) in scope;
// decl is the corresponding declaration in the AST. An error is reported
// if the object was declared before.
//
// TODO(gri) This is very similar to the declare function in go/parser; it
// is only used to associate methods with their respective receiver base types.
// In a future version, it might be simpler and cleaner to do all the resolution
// in the type-checking phase. It would simplify the parser, AST, and also
// reduce some amount of code duplication.
//
func (check *checker) declare(scope *ast.Scope, kind ast.ObjKind, ident *ast.Ident, decl ast.Decl) {
	assert(ident.Obj == nil) // identifier already declared or resolved
	obj := ast.NewObj(kind, ident.Name)
	obj.Decl = decl
	ident.Obj = obj
	if ident.Name != "_" {
		if alt := scope.Insert(obj); alt != nil {
			prevDecl := ""
			if pos := alt.Pos(); pos.IsValid() {
				prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", check.fset.Position(pos))
			}
			check.errorf(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
		}
	}
}

func (check *checker) valueSpec(pos token.Pos, obj *ast.Object, lhs []*ast.Ident, typ ast.Expr, rhs []ast.Expr, iota int) {
	if len(lhs) == 0 {
		check.invalidAST(pos, "missing lhs in declaration")
		return
	}

	// determine type for all of lhs, if any
	// (but only set it for the object we typecheck!)
	var t Type
	if typ != nil {
		t = check.typ(typ, false)
	}

	// len(lhs) > 0
	if len(lhs) == len(rhs) {
		// check only lhs and rhs corresponding to obj
		var l, r ast.Expr
		for i, name := range lhs {
			if name.Obj == obj {
				l = lhs[i]
				r = rhs[i]
				break
			}
		}
		assert(l != nil)
		obj.Type = t
		check.assign1to1(l, r, nil, true, iota)
		return
	}

	// there must be a type or initialization expressions
	if t == nil && len(rhs) == 0 {
		check.invalidAST(pos, "missing type or initialization expression")
		t = Typ[Invalid]
	}

	// if we have a type, mark all of lhs
	if t != nil {
		for _, name := range lhs {
			name.Obj.Type = t
		}
	}

	// check initial values, if any
	if len(rhs) > 0 {
		// TODO(gri) should try to avoid this conversion
		lhx := make([]ast.Expr, len(lhs))
		for i, e := range lhs {
			lhx[i] = e
		}
		check.assignNtoM(lhx, rhs, true, iota)
	}
}

// object typechecks an object by assigning it a type; obj.Type must be nil.
// Callers must check obj.Type before calling object; this eliminates a call
// for each identifier that has been typechecked already, a common scenario.
//
func (check *checker) object(obj *ast.Object, cycleOk bool) {
	assert(obj.Type == nil)

	switch obj.Kind {
	case ast.Bad, ast.Pkg:
		// nothing to do

	case ast.Con, ast.Var:
		// The obj.Data field for constants and variables is initialized
		// to the respective (hypothetical, for variables) iota value by
		// the parser. The object's fields can be in one of the following
		// states:
		// Type != nil  =>  the constant value is Data
		// Type == nil  =>  the object is not typechecked yet, and Data can be:
		// Data is int  =>  Data is the value of iota for this declaration
		// Data == nil  =>  the object's expression is being evaluated
		if obj.Data == nil {
			check.errorf(obj.Pos(), "illegal cycle in initialization of %s", obj.Name)
			obj.Type = Typ[Invalid]
			return
		}
		spec := obj.Decl.(*ast.ValueSpec)
		iota := obj.Data.(int)
		obj.Data = nil
		// determine spec for type and initialization expressions
		init := spec
		if len(init.Values) == 0 && obj.Kind == ast.Con {
			init = check.initspec[spec]
		}
		check.valueSpec(spec.Pos(), obj, spec.Names, init.Type, init.Values, iota)

	case ast.Typ:
		typ := &NamedType{Obj: obj}
		obj.Type = typ // "mark" object so recursion terminates
		typ.Underlying = underlying(check.typ(obj.Decl.(*ast.TypeSpec).Type, cycleOk))
		// typecheck associated method signatures
		if obj.Data != nil {
			scope := obj.Data.(*ast.Scope)
			switch t := typ.Underlying.(type) {
			case *Struct:
				// struct fields must not conflict with methods
				for _, f := range t.Fields {
					if m := scope.Lookup(f.Name); m != nil {
						check.errorf(m.Pos(), "type %s has both field and method named %s", obj.Name, f.Name)
						// ok to continue
					}
				}
			case *Interface:
				// methods cannot be associated with an interface type
				for _, m := range scope.Objects {
					recv := m.Decl.(*ast.FuncDecl).Recv.List[0].Type
					check.errorf(recv.Pos(), "invalid receiver type %s (%s is an interface type)", obj.Name, obj.Name)
					// ok to continue
				}
			}
			// typecheck method signatures
			for _, obj := range scope.Objects {
				mdecl := obj.Decl.(*ast.FuncDecl)
				sig := check.typ(mdecl.Type, cycleOk).(*Signature)
				params, _ := check.collectParams(mdecl.Recv, false)
				sig.Recv = params[0] // the parser/assocMethod ensure there is exactly one parameter
				obj.Type = sig
				check.later(obj, sig, mdecl.Body)
			}
		}

	case ast.Fun:
		fdecl := obj.Decl.(*ast.FuncDecl)
		// methods are typechecked when their receivers are typechecked
		if fdecl.Recv == nil {
			sig := check.typ(fdecl.Type, cycleOk).(*Signature)
			if obj.Name == "init" && (len(sig.Params) != 0 || len(sig.Results) != 0) {
				check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
				// ok to continue
			}
			obj.Type = sig
			check.later(obj, sig, fdecl.Body)
		}

	default:
		panic("unreachable")
	}
}

// assocInitvals associates "inherited" initialization expressions
// with the corresponding *ast.ValueSpec in the check.initspec map
// for constant declarations without explicit initialization expressions.
//
func (check *checker) assocInitvals(decl *ast.GenDecl) {
	var last *ast.ValueSpec
	for _, s := range decl.Specs {
		if s, ok := s.(*ast.ValueSpec); ok {
			if len(s.Values) > 0 {
				last = s
			} else {
				check.initspec[s] = last
			}
		}
	}
	if last == nil {
		check.invalidAST(decl.Pos(), "no initialization values provided")
	}
}

// assocMethod associates a method declaration with the respective
// receiver base type. meth.Recv must exist.
//
func (check *checker) assocMethod(meth *ast.FuncDecl) {
	// The receiver type is one of the following (enforced by parser):
	// - *ast.Ident
	// - *ast.StarExpr{*ast.Ident}
	// - *ast.BadExpr (parser error)
	typ := meth.Recv.List[0].Type
	if ptr, ok := typ.(*ast.StarExpr); ok {
		typ = ptr.X
	}
	// determine receiver base type object
	var obj *ast.Object
	if ident, ok := typ.(*ast.Ident); ok && ident.Obj != nil {
		obj = ident.Obj
		if obj.Kind != ast.Typ {
			check.errorf(ident.Pos(), "%s is not a type", ident.Name)
			return // ignore this method
		}
		// TODO(gri) determine if obj was defined in this package
		/*
			if check.notLocal(obj) {
				check.errorf(ident.Pos(), "cannot define methods on non-local type %s", ident.Name)
				return // ignore this method
			}
		*/
	} else {
		// If it's not an identifier or the identifier wasn't declared/resolved,
		// the parser/resolver already reported an error. Nothing to do here.
		return // ignore this method
	}
	// declare method in receiver base type scope
	var scope *ast.Scope
	if obj.Data != nil {
		scope = obj.Data.(*ast.Scope)
	} else {
		scope = ast.NewScope(nil)
		obj.Data = scope
	}
	check.declare(scope, ast.Fun, meth.Name, meth)
}

func (check *checker) assocInitvalsOrMethod(decl ast.Decl) {
	switch d := decl.(type) {
	case *ast.GenDecl:
		if d.Tok == token.CONST {
			check.assocInitvals(d)
		}
	case *ast.FuncDecl:
		if d.Recv != nil {
			check.assocMethod(d)
		}
	}
}

func (check *checker) decl(decl ast.Decl) {
	switch d := decl.(type) {
	case *ast.BadDecl:
		// ignore
	case *ast.GenDecl:
		for _, spec := range d.Specs {
			switch s := spec.(type) {
			case *ast.ImportSpec:
				// nothing to do (handled by ast.NewPackage)
			case *ast.ValueSpec:
				for _, name := range s.Names {
					if obj := name.Obj; obj.Type == nil {
						check.object(obj, false)
					}
				}
			case *ast.TypeSpec:
				if obj := s.Name.Obj; obj.Type == nil {
					check.object(obj, false)
				}
			default:
				check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
			}
		}
	case *ast.FuncDecl:
		// methods are checked when their respective base types are checked
		if d.Recv != nil {
			return
		}
		obj := d.Name.Obj
		// Initialization functions don't have an object associated with them
		// since they are not in any scope. Create a dummy object for them.
		if d.Name.Name == "init" {
			assert(obj == nil) // all other functions should have an object
			obj = ast.NewObj(ast.Fun, d.Name.Name)
			obj.Decl = d
			d.Name.Obj = obj
		}
		if obj.Type == nil {
			check.object(obj, false)
		}
	default:
		check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
	}
}

// iterate calls f for each package-level declaration.
func (check *checker) iterate(f func(*checker, ast.Decl)) {
	for _, file := range check.files {
		for _, decl := range file.Decls {
			f(check, decl)
		}
	}
}

// sortedFiles returns the sorted list of package files given a package file map.
func sortedFiles(m map[string]*ast.File) []*ast.File {
	keys := make([]string, len(m))
	i := 0
	for k, _ := range m {
		keys[i] = k
		i++
	}
	sort.Strings(keys)

	files := make([]*ast.File, len(m))
	for i, k := range keys {
		files[i] = m[k]
	}

	return files
}

// A bailout panic is raised to indicate early termination.
type bailout struct{}

func check(ctxt *Context, fset *token.FileSet, files map[string]*ast.File) (pkg *ast.Package, err error) {
	// initialize checker
	check := checker{
		ctxt:     ctxt,
		fset:     fset,
		files:    sortedFiles(files),
		initspec: make(map[*ast.ValueSpec]*ast.ValueSpec),
	}

	// handle panics
	defer func() {
		switch p := recover().(type) {
		case nil, bailout:
			// normal return or early exit
			err = check.firsterr
		default:
			// unexpected panic: don't crash clients
			// panic(p) // enable for debugging
			// TODO(gri) add a test case for this scenario
			err = fmt.Errorf("types internal error: %v", p)
		}
	}()

	// resolve identifiers
	imp := ctxt.Import
	if imp == nil {
		// wrap GcImport to import packages only once by default.
		imported := make(map[string]bool)
		imp = func(imports map[string]*ast.Object, path string) (*ast.Object, error) {
			if imported[path] && imports[path] != nil {
				return imports[path], nil
			}
			pkg, err := GcImport(imports, path)
			if err == nil {
				imported[path] = true
			}
			return pkg, err
		}
	}
	pkg, err = ast.NewPackage(fset, files, imp, Universe)
	if err != nil {
		if list, _ := err.(scanner.ErrorList); len(list) > 0 {
			for _, err := range list {
				check.err(err)
			}
		} else {
			check.err(err)
		}
	}
	check.pkgscope = pkg.Scope

	// determine missing constant initialization expressions
	// and associate methods with types
	check.iterate((*checker).assocInitvalsOrMethod)

	// typecheck all declarations
	check.iterate((*checker).decl)

	// typecheck all function/method bodies
	// (funclist may grow when checking statements - do not use range clause!)
	for i := 0; i < len(check.funclist); i++ {
		f := check.funclist[i]
		if trace {
			s := "<function literal>"
			if f.obj != nil {
				s = f.obj.Name
			}
			fmt.Println("---", s)
		}
		check.funcsig = f.sig
		check.stmtList(f.body.List)
	}

	return
}
<|endoftext|>