<commit_before>package main

import (
	"log"
	"os"
	"time"

	"github.com/banthar/Go-SDL/sdl"
)

var (
	// KeySym to time.Duration mapping
	kmVias = map[uint32]time.Duration{
		sdl.K_z:     -100 * time.Microsecond,
		sdl.K_x:     +100 * time.Microsecond,
		sdl.K_LEFT:  -1 * time.Second,
		sdl.K_RIGHT: +1 * time.Second,
		sdl.K_DOWN:  -10 * time.Second,
		sdl.K_UP:    +10 * time.Second,
	}

	kmFontSize = map[uint32]int{
		sdl.K_EQUALS:   +5, // +
		sdl.K_MINUS:    -5,
		sdl.K_KP_PLUS:  +5,
		sdl.K_KP_MINUS: -5,
	}

	kmNavScript = map[uint32]int{
		sdl.K_SPACE:  0,
		sdl.K_COMMA:  -1, // <
		sdl.K_PERIOD: +1, // >
	}
)

func eventLoop(c *Screen) {
EVENTLOOP:
	/* log.Printf("%#v\n", event) */
	switch e := sdl.PollEvent().(type) {
	case *sdl.QuitEvent:
		os.Exit(0)

	case *sdl.ResizeEvent:
		if opt.fullscreen {
			break
		}
		if err := c.setSurface(int(e.W), int(e.H)); err != nil {
			log.Fatal(err)
		}
		c.updateC <- 1

	case *sdl.KeyboardEvent:
		// Ignore key-up
		if e.State == 0 {
			break
		}

		keysym := e.Keysym.Sym
		if keysym == sdl.K_q {
			quitC <- true
			break
		}

		// tune timestamp
		if v, ok := kmVias[keysym]; ok {
			tsViasC <- v
			break
		}
		// tune font size
		if v, ok := kmFontSize[keysym]; ok {
			c.changeFontSize(v)
			break
		}

		// pause/resume
		if v, ok := kmNavScript[keysym]; ok {
			navC <- v
			break
		}
		log.Printf("Sim:%08x, Mod:%04x, Unicode:%02x, %t\n",
			e.Keysym.Sym, e.Keysym.Mod, e.Keysym.Unicode,
			e.Keysym.Unicode)
	} // end of switch
	time.Sleep(time.Millisecond)
	goto EVENTLOOP
}
<commit_msg>fix time.Sleep() to runtime.Gosched()<commit_after>package main

import (
	"log"
	"os"
	"runtime"
	"time"

	"github.com/banthar/Go-SDL/sdl"
)

var (
	// KeySym to time.Duration mapping
	kmVias = map[uint32]time.Duration{
		sdl.K_z:     -100 * time.Microsecond,
		sdl.K_x:     +100 * time.Microsecond,
		sdl.K_LEFT:  -1 * time.Second,
		sdl.K_RIGHT: +1 * time.Second,
		sdl.K_DOWN:  -10 * time.Second,
		sdl.K_UP:    +10 * time.Second,
	}

	kmFontSize = map[uint32]int{
		sdl.K_EQUALS:   +5, // +
		sdl.K_MINUS:    -5,
		sdl.K_KP_PLUS:  +5,
		sdl.K_KP_MINUS: -5,
	}

	kmNavScript = map[uint32]int{
		sdl.K_SPACE:  0,
		sdl.K_COMMA:  -1, // <
		sdl.K_PERIOD: +1, // >
	}
)

func eventLoop(c *Screen) {
EVENTLOOP:
	/* log.Printf("%#v\n", event) */
	switch e := sdl.PollEvent().(type) {
	case *sdl.QuitEvent:
		os.Exit(0)

	case *sdl.ResizeEvent:
		if opt.fullscreen {
			break
		}
		if err := c.setSurface(int(e.W), int(e.H)); err != nil {
			log.Fatal(err)
		}
		c.updateC <- 1

	case *sdl.KeyboardEvent:
		// Ignore key-up
		if e.State == 0 {
			break
		}

		keysym := e.Keysym.Sym
		if keysym == sdl.K_q {
			quitC <- true
			break
		}

		// tune timestamp
		if v, ok := kmVias[keysym]; ok {
			tsViasC <- v
			break
		}
		// tune font size
		if v, ok := kmFontSize[keysym]; ok {
			c.changeFontSize(v)
			break
		}

		// pause/resume
		if v, ok := kmNavScript[keysym]; ok {
			navC <- v
			break
		}
		log.Printf("Sim:%08x, Mod:%04x, Unicode:%02x, %t\n",
			e.Keysym.Sym, e.Keysym.Mod, e.Keysym.Unicode,
			e.Keysym.Unicode)
	} // end of switch

	runtime.Gosched()
	goto EVENTLOOP
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	"github.com/mattn/go-ole"
)
import "github.com/mattn/go-ole/oleutil"

func main() {
	ole.CoInitialize(0)
	unknown, _ := oleutil.CreateObject("Microsoft.XMLHTTP")
	xmlhttp, _ := unknown.QueryInterface(ole.IID_IDispatch)
	oleutil.CallMethod(xmlhttp, "open", "GET", "http://rss.slashdot.org/Slashdot/slashdot", false)
	oleutil.CallMethod(xmlhttp, "send", nil)
	state := -1
	for state != 4 {
		state = int(oleutil.MustGetProperty(xmlhttp, "readyState").Val)
		time.Sleep(10000000)
	}
	responseXml := oleutil.MustGetProperty(xmlhttp, "responseXml").ToIDispatch()
	items := oleutil.MustCallMethod(responseXml, "selectNodes", "rdf:RDF/item").ToIDispatch()
	length := int(oleutil.MustGetProperty(items, "length").Val)

	for n := 0; n < length; n++ {
		item := oleutil.MustGetProperty(items, "item", n).ToIDispatch()

		title := oleutil.MustCallMethod(item, "selectSingleNode", "title").ToIDispatch()
		println(oleutil.MustGetProperty(title, "text").ToString())

		link := oleutil.MustCallMethod(item, "selectSingleNode", "link").ToIDispatch()
		println("  " + oleutil.MustGetProperty(link, "text").ToString())

		title.Release()
		link.Release()
		item.Release()
	}
	items.Release()
	xmlhttp.Release()
}
<commit_msg>Fix example<commit_after>package main

import (
	"fmt"
	"time"

	"github.com/mattn/go-ole"
)
import "github.com/mattn/go-ole/oleutil"

func main() {
	ole.CoInitialize(0)
	unknown, _ := oleutil.CreateObject("Microsoft.XMLHTTP")
	xmlhttp, _ := unknown.QueryInterface(ole.IID_IDispatch)
	_, err := oleutil.CallMethod(xmlhttp, "open", "GET", "http://rss.slashdot.org/Slashdot/slashdot", false)
	if err != nil {
		panic(err.Error())
	}
	_, err = oleutil.CallMethod(xmlhttp, "send", nil)
	if err != nil {
		panic(err.Error())
	}
	state := -1
	for state != 4 {
		state = int(oleutil.MustGetProperty(xmlhttp, "readyState").Val)
		time.Sleep(10000000)
	}
	responseXml := oleutil.MustGetProperty(xmlhttp, "responseXml").ToIDispatch()
	items := oleutil.MustCallMethod(responseXml, "selectNodes", "/rss/channel/item").ToIDispatch()
	length := int(oleutil.MustGetProperty(items, "length").Val)

	for n := 0; n < length; n++ {
		item := oleutil.MustGetProperty(items, "item", n).ToIDispatch()

		title := oleutil.MustCallMethod(item, "selectSingleNode", "title").ToIDispatch()
		fmt.Println(oleutil.MustGetProperty(title, "text").ToString())

		link := oleutil.MustCallMethod(item, "selectSingleNode", "link").ToIDispatch()
		fmt.Println("  " + oleutil.MustGetProperty(link, "text").ToString())

		title.Release()
		link.Release()
		item.Release()
	}
	items.Release()
	xmlhttp.Release()
}
<|endoftext|>


<commit_before>package routers

import (
	"corpweb/controllers"
	// "corpweb/models"

	"github.com/astaxie/beego"
	// "github.com/astaxie/beego/context"
)

func init() {
	portalContr := &controllers.PortalController{}
	beego.Router("/", portalContr, "get:ToHome")
	beego.Router("/home", portalContr, "get:ToHome")
	beego.Router("/products", portalContr, "get:ToProducts")
	beego.Router("/products.json", portalContr, "get:GetProducts")
	beego.Router("/product/item/:prodId", portalContr, "get:ToProductItem")
	beego.Router("/blog", portalContr, "get:ToBlog")
	beego.Router("/blog/page", portalContr, "get:AjaxGetBlogPage")
	beego.Router("/blog/post/:blogId", portalContr, "get:ToBlogPost")
	beego.Router("/about", portalContr, "get:ToAbout")
	beego.Router("/contact", portalContr, "get:ToContact")
	beego.Router("/contact/msg/add", portalContr, "post:AddContactMsg")

	userContr := &controllers.UserController{}
	beego.Router("/login", userContr, "get:ToLogin")
	beego.Router("/login", userContr, "post:Login")
	beego.Router("/logout", userContr, "get:ToLogout")
	beego.Router("/admin/user/changepwd", userContr, "post:ChangePwd")

	prodContr := &controllers.ProductController{}
	beego.Router("/admin/product/add", prodContr, "get:ToProductAdd")
	beego.Router("/admin/product/add.json", prodContr, "post:AddProduct")
	beego.Router("/admin/product/mod", prodContr, "get:ToProductMod")
	beego.Router("/admin/product/mod.json", prodContr, "post:ModProduct")
	beego.Router("/admin/product", prodContr, "get:ToProducts")
	beego.Router("/admin/products.json", prodContr, "get:AjaxGetProductList")
	beego.Router("/admin/products/remove.json", prodContr, "post:RmProducts")
	beego.Router("/admin/products/pushpin.json", prodContr, "post:PushPin")

	caroContr := &controllers.CarouselController{}
	beego.Router("/admin/home/carousel", caroContr, "get:ToCarousel")
	beego.Router("/admin/home/carousel/add", caroContr, "get:ToAddCarousel")
	beego.Router("/admin/home/carousel/mod", caroContr, "get:ToModCarousel")
	beego.Router("/admin/home/carousel.json", caroContr, "get:GetCarousels")
	beego.Router("/admin/home/carousel/add.json", caroContr, "post:AddCarousel")
	beego.Router("/admin/home/carousel/mod.json", caroContr, "post:ModCarousel")
	beego.Router("/admin/home/carousel/remove.json", caroContr, "post:RmCarousel")
	beego.Router("/admin/home/carousel/pushpin.json", caroContr, "post:PushPin")

	flagshipContr := &controllers.FlagshipProductController{}
	beego.Router("/admin/home/products/flagship", flagshipContr, "get:ToFlagshipProducts")
	beego.Router("/admin/home/products/unflagship.json", flagshipContr, "get:AjaxGetProductsButFlagships")
	beego.Router("/admin/home/products/flagship.json", flagshipContr, "get:GetFlagshipProducts")
	beego.Router("/admin/home/products/flagship/add.json", flagshipContr, "post:AddFlagshipProducts")
	beego.Router("/admin/home/products/flagship/remove.json", flagshipContr, "post:RmFlagshipProduct")
	beego.Router("/admin/home/products/flagship/pushpin.json", flagshipContr, "post:PushPin")

	blogContr := &controllers.BlogController{}
	beego.Router("/admin/blog", blogContr, "get:ToBlog")
	beego.Router("/admin/blog/write", blogContr, "get:ToAddBlog")
	beego.Router("/admin/blog/edit/:blogId", blogContr, "get:ToEditBlog")
	beego.Router("/admin/blog/add", blogContr, "post:AjaxAddBlog")
	beego.Router("/admin/blog/mod/:blogId", blogContr, "post:AjaxModBlog")
	beego.Router("/admin/blog/remove/:blogId", blogContr, "post:AjaxRmBlog")
	beego.Router("/admin/blog/list", blogContr, "get:AjaxGetBlogList")
	beego.Router("/admin/blog/pushpin/:blogId", blogContr, "post:AjaxPushPin")

	msgContr := &controllers.MessageController{}
	beego.Router("/admin/message/contact", msgContr, "get:ToContactMsg")
	beego.Router("/admin/message/contact/page", msgContr, "get:AjaxGetContactMsgPage")
	beego.Router("/admin/message/contact/mark", msgContr, "post:AjaxMarkMsg")
	beego.Router("/admin/message/contact/search", msgContr, "post:SearchContactMsgPage")

	adminContr := &controllers.AdminController{}
	beego.Router("/admin/index", adminContr, "*:Index")
	beego.Router("/admin/img/upload", adminContr, "post:ImgUpload")
	beego.Router("/admin/img/crop", adminContr, "post:ImgCrop")
	beego.Router("/admin/markdown2html.json", adminContr, "post:Markdown2html")

	settingContr := &controllers.SettingsController{}
	beego.Router("/admin/settings/personal", settingContr, "get:ToPersonalSetting")
	beego.Router("/admin/settings/sys", settingContr, "get:ToSysSetting")
	beego.Router("/admin/settings/changepwd", settingContr, "get:ToChangePwd")

	// 登录过滤器
	/*beego.InsertFilter("/admin/*", beego.BeforeExec, func(ctx *context.Context) {
		user, ok := ctx.Input.Session("UserInfo").(models.User)
		// beego.Debug(fmt.Sprintf("filter: %t, %v", ok, user))

		if !ok || len(user.UserId) <= 0 || len(user.LoginName) <= 0 {
			ctx.Redirect(302, "/login")
		}
	})*/

}
<commit_msg>打开登录校验过滤器<commit_after>package routers

import (
	"corpweb/controllers"
	"corpweb/models"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"
)

func init() {
	portalContr := &controllers.PortalController{}
	beego.Router("/", portalContr, "get:ToHome")
	beego.Router("/home", portalContr, "get:ToHome")
	beego.Router("/products", portalContr, "get:ToProducts")
	beego.Router("/products.json", portalContr, "get:GetProducts")
	beego.Router("/product/item/:prodId", portalContr, "get:ToProductItem")
	beego.Router("/blog", portalContr, "get:ToBlog")
	beego.Router("/blog/page", portalContr, "get:AjaxGetBlogPage")
	beego.Router("/blog/post/:blogId", portalContr, "get:ToBlogPost")
	beego.Router("/about", portalContr, "get:ToAbout")
	beego.Router("/contact", portalContr, "get:ToContact")
	beego.Router("/contact/msg/add", portalContr, "post:AddContactMsg")

	userContr := &controllers.UserController{}
	beego.Router("/login", userContr, "get:ToLogin")
	beego.Router("/login", userContr, "post:Login")
	beego.Router("/logout", userContr, "get:ToLogout")
	beego.Router("/admin/user/changepwd", userContr, "post:ChangePwd")

	prodContr := &controllers.ProductController{}
	beego.Router("/admin/product/add", prodContr, "get:ToProductAdd")
	beego.Router("/admin/product/add.json", prodContr, "post:AddProduct")
	beego.Router("/admin/product/mod", prodContr, "get:ToProductMod")
	beego.Router("/admin/product/mod.json", prodContr, "post:ModProduct")
	beego.Router("/admin/product", prodContr, "get:ToProducts")
	beego.Router("/admin/products.json", prodContr, "get:AjaxGetProductList")
	beego.Router("/admin/products/remove.json", prodContr, "post:RmProducts")
	beego.Router("/admin/products/pushpin.json", prodContr, "post:PushPin")

	caroContr := &controllers.CarouselController{}
	beego.Router("/admin/home/carousel", caroContr, "get:ToCarousel")
	beego.Router("/admin/home/carousel/add", caroContr, "get:ToAddCarousel")
	beego.Router("/admin/home/carousel/mod", caroContr, "get:ToModCarousel")
	beego.Router("/admin/home/carousel.json", caroContr, "get:GetCarousels")
	beego.Router("/admin/home/carousel/add.json", caroContr, "post:AddCarousel")
	beego.Router("/admin/home/carousel/mod.json", caroContr, "post:ModCarousel")
	beego.Router("/admin/home/carousel/remove.json", caroContr, "post:RmCarousel")
	beego.Router("/admin/home/carousel/pushpin.json", caroContr, "post:PushPin")

	flagshipContr := &controllers.FlagshipProductController{}
	beego.Router("/admin/home/products/flagship", flagshipContr, "get:ToFlagshipProducts")
	beego.Router("/admin/home/products/unflagship.json", flagshipContr, "get:AjaxGetProductsButFlagships")
	beego.Router("/admin/home/products/flagship.json", flagshipContr, "get:GetFlagshipProducts")
	beego.Router("/admin/home/products/flagship/add.json", flagshipContr, "post:AddFlagshipProducts")
	beego.Router("/admin/home/products/flagship/remove.json", flagshipContr, "post:RmFlagshipProduct")
	beego.Router("/admin/home/products/flagship/pushpin.json", flagshipContr, "post:PushPin")

	blogContr := &controllers.BlogController{}
	beego.Router("/admin/blog", blogContr, "get:ToBlog")
	beego.Router("/admin/blog/write", blogContr, "get:ToAddBlog")
	beego.Router("/admin/blog/edit/:blogId", blogContr, "get:ToEditBlog")
	beego.Router("/admin/blog/add", blogContr, "post:AjaxAddBlog")
	beego.Router("/admin/blog/mod/:blogId", blogContr, "post:AjaxModBlog")
	beego.Router("/admin/blog/remove/:blogId", blogContr, "post:AjaxRmBlog")
	beego.Router("/admin/blog/list", blogContr, "get:AjaxGetBlogList")
	beego.Router("/admin/blog/pushpin/:blogId", blogContr, "post:AjaxPushPin")

	msgContr := &controllers.MessageController{}
	beego.Router("/admin/message/contact", msgContr, "get:ToContactMsg")
	beego.Router("/admin/message/contact/page", msgContr, "get:AjaxGetContactMsgPage")
	beego.Router("/admin/message/contact/mark", msgContr, "post:AjaxMarkMsg")
	beego.Router("/admin/message/contact/search", msgContr, "post:SearchContactMsgPage")

	adminContr := &controllers.AdminController{}
	beego.Router("/admin/index", adminContr, "*:Index")
	beego.Router("/admin/img/upload", adminContr, "post:ImgUpload")
	beego.Router("/admin/img/crop", adminContr, "post:ImgCrop")
	beego.Router("/admin/markdown2html.json", adminContr, "post:Markdown2html")

	settingContr := &controllers.SettingsController{}
	beego.Router("/admin/settings/personal", settingContr, "get:ToPersonalSetting")
	beego.Router("/admin/settings/sys", settingContr, "get:ToSysSetting")
	beego.Router("/admin/settings/changepwd", settingContr, "get:ToChangePwd")

	// 登录过滤器
	beego.InsertFilter("/admin/*", beego.BeforeExec, func(ctx *context.Context) {
		user, ok := ctx.Input.Session("UserInfo").(models.User)
		// beego.Debug(fmt.Sprintf("filter: %t, %v", ok, user))

		if !ok || len(user.UserId) <= 0 || len(user.LoginName) <= 0 {
			ctx.Redirect(302, "/login")
		}
	})

}
<|endoftext|>


<commit_before>// Package update provides functions to update a dependency to the latest version
package update

// Copyright 2013 Vubeology, Inc.

import (
	"github.com/vube/depman/colors"
	"github.com/vube/depman/dep"
	"github.com/vube/depman/install"
	"github.com/vube/depman/util"
)

// Update rewrites Dependency name in deps.json to use the last commit in branch as version
func Update(deps dep.DependencyMap, name string, branch string) {
	util.Print(colors.Blue("Updating:"))

	d, ok := deps.Map[name]
	if !ok {
		util.Fatal(colors.Red("Dependency Name '" + name + "' not found in deps.json"))
	}

	oldVersion := d.Version

	pwd := util.Pwd()
	util.Cd(d.Path())
	d.VCS.Checkout(d)
	d.VCS.Update(d)
	v, err := d.VCS.LastCommit(d, branch)
	if err != nil {
		util.Fatal(err)
	}
	d.Version = v

	util.PrintIndent(colors.Blue(name) + " (" + oldVersion + " --> " + d.Version + ")")

	util.Cd(pwd)
	deps.Map[name] = d
	deps.Write()

	install.Install(deps)

}
<commit_msg>Fix update command<commit_after>// Package update provides functions to update a dependency to the latest version
package update

// Copyright 2013 Vubeology, Inc.

import (
	"github.com/vube/depman/colors"
	"github.com/vube/depman/dep"
	"github.com/vube/depman/install"
	"github.com/vube/depman/util"
)

// Update rewrites Dependency name in deps.json to use the last commit in branch as version
func Update(deps dep.DependencyMap, name string, branch string) {
	util.Print(colors.Blue("Updating:"))

	d, ok := deps.Map[name]
	if !ok {
		util.Fatal(colors.Red("Dependency Name '" + name + "' not found in deps.json"))
	}

	// record the old version
	oldVersion := d.Version

	// temporarily use the branch
	d.Version = branch

	pwd := util.Pwd()
	util.Cd(d.Path())
	d.VCS.Checkout(d)
	d.VCS.Update(d)

	// get the last commit on the newly checked out branch
	v, err := d.VCS.LastCommit(d, branch)
	if err != nil {
		util.Fatal(err)
	}

	// set the version to be the last commit
	d.Version = v

	util.PrintIndent(colors.Blue(name) + " (" + oldVersion + " --> " + d.Version + ")")

	util.Cd(pwd)
	deps.Map[name] = d
	deps.Write()

	install.Install(deps)

}
<|endoftext|>


<commit_before>package registrar

import (
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/cloudfoundry/gibson"
	"github.com/cloudfoundry/yagnats"

	"github.com/cloudfoundry-incubator/route-registrar/config"
	. "github.com/cloudfoundry-incubator/route-registrar/healthchecker"
	. "github.com/cloudfoundry-incubator/route-registrar/logger"
)

type Registrar struct {
	Config               config.Config
	SignalChannel        chan os.Signal
	HealthChecker        HealthChecker
	previousHealthStatus bool
}

func NewRegistrar(clientConfig config.Config) *Registrar {
	registrar := new(Registrar)
	registrar.Config = clientConfig
	registrar.SignalChannel = make(chan os.Signal, 1)
	registrar.previousHealthStatus = false
	return registrar
}

func (registrar *Registrar) AddHealthCheckHandler(handler HealthChecker) {
	registrar.HealthChecker = handler
}

type callbackFunction func()

func (registrar *Registrar) RegisterRoutes() {
	messageBus := buildMessageBus(registrar)
	client := gibson.NewCFRouterClient(registrar.Config.ExternalIp, messageBus)

	// set up periodic registration
	client.Greet()

	done := make(chan bool)
	registrar.registerSignalHandler(done, client)

	if registrar.HealthChecker != nil {
		callbackInterval := time.Duration(registrar.Config.HealthChecker.Interval) * time.Second
		callbackPeriodically(callbackInterval,
			func() { registrar.updateRegistrationBasedOnHealthCheck(client) },
			done)
	} else {
		client.Register(registrar.Config.Port, registrar.Config.ExternalHost)

		select {
		case <-done:
			return
		}
	}
}

func buildMessageBus(registrar *Registrar) (messageBus yagnats.NATSClient) {

	messageBus = yagnats.NewClient()
	natsServers := []yagnats.ConnectionProvider{}

	for _, server := range registrar.Config.MessageBusServers {
		LogWithTimestamp("Adding NATS server %s, for user %s.", server.Host, server.User)
		natsServers = append(natsServers, &yagnats.ConnectionInfo{
			server.Host,
			server.User,
			server.Password,
		})
	}

	natsInfo := &yagnats.ConnectionCluster{natsServers}

	err := messageBus.Connect(natsInfo)

	if err != nil {
		LogWithTimestamp("Error connecting to NATS: %v\n", err)
		panic("Failed to connect to NATS bus.")
	}

	LogWithTimestamp("Successfully connected to NATS.")

	return
}

func callbackPeriodically(duration time.Duration, callback callbackFunction, done chan bool) {
	interval := time.NewTicker(duration)
	for stop := false; !stop; {
		select {
		case <-interval.C:
			callback()
		case stop = <-done:
			return
		}
	}
}

func (registrar *Registrar) updateRegistrationBasedOnHealthCheck(client *gibson.CFRouterClient) {
	current := registrar.HealthChecker.Check()
	if (!current) && registrar.previousHealthStatus {
		LogWithTimestamp("Health check status changed to unavailabile; unregistering the route\n")
		client.Unregister(registrar.Config.Port, registrar.Config.ExternalHost)
	} else if current && (!registrar.previousHealthStatus) {
		LogWithTimestamp("Health check status changed to availabile; registering the route\n")
		client.Register(registrar.Config.Port, registrar.Config.ExternalHost)
	}
	registrar.previousHealthStatus = current
}

func (registrar *Registrar) registerSignalHandler(done chan bool, client *gibson.CFRouterClient) {
	go func() {
		select {
		case <-registrar.SignalChannel:
			LogWithTimestamp("Received SIGTERM or SIGINT; unregistering the route\n")
			client.Unregister(registrar.Config.Port, registrar.Config.ExternalHost)
			done <- true
		}
	}()

	signal.Notify(registrar.SignalChannel, syscall.SIGINT, syscall.SIGTERM)
}
<commit_msg>Update to support latest yagnats<commit_after>package registrar

import (
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/cloudfoundry/gibson"
	"github.com/cloudfoundry/yagnats"

	"github.com/cloudfoundry-incubator/route-registrar/config"
	. "github.com/cloudfoundry-incubator/route-registrar/healthchecker"
	. "github.com/cloudfoundry-incubator/route-registrar/logger"
)

type Registrar struct {
	Config               config.Config
	SignalChannel        chan os.Signal
	HealthChecker        HealthChecker
	previousHealthStatus bool
}

func NewRegistrar(clientConfig config.Config) *Registrar {
	registrar := new(Registrar)
	registrar.Config = clientConfig
	registrar.SignalChannel = make(chan os.Signal, 1)
	registrar.previousHealthStatus = false
	return registrar
}

func (registrar *Registrar) AddHealthCheckHandler(handler HealthChecker) {
	registrar.HealthChecker = handler
}

type callbackFunction func()

func (registrar *Registrar) RegisterRoutes() {
	messageBus := buildMessageBus(registrar)
	client := gibson.NewCFRouterClient(registrar.Config.ExternalIp, messageBus)

	// set up periodic registration
	client.Greet()

	done := make(chan bool)
	registrar.registerSignalHandler(done, client)

	if registrar.HealthChecker != nil {
		callbackInterval := time.Duration(registrar.Config.HealthChecker.Interval) * time.Second
		callbackPeriodically(callbackInterval,
			func() { registrar.updateRegistrationBasedOnHealthCheck(client) },
			done)
	} else {
		client.Register(registrar.Config.Port, registrar.Config.ExternalHost)

		select {
		case <-done:
			return
		}
	}
}

func buildMessageBus(registrar *Registrar) (messageBus yagnats.NATSClient) {

	messageBus = yagnats.NewClient()
	natsServers := []yagnats.ConnectionProvider{}

	for _, server := range registrar.Config.MessageBusServers {
		LogWithTimestamp("Adding NATS server %s, for user %s.", server.Host, server.User)
		natsServers = append(natsServers, &yagnats.ConnectionInfo{
			server.Host,
			server.User,
			server.Password,
			nil,
		})
	}

	natsInfo := &yagnats.ConnectionCluster{natsServers}

	err := messageBus.Connect(natsInfo)

	if err != nil {
		LogWithTimestamp("Error connecting to NATS: %v\n", err)
		panic("Failed to connect to NATS bus.")
	}

	LogWithTimestamp("Successfully connected to NATS.")

	return
}

func callbackPeriodically(duration time.Duration, callback callbackFunction, done chan bool) {
	interval := time.NewTicker(duration)
	for stop := false; !stop; {
		select {
		case <-interval.C:
			callback()
		case stop = <-done:
			return
		}
	}
}

func (registrar *Registrar) updateRegistrationBasedOnHealthCheck(client *gibson.CFRouterClient) {
	current := registrar.HealthChecker.Check()
	if (!current) && registrar.previousHealthStatus {
		LogWithTimestamp("Health check status changed to unavailabile; unregistering the route\n")
		client.Unregister(registrar.Config.Port, registrar.Config.ExternalHost)
	} else if current && (!registrar.previousHealthStatus) {
		LogWithTimestamp("Health check status changed to availabile; registering the route\n")
		client.Register(registrar.Config.Port, registrar.Config.ExternalHost)
	}
	registrar.previousHealthStatus = current
}

func (registrar *Registrar) registerSignalHandler(done chan bool, client *gibson.CFRouterClient) {
	go func() {
		select {
		case <-registrar.SignalChannel:
			LogWithTimestamp("Received SIGTERM or SIGINT; unregistering the route\n")
			client.Unregister(registrar.Config.Port, registrar.Config.ExternalHost)
			done <- true
		}
	}()

	signal.Notify(registrar.SignalChannel, syscall.SIGINT, syscall.SIGTERM)
}
<|endoftext|>


<commit_before>package goutils

import (
	"math/rand"
	"reflect"
	"time"
)

const (
	number        = "1234567890"
	smallLetter   = "abcdefghijklmnopqrstuvwxyz"
	capitalLetter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	character     = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
	hiragana      = "ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん"
	katakana      = "ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ"
	hangul        = "ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎㄲㄸㅃㅆㅉㅏㅑㅓㅕㅗㅛㅜㅠㅡㅣㅐㅒㅔㅖㅘㅙㅚㅝㅞㅟㅢ"
)

// Random ...
type Random struct {
	Number        string
	SmallLetter   string
	CapitalLetter string
	Character     string
	Hiragana      string
	Katakana      string
	Hangul        string
}

// UseNumber ...
func (t *Random) UseNumber() {
	t.Number = number
}

// UseSmallLetter ...
func (t *Random) UseSmallLetter() {
	t.SmallLetter = smallLetter
}

// UseCapitalLetter ...
func (t *Random) UseCapitalLetter() {
	t.CapitalLetter = capitalLetter
}

// UseCharacter ...
func (t *Random) UseCharacter() {
	t.Character = character
}

// UseHiragana ...
func (t *Random) UseHiragana() {
	t.Hiragana = hiragana
}

// UseKatakana ...
func (t *Random) UseKatakana() {
	t.Katakana = katakana
}

// UseHangul ...
func (t *Random) UseHangul() {
	t.Hangul = hangul
}

// Random ...
func (t *Random) Random(n int) string {
	letters := []rune(t.generatorData())
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[randomInt(len(letters))]
	}
	return string(b)
}

func (t *Random) generatorData() string {
	st := reflect.ValueOf(*t)
	data := ""
	for i := 0; i < st.NumField(); i++ {
		field := st.Field(i)
		data += field.String()
	}
	return data
}

func randomInt(n int) int {
	rand.Seed(time.Now().UnixNano())
	return rand.Intn(n)
}
<commit_msg>Added shuzi<commit_after>package goutils

import (
	"math/rand"
	"reflect"
	"time"
)

const (
	number        = "1234567890"
	smallLetter   = "abcdefghijklmnopqrstuvwxyz"
	capitalLetter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	character     = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
	hiragana      = "ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん"
	katakana      = "ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ"
	hangul        = "ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎㄲㄸㅃㅆㅉㅏㅑㅓㅕㅗㅛㅜㅠㅡㅣㅐㅒㅔㅖㅘㅙㅚㅝㅞㅟㅢ"
	shuzi         = "一二三四五六七八九十零"
)

// Random ...
type Random struct {
	Number        string
	SmallLetter   string
	CapitalLetter string
	Character     string
	Hiragana      string
	Katakana      string
	Hangul        string
	Shuzi         string
}

// UseNumber ...
func (t *Random) UseNumber() {
	t.Number = number
}

// UseSmallLetter ...
func (t *Random) UseSmallLetter() {
	t.SmallLetter = smallLetter
}

// UseCapitalLetter ...
func (t *Random) UseCapitalLetter() {
	t.CapitalLetter = capitalLetter
}

// UseCharacter ...
func (t *Random) UseCharacter() {
	t.Character = character
}

// UseHiragana ...
func (t *Random) UseHiragana() {
	t.Hiragana = hiragana
}

// UseKatakana ...
func (t *Random) UseKatakana() {
	t.Katakana = katakana
}

// UseHangul ...
func (t *Random) UseHangul() {
	t.Hangul = hangul
}

// UseShuzi ...
func (t *Random) UseShuzi() {
	t.Shuzi = shuzi
}

// Random ...
func (t *Random) Random(n int) string {
	letters := []rune(t.generatorData())
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[randomInt(len(letters))]
	}
	return string(b)
}

func (t *Random) generatorData() string {
	st := reflect.ValueOf(*t)
	data := ""
	for i := 0; i < st.NumField(); i++ {
		field := st.Field(i)
		data += field.String()
	}
	return data
}

func randomInt(n int) int {
	rand.Seed(time.Now().UnixNano())
	return rand.Intn(n)
}
<|endoftext|>


<commit_before>// +build functional

package test

import (
	"os"
	"testing"

	dbm "github.com/tendermint/tmlibs/db"

	"github.com/bytom/protocol/bc/types"
	"github.com/bytom/protocol/vm"
)

// case1:           |------c1(height=7)
// --------(height=5)
//                  |------------c2(height=9)
func TestForkCase1(t *testing.T) {
	c1, err := declChain("chain1", nil, 0, 7)
	defer os.RemoveAll("chain1")
	if err != nil {
		t.Fatal(err)
	}

	c2, err := declChain("chain2", c1, 5, 9)
	defer os.RemoveAll("chain2")
	if err != nil {
		t.Fatal(err)
	}

	bestBlockHash := c2.BestBlockHash()
	if err := merge(c1, c2); err != nil {
		t.Fatal(err)
	}

	if *c1.BestBlockHash() != *bestBlockHash || *c2.BestBlockHash() != *bestBlockHash {
		t.Fatalf("test fork case1 failed")
	}

	if !c1.InMainChain(*bestBlockHash) || !c2.InMainChain(*bestBlockHash) {
		t.Fatalf("best block is not in main chain")
	}
}

// case2:            |----c1(height=6)
// ---------(height 5)
//                   |----c2(height=6)
func TestForkCase2(t *testing.T) {
	c1, err := declChain("chain1", nil, 0, 6)
	defer os.RemoveAll("chain1")
	if err != nil {
		t.Fatal(err)
	}

	c2, err := declChain("chain2", c1, 5, 6)
	defer os.RemoveAll("chain2")
	if err != nil {
		t.Fatal(err)
	}

	c1BestBlockHash := c1.BestBlockHash()
	c2BestBlockHash := c2.BestBlockHash()
	if err := merge(c1, c2); err != nil {
		t.Fatal(err)
	}

	if *c1.BestBlockHash() != *c1BestBlockHash || *c2.BestBlockHash() != *c2BestBlockHash {
		t.Fatalf("test fork case2 failed")
	}

	if !c1.InMainChain(*c1BestBlockHash) || !c2.InMainChain(*c2BestBlockHash) {
		t.Fatalf("best block is not in main chain")
	}
}

func TestBlockSync(t *testing.T) {
	c1, err := declChain("chain1", nil, 0, 5)
	defer os.RemoveAll("chain1")
	if err != nil {
		t.Fatal(err)
	}

	c2, err := declChain("chain2", c1, 5, 8)
	defer os.RemoveAll("chain2")
	if err != nil {
		t.Fatal(err)
	}

	bestBlockHash := c2.BestBlockHash()
	if err := merge(c1, c2); err != nil {
		t.Fatal(err)
	}

	if *c1.BestBlockHash() != *bestBlockHash || *c2.BestBlockHash() != *bestBlockHash {
		t.Fatalf("test block sync failed")
	}

	if !c1.InMainChain(*bestBlockHash) || !c2.InMainChain(*bestBlockHash) {
		t.Fatalf("test block sync failed, best block is not in main chain")
	}
}

func TestDoubleSpentInDiffBlock(t *testing.T) {
	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
	defer os.RemoveAll("tx_pool_test")
	chain, _, txPool, err := MockChain(chainDB)
	if err != nil {
		t.Fatal(err)
	}
	if err := AppendBlocks(chain, 6); err != nil {
		t.Fatal(err)
	}

	// create tx spend the coinbase output in block 1
	block, err := chain.GetBlockByHeight(1)
	if err != nil {
		t.Fatal(err)
	}
	tx, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	newBlock, err := NewBlock(chain, []*types.Tx{tx}, []byte{byte(vm.OP_TRUE)})
	err = SolveAndUpdate(chain, newBlock)
	if err != nil {
		t.Fatal(err)
	}

	// create a double spent tx in another block
	tx, err = CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	_, err = chain.ValidateTx(tx)
	if err == nil {
		t.Fatal("validate double spent tx success")
	}
	if txPool.HaveTransaction(&tx.ID) {
		t.Fatalf("tx pool have double spent tx")
	}
}

func TestDoubleSpentInSameBlock(t *testing.T) {
	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
	defer os.RemoveAll("tx_pool_test")
	chain, _, txPool, err := MockChain(chainDB)
	if err != nil {
		t.Fatal(err)
	}
	if err := AppendBlocks(chain, 7); err != nil {
		t.Fatal(err)
	}

	// create tx spend the coinbase output in block 1
	block, err := chain.GetBlockByHeight(1)
	if err != nil {
		t.Fatal(err)
	}
	tx1, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	// create tx spend the coinbase output in block 1
	tx2, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	_, err = chain.ValidateTx(tx1)
	if err != nil {
		t.Fatal(err)
	}
	_, err = chain.ValidateTx(tx2)
	if err != nil {
		t.Fatal(err)
	}

	if !txPool.HaveTransaction(&tx1.ID) {
		t.Fatalf("can't find tx in tx pool")
	}
	if !txPool.HaveTransaction(&tx2.ID) {
		t.Fatalf("can't find tx in tx pool")
	}

	block, err = NewBlock(chain, []*types.Tx{tx1, tx2}, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	if err := SolveAndUpdate(chain, block); err == nil {
		t.Fatalf("process double spent tx success")
	}
}

func TestTxPoolDependencyTx(t *testing.T) {
	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
	defer os.RemoveAll("tx_pool_test")
	chain, _, txPool, err := MockChain(chainDB)
	if err != nil {
		t.Fatal(err)
	}
	if err := AppendBlocks(chain, 7); err != nil {
		t.Fatal(err)
	}

	block, err := chain.GetBlockByHeight(1)
	if err != nil {
		t.Fatal(err)
	}

	tx, err := CreateTxFromTx(block.Transactions[0], 0, 5000000000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	outputAmount := uint64(5000000000)
	txs := []*types.Tx{nil}
	txs[0] = tx
	for i := 1; i < 10; i++ {
		outputAmount -= 50000000
		tx, err := CreateTxFromTx(txs[i-1], 0, outputAmount, []byte{byte(vm.OP_TRUE)})
		if err != nil {
			t.Fatal(err)
		}
		txs = append(txs, tx)
	}

	// validate tx and put it into tx pool
	for _, tx := range txs {
		if _, err := chain.ValidateTx(tx); err != nil {
			t.Fatal(err)
		}
		if !txPool.HaveTransaction(&tx.ID) {
			t.Fatal("can't find tx in txpool")
		}
	}

	block, err = NewBlock(chain, txs, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	if err := SolveAndUpdate(chain, block); err != nil {
		t.Fatal("process dependency tx failed")
	}
}
<commit_msg>test add invalid tx to txpool<commit_after>// +build functional

package test

import (
	"os"
	"testing"

	dbm "github.com/tendermint/tmlibs/db"

	"github.com/bytom/protocol/bc/types"
	"github.com/bytom/protocol/vm"
)

// case1:           |------c1(height=7)
// --------(height=5)
//                  |------------c2(height=9)
func TestForkCase1(t *testing.T) {
	c1, err := declChain("chain1", nil, 0, 7)
	defer os.RemoveAll("chain1")
	if err != nil {
		t.Fatal(err)
	}

	c2, err := declChain("chain2", c1, 5, 9)
	defer os.RemoveAll("chain2")
	if err != nil {
		t.Fatal(err)
	}

	bestBlockHash := c2.BestBlockHash()
	if err := merge(c1, c2); err != nil {
		t.Fatal(err)
	}

	if *c1.BestBlockHash() != *bestBlockHash || *c2.BestBlockHash() != *bestBlockHash {
		t.Fatalf("test fork case1 failed")
	}

	if !c1.InMainChain(*bestBlockHash) || !c2.InMainChain(*bestBlockHash) {
		t.Fatalf("best block is not in main chain")
	}
}

// case2:            |----c1(height=6)
// ---------(height 5)
//                   |----c2(height=6)
func TestForkCase2(t *testing.T) {
	c1, err := declChain("chain1", nil, 0, 6)
	defer os.RemoveAll("chain1")
	if err != nil {
		t.Fatal(err)
	}

	c2, err := declChain("chain2", c1, 5, 6)
	defer os.RemoveAll("chain2")
	if err != nil {
		t.Fatal(err)
	}

	c1BestBlockHash := c1.BestBlockHash()
	c2BestBlockHash := c2.BestBlockHash()
	if err := merge(c1, c2); err != nil {
		t.Fatal(err)
	}

	if *c1.BestBlockHash() != *c1BestBlockHash || *c2.BestBlockHash() != *c2BestBlockHash {
		t.Fatalf("test fork case2 failed")
	}

	if !c1.InMainChain(*c1BestBlockHash) || !c2.InMainChain(*c2BestBlockHash) {
		t.Fatalf("best block is not in main chain")
	}
}

func TestBlockSync(t *testing.T) {
	c1, err := declChain("chain1", nil, 0, 5)
	defer os.RemoveAll("chain1")
	if err != nil {
		t.Fatal(err)
	}

	c2, err := declChain("chain2", c1, 5, 8)
	defer os.RemoveAll("chain2")
	if err != nil {
		t.Fatal(err)
	}

	bestBlockHash := c2.BestBlockHash()
	if err := merge(c1, c2); err != nil {
		t.Fatal(err)
	}

	if *c1.BestBlockHash() != *bestBlockHash || *c2.BestBlockHash() != *bestBlockHash {
		t.Fatalf("test block sync failed")
	}

	if !c1.InMainChain(*bestBlockHash) || !c2.InMainChain(*bestBlockHash) {
		t.Fatalf("test block sync failed, best block is not in main chain")
	}
}

func TestDoubleSpentInDiffBlock(t *testing.T) {
	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
	defer os.RemoveAll("tx_pool_test")
	chain, _, txPool, err := MockChain(chainDB)
	if err != nil {
		t.Fatal(err)
	}
	if err := AppendBlocks(chain, 6); err != nil {
		t.Fatal(err)
	}

	// create tx spend the coinbase output in block 1
	block, err := chain.GetBlockByHeight(1)
	if err != nil {
		t.Fatal(err)
	}
	tx, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	newBlock, err := NewBlock(chain, []*types.Tx{tx}, []byte{byte(vm.OP_TRUE)})
	err = SolveAndUpdate(chain, newBlock)
	if err != nil {
		t.Fatal(err)
	}

	// create a double spent tx in another block
	tx, err = CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	_, err = chain.ValidateTx(tx)
	if err == nil {
		t.Fatal("validate double spent tx success")
	}
	if txPool.HaveTransaction(&tx.ID) {
		t.Fatalf("tx pool have double spent tx")
	}
}

func TestDoubleSpentInSameBlock(t *testing.T) {
	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
	defer os.RemoveAll("tx_pool_test")
	chain, _, txPool, err := MockChain(chainDB)
	if err != nil {
		t.Fatal(err)
	}
	if err := AppendBlocks(chain, 7); err != nil {
		t.Fatal(err)
	}

	// create tx spend the coinbase output in block 1
	block, err := chain.GetBlockByHeight(1)
	if err != nil {
		t.Fatal(err)
	}
	tx1, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	// create tx spend the coinbase output in block 1
	tx2, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	_, err = chain.ValidateTx(tx1)
	if err != nil {
		t.Fatal(err)
	}
	_, err = chain.ValidateTx(tx2)
	if err != nil {
		t.Fatal(err)
	}

	if !txPool.HaveTransaction(&tx1.ID) {
		t.Fatalf("can't find tx in tx pool")
	}
	if !txPool.HaveTransaction(&tx2.ID) {
		t.Fatalf("can't find tx in tx pool")
	}

	block, err = NewBlock(chain, []*types.Tx{tx1, tx2}, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	if err := SolveAndUpdate(chain, block); err == nil {
		t.Fatalf("process double spent tx success")
	}
}

func TestTxPoolDependencyTx(t *testing.T) {
	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
	defer os.RemoveAll("tx_pool_test")
	chain, _, txPool, err := MockChain(chainDB)
	if err != nil {
		t.Fatal(err)
	}
	if err := AppendBlocks(chain, 7); err != nil {
		t.Fatal(err)
	}

	block, err := chain.GetBlockByHeight(1)
	if err != nil {
		t.Fatal(err)
	}

	tx, err := CreateTxFromTx(block.Transactions[0], 0, 5000000000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	outputAmount := uint64(5000000000)
	txs := []*types.Tx{nil}
	txs[0] = tx
	for i := 1; i < 10; i++ {
		outputAmount -= 50000000
		tx, err := CreateTxFromTx(txs[i-1], 0, outputAmount, []byte{byte(vm.OP_TRUE)})
		if err != nil {
			t.Fatal(err)
		}
		txs = append(txs, tx)
	}

	// validate tx and put it into tx pool
	for _, tx := range txs {
		if _, err := chain.ValidateTx(tx); err != nil {
			t.Fatal(err)
		}
		if !txPool.HaveTransaction(&tx.ID) {
			t.Fatal("can't find tx in txpool")
		}
	}

	block, err = NewBlock(chain, txs, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	if err := SolveAndUpdate(chain, block); err != nil {
		t.Fatal("process dependency tx failed")
	}
}

func TestAddInvalidTxToTxPool(t *testing.T) {
	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
	defer os.RemoveAll("tx_pool_test")

	chain, _, txPool, err := MockChain(chainDB)
	if err != nil {
		t.Fatal(err)
	}

	if err := AppendBlocks(chain, 7); err != nil {
		t.Fatal(err)
	}

	block, err := chain.GetBlockByHeight(1)
	if err != nil {
		t.Fatal(err)
	}

	//invalid tx, output amount greater than input
	tx, err := CreateTxFromTx(block.Transactions[0], 0, 60000000000, []byte{byte(vm.OP_TRUE)})
	if err != nil {
		t.Fatal(err)
	}

	if _, err := chain.ValidateTx(tx); err == nil {
		t.Fatalf("add invalid tx to txpool success")
	}

	if txPool.IsTransactionInPool(&tx.ID) {
		t.Fatalf("add invalid tx to txpool success")
	}

	if !txPool.IsTransactionInErrCache(&tx.ID) {
		t.Fatalf("can't find invalid tx in txpool err cache")
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

// Godoc comment extraction and comment -> HTML formatting.

package doc

import (
	"go/ast";
	"io";
	"once";
	"regexp";
	"strings";
	"template";	// for htmlEscape
)

// Comment extraction

var (
	comment_markers *regexp.Regexp;
	trailing_whitespace *regexp.Regexp;
	comment_junk *regexp.Regexp;
)

func makeRex(s string) *regexp.Regexp {
	re, err := regexp.Compile(s);
	if err != nil {
		panic("MakeRegexp ", s, " ", err.String());
	}
	return re;
}

// TODO(rsc): Cannot use var initialization for regexps,
// because Regexp constructor needs threads.
func setupRegexps() {
	comment_markers = makeRex("^/[/*] ?");
	trailing_whitespace = makeRex("[ \t\r]+$");
	comment_junk = makeRex("^[ \t]*(/\\*|\\*/)[ \t]*$");
}

// CommentText returns the text of comment,
// with the comment markers - //, /*, and */ - removed.
func CommentText(comment *ast.CommentGroup) string {
	if comment == nil {
		return "";
	}
	comments := make([]string, len(comment.List));
	for i, c := range comment.List {
		comments[i] = string(c.Text);
	}

	once.Do(setupRegexps);
	lines := make([]string, 0, 20);
	for _, c := range comments {
		// split on newlines
		cl := strings.Split(c, "\n", 0);

		// walk lines, stripping comment markers
		w := 0;
		for _, l := range cl {
			// remove /* and */ lines
			if comment_junk.MatchString(l) {
				continue;
			}

			// strip trailing white space
			m := trailing_whitespace.ExecuteString(l);
			if len(m) > 0 {
				l = l[0 : m[1]];
			}

			// strip leading comment markers
			m = comment_markers.ExecuteString(l);
			if len(m) > 0 {
				l = l[m[1] : len(l)];
			}

			cl[w] = l;
			w++;
		}
		cl = cl[0:w];

		// Add this comment to total list.
		for _, l := range cl {
			n := len(lines);
			if n+1 >= cap(lines) {
				newlines := make([]string, n, 2*cap(lines));
				for k := range newlines {
					newlines[k] = lines[k];
				}
				lines = newlines;
			}
			lines = lines[0 : n+1];
			lines[n] = l;
		}
	}

	// Remove leading blank lines; convert runs of
	// interior blank lines to a single blank line.
	n := 0;
	for _, line := range lines {
		if line != "" || n > 0 && lines[n-1] != "" {
			lines[n] = line;
			n++;
		}
	}
	lines = lines[0 : n];

	// Add final "" entry to get trailing newline from Join.
	// The original loop always leaves room for one more.
	if n > 0 && lines[n-1] != "" {
		lines = lines[0 : n+1];
		lines[n] = "";
	}

	return strings.Join(lines, "\n");
}

// Split bytes into lines.
func split(text []byte) [][]byte {
	// count lines
	n := 0;
	last := 0;
	for i, c := range text {
		if c == '\n' {
			last = i+1;
			n++;
		}
	}
	if last < len(text) {
		n++;
	}

	// split
	out := make([][]byte, n);
	last = 0;
	n = 0;
	for i, c := range text {
		if c == '\n' {
			out[n] = text[last : i+1];
			last = i+1;
			n++;
		}
	}
	if last < len(text) {
		out[n] = text[last : len(text)];
	}

	return out;
}

var (
	ldquo = strings.Bytes("“");
	rdquo = strings.Bytes("”");
)

// Escape comment text for HTML.
// Also, turn `` into “ and '' into ”.
func commentEscape(w io.Writer, s []byte) {
	last := 0;
	for i := 0; i < len(s)-1; i++ {
		if s[i] == s[i+1] && (s[i] == '`' || s[i] == '\'') {
			template.HtmlEscape(w, s[last : i]);
			last = i+2;
			switch s[i] {
			case '`':
				w.Write(ldquo);
			case '\'':
				w.Write(rdquo);
			}
			i++;	// loop will add one more
		}
	}
	template.HtmlEscape(w, s[last : len(s)]);
}

var (
	html_p = strings.Bytes("
\n");
	html_endp = strings.Bytes("
\n");
	html_pre = strings.Bytes("
");
	html_endpre = strings.Bytes("
\n");
)

func indentLen(s []byte) int {
	i := 0;
	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
		i++;
	}
	return i;
}

func isBlank(s []byte) bool {
	return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
}

func commonPrefix(a, b []byte) []byte {
	i := 0;
	for i < len(a) && i < len(b) && a[i] == b[i] {
		i++;
	}
	return a[0 : i];
}

func unindent(block [][]byte) {
	if len(block) == 0 {
		return;
	}

	// compute maximum common white prefix
	prefix := block[0][0 : indentLen(block[0])];
	for _, line := range block {
		if !isBlank(line) {
			prefix = commonPrefix(prefix, line[0 : indentLen(line)]);
		}
	}
	n := len(prefix);

	// remove
	for i, line := range block {
		if !isBlank(line) {
			block[i] = line[n : len(line)];
		}
	}
}

// Convert comment text to formatted HTML.
// The comment was prepared by DocReader,
// so it is known not to have leading, trailing blank lines
// nor to have trailing spaces at the end of lines.
// The comment markers have already been removed.
//
// Turn each run of multiple \n into

// Turn each run of indented lines into
 without indent.
//
// TODO(rsc): I'd like to pass in an array of variable names []string
// and then italicize those strings when they appear as words.
func ToHtml(w io.Writer, s []byte) {
	inpara := false;

	/* TODO(rsc): 6g cant generate code for these
	close := func() {
		if inpara {
			w.Write(html_endp);
			inpara = false;
		}
	};
	open := func() {
		if !inpara {
			w.Write(html_p);
			inpara = true;
		}
	};
	*/

	lines := split(s);
	unindent(lines);
	for i := 0; i < len(lines);  {
		line := lines[i];
		if isBlank(line) {
			// close paragraph
			if inpara {
				w.Write(html_endp);
				inpara = false;
			}
			i++;
			continue;
		}
		if indentLen(line) > 0 {
			// close paragraph
			if inpara {
				w.Write(html_endp);
				inpara = false;
			}

			// count indented or blank lines
			j := i+1;
			for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
				j++;
			}
			// but not trailing blank lines
			for j > i && isBlank(lines[j-1]) {
				j--;
			}
			block := lines[i : j];
			i = j;

			unindent(block);

			// put those lines in a pre block.
			// they don't get the nice text formatting,
			// just html escaping
			w.Write(html_pre);
			for _, line := range block {
				template.HtmlEscape(w, line);
			}
			w.Write(html_endpre);
			continue;
		}
		// open paragraph
		if !inpara {
			w.Write(html_p);
			inpara = true;
		}
		commentEscape(w, lines[i]);
		i++;
	}
	if inpara {
		w.Write(html_endp);
		inpara = false;
	}
}

<commit_msg>more comment work. got rid of regexps. primary bug fix is that // inside /* */ do not get stripped anymore, so that the text inside<commit_after>// Copyright 2009 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.

// Godoc comment extraction and comment -> HTML formatting.

package doc

import (
	"go/ast";
	"io";
	"strings";
	"template";	// for htmlEscape
)

// Comment extraction

// CommentText returns the text of comment,
// with the comment markers - //, /*, and */ - removed.
func CommentText(comment *ast.CommentGroup) string {
	if comment == nil {
		return "";
	}
	comments := make([]string, len(comment.List));
	for i, c := range comment.List {
		comments[i] = string(c.Text);
	}

	lines := make([]string, 0, 20);
	for _, c := range comments {
		// Remove comment markers.
		// The parser has given us exactly the comment text.
		switch n := len(c); {
		case n >= 4 && c[0:2] == "/*" && c[n-2:n] == "*/":
			c = c[2:n-2];
		case n >= 2 && c[0:2] == "//":
			c = c[2:n];
			// Remove leading space after //, if there is one.
			if len(c) > 0 && c[0] == ' ' {
				c = c[1:len(c)];
			}
		}

		// Split on newlines.
		cl := strings.Split(c, "\n", 0);

		// Walk lines, stripping trailing white space and adding to list.
		for _, l := range cl {
			// Strip trailing white space
			m := len(l);
			for m > 0 && (l[m-1] == ' ' || l[m-1] == '\n' || l[m-1] == '\t' || l[m-1] == '\r') {
				m--;
			}
			l = l[0 : m];

			// Add to list.
			n := len(lines);
			if n+1 >= cap(lines) {
				newlines := make([]string, n, 2*cap(lines));
				for k := range newlines {
					newlines[k] = lines[k];
				}
				lines = newlines;
			}
			lines = lines[0 : n+1];
			lines[n] = l;
		}
	}

	// Remove leading blank lines; convert runs of
	// interior blank lines to a single blank line.
	n := 0;
	for _, line := range lines {
		if line != "" || n > 0 && lines[n-1] != "" {
			lines[n] = line;
			n++;
		}
	}
	lines = lines[0 : n];

	// Add final "" entry to get trailing newline from Join.
	// The original loop always leaves room for one more.
	if n > 0 && lines[n-1] != "" {
		lines = lines[0 : n+1];
		lines[n] = "";
	}

	return strings.Join(lines, "\n");
}

// Split bytes into lines.
func split(text []byte) [][]byte {
	// count lines
	n := 0;
	last := 0;
	for i, c := range text {
		if c == '\n' {
			last = i+1;
			n++;
		}
	}
	if last < len(text) {
		n++;
	}

	// split
	out := make([][]byte, n);
	last = 0;
	n = 0;
	for i, c := range text {
		if c == '\n' {
			out[n] = text[last : i+1];
			last = i+1;
			n++;
		}
	}
	if last < len(text) {
		out[n] = text[last : len(text)];
	}

	return out;
}

var (
	ldquo = strings.Bytes("“");
	rdquo = strings.Bytes("”");
)

// Escape comment text for HTML.
// Also, turn `` into “ and '' into ”.
func commentEscape(w io.Writer, s []byte) {
	last := 0;
	for i := 0; i < len(s)-1; i++ {
		if s[i] == s[i+1] && (s[i] == '`' || s[i] == '\'') {
			template.HtmlEscape(w, s[last : i]);
			last = i+2;
			switch s[i] {
			case '`':
				w.Write(ldquo);
			case '\'':
				w.Write(rdquo);
			}
			i++;	// loop will add one more
		}
	}
	template.HtmlEscape(w, s[last : len(s)]);
}

var (
	html_p = strings.Bytes("
\n");
	html_endp = strings.Bytes("
\n");
	html_pre = strings.Bytes("
");
	html_endpre = strings.Bytes("
\n");
)

func indentLen(s []byte) int {
	i := 0;
	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
		i++;
	}
	return i;
}

func isBlank(s []byte) bool {
	return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
}

func commonPrefix(a, b []byte) []byte {
	i := 0;
	for i < len(a) && i < len(b) && a[i] == b[i] {
		i++;
	}
	return a[0 : i];
}

func unindent(block [][]byte) {
	if len(block) == 0 {
		return;
	}

	// compute maximum common white prefix
	prefix := block[0][0 : indentLen(block[0])];
	for _, line := range block {
		if !isBlank(line) {
			prefix = commonPrefix(prefix, line[0 : indentLen(line)]);
		}
	}
	n := len(prefix);

	// remove
	for i, line := range block {
		if !isBlank(line) {
			block[i] = line[n : len(line)];
		}
	}
}

// Convert comment text to formatted HTML.
// The comment was prepared by DocReader,
// so it is known not to have leading, trailing blank lines
// nor to have trailing spaces at the end of lines.
// The comment markers have already been removed.
//
// Turn each run of multiple \n into

// Turn each run of indented lines into
 without indent.
//
// TODO(rsc): I'd like to pass in an array of variable names []string
// and then italicize those strings when they appear as words.
func ToHtml(w io.Writer, s []byte) {
	inpara := false;

	/* TODO(rsc): 6g cant generate code for these
	close := func() {
		if inpara {
			w.Write(html_endp);
			inpara = false;
		}
	};
	open := func() {
		if !inpara {
			w.Write(html_p);
			inpara = true;
		}
	};
	*/

	lines := split(s);
	unindent(lines);
	for i := 0; i < len(lines);  {
		line := lines[i];
		if isBlank(line) {
			// close paragraph
			if inpara {
				w.Write(html_endp);
				inpara = false;
			}
			i++;
			continue;
		}
		if indentLen(line) > 0 {
			// close paragraph
			if inpara {
				w.Write(html_endp);
				inpara = false;
			}

			// count indented or blank lines
			j := i+1;
			for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
				j++;
			}
			// but not trailing blank lines
			for j > i && isBlank(lines[j-1]) {
				j--;
			}
			block := lines[i : j];
			i = j;

			unindent(block);

			// put those lines in a pre block.
			// they don't get the nice text formatting,
			// just html escaping
			w.Write(html_pre);
			for _, line := range block {
				template.HtmlEscape(w, line);
			}
			w.Write(html_endpre);
			continue;
		}
		// open paragraph
		if !inpara {
			w.Write(html_p);
			inpara = true;
		}
		commentEscape(w, lines[i]);
		i++;
	}
	if inpara {
		w.Write(html_endp);
		inpara = false;
	}
}

<|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.

// Extract example functions from file ASTs.

package doc

import (
	"go/ast"
	"go/token"
	"path"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
)

type Example struct {
	Name     string // name of the item being exemplified
	Doc      string // example function doc string
	Code     ast.Node
	Play     *ast.File // a whole program version of the example
	Comments []*ast.CommentGroup
	Output   string // expected output
}

func Examples(files ...*ast.File) []*Example {
	var list []*Example
	for _, file := range files {
		hasTests := false // file contains tests or benchmarks
		numDecl := 0      // number of non-import declarations in the file
		var flist []*Example
		for _, decl := range file.Decls {
			if g, ok := decl.(*ast.GenDecl); ok && g.Tok != token.IMPORT {
				numDecl++
				continue
			}
			f, ok := decl.(*ast.FuncDecl)
			if !ok {
				continue
			}
			numDecl++
			name := f.Name.Name
			if isTest(name, "Test") || isTest(name, "Benchmark") {
				hasTests = true
				continue
			}
			if !isTest(name, "Example") {
				continue
			}
			var doc string
			if f.Doc != nil {
				doc = f.Doc.Text()
			}
			flist = append(flist, &Example{
				Name:     name[len("Example"):],
				Doc:      doc,
				Code:     f.Body,
				Play:     playExample(file, f.Body),
				Comments: file.Comments,
				Output:   exampleOutput(f.Body, file.Comments),
			})
		}
		if !hasTests && numDecl > 1 && len(flist) == 1 {
			// If this file only has one example function, some
			// other top-level declarations, and no tests or
			// benchmarks, use the whole file as the example.
			flist[0].Code = file
			flist[0].Play = playExampleFile(file)
		}
		list = append(list, flist...)
	}
	sort.Sort(exampleByName(list))
	return list
}

var outputPrefix = regexp.MustCompile(`(?i)^[[:space:]]*output:`)

func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) string {
	if _, last := lastComment(b, comments); last != nil {
		// test that it begins with the correct prefix
		text := last.Text()
		if loc := outputPrefix.FindStringIndex(text); loc != nil {
			return strings.TrimSpace(text[loc[1]:])
		}
	}
	return "" // no suitable comment found
}

// isTest tells whether name looks like a test, example, or benchmark.
// It is a Test (say) if there is a character after Test that is not a
// lower-case letter. (We don't want Testiness.)
func isTest(name, prefix string) bool {
	if !strings.HasPrefix(name, prefix) {
		return false
	}
	if len(name) == len(prefix) { // "Test" is ok
		return true
	}
	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
	return !unicode.IsLower(rune)
}

type exampleByName []*Example

func (s exampleByName) Len() int           { return len(s) }
func (s exampleByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s exampleByName) Less(i, j int) bool { return s[i].Name < s[j].Name }

// playExample synthesizes a new *ast.File based on the provided
// file with the provided function body as the body of main.
func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
	if !strings.HasSuffix(file.Name.Name, "_test") {
		// We don't support examples that are part of the
		// greater package (yet).
		return nil
	}

	// Find top-level declarations in the file.
	topDecls := make(map[*ast.Object]bool)
	for _, decl := range file.Decls {
		switch d := decl.(type) {
		case *ast.FuncDecl:
			topDecls[d.Name.Obj] = true
		case *ast.GenDecl:
			for _, spec := range d.Specs {
				switch s := spec.(type) {
				case *ast.TypeSpec:
					topDecls[s.Name.Obj] = true
				case *ast.ValueSpec:
					for _, id := range s.Names {
						topDecls[id.Obj] = true
					}
				}
			}
		}
	}

	// Find unresolved identifiers and uses of top-level declarations.
	unresolved := make(map[string]bool)
	usesTopDecl := false
	ast.Inspect(body, func(n ast.Node) bool {
		// For an expression like fmt.Println, only add "fmt" to the
		// set of unresolved names.
		if e, ok := n.(*ast.SelectorExpr); ok {
			if id, ok := e.X.(*ast.Ident); ok && id.Obj == nil {
				unresolved[id.Name] = true
			}
			return false
		}
		if id, ok := n.(*ast.Ident); ok {
			if id.Obj == nil {
				unresolved[id.Name] = true
			} else if topDecls[id.Obj] {
				usesTopDecl = true
			}
		}
		return true
	})
	if usesTopDecl {
		// We don't support examples that are not self-contained (yet).
		return nil
	}

	// Remove predeclared identifiers from unresolved list.
	for n := range unresolved {
		if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] {
			delete(unresolved, n)
		}
	}

	// Use unresolved identifiers to determine the imports used by this
	// example. The heuristic assumes package names match base import
	// paths for imports w/o renames (should be good enough most of the time).
	namedImports := make(map[string]string) // [name]path
	var blankImports []ast.Spec             // _ imports
	for _, s := range file.Imports {
		p, err := strconv.Unquote(s.Path.Value)
		if err != nil {
			continue
		}
		n := path.Base(p)
		if s.Name != nil {
			n = s.Name.Name
			switch n {
			case "_":
				blankImports = append(blankImports, s)
				continue
			case ".":
				// We can't resolve dot imports (yet).
				return nil
			}
		}
		if unresolved[n] {
			namedImports[n] = p
			delete(unresolved, n)
		}
	}

	// If there are other unresolved identifiers, give up because this
	// synthesized file is not going to build.
	if len(unresolved) > 0 {
		return nil
	}

	// Include documentation belonging to blank imports.
	var comments []*ast.CommentGroup
	for _, s := range blankImports {
		if c := s.(*ast.ImportSpec).Doc; c != nil {
			comments = append(comments, c)
		}
	}

	// Include comments that are inside the function body.
	for _, c := range file.Comments {
		if body.Pos() <= c.Pos() && c.End() <= body.End() {
			comments = append(comments, c)
		}
	}

	// Strip "Output:" commment and adjust body end position.
	body, comments = stripOutputComment(body, comments)

	// Synthesize import declaration.
	importDecl := &ast.GenDecl{
		Tok:    token.IMPORT,
		Lparen: 1, // Need non-zero Lparen and Rparen so that printer
		Rparen: 1, // treats this as a factored import.
	}
	for n, p := range namedImports {
		s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p)}}
		if path.Base(p) != n {
			s.Name = ast.NewIdent(n)
		}
		importDecl.Specs = append(importDecl.Specs, s)
	}
	importDecl.Specs = append(importDecl.Specs, blankImports...)

	// Synthesize main function.
	funcDecl := &ast.FuncDecl{
		Name: ast.NewIdent("main"),
		Type: &ast.FuncType{},
		Body: body,
	}

	// Synthesize file.
	return &ast.File{
		Name:     ast.NewIdent("main"),
		Decls:    []ast.Decl{importDecl, funcDecl},
		Comments: comments,
	}
}

// playExampleFile takes a whole file example and synthesizes a new *ast.File
// such that the example is function main in package main.
func playExampleFile(file *ast.File) *ast.File {
	// Strip copyright comment if present.
	comments := file.Comments
	if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright") {
		comments = comments[1:]
	}

	// Copy declaration slice, rewriting the ExampleX function to main.
	var decls []ast.Decl
	for _, d := range file.Decls {
		if f, ok := d.(*ast.FuncDecl); ok && isTest(f.Name.Name, "Example") {
			// Copy the FuncDecl, as it may be used elsewhere.
			newF := *f
			newF.Name = ast.NewIdent("main")
			newF.Body, comments = stripOutputComment(f.Body, comments)
			d = &newF
		}
		decls = append(decls, d)
	}

	// Copy the File, as it may be used elsewhere.
	f := *file
	f.Name = ast.NewIdent("main")
	f.Decls = decls
	f.Comments = comments
	return &f
}

// stripOutputComment finds and removes an "Output:" commment from body
// and comments, and adjusts the body block's end position.
func stripOutputComment(body *ast.BlockStmt, comments []*ast.CommentGroup) (*ast.BlockStmt, []*ast.CommentGroup) {
	// Do nothing if no "Output:" comment found.
	i, last := lastComment(body, comments)
	if last == nil || !outputPrefix.MatchString(last.Text()) {
		return body, comments
	}

	// Copy body and comments, as the originals may be used elsewhere.
	newBody := &ast.BlockStmt{
		Lbrace: body.Lbrace,
		List:   body.List,
		Rbrace: last.Pos(),
	}
	newComments := make([]*ast.CommentGroup, len(comments)-1)
	copy(newComments, comments[:i])
	copy(newComments[i:], comments[i+1:])
	return newBody, newComments
}

// lastComment returns the last comment inside the provided block.
func lastComment(b *ast.BlockStmt, c []*ast.CommentGroup) (i int, last *ast.CommentGroup) {
	pos, end := b.Pos(), b.End()
	for j, cg := range c {
		if cg.Pos() < pos {
			continue
		}
		if cg.End() > end {
			break
		}
		i, last = j, cg
	}
	return
}
<commit_msg>go/doc: trim only first space or newline from example output comment<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.

// Extract example functions from file ASTs.

package doc

import (
	"go/ast"
	"go/token"
	"path"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"
)

type Example struct {
	Name     string // name of the item being exemplified
	Doc      string // example function doc string
	Code     ast.Node
	Play     *ast.File // a whole program version of the example
	Comments []*ast.CommentGroup
	Output   string // expected output
}

func Examples(files ...*ast.File) []*Example {
	var list []*Example
	for _, file := range files {
		hasTests := false // file contains tests or benchmarks
		numDecl := 0      // number of non-import declarations in the file
		var flist []*Example
		for _, decl := range file.Decls {
			if g, ok := decl.(*ast.GenDecl); ok && g.Tok != token.IMPORT {
				numDecl++
				continue
			}
			f, ok := decl.(*ast.FuncDecl)
			if !ok {
				continue
			}
			numDecl++
			name := f.Name.Name
			if isTest(name, "Test") || isTest(name, "Benchmark") {
				hasTests = true
				continue
			}
			if !isTest(name, "Example") {
				continue
			}
			var doc string
			if f.Doc != nil {
				doc = f.Doc.Text()
			}
			flist = append(flist, &Example{
				Name:     name[len("Example"):],
				Doc:      doc,
				Code:     f.Body,
				Play:     playExample(file, f.Body),
				Comments: file.Comments,
				Output:   exampleOutput(f.Body, file.Comments),
			})
		}
		if !hasTests && numDecl > 1 && len(flist) == 1 {
			// If this file only has one example function, some
			// other top-level declarations, and no tests or
			// benchmarks, use the whole file as the example.
			flist[0].Code = file
			flist[0].Play = playExampleFile(file)
		}
		list = append(list, flist...)
	}
	sort.Sort(exampleByName(list))
	return list
}

var outputPrefix = regexp.MustCompile(`(?i)^[[:space:]]*output:`)

func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) string {
	if _, last := lastComment(b, comments); last != nil {
		// test that it begins with the correct prefix
		text := last.Text()
		if loc := outputPrefix.FindStringIndex(text); loc != nil {
			text = text[loc[1]:]
			// Strip zero or more spaces followed by \n or a single space.
			text = strings.TrimLeft(text, " ")
			if len(text) > 0 && text[0] == '\n' {
				text = text[1:]
			}
			return text
		}
	}
	return "" // no suitable comment found
}

// isTest tells whether name looks like a test, example, or benchmark.
// It is a Test (say) if there is a character after Test that is not a
// lower-case letter. (We don't want Testiness.)
func isTest(name, prefix string) bool {
	if !strings.HasPrefix(name, prefix) {
		return false
	}
	if len(name) == len(prefix) { // "Test" is ok
		return true
	}
	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
	return !unicode.IsLower(rune)
}

type exampleByName []*Example

func (s exampleByName) Len() int           { return len(s) }
func (s exampleByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s exampleByName) Less(i, j int) bool { return s[i].Name < s[j].Name }

// playExample synthesizes a new *ast.File based on the provided
// file with the provided function body as the body of main.
func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
	if !strings.HasSuffix(file.Name.Name, "_test") {
		// We don't support examples that are part of the
		// greater package (yet).
		return nil
	}

	// Find top-level declarations in the file.
	topDecls := make(map[*ast.Object]bool)
	for _, decl := range file.Decls {
		switch d := decl.(type) {
		case *ast.FuncDecl:
			topDecls[d.Name.Obj] = true
		case *ast.GenDecl:
			for _, spec := range d.Specs {
				switch s := spec.(type) {
				case *ast.TypeSpec:
					topDecls[s.Name.Obj] = true
				case *ast.ValueSpec:
					for _, id := range s.Names {
						topDecls[id.Obj] = true
					}
				}
			}
		}
	}

	// Find unresolved identifiers and uses of top-level declarations.
	unresolved := make(map[string]bool)
	usesTopDecl := false
	ast.Inspect(body, func(n ast.Node) bool {
		// For an expression like fmt.Println, only add "fmt" to the
		// set of unresolved names.
		if e, ok := n.(*ast.SelectorExpr); ok {
			if id, ok := e.X.(*ast.Ident); ok && id.Obj == nil {
				unresolved[id.Name] = true
			}
			return false
		}
		if id, ok := n.(*ast.Ident); ok {
			if id.Obj == nil {
				unresolved[id.Name] = true
			} else if topDecls[id.Obj] {
				usesTopDecl = true
			}
		}
		return true
	})
	if usesTopDecl {
		// We don't support examples that are not self-contained (yet).
		return nil
	}

	// Remove predeclared identifiers from unresolved list.
	for n := range unresolved {
		if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] {
			delete(unresolved, n)
		}
	}

	// Use unresolved identifiers to determine the imports used by this
	// example. The heuristic assumes package names match base import
	// paths for imports w/o renames (should be good enough most of the time).
	namedImports := make(map[string]string) // [name]path
	var blankImports []ast.Spec             // _ imports
	for _, s := range file.Imports {
		p, err := strconv.Unquote(s.Path.Value)
		if err != nil {
			continue
		}
		n := path.Base(p)
		if s.Name != nil {
			n = s.Name.Name
			switch n {
			case "_":
				blankImports = append(blankImports, s)
				continue
			case ".":
				// We can't resolve dot imports (yet).
				return nil
			}
		}
		if unresolved[n] {
			namedImports[n] = p
			delete(unresolved, n)
		}
	}

	// If there are other unresolved identifiers, give up because this
	// synthesized file is not going to build.
	if len(unresolved) > 0 {
		return nil
	}

	// Include documentation belonging to blank imports.
	var comments []*ast.CommentGroup
	for _, s := range blankImports {
		if c := s.(*ast.ImportSpec).Doc; c != nil {
			comments = append(comments, c)
		}
	}

	// Include comments that are inside the function body.
	for _, c := range file.Comments {
		if body.Pos() <= c.Pos() && c.End() <= body.End() {
			comments = append(comments, c)
		}
	}

	// Strip "Output:" commment and adjust body end position.
	body, comments = stripOutputComment(body, comments)

	// Synthesize import declaration.
	importDecl := &ast.GenDecl{
		Tok:    token.IMPORT,
		Lparen: 1, // Need non-zero Lparen and Rparen so that printer
		Rparen: 1, // treats this as a factored import.
	}
	for n, p := range namedImports {
		s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p)}}
		if path.Base(p) != n {
			s.Name = ast.NewIdent(n)
		}
		importDecl.Specs = append(importDecl.Specs, s)
	}
	importDecl.Specs = append(importDecl.Specs, blankImports...)

	// Synthesize main function.
	funcDecl := &ast.FuncDecl{
		Name: ast.NewIdent("main"),
		Type: &ast.FuncType{},
		Body: body,
	}

	// Synthesize file.
	return &ast.File{
		Name:     ast.NewIdent("main"),
		Decls:    []ast.Decl{importDecl, funcDecl},
		Comments: comments,
	}
}

// playExampleFile takes a whole file example and synthesizes a new *ast.File
// such that the example is function main in package main.
func playExampleFile(file *ast.File) *ast.File {
	// Strip copyright comment if present.
	comments := file.Comments
	if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright") {
		comments = comments[1:]
	}

	// Copy declaration slice, rewriting the ExampleX function to main.
	var decls []ast.Decl
	for _, d := range file.Decls {
		if f, ok := d.(*ast.FuncDecl); ok && isTest(f.Name.Name, "Example") {
			// Copy the FuncDecl, as it may be used elsewhere.
			newF := *f
			newF.Name = ast.NewIdent("main")
			newF.Body, comments = stripOutputComment(f.Body, comments)
			d = &newF
		}
		decls = append(decls, d)
	}

	// Copy the File, as it may be used elsewhere.
	f := *file
	f.Name = ast.NewIdent("main")
	f.Decls = decls
	f.Comments = comments
	return &f
}

// stripOutputComment finds and removes an "Output:" commment from body
// and comments, and adjusts the body block's end position.
func stripOutputComment(body *ast.BlockStmt, comments []*ast.CommentGroup) (*ast.BlockStmt, []*ast.CommentGroup) {
	// Do nothing if no "Output:" comment found.
	i, last := lastComment(body, comments)
	if last == nil || !outputPrefix.MatchString(last.Text()) {
		return body, comments
	}

	// Copy body and comments, as the originals may be used elsewhere.
	newBody := &ast.BlockStmt{
		Lbrace: body.Lbrace,
		List:   body.List,
		Rbrace: last.Pos(),
	}
	newComments := make([]*ast.CommentGroup, len(comments)-1)
	copy(newComments, comments[:i])
	copy(newComments[i:], comments[i+1:])
	return newBody, newComments
}

// lastComment returns the last comment inside the provided block.
func lastComment(b *ast.BlockStmt, c []*ast.CommentGroup) (i int, last *ast.CommentGroup) {
	pos, end := b.Pos(), b.End()
	for j, cg := range c {
		if cg.Pos() < pos {
			continue
		}
		if cg.End() > end {
			break
		}
		i, last = j, cg
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

// +build darwin freebsd linux netbsd openbsd windows

package net

import (
	"syscall"
	"time"
)

// A sockaddr represents a TCP, UDP, IP or Unix network endpoint
// address that can be converted into a syscall.Sockaddr.
type sockaddr interface {
	Addr
	family() int
	isWildcard() bool
	sockaddr(family int) (syscall.Sockaddr, error)
	toAddr() sockaddr
}

// Generic POSIX socket creation.
func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
	s, err := sysSocket(f, t, p)
	if err != nil {
		return nil, err
	}

	if err = setDefaultSockopts(s, f, t, ipv6only); err != nil {
		closesocket(s)
		return nil, err
	}

	// This socket is used by a listener.
	if ulsa != nil && ursa == nil {
		// We provide a socket that listens to a wildcard
		// address with reusable UDP port when the given ulsa
		// is an appropriate UDP multicast address prefix.
		// This makes it possible for a single UDP listener
		// to join multiple different group addresses, for
		// multiple UDP listeners that listen on the same UDP
		// port to join the same group address.
		if ulsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil {
			closesocket(s)
			return nil, err
		}
	}

	if ulsa != nil {
		if err = syscall.Bind(s, ulsa); err != nil {
			closesocket(s)
			return nil, err
		}
	}

	if fd, err = newFD(s, f, t, net); err != nil {
		closesocket(s)
		return nil, err
	}

	// This socket is used by a dialer.
	if ursa != nil {
		if !deadline.IsZero() {
			setWriteDeadline(fd, deadline)
		}
		if err = fd.connect(ulsa, ursa); err != nil {
			fd.Close()
			return nil, err
		}
		fd.isConnected = true
		if !deadline.IsZero() {
			setWriteDeadline(fd, noDeadline)
		}
	}

	lsa, _ := syscall.Getsockname(s)
	laddr := toAddr(lsa)
	rsa, _ := syscall.Getpeername(s)
	if rsa == nil {
		rsa = ursa
	}
	raddr := toAddr(rsa)
	fd.setAddr(laddr, raddr)
	return fd, nil
}
<commit_msg>net: document sockaddr interface<commit_after>// Copyright 2009 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.

// +build darwin freebsd linux netbsd openbsd windows

package net

import (
	"syscall"
	"time"
)

// A sockaddr represents a TCP, UDP, IP or Unix network endpoint
// address that can be converted into a syscall.Sockaddr.
type sockaddr interface {
	Addr

	// family returns the platform-dependent address family
	// identifier.
	family() int

	// isWildcard reports whether the address is a wildcard
	// address.
	isWildcard() bool

	// sockaddr returns the address converted into a syscall
	// sockaddr type that implements syscall.Sockaddr
	// interface. It returns a nil interface when the address is
	// nil.
	sockaddr(family int) (syscall.Sockaddr, error)

	// toAddr returns the address represented in sockaddr
	// interface. It returns a nil interface when the address is
	// nil.
	toAddr() sockaddr
}

// Generic POSIX socket creation.
func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
	s, err := sysSocket(f, t, p)
	if err != nil {
		return nil, err
	}

	if err = setDefaultSockopts(s, f, t, ipv6only); err != nil {
		closesocket(s)
		return nil, err
	}

	// This socket is used by a listener.
	if ulsa != nil && ursa == nil {
		// We provide a socket that listens to a wildcard
		// address with reusable UDP port when the given ulsa
		// is an appropriate UDP multicast address prefix.
		// This makes it possible for a single UDP listener
		// to join multiple different group addresses, for
		// multiple UDP listeners that listen on the same UDP
		// port to join the same group address.
		if ulsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil {
			closesocket(s)
			return nil, err
		}
	}

	if ulsa != nil {
		if err = syscall.Bind(s, ulsa); err != nil {
			closesocket(s)
			return nil, err
		}
	}

	if fd, err = newFD(s, f, t, net); err != nil {
		closesocket(s)
		return nil, err
	}

	// This socket is used by a dialer.
	if ursa != nil {
		if !deadline.IsZero() {
			setWriteDeadline(fd, deadline)
		}
		if err = fd.connect(ulsa, ursa); err != nil {
			fd.Close()
			return nil, err
		}
		fd.isConnected = true
		if !deadline.IsZero() {
			setWriteDeadline(fd, noDeadline)
		}
	}

	lsa, _ := syscall.Getsockname(s)
	laddr := toAddr(lsa)
	rsa, _ := syscall.Getpeername(s)
	if rsa == nil {
		rsa = ursa
	}
	raddr := toAddr(rsa)
	fd.setAddr(laddr, raddr)
	return fd, nil
}
<|endoftext|>


<commit_before>package main

import (
    "encoding/json"
    "io"
    "net/http"
    "os/exec"
    "syscall"
    "bufio"
    "fmt"
    "log"
    "os"
)

// UptimeInfo represents the system load average as reported by the uptime command.
type UptimeInfo struct {
	One     float64 `json:"one_minute"`
	Five    float64 `json:"five_minutes"`
	Fifteen float64 `json:"fifteen_minutes"`
}

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
  file, err := os.Open(path)
  if err != nil {
    return nil, err
  }
  defer file.Close()

  var lines []string
  scanner := bufio.NewScanner(file)
  for scanner.Scan() {
    lines = append(lines, scanner.Text())
  }
  return lines, scanner.Err()
}

// list_contains checks a list for a member
func list_contains(member string, list []string) bool {

    for _,element := range list {
        // index is the index where we are
        // element is the element from someSlice for where we are
        if element == member {
            return true
        }
    }
    return false
}

// uptime executes the uptime command.
func uptime() ([]byte, error) {
	cmd := exec.Command("uptime")
	return cmd.Output()
}

// user12 kills a process with USR1 then USR2
func usr12(pid int) () {
	syscall.Kill(pid, syscall.SIGUSR1)
	syscall.Kill(pid, syscall.SIGUSR2)
}

// uptimeServer servers the system load average as reported by the uptime
// command. It returns the system uptime in the following format:
//
//   {
//     "one_minute": 1.0199999809265137,
//     "five_minutes": 1.2100000381469727,
//     "fifteen_minutes": 1.2300000190734863
//   }
//
func uptimeServer(w http.ResponseWriter, req *http.Request) {
    // Get first list of lines
    lines1, err := readLines("/var/log/tinc/tinc.log")
    if err != nil {
        log.Fatalf("readLines: %s", err)
    }
    // Send signals
    usr12(22899)
    // Confirm flush of data to file
    syscall.Sync()
    // Get second list of lines
    lines2, err := readLines("/var/log/tinc/tinc.log")
    if err != nil {
        log.Fatalf("readLines: %s", err)
    }

    // Print out unique lines in the second set
    for i, line := range lines2 {
        if list_contains(line, lines1) == false {
            fmt.Println(i, line)
        }
    }

    output, err := uptime()
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Convert the raw uptime output to an UptimeInfo object.
	ui, err := parseUptimeInfo(output)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Create the JSON representation of the system uptime.
	data, err := json.MarshalIndent(ui, " ", "")
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the HTTP response headers and body.
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	io.WriteString(w, string(data))
}
<commit_msg>Pid detection<commit_after>package main

import (
    "bufio"
    "encoding/json"
    "errors"
    "fmt"
    "github.com/mitchellh/go-ps"
    "io"
    "log"
    "net/http"
    "os"
    "os/exec"
    "syscall"
)

// UptimeInfo represents the system load average as reported by the uptime command.
type UptimeInfo struct {
	One     float64 `json:"one_minute"`
	Five    float64 `json:"five_minutes"`
	Fifteen float64 `json:"fifteen_minutes"`
}

// findTincPid finds the process of the 'tincd' daemon
func findTincPid() (int, error) {

    procs, err := ps.Processes()
    if err != nil {
        log.Fatalf("findTincPid: %s", err)
    }

    for _, proc := range procs {

        if proc.Executable() == "tincd" {
            //fmt.Println("pid: ", proc.Pid())
            //fmt.Println("ppid: ", proc.PPid())
            //fmt.Println("name: ", proc.Executable())
            //fmt.Println("raw: ", proc)
            return proc.Pid(), err
        }
    }
    return 0, errors.New("findTincPid: Pid not found, is tinc running?")
}

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
  file, err := os.Open(path)
  if err != nil {
    return nil, err
  }
  defer file.Close()

  var lines []string
  scanner := bufio.NewScanner(file)
  for scanner.Scan() {
    lines = append(lines, scanner.Text())
  }
  return lines, scanner.Err()
}

// list_contains checks a list for a member
func list_contains(member string, list []string) bool {

    for _,element := range list {
        // index is the index where we are
        // element is the element from someSlice for where we are
        if element == member {
            return true
        }
    }
    return false
}

// uptime executes the uptime command.
func uptime() ([]byte, error) {
	cmd := exec.Command("uptime")
	return cmd.Output()
}

// user12 kills a process with USR1 then USR2
func usr12(pid int) () {
	syscall.Kill(pid, syscall.SIGUSR1)
	syscall.Kill(pid, syscall.SIGUSR2)
}

// uptimeServer servers the system load average as reported by the uptime
// command. It returns the system uptime in the following format:
//
//   {
//     "one_minute": 1.0199999809265137,
//     "five_minutes": 1.2100000381469727,
//     "fifteen_minutes": 1.2300000190734863
//   }
//
func uptimeServer(w http.ResponseWriter, req *http.Request) {
    // Get tinc pid
    tincPid, err := findTincPid()
    if err != nil {
        log.Fatalf("findTincPid: %s", err)
    }

    // Get first list of lines
    lines1, err := readLines("/var/log/tinc/tinc.log")
    if err != nil {
        log.Fatalf("readLines: %s", err)
    }
    // Send signals
    usr12(tincPid)
    // Confirm flush of data to file
    syscall.Sync()
    // Get second list of lines
    lines2, err := readLines("/var/log/tinc/tinc.log")
    if err != nil {
        log.Fatalf("readLines: %s", err)
    }

    // Print out unique lines in the second set
    for i, line := range lines2 {
        if list_contains(line, lines1) == false {
            fmt.Println(i, line)
        }
    }

    output, err := uptime()
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Convert the raw uptime output to an UptimeInfo object.
	ui, err := parseUptimeInfo(output)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Create the JSON representation of the system uptime.
	data, err := json.MarshalIndent(ui, " ", "")
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// Write the HTTP response headers and body.
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	io.WriteString(w, string(data))
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

package path

import (
	"os";
	"testing";
)

type CleanTest struct {
	path, clean string;
}

var cleantests = []CleanTest{
	// Already clean
	CleanTest{"", "."},
	CleanTest{"abc", "abc"},
	CleanTest{"abc/def", "abc/def"},
	CleanTest{"a/b/c", "a/b/c"},
	CleanTest{".", "."},
	CleanTest{"..", ".."},
	CleanTest{"../..", "../.."},
	CleanTest{"../../abc", "../../abc"},
	CleanTest{"/abc", "/abc"},
	CleanTest{"/", "/"},

	// Remove trailing slash
	CleanTest{"abc/", "abc"},
	CleanTest{"abc/def/", "abc/def"},
	CleanTest{"a/b/c/", "a/b/c"},
	CleanTest{"./", "."},
	CleanTest{"../", ".."},
	CleanTest{"../../", "../.."},
	CleanTest{"/abc/", "/abc"},

	// Remove doubled slash
	CleanTest{"abc//def//ghi", "abc/def/ghi"},
	CleanTest{"//abc", "/abc"},
	CleanTest{"///abc", "/abc"},
	CleanTest{"//abc//", "/abc"},
	CleanTest{"abc//", "abc"},

	// Remove . elements
	CleanTest{"abc/./def", "abc/def"},
	CleanTest{"/./abc/def", "/abc/def"},
	CleanTest{"abc/.", "abc"},

	// Remove .. elements
	CleanTest{"abc/def/ghi/../jkl", "abc/def/jkl"},
	CleanTest{"abc/def/../ghi/../jkl", "abc/jkl"},
	CleanTest{"abc/def/..", "abc"},
	CleanTest{"abc/def/../..", "."},
	CleanTest{"/abc/def/../..", "/"},
	CleanTest{"abc/def/../../..", ".."},
	CleanTest{"/abc/def/../../..", "/"},
	CleanTest{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},

	// Combinations
	CleanTest{"abc/./../def", "def"},
	CleanTest{"abc//./../def", "def"},
	CleanTest{"abc/../../././../def", "../../def"},
}

func TestClean(t *testing.T) {
	for _, test := range cleantests {
		if s := Clean(test.path); s != test.clean {
			t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.clean)
		}
	}
}

type SplitTest struct {
	path, dir, file string;
}

var splittests = []SplitTest{
	SplitTest{"a/b", "a/", "b"},
	SplitTest{"a/b/", "a/b/", ""},
	SplitTest{"a/", "a/", ""},
	SplitTest{"a", "", "a"},
	SplitTest{"/", "/", ""},
}

func TestSplit(t *testing.T) {
	for _, test := range splittests {
		if d, f := Split(test.path); d != test.dir || f != test.file {
			t.Errorf("Split(%q) = %q, %q, want %q, %q", test.path, d, f, test.dir, test.file)
		}
	}
}

type JoinTest struct {
	dir, file, path string;
}

var jointests = []JoinTest{
	JoinTest{"a", "b", "a/b"},
	JoinTest{"a", "", "a"},
	JoinTest{"", "b", "b"},
	JoinTest{"/", "a", "/a"},
	JoinTest{"/", "", "/"},
	JoinTest{"a/", "b", "a/b"},
	JoinTest{"a/", "", "a"},
}

func TestJoin(t *testing.T) {
	for _, test := range jointests {
		if p := Join(test.dir, test.file); p != test.path {
			t.Errorf("Join(%q, %q) = %q, want %q", test.dir, test.file, p, test.path)
		}
	}
}

type ExtTest struct {
	path, ext string;
}

var exttests = []ExtTest{
	ExtTest{"path.go", ".go"},
	ExtTest{"path.pb.go", ".go"},
	ExtTest{"a.dir/b", ""},
	ExtTest{"a.dir/b.go", ".go"},
	ExtTest{"a.dir/", ""},
}

func TestExt(t *testing.T) {
	for _, test := range exttests {
		if x := Ext(test.path); x != test.ext {
			t.Errorf("Ext(%q) = %q, want %q", test.path, x, test.ext)
		}
	}
}

type Node struct {
	name	string;
	entries	[]*Node;	// nil if the entry is a file
	mark	int;
}

var tree = &Node{
	"testdata",
	[]*Node{
		&Node{"a", nil, 0},
		&Node{"b", []*Node{}, 0},
		&Node{"c", nil, 0},
		&Node{
			"d",
			[]*Node{
				&Node{"x", nil, 0},
				&Node{"y", []*Node{}, 0},
				&Node{
					"z",
					[]*Node{
						&Node{"u", nil, 0},
						&Node{"v", nil, 0},
					},
					0,
				},
			},
			0,
		},
	},
	0,
}

func walkTree(n *Node, path string, f func(path string, n *Node)) {
	f(path, n);
	for _, e := range n.entries {
		walkTree(e, Join(path, e.name), f)
	}
}

func makeTree(t *testing.T) {
	walkTree(tree, tree.name, func(path string, n *Node) {
		if n.entries == nil {
			fd, err := os.Open(path, os.O_CREAT, 0660);
			if err != nil {
				t.Errorf("makeTree: %v", err)
			}
			fd.Close();
		} else {
			os.Mkdir(path, 0770)
		}
	})
}

func markTree(n *Node)	{ walkTree(n, "", func(path string, n *Node) { n.mark++ }) }

func checkMarks(t *testing.T) {
	walkTree(tree, tree.name, func(path string, n *Node) {
		if n.mark != 1 {
			t.Errorf("node %s mark = %d; expected 1", path, n.mark)
		}
		n.mark = 0;
	})
}

// Assumes that each node name is unique. Good enough for a test.
func mark(name string) {
	walkTree(tree, tree.name, func(path string, n *Node) {
		if n.name == name {
			n.mark++
		}
	})
}

type TestVisitor struct{}

func (v *TestVisitor) VisitDir(path string, d *os.Dir) bool {
	mark(d.Name);
	return true;
}

func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
	mark(d.Name)
}

func TestWalk(t *testing.T) {
	makeTree(t);

	// 1) ignore error handling, expect none
	v := &TestVisitor{};
	Walk(tree.name, v, nil);
	checkMarks(t);

	// 2) handle errors, expect none
	errors := make(chan os.Error, 64);
	Walk(tree.name, v, errors);
	if err, ok := <-errors; ok {
		t.Errorf("no error expected, found: s", err)
	}
	checkMarks(t);

	// introduce 2 errors: chmod top-level directories to 0
	os.Chmod(Join(tree.name, tree.entries[1].name), 0);
	os.Chmod(Join(tree.name, tree.entries[3].name), 0);
	// mark respective subtrees manually
	markTree(tree.entries[1]);
	markTree(tree.entries[3]);
	// correct double-marking of directory itself
	tree.entries[1].mark--;
	tree.entries[3].mark--;

	// 3) handle errors, expect two
	errors = make(chan os.Error, 64);
	os.Chmod(Join(tree.name, tree.entries[1].name), 0);
	Walk(tree.name, v, errors);
	for i := 1; i <= 2; i++ {
		if _, ok := <-errors; !ok {
			t.Errorf("%d. error expected, none found", i);
			break;
		}
	}
	if err, ok := <-errors; ok {
		t.Errorf("only two errors expected, found 3rd: %v", err)
	}
	// the inaccessible subtrees were marked manually
	checkMarks(t);

	// cleanup
	os.Chmod(Join(tree.name, tree.entries[1].name), 0770);
	os.Chmod(Join(tree.name, tree.entries[3].name), 0770);
	if err := os.RemoveAll(tree.name); err != nil {
		t.Errorf("removeTree: %v", err)
	}
}
<commit_msg>path.TestWalk: disable error case if root (chmod 0 doesn't cause errors for root)<commit_after>// Copyright 2009 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.

package path

import (
	"os";
	"testing";
)

type CleanTest struct {
	path, clean string;
}

var cleantests = []CleanTest{
	// Already clean
	CleanTest{"", "."},
	CleanTest{"abc", "abc"},
	CleanTest{"abc/def", "abc/def"},
	CleanTest{"a/b/c", "a/b/c"},
	CleanTest{".", "."},
	CleanTest{"..", ".."},
	CleanTest{"../..", "../.."},
	CleanTest{"../../abc", "../../abc"},
	CleanTest{"/abc", "/abc"},
	CleanTest{"/", "/"},

	// Remove trailing slash
	CleanTest{"abc/", "abc"},
	CleanTest{"abc/def/", "abc/def"},
	CleanTest{"a/b/c/", "a/b/c"},
	CleanTest{"./", "."},
	CleanTest{"../", ".."},
	CleanTest{"../../", "../.."},
	CleanTest{"/abc/", "/abc"},

	// Remove doubled slash
	CleanTest{"abc//def//ghi", "abc/def/ghi"},
	CleanTest{"//abc", "/abc"},
	CleanTest{"///abc", "/abc"},
	CleanTest{"//abc//", "/abc"},
	CleanTest{"abc//", "abc"},

	// Remove . elements
	CleanTest{"abc/./def", "abc/def"},
	CleanTest{"/./abc/def", "/abc/def"},
	CleanTest{"abc/.", "abc"},

	// Remove .. elements
	CleanTest{"abc/def/ghi/../jkl", "abc/def/jkl"},
	CleanTest{"abc/def/../ghi/../jkl", "abc/jkl"},
	CleanTest{"abc/def/..", "abc"},
	CleanTest{"abc/def/../..", "."},
	CleanTest{"/abc/def/../..", "/"},
	CleanTest{"abc/def/../../..", ".."},
	CleanTest{"/abc/def/../../..", "/"},
	CleanTest{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},

	// Combinations
	CleanTest{"abc/./../def", "def"},
	CleanTest{"abc//./../def", "def"},
	CleanTest{"abc/../../././../def", "../../def"},
}

func TestClean(t *testing.T) {
	for _, test := range cleantests {
		if s := Clean(test.path); s != test.clean {
			t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.clean)
		}
	}
}

type SplitTest struct {
	path, dir, file string;
}

var splittests = []SplitTest{
	SplitTest{"a/b", "a/", "b"},
	SplitTest{"a/b/", "a/b/", ""},
	SplitTest{"a/", "a/", ""},
	SplitTest{"a", "", "a"},
	SplitTest{"/", "/", ""},
}

func TestSplit(t *testing.T) {
	for _, test := range splittests {
		if d, f := Split(test.path); d != test.dir || f != test.file {
			t.Errorf("Split(%q) = %q, %q, want %q, %q", test.path, d, f, test.dir, test.file)
		}
	}
}

type JoinTest struct {
	dir, file, path string;
}

var jointests = []JoinTest{
	JoinTest{"a", "b", "a/b"},
	JoinTest{"a", "", "a"},
	JoinTest{"", "b", "b"},
	JoinTest{"/", "a", "/a"},
	JoinTest{"/", "", "/"},
	JoinTest{"a/", "b", "a/b"},
	JoinTest{"a/", "", "a"},
}

func TestJoin(t *testing.T) {
	for _, test := range jointests {
		if p := Join(test.dir, test.file); p != test.path {
			t.Errorf("Join(%q, %q) = %q, want %q", test.dir, test.file, p, test.path)
		}
	}
}

type ExtTest struct {
	path, ext string;
}

var exttests = []ExtTest{
	ExtTest{"path.go", ".go"},
	ExtTest{"path.pb.go", ".go"},
	ExtTest{"a.dir/b", ""},
	ExtTest{"a.dir/b.go", ".go"},
	ExtTest{"a.dir/", ""},
}

func TestExt(t *testing.T) {
	for _, test := range exttests {
		if x := Ext(test.path); x != test.ext {
			t.Errorf("Ext(%q) = %q, want %q", test.path, x, test.ext)
		}
	}
}

type Node struct {
	name	string;
	entries	[]*Node;	// nil if the entry is a file
	mark	int;
}

var tree = &Node{
	"testdata",
	[]*Node{
		&Node{"a", nil, 0},
		&Node{"b", []*Node{}, 0},
		&Node{"c", nil, 0},
		&Node{
			"d",
			[]*Node{
				&Node{"x", nil, 0},
				&Node{"y", []*Node{}, 0},
				&Node{
					"z",
					[]*Node{
						&Node{"u", nil, 0},
						&Node{"v", nil, 0},
					},
					0,
				},
			},
			0,
		},
	},
	0,
}

func walkTree(n *Node, path string, f func(path string, n *Node)) {
	f(path, n);
	for _, e := range n.entries {
		walkTree(e, Join(path, e.name), f)
	}
}

func makeTree(t *testing.T) {
	walkTree(tree, tree.name, func(path string, n *Node) {
		if n.entries == nil {
			fd, err := os.Open(path, os.O_CREAT, 0660);
			if err != nil {
				t.Errorf("makeTree: %v", err)
			}
			fd.Close();
		} else {
			os.Mkdir(path, 0770)
		}
	})
}

func markTree(n *Node)	{ walkTree(n, "", func(path string, n *Node) { n.mark++ }) }

func checkMarks(t *testing.T) {
	walkTree(tree, tree.name, func(path string, n *Node) {
		if n.mark != 1 {
			t.Errorf("node %s mark = %d; expected 1", path, n.mark)
		}
		n.mark = 0;
	})
}

// Assumes that each node name is unique. Good enough for a test.
func mark(name string) {
	walkTree(tree, tree.name, func(path string, n *Node) {
		if n.name == name {
			n.mark++
		}
	})
}

type TestVisitor struct{}

func (v *TestVisitor) VisitDir(path string, d *os.Dir) bool {
	mark(d.Name);
	return true;
}

func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
	mark(d.Name)
}

func TestWalk(t *testing.T) {
	makeTree(t);

	// 1) ignore error handling, expect none
	v := &TestVisitor{};
	Walk(tree.name, v, nil);
	checkMarks(t);

	// 2) handle errors, expect none
	errors := make(chan os.Error, 64);
	Walk(tree.name, v, errors);
	if err, ok := <-errors; ok {
		t.Errorf("no error expected, found: s", err)
	}
	checkMarks(t);

	if os.Getuid() != 0 {
		// introduce 2 errors: chmod top-level directories to 0
		os.Chmod(Join(tree.name, tree.entries[1].name), 0);
		os.Chmod(Join(tree.name, tree.entries[3].name), 0);
		// mark respective subtrees manually
		markTree(tree.entries[1]);
		markTree(tree.entries[3]);
		// correct double-marking of directory itself
		tree.entries[1].mark--;
		tree.entries[3].mark--;

		// 3) handle errors, expect two
		errors = make(chan os.Error, 64);
		os.Chmod(Join(tree.name, tree.entries[1].name), 0);
		Walk(tree.name, v, errors);
		for i := 1; i <= 2; i++ {
			if _, ok := <-errors; !ok {
				t.Errorf("%d. error expected, none found", i);
				break;
			}
		}
		if err, ok := <-errors; ok {
			t.Errorf("only two errors expected, found 3rd: %v", err)
		}
		// the inaccessible subtrees were marked manually
		checkMarks(t);
	}

	// cleanup
	os.Chmod(Join(tree.name, tree.entries[1].name), 0770);
	os.Chmod(Join(tree.name, tree.entries[3].name), 0770);
	if err := os.RemoveAll(tree.name); err != nil {
		t.Errorf("removeTree: %v", err)
	}
}
<|endoftext|>