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

package storage_test

import (
	"io/ioutil"
	"log"
	"net/http"
	"testing"

	"github.com/golang/oauth2"
	"github.com/golang/oauth2/google"
	"google.golang.org/cloud"
	"google.golang.org/cloud/storage"
)

// TODO(jbd): Remove after Go 1.4.
// Related to https://codereview.appspot.com/107320046
func TestA(t *testing.T) {}

func Example_auth() {
	// Initialize an authorized transport with Google Developers Console
	// JSON key. Read the google package examples to learn more about
	// different authorization flows you can use.
	// http://godoc.org/github.com/golang/oauth2/google
	f, err := oauth2.New(
		google.ServiceAccountJSONKey("/path/to/json/keyfile.json"),
		oauth2.Scope(storage.ScopeFullControl),
	)
	if err != nil {
		log.Fatal(err)
	}

	ctx := cloud.NewContext("project-id", &http.Client{Transport: f.NewTransport()})
	_ = ctx // Use the context (see other examples)
}

func Example_listObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	var query *storage.Query
	for {
		// If you are using this package on App Engine Managed VMs runtime,
		// you can init a bucket client with your app's default bucket name.
		// See http://godoc.org/google.golang.org/appengine/file#DefaultBucketName.
		objects, err := storage.ListObjects(ctx, "bucketname", query)
		if err != nil {
			log.Fatal(err)
		}
		for _, obj := range objects.Results {
			log.Printf("object name: %s, size: %v", obj.Name, obj.Size)
		}
		// if there are more results, objects.Next
		// will be non-nil.
		query = objects.Next
		if query == nil {
			break
		}
	}

	log.Println("paginated through all object items in the bucket you specified.")
}

func Example_readObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	rc, err := storage.NewReader(ctx, "bucketname", "filename1")
	if err != nil {
		log.Fatal(err)
	}
	slurp, err := ioutil.ReadAll(rc)
	rc.Close()
	if err != nil {
		log.Fatal(err)
	}

	log.Println("file contents:", slurp)
}

func Example_writeObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	wc := storage.NewWriter(ctx, "bucketname", "filename1", &storage.Object{
		ContentType: "text/plain",
		ACL:         []storage.ACLRule{storage.ACLRule{"allUsers", storage.RoleReader}}, // Shared Publicly
	})
	if _, err := wc.Write([]byte("hello world")); err != nil {
		log.Fatal(err)
	}
	if err := wc.Close(); err != nil {
		log.Fatal(err)
	}

	o, err := wc.Object()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("updated object:", o)
}

func Example_touchObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	o, err := storage.PutObject(ctx, "bucketname", "filename", &storage.Object{
		ContentType: "text/plain",
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Println("touched new file:", o)
}

func Example_copyObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	o, err := storage.CopyObject(ctx, "bucketname", "file1", &storage.Object{
		Name:   "file2",
		Bucket: "yet-another-bucketname",
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Println("copied file:", o)
}
<commit_msg>cloud/storage: Remove the obsolete object touching example<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage_test

import (
	"io/ioutil"
	"log"
	"net/http"
	"testing"

	"github.com/golang/oauth2"
	"github.com/golang/oauth2/google"
	"google.golang.org/cloud"
	"google.golang.org/cloud/storage"
)

// TODO(jbd): Remove after Go 1.4.
// Related to https://codereview.appspot.com/107320046
func TestA(t *testing.T) {}

func Example_auth() {
	// Initialize an authorized transport with Google Developers Console
	// JSON key. Read the google package examples to learn more about
	// different authorization flows you can use.
	// http://godoc.org/github.com/golang/oauth2/google
	f, err := oauth2.New(
		google.ServiceAccountJSONKey("/path/to/json/keyfile.json"),
		oauth2.Scope(storage.ScopeFullControl),
	)
	if err != nil {
		log.Fatal(err)
	}

	ctx := cloud.NewContext("project-id", &http.Client{Transport: f.NewTransport()})
	_ = ctx // Use the context (see other examples)
}

func Example_listObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	var query *storage.Query
	for {
		// If you are using this package on App Engine Managed VMs runtime,
		// you can init a bucket client with your app's default bucket name.
		// See http://godoc.org/google.golang.org/appengine/file#DefaultBucketName.
		objects, err := storage.ListObjects(ctx, "bucketname", query)
		if err != nil {
			log.Fatal(err)
		}
		for _, obj := range objects.Results {
			log.Printf("object name: %s, size: %v", obj.Name, obj.Size)
		}
		// if there are more results, objects.Next
		// will be non-nil.
		query = objects.Next
		if query == nil {
			break
		}
	}

	log.Println("paginated through all object items in the bucket you specified.")
}

func Example_readObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	rc, err := storage.NewReader(ctx, "bucketname", "filename1")
	if err != nil {
		log.Fatal(err)
	}
	slurp, err := ioutil.ReadAll(rc)
	rc.Close()
	if err != nil {
		log.Fatal(err)
	}

	log.Println("file contents:", slurp)
}

func Example_writeObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	wc := storage.NewWriter(ctx, "bucketname", "filename1", &storage.Object{
		ContentType: "text/plain",
		ACL:         []storage.ACLRule{storage.ACLRule{"allUsers", storage.RoleReader}}, // Shared Publicly
	})
	if _, err := wc.Write([]byte("hello world")); err != nil {
		log.Fatal(err)
	}
	if err := wc.Close(); err != nil {
		log.Fatal(err)
	}

	o, err := wc.Object()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("updated object:", o)
}

func Example_copyObjects() {
	// see the auth example how to initiate a context.
	ctx := cloud.NewContext("project-id", &http.Client{Transport: nil})

	o, err := storage.CopyObject(ctx, "bucketname", "file1", &storage.Object{
		Name:   "file2",
		Bucket: "yet-another-bucketname",
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Println("copied file:", o)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/jh-bate/fantail-bot/Godeps/_workspace/src/github.com/tucnak/telebot"
	"github.com/jh-bate/fantail-bot/lib"
)

const (
	//commands
	yostart_command = "/hey"
	yobg_command    = "/bg"
	yolow_command   = "/low"

	typing_action = "typing"
)

type (
	fantailBot struct {
		bot *telebot.Bot
		*running
	}

	running struct {
		Parts lib.Parts
		Name  string
	}
)

func newFantailBot() *fantailBot {
	botToken := os.Getenv("BOT_TOKEN")

	if botToken == "" {
		log.Fatal("$BOT_TOKEN must be set")
	}

	bot, err := telebot.NewBot(botToken)
	if err != nil {
		return nil
	}
	return &fantailBot{bot: bot}
}

func (this *fantailBot) showOptions(usr telebot.User) {
	this.bot.SendMessage(
		usr,
		fmt.Sprintf("Hey %s", usr.FirstName),
		nil)
	this.bot.SendMessage(
		usr,
		"Sorry but at this time you can only choose from the options below ...",
		nil)
	this.bot.SendMessage(
		usr,
		fmt.Sprintf("Select one and we can get this party started!"),
		&telebot.SendOptions{
			ReplyMarkup: telebot.ReplyMarkup{
				ForceReply: false,
				CustomKeyboard: [][]string{
					[]string{yobg_command},
					[]string{yolow_command},
				},
				ResizeKeyboard:  false,
				OneTimeKeyboard: false,
			},
		})
	return
}

func (this *fantailBot) setRunning(p lib.Parts, n string) {
	this.running = &running{Parts: p, Name: n}
	return
}

func (this *fantailBot) isRunning(name string) bool {
	return this.running != nil && this.running.Name == name
}

func main() {

	fBot := newFantailBot()
	messages := make(chan telebot.Message)
	fBot.bot.Listen(messages, 1*time.Second)

	for msg := range messages {

		log.Println("incoming ...", msg.Text)

		if strings.Contains(msg.Text, yobg_command) || fBot.isRunning(yobg_command) {
			if fBot.isRunning(yobg_command) == false {
				fBot.setRunning(
					lib.NewBg(&lib.Details{Bot: fBot.bot, User: msg.Chat}).GetParts(),
					yobg_command,
				)
			}
			lib.Run(msg, fBot.running.Parts)
		} else if strings.Contains(msg.Text, yolow_command) || fBot.isRunning(yolow_command) {
			if fBot.isRunning(yolow_command) == false {
				fBot.setRunning(
					lib.NewLow(&lib.Details{Bot: fBot.bot, User: msg.Chat}).GetParts(),
					yolow_command,
				)
			}
			lib.Run(msg, fBot.running.Parts)
		} else {
			fBot.showOptions(msg.Chat)
		}
	}

}
<commit_msg>reset when starting new process<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/jh-bate/fantail-bot/Godeps/_workspace/src/github.com/tucnak/telebot"
	"github.com/jh-bate/fantail-bot/lib"
)

const (
	//commands
	yostart_command = "/hey"
	yobg_command    = "/bg"
	yolow_command   = "/low"

	typing_action = "typing"
)

type (
	fantailBot struct {
		bot *telebot.Bot
		*running
	}

	running struct {
		Parts lib.Parts
		Name  string
	}
)

func newFantailBot() *fantailBot {
	botToken := os.Getenv("BOT_TOKEN")

	if botToken == "" {
		log.Fatal("$BOT_TOKEN must be set")
	}

	bot, err := telebot.NewBot(botToken)
	if err != nil {
		return nil
	}
	return &fantailBot{bot: bot}
}

func (this *fantailBot) showOptions(usr telebot.User) {
	this.bot.SendMessage(
		usr,
		fmt.Sprintf("Hey %s", usr.FirstName),
		nil)
	this.bot.SendMessage(
		usr,
		"Sorry but at this time you can only choose from the options below ...",
		nil)
	this.bot.SendMessage(
		usr,
		fmt.Sprintf("Select one and we can get this party started!"),
		&telebot.SendOptions{
			ReplyMarkup: telebot.ReplyMarkup{
				ForceReply: false,
				CustomKeyboard: [][]string{
					[]string{yobg_command},
					[]string{yolow_command},
				},
				ResizeKeyboard:  false,
				OneTimeKeyboard: false,
			},
		})
	return
}

func (this *fantailBot) setRunning(p lib.Parts, n string) {
	this.running = &running{Parts: p, Name: n}
	return
}

func (this *fantailBot) isRunning() bool {
	return this.running != nil && len(this.running.Parts) > 0
}

func (this *fantailBot) startLow(usr telebot.User) {
	log.Println("init LOW setup")
	this.running = nil
	this.setRunning(
		lib.NewLow(&lib.Details{Bot: this.bot, User: usr}).GetParts(),
		yolow_command,
	)
}

func (this *fantailBot) startBg(usr telebot.User) {
	log.Println("init BG setup")
	this.running = nil
	this.setRunning(
		lib.NewBg(&lib.Details{Bot: this.bot, User: usr}).GetParts(),
		yobg_command,
	)
}

func main() {

	fBot := newFantailBot()
	messages := make(chan telebot.Message)
	fBot.bot.Listen(messages, 1*time.Second)

	for msg := range messages {

		log.Println("incoming ...", msg.Text)

		if strings.Contains(msg.Text, yobg_command) {
			fBot.startBg(msg.Chat)
		} else if strings.Contains(msg.Text, yolow_command) {
			fBot.startLow(msg.Chat)
		}
		if fBot.isRunning() {
			lib.Run(msg, fBot.running.Parts)
		}
	}

}
<|endoftext|>


<commit_before>package gform

import (
    "unsafe"
    "w32"
    "w32/user32"
)

type Dialog struct {
    Form

    isModal  bool
    template *uint16

    Data interface{}

    onLoad         EventManager
    onOK, onCancel EventManager
}

func NewDialogFromResId(parent Controller, resId uint) *Dialog {
    d := new(Dialog)

    d.isForm = true
    d.isModal = false
    d.template = w32.MakeIntResource(uint16(resId))

    d.OnOK().Attach(dlg_OnOK)
    d.OnCancel().Attach(dlg_OnCancel)

    if parent != nil {
        d.parent = parent
    }

    return d
}

// internal event handlers
func dlg_OnOK(arg *EventArg) {
    if d, ok := arg.Sender().(*Dialog); ok {
        d.Close(w32.IDOK)
    }
}

func dlg_OnCancel(arg *EventArg) {
    if d, ok := arg.Sender().(*Dialog); ok {
        d.Close(w32.IDCANCEL)
    }
}

// Events
func (this *Dialog) OnLoad() *EventManager {
    return &this.onLoad
}

func (this *Dialog) OnOK() *EventManager {
    return &this.onOK
}

func (this *Dialog) OnCancel() *EventManager {
    return &this.onCancel
}

// Public methods
func (this *Dialog) Show() {
    this.ShowWithData(nil)
}

func (this *Dialog) ShowModal() int {
    return this.ShowModalWithData(nil)
}

func (this *Dialog) ShowWithData(data interface{}) {
    var parentHwnd w32.HWND
    if this.Parent() != nil {
        parentHwnd = this.Parent().Handle()
    }

    gDialogWaiting = this
    this.hwnd = user32.CreateDialog(GetAppInstance(), this.template, parentHwnd, GeneralWndprocCallBack)
    this.Data = data
    if ico, err := NewIconFromResource(GetAppInstance(), 101); err == nil {
        this.SetIcon(0, ico)
    }
    this.Form.Show()
}

func (this *Dialog) ShowModalWithData(data interface{}) (result int) {
    this.isModal = true
    this.Data = data

    var parentHwnd w32.HWND
    if this.Parent() != nil {
        parentHwnd = this.Parent().Handle()
    }

    gDialogWaiting = this
    if result = user32.DialogBox(GetAppInstance(), this.template, parentHwnd, GeneralWndprocCallBack); result == -1 {
        panic("Failed to create modal dialog box")
    }

    return result
}

func (this *Dialog) Close(result int) {
    this.onClose.Fire(NewEventArg(this, nil))

    if this.isModal {
        user32.EndDialog(this.hwnd, uintptr(result))
    } else {
        user32.DestroyWindow(this.hwnd)
    }

    UnRegMsgHandler(this.hwnd)
}

func (this *Dialog) PreTranslateMessage(msg *w32.MSG) bool {
    if msg.Message >= w32.WM_KEYFIRST && msg.Message <= w32.WM_KEYLAST {
        if !this.isModal && user32.IsDialogMessage(this.hwnd, msg) {
            return true
        }
    }

    return false
}

func (this *Dialog) WndProc(msg uint, wparam, lparam uintptr) uintptr {
    switch msg {
    case w32.WM_INITDIALOG:
        gDialogWaiting = nil
        this.onLoad.Fire(NewEventArg(this, nil))
    case w32.WM_NOTIFY:
        nm := (*w32.NMHDR)(unsafe.Pointer(lparam))
        if msgHandler := GetMsgHandler(nm.HwndFrom); msgHandler != nil {
            ret := msgHandler.WndProc(msg, wparam, lparam)
            if ret != 0 {
                user32.SetWindowLong(this.hwnd, w32.DWL_MSGRESULT, uint32(ret))
                return w32.TRUE
            }
        }
    case w32.WM_COMMAND:
        if lparam != 0 { //Reflict message to control
            h := w32.HWND(lparam)
            if msgHandler := GetMsgHandler(h); msgHandler != nil {
                ret := msgHandler.WndProc(msg, wparam, lparam)
                if ret != 0 {
                    user32.SetWindowLong(this.hwnd, w32.DWL_MSGRESULT, uint32(ret))
                    return w32.TRUE
                }
            }
        }
        switch w32.LOWORD(uint(wparam)) {
        case w32.IDOK:
            this.onOK.Fire(NewEventArg(this, nil))
            return w32.TRUE
        case w32.IDCANCEL:
            this.onCancel.Fire(NewEventArg(this, nil))
            return w32.TRUE
        }
    case w32.WM_DESTROY:
        if this.parent == nil {
            Exit()
        }
    }
    return w32.FALSE
}
<commit_msg>Process WM_CLOSE for dialog.<commit_after>package gform

import (
    "unsafe"
    "w32"
    "w32/user32"
)

type Dialog struct {
    Form

    isModal  bool
    template *uint16

    Data interface{}

    onLoad         EventManager
    onOK, onCancel EventManager
}

func NewDialogFromResId(parent Controller, resId uint) *Dialog {
    d := new(Dialog)

    d.isForm = true
    d.isModal = false
    d.template = w32.MakeIntResource(uint16(resId))

    d.OnOK().Attach(dlg_OnOK)
    d.OnCancel().Attach(dlg_OnCancel)

    if parent != nil {
        d.parent = parent
    }

    return d
}

// internal event handlers
func dlg_OnOK(arg *EventArg) {
    if d, ok := arg.Sender().(*Dialog); ok {
        d.Close(w32.IDOK)
    }
}

func dlg_OnCancel(arg *EventArg) {
    if d, ok := arg.Sender().(*Dialog); ok {
        d.Close(w32.IDCANCEL)
    }
}

// Events
func (this *Dialog) OnLoad() *EventManager {
    return &this.onLoad
}

func (this *Dialog) OnOK() *EventManager {
    return &this.onOK
}

func (this *Dialog) OnCancel() *EventManager {
    return &this.onCancel
}

// Public methods
func (this *Dialog) Show() {
    this.ShowWithData(nil)
}

func (this *Dialog) ShowModal() int {
    return this.ShowModalWithData(nil)
}

func (this *Dialog) ShowWithData(data interface{}) {
    var parentHwnd w32.HWND
    if this.Parent() != nil {
        parentHwnd = this.Parent().Handle()
    }

    gDialogWaiting = this
    this.hwnd = user32.CreateDialog(GetAppInstance(), this.template, parentHwnd, GeneralWndprocCallBack)
    this.Data = data
    if ico, err := NewIconFromResource(GetAppInstance(), 101); err == nil {
        this.SetIcon(0, ico)
    }
    this.Form.Show()
}

func (this *Dialog) ShowModalWithData(data interface{}) (result int) {
    this.isModal = true
    this.Data = data

    var parentHwnd w32.HWND
    if this.Parent() != nil {
        parentHwnd = this.Parent().Handle()
    }

    gDialogWaiting = this
    if result = user32.DialogBox(GetAppInstance(), this.template, parentHwnd, GeneralWndprocCallBack); result == -1 {
        panic("Failed to create modal dialog box")
    }

    return result
}

func (this *Dialog) Close(result int) {
    this.onClose.Fire(NewEventArg(this, nil))

    if this.isModal {
        user32.EndDialog(this.hwnd, uintptr(result))
    } else {
        user32.DestroyWindow(this.hwnd)
    }

    UnRegMsgHandler(this.hwnd)
}

func (this *Dialog) PreTranslateMessage(msg *w32.MSG) bool {
    if msg.Message >= w32.WM_KEYFIRST && msg.Message <= w32.WM_KEYLAST {
        if !this.isModal && user32.IsDialogMessage(this.hwnd, msg) {
            return true
        }
    }

    return false
}

func (this *Dialog) WndProc(msg uint, wparam, lparam uintptr) uintptr {
    switch msg {
    case w32.WM_INITDIALOG:
        gDialogWaiting = nil
        this.onLoad.Fire(NewEventArg(this, nil))
    case w32.WM_NOTIFY:
        nm := (*w32.NMHDR)(unsafe.Pointer(lparam))
        if msgHandler := GetMsgHandler(nm.HwndFrom); msgHandler != nil {
            ret := msgHandler.WndProc(msg, wparam, lparam)
            if ret != 0 {
                user32.SetWindowLong(this.hwnd, w32.DWL_MSGRESULT, uint32(ret))
                return w32.TRUE
            }
        }
    case w32.WM_COMMAND:
        if lparam != 0 { //Reflict message to control
            h := w32.HWND(lparam)
            if msgHandler := GetMsgHandler(h); msgHandler != nil {
                ret := msgHandler.WndProc(msg, wparam, lparam)
                if ret != 0 {
                    user32.SetWindowLong(this.hwnd, w32.DWL_MSGRESULT, uint32(ret))
                    return w32.TRUE
                }
            }
        }
        switch w32.LOWORD(uint(wparam)) {
        case w32.IDOK:
            this.onOK.Fire(NewEventArg(this, nil))
            return w32.TRUE
        case w32.IDCANCEL:
            this.onCancel.Fire(NewEventArg(this, nil))
            return w32.TRUE
        }
    case w32.WM_CLOSE:
        this.Close(w32.IDCANCEL)
    case w32.WM_DESTROY:
        if this.parent == nil {
            Exit()
        }
    }
    return w32.FALSE
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"log"
	"net/url"
	"os"
	"strings"
)

var (
	EcAsics = []string{"http://www.asics.com/gb/en-gb", "http://www.asics.com/fr/fr-fr", "http://www.asics.com/es/es-es", "http://www.asics.com/it/it-it"}

	NoEcAsics = []string{"https://www.asics.co.za/", "https://www.asics.pl", "https://de.asics.ch"}
)

type ParseData struct {
	Locale string
	Header []Link
	Footer []Link
}

type Link struct {
	Title string
	Url   string
	Index int
	img   string
	Items []ItemLink
}

type ItemLink struct {
	Title string
	Url   string
	Index int
	img   string
}

func ParseECHtml(url_string string) {

	target_url, _ := url.Parse(url_string)
	doc, err := goquery.NewDocument(url_string)
	if err != nil {
		log.Fatal(err)
	}

	parsedata := ParseData{
		Locale: strings.Split(target_url.Path, "/")[2],
	}

	//parse the header
	// doc.Find("header #main-menu").Children().Each(func(i int, s *goquery.Selection) {

	//parse the footer
	doc.Find("footer").Children().Filter(".tiger-clearfix-toggle").Each(func(i int, s *goquery.Selection) {
		link := Link{
			Title: s.Children().Filter("h4").First().Text(),
			Url:   "#",
			Index: i + 1,
			img:   "",
		}

		s.Children().Filter("ul").Children().Each(func(i int, s *goquery.Selection) {
			itemlink := ItemLink{
				Title: s.Children().First().Text(),
				Url:   target_url.Scheme + "://" + target_url.Host + s.Children().First().AttrOr("href", "#"),
				Index: i + 1,
			}
			link.Items = append(link.Items, itemlink)
		})
		parsedata.Footer = append(parsedata.Footer, link)
	})

	jsondata, _ := json.Marshal(parsedata)

	file, _ := os.OpenFile(strings.Split(target_url.Path, "/")[2]+".json", os.O_WRONLY|os.O_CREATE, 0666)
	file.Write(jsondata)

	fmt.Println(string(jsondata))

}

func ParseNoECHtml(url_string string) {

	target_url, _ := url.Parse(url_string)
	doc, err := goquery.NewDocument(url_string)
	if err != nil {
		log.Fatal(err)
	}

	locale := strings.Split(target_url.Host, ".")[0] + "-" + strings.Split(target_url.Host, ".")[2]
	parsedata := ParseData{
		Locale: locale,
	}

	//parse the footer
	doc.Find(".footer section").Children().Each(func(i int, s *goquery.Selection) {
		link := Link{
			Title: s.Children().Filter("h4").First().Text(),
			Url:   "#",
			Index: i + 1,
			img:   "",
		}

		s.Children().Filter("ul").Children().Each(func(i int, s *goquery.Selection) {
			itemlink := ItemLink{
				Title: s.Children().First().Text(),
				Url:   target_url.Scheme + "://" + target_url.Host + s.Children().First().AttrOr("href", "#"),
				Index: i + 1,
			}
			link.Items = append(link.Items, itemlink)
		})
		parsedata.Footer = append(parsedata.Footer, link)
	})

	jsondata, _ := json.Marshal(parsedata)

	file, _ := os.OpenFile(locale, os.O_WRONLY|os.O_CREATE, 0666)
	file.Write(jsondata)

	fmt.Println(string(jsondata))

}

func main() {
	for _, url := range EcAsics {
		ParseECHtml(url)
	}
	for _, url := range NoEcAsics {
		ParseNoECHtml(url)
	}
}
<commit_msg>modify the img to exportable<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"log"
	"net/url"
	"os"
	"strings"
)

var (
	EcAsics = []string{"http://www.asics.com/gb/en-gb", "http://www.asics.com/fr/fr-fr", "http://www.asics.com/es/es-es", "http://www.asics.com/it/it-it"}

	NoEcAsics = []string{"https://www.asics.co.za/", "https://www.asics.pl", "https://de.asics.ch"}
)

type ParseData struct {
	Locale string
	Header []Link
	Footer []Link
}

type Link struct {
	Title string
	Url   string
	Index int
	Img   string
	Items []ItemLink
}

type ItemLink struct {
	Title string
	Url   string
	Index int
	Img   string
}

func ParseECHtml(url_string string) {

	target_url, _ := url.Parse(url_string)
	doc, err := goquery.NewDocument(url_string)
	if err != nil {
		log.Fatal(err)
	}

	parsedata := ParseData{
		Locale: strings.Split(target_url.Path, "/")[2],
	}

	//parse the header
	// doc.Find("header #main-menu").Children().Each(func(i int, s *goquery.Selection) {

	//parse the footer
	doc.Find("footer").Children().Filter(".tiger-clearfix-toggle").Each(func(i int, s *goquery.Selection) {
		link := Link{
			Title: s.Children().Filter("h4").First().Text(),
			Url:   "#",
			Index: i + 1,
			img:   "",
		}

		s.Children().Filter("ul").Children().Each(func(i int, s *goquery.Selection) {
			itemlink := ItemLink{
				Title: s.Children().First().Text(),
				Url:   target_url.Scheme + "://" + target_url.Host + s.Children().First().AttrOr("href", "#"),
				Index: i + 1,
			}
			link.Items = append(link.Items, itemlink)
		})
		parsedata.Footer = append(parsedata.Footer, link)
	})

	jsondata, _ := json.Marshal(parsedata)

	file, _ := os.OpenFile(strings.Split(target_url.Path, "/")[2]+".json", os.O_WRONLY|os.O_CREATE, 0666)
	file.Write(jsondata)

	fmt.Println(string(jsondata))

}

func ParseNoECHtml(url_string string) {

	target_url, _ := url.Parse(url_string)
	doc, err := goquery.NewDocument(url_string)
	if err != nil {
		log.Fatal(err)
	}

	locale := strings.Split(target_url.Host, ".")[0] + "-" + strings.Split(target_url.Host, ".")[2]
	parsedata := ParseData{
		Locale: locale,
	}

	//parse the footer
	doc.Find(".footer section").Children().Each(func(i int, s *goquery.Selection) {
		link := Link{
			Title: s.Children().Filter("h4").First().Text(),
			Url:   "#",
			Index: i + 1,
			img:   "",
		}

		s.Children().Filter("ul").Children().Each(func(i int, s *goquery.Selection) {
			itemlink := ItemLink{
				Title: s.Children().First().Text(),
				Url:   target_url.Scheme + "://" + target_url.Host + s.Children().First().AttrOr("href", "#"),
				Index: i + 1,
			}
			link.Items = append(link.Items, itemlink)
		})
		parsedata.Footer = append(parsedata.Footer, link)
	})

	jsondata, _ := json.Marshal(parsedata)

	file, _ := os.OpenFile(locale, os.O_WRONLY|os.O_CREATE, 0666)
	file.Write(jsondata)

	fmt.Println(string(jsondata))

}

func main() {
	for _, url := range EcAsics {
		ParseECHtml(url)
	}
	for _, url := range NoEcAsics {
		ParseNoECHtml(url)
	}
}
<|endoftext|>


<commit_before>//
// repos.go
// Copyright (C) 2016 datawolf <datawolf@datawolf-Lenovo-G460>
//
// Distributed under terms of the MIT license.
//

package index

import (
	"bytes"
	"fmt"

	qs "github.com/google/go-querystring/query"
)

// RepositoriesService handles communication with the repository related
// methods of the rnd-dockerhub API
type RepositoriesService struct {
	client *Client
}

// Repository represents a rmd-dockerhub repository
type Repository struct {
	Description *string `json:"description,omitempty"`
	IsOfficial  *bool   `json:"is_official,omitempty"`
	IsTrusted   *bool   `json:"is_trusted,omitempty"`
	Name        *string `json:"name,omitempty"`
	StarCount   *int    `json:"star_count,omitempty"`
}

func (r Repository) String() string {
	return Stringify(r)
}

type Image struct {
	Tag  *string `json:"tag,omitempty"`
	Size *int    `json:"size,omitempty"`
}

func (i Image) String() string {
	return Stringify(i)
}

// Property represents a rund-dockerhub repo's property
type Property struct {
	NumberDL    *int    `json:"download_num,omitempty"`
	ImageList   []Image `json:"image_list,omitempty"`
	NumberImage *int    `json:"image_num,omitempty"`
	Property    *string `json:"property,omitempty"`
	RepoName    *string `json:"repo,omitempty"`
	Size        *int    `json:"size,omitempty"`
}

func (s *RepositoriesService) Get(repo string) (*Property, *Response, error) {
	result := new(Property)
	u := fmt.Sprintf("/index/repositories/%s/properties", repo)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return result, nil, err
	}
	resp, err := s.client.Do(req, result)
	return result, resp, err
}

func (s *RepositoriesService) Set(repo string, property *Property) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/properties", repo)
	req, err := s.client.NewRequest("PUT", u, property)
	if err != nil {
		return "", nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return "", nil, err
	}

	return "SUCCESS", resp, nil
}

type RepoDesc struct {
	Description string `json:"description,omitempty"`
}

func (s *RepositoriesService) GetRepoDesc(repo string) (*RepoDesc, *Response, error) {
	result := new(RepoDesc)
	u := fmt.Sprintf("/index/repositories/%s/description", repo)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return result, nil, err
	}
	resp, err := s.client.Do(req, result)
	return result, resp, err
}

func (s *RepositoriesService) SetRepoDesc(repo string, repoDesc *RepoDesc) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/description", repo)
	req, err := s.client.NewRequest("PUT", u, property)
	if err != nil {
		return "", nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return "", nil, err
	}

	return "SUCCESS", resp, nil
}

func (s *RepositoriesService) DeleteRepo(repo string) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/entirety", repo)
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return "", nil, err
	}

	buf := new(bytes.Buffer)
	resp, err := s.client.Do(req, buf)
	if err != nil {
		return "", err
	}

	return buf.String(), resp, nil
}

func (s *RepositoriesService) DeleteTag(repo string, tag string) (string, *Response, error) {
	params, err := qs.Values(nil)
	if err != nil {
		return nil, err
	}
	params.Add("tag", tag)
	u := fmt.Sprintf("/index/repositories/%s/tag?%s", repo, params.Encode())
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return "", nil, err
	}

	buf := new(bytes.Buffer)
	resp, err := s.client.Do(req, buf)
	if err != nil {
		return "", err
	}

	return buf.String(), resp, nil
}
<commit_msg>fix the return error<commit_after>//
// repos.go
// Copyright (C) 2016 datawolf <datawolf@datawolf-Lenovo-G460>
//
// Distributed under terms of the MIT license.
//

package index

import (
	"bytes"
	"fmt"

	qs "github.com/google/go-querystring/query"
)

// RepositoriesService handles communication with the repository related
// methods of the rnd-dockerhub API
type RepositoriesService struct {
	client *Client
}

// Repository represents a rmd-dockerhub repository
type Repository struct {
	Description *string `json:"description,omitempty"`
	IsOfficial  *bool   `json:"is_official,omitempty"`
	IsTrusted   *bool   `json:"is_trusted,omitempty"`
	Name        *string `json:"name,omitempty"`
	StarCount   *int    `json:"star_count,omitempty"`
}

func (r Repository) String() string {
	return Stringify(r)
}

type Image struct {
	Tag  *string `json:"tag,omitempty"`
	Size *int    `json:"size,omitempty"`
}

func (i Image) String() string {
	return Stringify(i)
}

// Property represents a rund-dockerhub repo's property
type Property struct {
	NumberDL    *int    `json:"download_num,omitempty"`
	ImageList   []Image `json:"image_list,omitempty"`
	NumberImage *int    `json:"image_num,omitempty"`
	Property    *string `json:"property,omitempty"`
	RepoName    *string `json:"repo,omitempty"`
	Size        *int    `json:"size,omitempty"`
}

func (s *RepositoriesService) Get(repo string) (*Property, *Response, error) {
	result := new(Property)
	u := fmt.Sprintf("/index/repositories/%s/properties", repo)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return result, nil, err
	}
	resp, err := s.client.Do(req, result)
	return result, resp, err
}

func (s *RepositoriesService) Set(repo string, property *Property) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/properties", repo)
	req, err := s.client.NewRequest("PUT", u, property)
	if err != nil {
		return "", nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return "", nil, err
	}

	return "SUCCESS", resp, nil
}

type RepoDesc struct {
	Description string `json:"description,omitempty"`
}

func (s *RepositoriesService) GetRepoDesc(repo string) (*RepoDesc, *Response, error) {
	result := new(RepoDesc)
	u := fmt.Sprintf("/index/repositories/%s/description", repo)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return result, nil, err
	}
	resp, err := s.client.Do(req, result)
	return result, resp, err
}

func (s *RepositoriesService) SetRepoDesc(repo string, repoDesc *RepoDesc) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/description", repo)
	req, err := s.client.NewRequest("PUT", u, repoDesc)
	if err != nil {
		return "", nil, err
	}
	req.Header.Add("Content-Type", "application/json")

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return "", nil, err
	}

	return "SUCCESS", resp, nil
}

func (s *RepositoriesService) DeleteRepo(repo string) (string, *Response, error) {
	u := fmt.Sprintf("/index/repositories/%s/entirety", repo)
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return "", nil, err
	}

	buf := new(bytes.Buffer)
	resp, err := s.client.Do(req, buf)
	if err != nil {
		return "", resp, err
	}

	return buf.String(), resp, nil
}

func (s *RepositoriesService) DeleteTag(repo string, tag string) (string, *Response, error) {
	params, err := qs.Values(nil)
	if err != nil {
		return "", nil, err
	}
	params.Add("tag", tag)
	u := fmt.Sprintf("/index/repositories/%s/tag?%s", repo, params.Encode())
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return "", nil, err
	}

	buf := new(bytes.Buffer)
	resp, err := s.client.Do(req, buf)
	if err != nil {
		return "", resp, err
	}

	return buf.String(), resp, nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gorilla/websocket"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"log"
	"encoding/json"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"flag"
	"github.com/coreos/go-etcd/etcd"
)

var kubernetesEndpoint string
var etcdAddress string

type Registration struct {
	URL string
}

func init() {
	flag.StringVar(&kubernetesEndpoint, "pods", "", "Endpoint of Kubernetes pods API")
	flag.StringVar(&etcdAddress, "etcd", "", "etcd address")

	flag.Parse()
}

func main() {
	listenForPods()
}

func listenForPods() {

	wsConn := openConnection()

	var wsErrors chan string = make(chan string)

	go listen(wsConn, wsErrors)
	go reconnector(wsErrors)

	var input string
	fmt.Scanln(&input)

}

func openConnection() *websocket.Conn {
	u, err := url.Parse(kubernetesEndpoint)
	if err != nil {
		log.Fatal(err)
	}

	rawConn, err := net.Dial("tcp", u.Host)
	if err != nil {
		log.Fatal(err)
	}

	wsHeaders := http.Header{
		"Origin":                   {kubernetesEndpoint},
		"Sec-WebSocket-Extensions": {"permessage-deflate; client_max_window_bits, x-webkit-deflate-frame"},
	}

	wsConn, resp, err := websocket.NewClient(rawConn, u, wsHeaders, 1024, 1024)
	if err != nil {
		log.Fatal(fmt.Errorf("websocket.NewClient Error: %s\nResp:%+v", err, resp))

	}

	return wsConn
}

func reconnector(wsErrors chan string) {
	for {
		_ = <- wsErrors
		log.Println("Reconnecting...")
		go listen(openConnection(), wsErrors)
	}
}

func listen(wsConn *websocket.Conn, wsErrors chan string) {
	log.Println("Listening for pods")

	for {
		_, r, err := wsConn.NextReader()

		if err != nil {
			log.Printf("Error getting reader: %v",err)
			wsErrors <- "Error"
			return
		}

		dec := json.NewDecoder(r)
		var objmap map[string]*json.RawMessage
		dec.Decode(&objmap)

		var actionType string
		json.Unmarshal(*objmap["type"], &actionType)

		var pod api.Pod
		err = json.Unmarshal(*objmap["object"], &pod)

		switch actionType {
		case "MODIFIED":
			registrate(pod)
		case "DELETED":
			deletePod(pod)
		}
	}
}

func registrate(pod api.Pod) {
	if(pod.Status.Phase != "Running") {
		return
	}

	fmt.Printf("Registrating pod %v listening on %v to %v\n", pod.Name, pod.Status.PodIP, etcdAddress)

	machines := []string{etcdAddress}
	client := etcd.NewClient(machines)

	podUrl := fmt.Sprintf("http://%v:%v", pod.Status.PodIP, pod.Spec.Containers[0].Ports[0].HostPort)

	if _, err := client.Set("vulcan/backends/todo_app_backend/servers/" + pod.Status.PodIP, `{"URL": "` + podUrl + `"}`, 0); err != nil {
		log.Fatal(err)
	}
}

func deletePod(pod api.Pod) {
	fmt.Printf("Deleting pod %v from %v\n", pod.Name, etcdAddress)

	machines := []string{etcdAddress}
	client := etcd.NewClient(machines)

	_, err := client.Delete("vulcan/backends/todo_app_backend/servers/" + pod.Status.PodIP, false);

	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Etcd url now contains pod label name<commit_after>package main

import (
	"github.com/gorilla/websocket"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"log"
	"encoding/json"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"flag"
	"github.com/coreos/go-etcd/etcd"
)

var kubernetesEndpoint string
var etcdAddress string

type Registration struct {
	URL string
}

func init() {
	flag.StringVar(&kubernetesEndpoint, "pods", "", "Endpoint of Kubernetes pods API")
	flag.StringVar(&etcdAddress, "etcd", "", "etcd address")

	flag.Parse()
}

func main() {
	listenForPods()
}

func listenForPods() {

	wsConn := openConnection()

	var wsErrors chan string = make(chan string)

	go listen(wsConn, wsErrors)
	go reconnector(wsErrors)

	var input string
	fmt.Scanln(&input)

}

func openConnection() *websocket.Conn {
	u, err := url.Parse(kubernetesEndpoint)
	if err != nil {
		log.Fatal(err)
	}

	rawConn, err := net.Dial("tcp", u.Host)
	if err != nil {
		log.Fatal(err)
	}

	wsHeaders := http.Header{
		"Origin":                   {kubernetesEndpoint},
		"Sec-WebSocket-Extensions": {"permessage-deflate; client_max_window_bits, x-webkit-deflate-frame"},
	}

	wsConn, resp, err := websocket.NewClient(rawConn, u, wsHeaders, 1024, 1024)
	if err != nil {
		log.Fatal(fmt.Errorf("websocket.NewClient Error: %s\nResp:%+v", err, resp))

	}

	return wsConn
}

func reconnector(wsErrors chan string) {
	for {
		_ = <- wsErrors
		log.Println("Reconnecting...")
		go listen(openConnection(), wsErrors)
	}
}

func listen(wsConn *websocket.Conn, wsErrors chan string) {
	log.Println("Listening for pods")

	for {
		_, r, err := wsConn.NextReader()

		if err != nil {
			log.Printf("Error getting reader: %v",err)
			wsErrors <- "Error"
			return
		}

		dec := json.NewDecoder(r)
		var objmap map[string]*json.RawMessage
		dec.Decode(&objmap)

		var actionType string
		json.Unmarshal(*objmap["type"], &actionType)

		var pod api.Pod
		err = json.Unmarshal(*objmap["object"], &pod)

		switch actionType {
		case "MODIFIED":
			registrate(pod)
		case "DELETED":
			deletePod(pod)
		}
	}
}

func registrate(pod api.Pod) {
	if(pod.Status.Phase != "Running") {
		return
	}

	fmt.Printf("Registrating pod %v listening on %v to %v\n", pod.Name, pod.Status.PodIP, etcdAddress)

	machines := []string{etcdAddress}
	client := etcd.NewClient(machines)

	podUrl := fmt.Sprintf("http://%v:%v", pod.Status.PodIP, pod.Spec.Containers[0].Ports[0].HostPort)

	if _, err := client.Set("vulcan/backends/" + pod.Labels["name"] + "/servers/" + pod.Status.PodIP, `{"URL": "` + podUrl + `"}`, 0); err != nil {
		log.Fatal(err)
	}
}

func deletePod(pod api.Pod) {
	fmt.Printf("Deleting pod %v from %v\n", pod.Name, etcdAddress)

	machines := []string{etcdAddress}
	client := etcd.NewClient(machines)

	_, err := client.Delete("vulcan/backends/todo_app_backend/servers/" + pod.Status.PodIP, false);

	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


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

/**
This tool watches the Kubernetes API server for Pod (de)registration. New Pods are registered to
Vulcan by setting the correct etcd keys. A deleted Pod is deleted from Vulcan as well by removing it's key in etcd.
Pods will be registered using the following key pattern in etcd: /vulcan/backends/[pod label name]/servers/[pod IP]. Make sure
your Vulcan backend/frontend configuration is configured to use backend servers based on the pod name.
 */
package main

import (
	"github.com/gorilla/websocket"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"log"
	"encoding/json"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"flag"
	"github.com/coreos/go-etcd/etcd"
)

var kubernetesEndpoint string
var etcdAddress string

type Registration struct {
	URL string
}

func init() {
	flag.StringVar(&kubernetesEndpoint, "pods", "", "Endpoint of Kubernetes pods API")
	flag.StringVar(&etcdAddress, "etcd", "", "etcd address")

	flag.Parse()

	if kubernetesEndpoint == "" || etcdAddress == "" {
		log.Fatal(`Missing required properties. Usage: Registrator -pods "ws://[kubernetes-server]/api/v1beta3/namespaces/default/pods?watch=true" -etcd "[etcd-address]"`)
	}
}

func main() {
	listenForPods()
}

/**
Open WS connection and start Go routines to listen for pods.
 */
func listenForPods() {

	wsConn := openConnection()

	var wsErrors chan string = make(chan string)

	go listen(wsConn, wsErrors)
	go reconnector(wsErrors)

	var input string
	fmt.Scanln(&input)

}

/**
Open WebSocket connection to Kubernetes API server
 */
func openConnection() *websocket.Conn {
	u, err := url.Parse(kubernetesEndpoint)
	if err != nil {
		log.Fatal(err)
	}

	rawConn, err := net.Dial("tcp", u.Host)
	if err != nil {
		log.Fatal(err)
	}

	wsHeaders := http.Header{
		"Origin":                   {kubernetesEndpoint},
		"Sec-WebSocket-Extensions": {"permessage-deflate; client_max_window_bits, x-webkit-deflate-frame"},
	}

	wsConn, resp, err := websocket.NewClient(rawConn, u, wsHeaders, 1024, 1024)
	if err != nil {
		log.Fatal(fmt.Errorf("websocket.NewClient Error: %s\nResp:%+v", err, resp))

	}

	return wsConn
}

/**
When the WebSocket connection disconnects for some reason, try to reconnect.
 */
func reconnector(wsErrors chan string) {
	for {
		_ = <- wsErrors
		log.Println("Reconnecting...")
		go listen(openConnection(), wsErrors)
	}
}

/**
Listen for Pods. We're only interested in MODIFIED and DELETED events.
 */
func listen(wsConn *websocket.Conn, wsErrors chan string) {
	log.Println("Listening for pods")

	for {
		_, r, err := wsConn.NextReader()

		if err != nil {
			log.Printf("Error getting reader: %v",err)
			wsErrors <- "Error"
			return
		}

		dec := json.NewDecoder(r)
		var objmap map[string]*json.RawMessage
		dec.Decode(&objmap)

		var actionType string
		json.Unmarshal(*objmap["type"], &actionType)

		var pod api.Pod
		err = json.Unmarshal(*objmap["object"], &pod)

		switch actionType {
		case "MODIFIED":
			register(pod)
		case "DELETED":
			deletePod(pod)
		}
	}
}

/**
Register a new backend server in Vulcan based on the new Pod
 */
func register(pod api.Pod) {
	if(pod.Status.Phase != "Running") {
		return
	}

	log.Printf("Registrating pod %v listening on %v to %v\n", pod.Name, pod.Status.PodIP, etcdAddress)

	machines := []string{etcdAddress}
	client := etcd.NewClient(machines)

	podUrl := fmt.Sprintf("http://%v:%v", pod.Status.PodIP, pod.Spec.Containers[0].Ports[0].HostPort)

	if _, err := client.Set("vulcan/backends/" + pod.Labels["name"] + "/servers/" + pod.Status.PodIP, `{"URL": "` + podUrl + `"}`, 0); err != nil {
		log.Fatal(err)
	}
}

/**
Delete a backend server from Vulcan when a Pod is deleted.
 */
func deletePod(pod api.Pod) {
	log.Printf("Deleting pod %v from %v\n", pod.Name, etcdAddress)

	machines := []string{etcdAddress}
	client := etcd.NewClient(machines)

	_, err := client.Delete("vulcan/backends/" + pod.Labels["name"] + "/servers/" + pod.Status.PodIP, false);

	if err != nil {
		log.Printf("Failed to delete backend '%v'", pod.Labels["name"]);
	}
}
<commit_msg>Removed dependency on a shell<commit_after>/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
This tool watches the Kubernetes API server for Pod (de)registration. New Pods are registered to
Vulcan by setting the correct etcd keys. A deleted Pod is deleted from Vulcan as well by removing it's key in etcd.
Pods will be registered using the following key pattern in etcd: /vulcan/backends/[pod label name]/servers/[pod IP]. Make sure
your Vulcan backend/frontend configuration is configured to use backend servers based on the pod name.
 */
package main

import (
	"github.com/gorilla/websocket"
	"net"
	"net/http"
	"net/url"
	"log"
	"encoding/json"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"flag"
	"github.com/coreos/go-etcd/etcd"
	"fmt"
)

var kubernetesEndpoint string
var etcdAddress string

type Registration struct {
	URL string
}

func init() {
	flag.StringVar(&kubernetesEndpoint, "pods", "", "Endpoint of Kubernetes pods API")
	flag.StringVar(&etcdAddress, "etcd", "", "etcd address")

	flag.Parse()

	if kubernetesEndpoint == "" || etcdAddress == "" {
		log.Fatal(`Missing required properties. Usage: Registrator -pods "ws://[kubernetes-server]/api/v1beta3/namespaces/default/pods?watch=true" -etcd "[etcd-address]"`)
	}
}

func main() {
	listenForPods()
}

/**
Open WS connection and start Go routines to listen for pods.
 */
func listenForPods() {

	wsConn := openConnection()

	var wsErrors chan string = make(chan string)
	go listen(wsConn, wsErrors)
	go reconnector(wsErrors)
	select {}

}

/**
Open WebSocket connection to Kubernetes API server
 */
func openConnection() *websocket.Conn {
	u, err := url.Parse(kubernetesEndpoint)
	if err != nil {
		log.Fatal(err)
	}

	rawConn, err := net.Dial("tcp", u.Host)
	if err != nil {
		log.Fatal(err)
	}

	wsHeaders := http.Header{
		"Origin":                   {kubernetesEndpoint},
		"Sec-WebSocket-Extensions": {"permessage-deflate; client_max_window_bits, x-webkit-deflate-frame"},
	}

	wsConn, resp, err := websocket.NewClient(rawConn, u, wsHeaders, 1024, 1024)
	if err != nil {
		log.Fatalf("websocket.NewClient Error: %s\nResp:%+v", err, resp)

	}

	return wsConn
}

/**
When the WebSocket connection disconnects for some reason, try to reconnect.
 */
func reconnector(wsErrors chan string) {
	for {
		_ = <- wsErrors
		log.Println("Reconnecting...")
		go listen(openConnection(), wsErrors)
	}
}

/**
Listen for Pods. We're only interested in MODIFIED and DELETED events.
 */
func listen(wsConn *websocket.Conn, wsErrors chan string) {
	log.Println("Listening for pods")

	for {
		_, r, err := wsConn.NextReader()

		if err != nil {
			log.Printf("Error getting reader: %v",err)
			wsErrors <- "Error"
			return
		}

		dec := json.NewDecoder(r)
		var objmap map[string]*json.RawMessage
		dec.Decode(&objmap)

		var actionType string
		json.Unmarshal(*objmap["type"], &actionType)

		var pod api.Pod
		err = json.Unmarshal(*objmap["object"], &pod)

		switch actionType {
		case "MODIFIED":
			register(pod)
		case "DELETED":
			deletePod(pod)
		}
	}
}

/**
Register a new backend server in Vulcan based on the new Pod
 */
func register(pod api.Pod) {
	if(pod.Status.Phase != "Running") {
		return
	}

	log.Printf("Registrating pod %v listening on %v to %v\n", pod.Name, pod.Status.PodIP, etcdAddress)

	machines := []string{etcdAddress}
	client := etcd.NewClient(machines)

	podUrl := fmt.Sprintf("http://%v:%v", pod.Status.PodIP, pod.Spec.Containers[0].Ports[0].HostPort)

	if _, err := client.Set("vulcan/backends/" + pod.Labels["name"] + "/servers/" + pod.Status.PodIP, `{"URL": "` + podUrl + `"}`, 0); err != nil {
		log.Fatal(err)
	}
}

/**
Delete a backend server from Vulcan when a Pod is deleted.
 */
func deletePod(pod api.Pod) {
	log.Printf("Deleting pod %v from %v\n", pod.Name, etcdAddress)

	machines := []string{etcdAddress}
	client := etcd.NewClient(machines)

	_, err := client.Delete("vulcan/backends/" + pod.Labels["name"] + "/servers/" + pod.Status.PodIP, false);

	if err != nil {
		log.Printf("Failed to delete backend '%v'", pod.Labels["name"]);
	}
}
<|endoftext|>


<commit_before>package indigo

import (
	"math"
	"math/rand"
	"sort"
	"sync"
	"testing"
	"time"

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

var mid = func() (uint16, error) { return math.MaxUint16, nil }

func TestNew(t *testing.T) {

	s := Settings{
		StartTime: time.Now(),
		MachineID: mid,
	}

	g := New(s)
	require.NotNil(t, g.sf)
	require.NotNil(t, g.enc)
}

func TestGenerator_NextID(t *testing.T) {

	g := New(Settings{
		StartTime: time.Now(),
		MachineID: mid,
	})

	id1, err := g.NextID()
	require.NoError(t, err)
	assert.NotEmpty(t, id1)

	id2, err := g.NextID()
	require.NoError(t, err)
	assert.NotEmpty(t, id2)
	assert.NotEqual(t, id1, id2)
}

func TestGenerator_Decompose(t *testing.T) {

	g := New(Settings{
		StartTime: time.Now(),
		MachineID: mid,
	})

	m, err := g.Decompose("KGuFE14P")
	require.NoError(t, err)
	require.NotEmpty(t, m)
	assert.NotEmpty(t, m["id"])

	_, err = g.Decompose("")
	require.Error(t, err)
}

func TestGenerator_NextID_Race(t *testing.T) {

	g := New(Settings{
		StartTime: time.Now(),
		MachineID: mid,
	})

	gs := 2048

	var wg sync.WaitGroup
	wg.Add(gs)

	for i := 0; i < gs; i++ {
		go func() {
			defer wg.Done()
			id, err := g.NextID()
			require.NoError(t, err)
			require.NotEmpty(t, id)
		}()
	}

	wg.Wait()
}

func TestGenerator_NextID_SortIDs(t *testing.T) {

	g := New(Settings{
		StartTime: time.Now(),
		MachineID: mid,
	})

	ids := make([]string, 10)

	var err error
	for i := range ids {
		time.Sleep(10 * time.Millisecond)
		ids[i], err = g.NextID()
		require.NoError(t, err)
	}

	for i := range ids {
		j := rand.Intn(i + 1)
		ids[i], ids[j] = ids[j], ids[i]
	}

	old := make([]string, 10)

	copy(old, ids)
	require.Equal(t, old, ids)

	sort.Strings(ids)
	require.NotEqual(t, old, ids)

	var prev uint64
	for i := range ids {
		m, err := g.Decompose(ids[i])
		require.NoError(t, err)
		require.True(t, prev < m["time"])
		prev = m["time"]
	}
}

func BenchmarkGenerator_NextID(b *testing.B) {

	g := New(Settings{
		StartTime: time.Now(),
		MachineID: mid,
	})

	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		g.NextID()
	}
}
<commit_msg>Refactor sort id test (#26)<commit_after>package indigo

import (
	"math"
	"math/rand"
	"sort"
	"sync"
	"testing"
	"time"

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

var (
	start = time.Unix(1257894000, 0)
	mid   = func() (uint16, error) { return math.MaxUint16, nil }
)

func TestNew(t *testing.T) {

	s := Settings{
		StartTime: start,
		MachineID: mid,
	}

	g := New(s)
	require.NotNil(t, g.sf)
	require.NotNil(t, g.enc)
}

func TestGenerator_NextID(t *testing.T) {

	g := New(Settings{
		StartTime: start,
		MachineID: mid,
	})

	id1, err := g.NextID()
	require.NoError(t, err)
	assert.NotEmpty(t, id1)

	id2, err := g.NextID()
	require.NoError(t, err)
	assert.NotEmpty(t, id2)
	assert.NotEqual(t, id1, id2)
}

func TestGenerator_Decompose(t *testing.T) {

	g := New(Settings{
		StartTime: start,
		MachineID: mid,
	})

	m, err := g.Decompose("KGuFE14P")
	require.NoError(t, err)
	require.NotEmpty(t, m)
	assert.NotEmpty(t, m["id"])

	_, err = g.Decompose("")
	require.Error(t, err)
}

func TestGenerator_NextID_Race(t *testing.T) {

	g := New(Settings{
		StartTime: start,
		MachineID: mid,
	})

	gs := 2048

	var wg sync.WaitGroup
	wg.Add(gs)

	for i := 0; i < gs; i++ {
		go func() {
			defer wg.Done()
			id, err := g.NextID()
			require.NoError(t, err)
			require.NotEmpty(t, id)
		}()
	}

	wg.Wait()
}

func TestGenerator_NextID_SortIDs(t *testing.T) {

	th := 10
	ids := make([]string, 0, 100)

	m := sync.Mutex{}
	wg := sync.WaitGroup{}
	wg.Add(th)

	for i := 0; i < th; i++ {
		go func(mm uint16) {
			defer wg.Done()

			g := New(Settings{
				StartTime: start,
				MachineID: func() (uint16, error) {
					return mm, nil
				},
			})

			r := rand.New(rand.NewSource(time.Now().UnixNano()))

			s := make([]string, 0, th)
			for j := 0; j < th; j++ {
				time.Sleep(10*time.Millisecond + time.Duration(r.Intn(1e9)))
				id, err := g.NextID()
				require.NoError(t, err)
				s = append(s, id)
			}

			m.Lock()
			ids = append(ids, s...)
			m.Unlock()
		}(uint16(i+1))
	}

	wg.Wait()

	old := make([]string, 100)
	copy(old, ids)
	require.Equal(t, old, ids)

	sort.Strings(ids)
	require.NotEqual(t, old, ids)

	g := New(Settings{
		StartTime: start,
		MachineID: mid,
	})

	var prev uint64
	for i := range ids {
		m, err := g.Decompose(ids[i])
		require.NoError(t, err)
		require.True(t, prev <= m["time"])
		prev = m["time"]
	}
}

func BenchmarkGenerator_NextID(b *testing.B) {

	g := New(Settings{
		StartTime: time.Now(),
		MachineID: mid,
	})

	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		g.NextID()
	}
}
<|endoftext|>


<commit_before>package resp

import (
	"bufio"
	"fmt"
	"strings"
	"testing"
)

func BenchmarkIntUnmarshalRESP(b *testing.B) {
	tests := []struct {
		Input string
	}{
		{"-1"},
		{"-123"},
		{"1"},
		{"123"},
		{"+1"},
		{"+123"},
	}

	for _, test := range tests {
		input := ":" + test.Input + "\r\n"

		b.Run(fmt.Sprint(test.Input), func(b *testing.B) {
			var sr strings.Reader
			br := bufio.NewReader(&sr)

			for i := 0; i < b.N; i++ {
				sr.Reset(input)
				br.Reset(&sr)

				var i Int
				if err := i.UnmarshalRESP(br); err != nil {
					b.Fatalf("failed to unmarshal %q: %s", test.Input, err)
				}
			}
		})
	}
}

var bfloat float64

func BenchmarkReadFloat(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"1.23"},
		{"-1"},
		{"-1.23"},
		{"+1"},
		{"+1.23"},
	}

	for _, test := range tests {
		test := test

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(test.In)
				bfloat, _ = readFloat(&r, 64)
			}
		})
	}
}

var bint int64

func BenchmarkReadInt(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"123"},
		{"-1"},
		{"-123"},
		{"+1"},
		{"+123"},
	}

	for _, test := range tests {
		test := test

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(test.In)
				bint, _ = readInt(&r)
			}
		})
	}
}

var buint uint64

func BenchmarkReadUint(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"123"},
	}

	for _, test := range tests {
		test := test

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(test.In)
				buint, _ = readUint(&r)
			}
		})
	}
}
<commit_msg>Make benchmarks more consistent<commit_after>package resp

import (
	"bufio"
	"fmt"
	"strings"
	"testing"
)

func BenchmarkIntUnmarshalRESP(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"-1"},
		{"-123"},
		{"1"},
		{"123"},
		{"+1"},
		{"+123"},
	}

	for _, test := range tests {
		input := ":" + test.In + "\r\n"

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var sr strings.Reader
			br := bufio.NewReader(&sr)

			for i := 0; i < b.N; i++ {
				sr.Reset(input)
				br.Reset(&sr)

				var i Int
				if err := i.UnmarshalRESP(br); err != nil {
					b.Fatalf("failed to unmarshal %q: %s", input, err)
				}
			}
		})
	}
}

var bfloat float64

func BenchmarkReadFloat(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"1.23"},
		{"-1"},
		{"-1.23"},
		{"+1"},
		{"+1.23"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				bfloat, _ = readFloat(&r, 64)
			}
		})
	}
}

var bint int64

func BenchmarkReadInt(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"123"},
		{"-1"},
		{"-123"},
		{"+1"},
		{"+123"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				bint, _ = readInt(&r)
			}
		})
	}
}

var buint uint64

func BenchmarkReadUint(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"123"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				buint, _ = readUint(&r)
			}
		})
	}
}
<|endoftext|>


<commit_before>package resp

import (
	"bufio"
	"fmt"
	"strings"
	"testing"
)

func BenchmarkIntUnmarshalRESP(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"-1"},
		{"-123"},
		{"1"},
		{"123"},
		{"+1"},
		{"+123"},
	}

	for _, test := range tests {
		input := ":" + test.In + "\r\n"

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var sr strings.Reader
			br := bufio.NewReader(&sr)

			for i := 0; i < b.N; i++ {
				sr.Reset(input)
				br.Reset(&sr)

				var i Int
				if err := i.UnmarshalRESP(br); err != nil {
					b.Fatalf("failed to unmarshal %q: %s", input, err)
				}
			}
		})
	}
}

var bfloat float64

func BenchmarkReadFloat(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"1.23"},
		{"-1"},
		{"-1.23"},
		{"+1"},
		{"+1.23"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				bfloat, _ = readFloat(&r, 64)
			}
		})
	}
}

var bint int64

func BenchmarkReadInt(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"123"},
		{"-1"},
		{"-123"},
		{"+1"},
		{"+123"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				bint, _ = readInt(&r)
			}
		})
	}
}

var buint uint64

func BenchmarkReadUint(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"123"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				buint, _ = readUint(&r)
			}
		})
	}
}
<commit_msg>add a benchmark for readAllAppend<commit_after>package resp

import (
	"bufio"
	"bytes"
	"fmt"
	"strconv"
	"strings"
	"testing"
)

func BenchmarkIntUnmarshalRESP(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"-1"},
		{"-123"},
		{"1"},
		{"123"},
		{"+1"},
		{"+123"},
	}

	for _, test := range tests {
		input := ":" + test.In + "\r\n"

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var sr strings.Reader
			br := bufio.NewReader(&sr)

			for i := 0; i < b.N; i++ {
				sr.Reset(input)
				br.Reset(&sr)

				var i Int
				if err := i.UnmarshalRESP(br); err != nil {
					b.Fatalf("failed to unmarshal %q: %s", input, err)
				}
			}
		})
	}
}

var bfloat float64

func BenchmarkReadFloat(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"1.23"},
		{"-1"},
		{"-1.23"},
		{"+1"},
		{"+1.23"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				bfloat, _ = readFloat(&r, 64)
			}
		})
	}
}

var bint int64

func BenchmarkReadInt(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"123"},
		{"-1"},
		{"-123"},
		{"+1"},
		{"+123"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				bint, _ = readInt(&r)
			}
		})
	}
}

var buint uint64

func BenchmarkReadUint(b *testing.B) {
	tests := []struct {
		In string
	}{
		{"1"},
		{"123"},
	}

	for _, test := range tests {
		input := test.In

		b.Run(fmt.Sprint(test.In), func(b *testing.B) {
			var r strings.Reader

			for i := 0; i < b.N; i++ {
				r.Reset(input)
				buint, _ = readUint(&r)
			}
		})
	}
}

func BenchmarkReadAllAppend(b *testing.B) {
	respBytes := []byte("$5\r\nhello\r\n")

	for _, bcap := range []int{0, len(respBytes), len(respBytes) + bytes.MinRead} {
		b.Run("Capacity"+strconv.Itoa(bcap), func(b *testing.B) {
			var br bytes.Reader
			buf := make([]byte, 0, bcap)

			for i := 0; i < b.N; i++ {
				br.Reset(respBytes)

				if _, err := readAllAppend(&br, buf); err != nil {
					b.Fatal(err)
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>package model

import (
	"fmt"
	"github.com/viant/endly"
	"github.com/viant/endly/criteria"
	"github.com/viant/endly/util"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/data"
)

//SliceKey represents slice key
const SliceKey = "data"

//Repeater represent repeated execution
type Repeater struct {
	Extraction  Extracts  //textual regexp based data extraction
	Variables   Variables //structure data based data extraction
	Repeat      int       //how many time send this request
	SleepTimeMs int       //Sleep time after request send, this only makes sense with repeat option
	Exit        string    //Exit criteria, it uses extracted variable to determine repeat termination
}

//Get returns non empty instance of default instance
func (r *Repeater) Init() *Repeater {
	if r == nil {
		repeater := NewRepeater()
		r = repeater
	}
	if r.Repeat == 0 {
		r.Repeat = 1
	}
	return r
}

//EvaluateExitCriteria check is exit criteria is met.
func (r *Repeater) EvaluateExitCriteria(callerInfo string, context *endly.Context, extracted map[string]interface{}) (bool, error) {
	var state = context.State()
	var extractedState = state.Clone()
	for k, v := range extracted {
		extractedState[k] = v
	}
	canBreak, err := criteria.Evaluate(context, extractedState, r.Exit, callerInfo, false)
	if err != nil {
		return true, fmt.Errorf("failed to check %v exit criteia: %v", callerInfo, err)
	}
	if canBreak {
		return true, nil
	}
	return false, nil

}

func (r *Repeater) runOnce(service *endly.AbstractService, callerInfo string, context *endly.Context, handler func() (interface{}, error), extracted map[string]interface{}) (bool, error) {
	defer service.Sleep(context, r.SleepTimeMs)
	out, err := handler()
	if err != nil {
		return false, err
	}
	if out == nil {
		return true, nil
	}
	extractableOutput, structuredOutput := util.AsExtractable(out)
	state := context.State()
	if len(structuredOutput) > 0 {
		var extractedVariables = data.NewMap()
		err = r.Variables.Apply(structuredOutput, extractedVariables)
		if len(extractedVariables) > 0 {
			context.Publish(NewModifiedStateEvent(r.Variables, structuredOutput, extractedVariables))

			state.Apply(extractedVariables)
		}

		for k, v := range extractedVariables {
			extracted[k] = toolbox.AsString(v)
		}
		if extractableOutput == "" {
			extractableOutput, _ = toolbox.AsJSONText(structuredOutput)
		}
	}

	err = r.Extraction.Extract(context, extracted, extractableOutput)
	if err != nil {
		return false, err
	}
	if extractableOutput != "" {
		extracted["value"] = extractableOutput //string output is published as $value
	}

	if r.Exit != "" {
		context.Publish(NewExtractEvent(extractableOutput, structuredOutput, extracted))
		if shouldBreak, err := r.EvaluateExitCriteria(callerInfo+"ExitEvaluation", context, extracted); shouldBreak || err != nil {
			return !shouldBreak, err
		}
	}
	return true, nil
}

//Run repeats x times supplied handler
func (r *Repeater) Run(service *endly.AbstractService, callerInfo string, context *endly.Context, handler func() (interface{}, error), extracted map[string]interface{}) error {
	for i := 0; i < r.Repeat; i++ {
		shouldContinue, err := r.runOnce(service, callerInfo, context, handler, extracted)
		if err != nil || !shouldContinue {
			return err
		}
	}
	return nil
}

//NewRepeater creates a new repeatable struct
func NewRepeater() *Repeater {
	return &Repeater{
		Repeat: 1,
	}
}
<commit_msg>patched repeater<commit_after>package model

import (
	"fmt"
	"github.com/viant/endly"
	"github.com/viant/endly/criteria"
	"github.com/viant/endly/util"
	"github.com/viant/toolbox"
)

//SliceKey represents slice key
const SliceKey = "data"

//Repeater represent repeated execution
type Repeater struct {
	Extraction  Extracts  //textual regexp based data extraction
	Variables   Variables //structure data based data extraction
	Repeat      int       //how many time send this request
	SleepTimeMs int       //Sleep time after request send, this only makes sense with repeat option
	Exit        string    //Exit criteria, it uses extracted variable to determine repeat termination
}

//Get returns non empty instance of default instance
func (r *Repeater) Init() *Repeater {
	if r == nil {
		repeater := NewRepeater()
		r = repeater
	}
	if r.Repeat == 0 {
		r.Repeat = 1
	}
	return r
}

//EvaluateExitCriteria check is exit criteria is met.
func (r *Repeater) EvaluateExitCriteria(callerInfo string, context *endly.Context, extracted map[string]interface{}) (bool, error) {
	var state = context.State()
	var extractedState = state.Clone()
	for k, v := range extracted {
		extractedState[k] = v
	}
	canBreak, err := criteria.Evaluate(context, extractedState, r.Exit, callerInfo, false)
	if err != nil {
		return true, fmt.Errorf("failed to check %v exit criteia: %v", callerInfo, err)
	}
	if canBreak {
		return true, nil
	}
	return false, nil

}

func (r *Repeater) runOnce(service *endly.AbstractService, callerInfo string, context *endly.Context, handler func() (interface{}, error), extracted map[string]interface{}) (bool, error) {
	defer service.Sleep(context, r.SleepTimeMs)
	out, err := handler()
	if err != nil {
		return false, err
	}
	if out == nil {
		return true, nil
	}
	extractableOutput, structuredOutput := util.AsExtractable(out)

	if len(structuredOutput) > 0 {

		if len(r.Variables) > 0 {
			err = r.Variables.Apply(structuredOutput, extracted)
		}
		if extractableOutput == "" {
			extractableOutput, _ = toolbox.AsJSONText(structuredOutput)
		}
	}

	err = r.Extraction.Extract(context, extracted, extractableOutput)
	if err != nil {
		return false, err
	}
	if extractableOutput != "" {
		extracted["value"] = extractableOutput //string output is published as $value
	}
	if r.Exit != "" {
		context.Publish(NewExtractEvent(extractableOutput, structuredOutput, extracted))
		if shouldBreak, err := r.EvaluateExitCriteria(callerInfo+"ExitEvaluation", context, extracted); shouldBreak || err != nil {
			return !shouldBreak, err
		}
	}
	return true, nil
}

//Run repeats x times supplied handler
func (r *Repeater) Run(service *endly.AbstractService, callerInfo string, context *endly.Context, handler func() (interface{}, error), extracted map[string]interface{}) error {
	for i := 0; i < r.Repeat; i++ {
		shouldContinue, err := r.runOnce(service, callerInfo, context, handler, extracted)
		if err != nil || !shouldContinue {
			return err
		}
	}
	return nil
}

//NewRepeater creates a new repeatable struct
func NewRepeater() *Repeater {
	return &Repeater{
		Repeat: 1,
	}
}
<|endoftext|>


<commit_before>package rewrite

import (
	"bufio"
	"bytes"
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/token"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"sync"

	fs "github.com/kr/fs"
)

var bufpool = &sync.Pool{
	New: func() interface{} {
		return new(bytes.Buffer)
	},
}

var cfg = &printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}

func RewriteImports(ipath string, rw func(string) string, filter func(string) bool) error {
	path, err := filepath.EvalSymlinks(ipath)
	if err != nil {
		return err
	}

	var rwLock sync.Mutex

	var wg sync.WaitGroup
	torewrite := make(chan string)
	for i := 0; i < runtime.NumCPU(); i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for path := range torewrite {
				err := rewriteImportsInFile(path, rw, &rwLock)
				if err != nil {
					fmt.Println("rewrite error: ", err)
				}
			}
		}()
	}

	w := fs.Walk(path)
	for w.Step() {
		rel := w.Path()[len(path):]
		if len(rel) == 0 {
			continue
		}
		rel = rel[1:]

		if strings.HasPrefix(rel, ".git") || strings.HasPrefix(rel, "vendor") {
			w.SkipDir()
			continue
		}

		if !strings.HasSuffix(w.Path(), ".go") {
			continue
		}

		if !filter(rel) {
			continue
		}
		torewrite <- w.Path()
	}
	close(torewrite)
	wg.Wait()
	return nil
}

// inspired by godeps rewrite, rewrites import paths with gx vendored names
func rewriteImportsInFile(fi string, rw func(string) string, rwLock *sync.Mutex) error {
	// 1. Rewrite the imports (if we have any)
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, fi, nil, parser.ParseComments|parser.ImportsOnly)
	if err != nil {
		return err
	}
	if len(file.Imports) == 0 {
		return nil
	}

	oldImportsEnd := fset.Position(file.Imports[len(file.Imports)-1].End()).Offset

	rwLock.Lock()
	var changed bool
	for _, imp := range file.Imports {
		p, err := strconv.Unquote(imp.Path.Value)
		if err != nil {
			rwLock.Unlock()
			return err
		}

		np := rw(p)

		if np != p {
			changed = true
			imp.Path.Value = strconv.Quote(np)
		}
	}
	rwLock.Unlock()

	if !changed {
		return nil
	}

	buf := bufpool.Get().(*bytes.Buffer)
	defer func() {
		bufpool.Put(buf)
	}()

	// Write them back to a temporary buffer

	buf.Reset()
	if err = cfg.Fprint(buf, fset, file); err != nil {
		return err
	}

	// 2. Read the imports back in to sort them.

	fset = token.NewFileSet()
	file, err = parser.ParseFile(fset, fi, buf, parser.ParseComments|parser.ImportsOnly)
	if err != nil {
		return err
	}

	ast.SortImports(fset, file)

	// Write them back to a temporary buffer

	buf.Reset()
	if err = cfg.Fprint(buf, fset, file); err != nil {
		return err
	}

	// 3. Read them back in to find the new end of the imports.

	fset = token.NewFileSet()
	file, err = parser.ParseFile(fset, fi, buf, parser.ParseComments|parser.ImportsOnly)
	if err != nil {
		return err
	}

	newImportsEnd := fset.Position(file.Imports[len(file.Imports)-1].End()).Offset

	// Write them back to the buffer and truncate.
	buf.Reset()
	if err = cfg.Fprint(buf, fset, file); err != nil {
		return err
	}
	buf.Truncate(newImportsEnd)

	// Finally, build the file.

	tmppath := fi + ".temp"
	tmp, err := os.Create(tmppath)
	if err != nil {
		return err
	}

	src, err := os.Open(fi)
	if err != nil {
		return err
	}
	defer src.Close()

	_, err = src.Seek(int64(oldImportsEnd), io.SeekStart)
	if err != nil {
		return err
	}

	buf.WriteTo(tmp)

	_, err = io.Copy(tmp, src)
	if err != nil {
		return err
	}

	if err = tmp.Close(); err != nil {
		return err
	}

	return os.Rename(tmppath, fi)
}

func fixCanonicalImports(buf []byte) (bool, error) {
	var i int
	var changed bool
	for {
		n, tok, err := bufio.ScanLines(buf[i:], true)
		if err != nil {
			return false, err
		}
		if n == 0 {
			return changed, nil
		}
		i += n

		stripped := stripImportComment(tok)
		if stripped != nil {
			nstr := copy(tok, stripped)
			copy(tok[nstr:], bytes.Repeat([]byte(" "), len(tok)-nstr))
			changed = true
		}
	}
}

// more code from our friends over at godep
const (
	importAnnotation = `import\s+(?:"[^"]*"|` + "`[^`]*`" + `)`
	importComment    = `(?://\s*` + importAnnotation + `\s*$|/\*\s*` + importAnnotation + `\s*\*/)`
)

var (
	importCommentRE = regexp.MustCompile(`\s*(package\s+\w+)\s+` + importComment + `(.*)`)
	pkgPrefix       = []byte("package ")
)

func stripImportComment(line []byte) []byte {
	if !bytes.HasPrefix(line, pkgPrefix) {
		// Fast path; this will skip all but one line in the file.
		// This assumes there is no whitespace before the keyword.
		return nil
	}
	if m := importCommentRE.FindSubmatch(line); m != nil {
		return append(m[1], m[2]...)
	}
	return nil
}
<commit_msg>close dest before source renaming<commit_after>package rewrite

import (
	"bufio"
	"bytes"
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/token"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"sync"

	fs "github.com/kr/fs"
)

var bufpool = &sync.Pool{
	New: func() interface{} {
		return new(bytes.Buffer)
	},
}

var cfg = &printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}

func RewriteImports(ipath string, rw func(string) string, filter func(string) bool) error {
	path, err := filepath.EvalSymlinks(ipath)
	if err != nil {
		return err
	}

	var rwLock sync.Mutex

	var wg sync.WaitGroup
	torewrite := make(chan string)
	for i := 0; i < runtime.NumCPU(); i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for path := range torewrite {
				err := rewriteImportsInFile(path, rw, &rwLock)
				if err != nil {
					fmt.Println("rewrite error: ", err)
				}
			}
		}()
	}

	w := fs.Walk(path)
	for w.Step() {
		rel := w.Path()[len(path):]
		if len(rel) == 0 {
			continue
		}
		rel = rel[1:]

		if strings.HasPrefix(rel, ".git") || strings.HasPrefix(rel, "vendor") {
			w.SkipDir()
			continue
		}

		if !strings.HasSuffix(w.Path(), ".go") {
			continue
		}

		if !filter(rel) {
			continue
		}
		torewrite <- w.Path()
	}
	close(torewrite)
	wg.Wait()
	return nil
}

// inspired by godeps rewrite, rewrites import paths with gx vendored names
func rewriteImportsInFile(fi string, rw func(string) string, rwLock *sync.Mutex) error {
	// 1. Rewrite the imports (if we have any)
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, fi, nil, parser.ParseComments|parser.ImportsOnly)
	if err != nil {
		return err
	}
	if len(file.Imports) == 0 {
		return nil
	}

	oldImportsEnd := fset.Position(file.Imports[len(file.Imports)-1].End()).Offset

	rwLock.Lock()
	var changed bool
	for _, imp := range file.Imports {
		p, err := strconv.Unquote(imp.Path.Value)
		if err != nil {
			rwLock.Unlock()
			return err
		}

		np := rw(p)

		if np != p {
			changed = true
			imp.Path.Value = strconv.Quote(np)
		}
	}
	rwLock.Unlock()

	if !changed {
		return nil
	}

	buf := bufpool.Get().(*bytes.Buffer)
	defer func() {
		bufpool.Put(buf)
	}()

	// Write them back to a temporary buffer

	buf.Reset()
	if err = cfg.Fprint(buf, fset, file); err != nil {
		return err
	}

	// 2. Read the imports back in to sort them.

	fset = token.NewFileSet()
	file, err = parser.ParseFile(fset, fi, buf, parser.ParseComments|parser.ImportsOnly)
	if err != nil {
		return err
	}

	ast.SortImports(fset, file)

	// Write them back to a temporary buffer

	buf.Reset()
	if err = cfg.Fprint(buf, fset, file); err != nil {
		return err
	}

	// 3. Read them back in to find the new end of the imports.

	fset = token.NewFileSet()
	file, err = parser.ParseFile(fset, fi, buf, parser.ParseComments|parser.ImportsOnly)
	if err != nil {
		return err
	}

	newImportsEnd := fset.Position(file.Imports[len(file.Imports)-1].End()).Offset

	// Write them back to the buffer and truncate.
	buf.Reset()
	if err = cfg.Fprint(buf, fset, file); err != nil {
		return err
	}
	buf.Truncate(newImportsEnd)

	// Finally, build the file.

	tmppath := fi + ".temp"
	tmp, err := os.Create(tmppath)
	if err != nil {
		return err
	}

	// Write the imports
	_, err = buf.WriteTo(tmp)
	if err != nil {
		return err
	}

	// Copy the rest
	src, err := os.Open(fi)
	if err != nil {
		return err
	}

	_, err = src.Seek(int64(oldImportsEnd), io.SeekStart)
	if err != nil {
		src.Close()
		return err
	}

	_, err = io.Copy(tmp, src)
	if err != nil {
		src.Close()
		return err
	}

	// Ignore any errors, we didn't modify this file.
	src.Close()

	// Update the file
	if err = tmp.Close(); err != nil {
		return err
	}

	return os.Rename(tmppath, fi)
}

func fixCanonicalImports(buf []byte) (bool, error) {
	var i int
	var changed bool
	for {
		n, tok, err := bufio.ScanLines(buf[i:], true)
		if err != nil {
			return false, err
		}
		if n == 0 {
			return changed, nil
		}
		i += n

		stripped := stripImportComment(tok)
		if stripped != nil {
			nstr := copy(tok, stripped)
			copy(tok[nstr:], bytes.Repeat([]byte(" "), len(tok)-nstr))
			changed = true
		}
	}
}

// more code from our friends over at godep
const (
	importAnnotation = `import\s+(?:"[^"]*"|` + "`[^`]*`" + `)`
	importComment    = `(?://\s*` + importAnnotation + `\s*$|/\*\s*` + importAnnotation + `\s*\*/)`
)

var (
	importCommentRE = regexp.MustCompile(`\s*(package\s+\w+)\s+` + importComment + `(.*)`)
	pkgPrefix       = []byte("package ")
)

func stripImportComment(line []byte) []byte {
	if !bytes.HasPrefix(line, pkgPrefix) {
		// Fast path; this will skip all but one line in the file.
		// This assumes there is no whitespace before the keyword.
		return nil
	}
	if m := importCommentRE.FindSubmatch(line); m != nil {
		return append(m[1], m[2]...)
	}
	return nil
}
<|endoftext|>


<commit_before>package watch

import (
	"io/ioutil"
	"os"
	"sync"
	"testing"
	"time"
)

func equal(a1, a2 []string) bool {
	if len(a1) != len(a2) {
		return false
	}
	for _, a := range a1 {
		if !exist(a2, a) {
			return false
		}
	}
	return true
}

type dummy struct {
	name string
}

func (d *dummy) Name() string {
	return d.name
}

func (d *dummy) Reload() {}

func TestWatch(t *testing.T) {
	tests := []struct {
		paths       []string
		expWatched  []string
		expWatchers []string
	}{
		{
			[]string{"testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata/dummy.txt", "testdata/test.txt"},
		},
		{
			[]string{"testdata", "testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata", "testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata"},
		},
		{
			[]string{"testdata/dummy.txt", "testdata/test.txt", "testdata"},
			[]string{"testdata", "testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata"},
		},
		// 2 path refer same file or dir but different(e.g abs path and relative path)
	}
	for i, test := range tests {
		watcher, err := NewWatcher()
		if err != nil {
			t.Fatalf("Couldn't create watcher: %s", err)
		}
		for _, name := range test.paths {
			if err := watcher.Watch(&dummy{name}); err != nil {
				t.Fatalf("Couldn' Watch %s : %s", name, err)
			}
		}
		if len(watcher.watched) != len(test.expWatched) {
			t.Errorf("Test %d: Expected len of watched %d, but got %d", i, len(test.expWatched), len(watcher.watched))
		}
		for _, p := range test.expWatched {
			if _, exist := watcher.watched[p]; !exist {
				t.Errorf("Test %d: Expected %s exist in watched", i, p)
			}
		}
		if !equal(test.expWatchers, watcher.watchers) {
			t.Errorf("Test %d: Expected watchers %v, but got %v", i, test.expWatchers, watcher.watchers)
		}
	}
}

func TestUnWatch(t *testing.T) {
	name := "testdata/dummy.txt"
	d := &dummy{name}
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	if err := watcher.Watch(d); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d, err)
	}
	if err := watcher.UnWatch(d); err != nil {
		t.Fatalf("Couldn' UnWatch %s : %s", d, err)
	}
	if len(watcher.watched) != 0 {
		t.Errorf("Expected watcheds be empty, but got %s", watcher.watched)
	}
}

func TestUnWatchDirectory(t *testing.T) {
	name := "testdata/dummy.txt"
	dir := "testdata"
	d := &dummy{name}
	d1 := NewWatchedDir(dir)
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	if err := watcher.Watch(d); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d, err)
	}
	if err := watcher.Watch(d1); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d1, err)
	}
	if !equal(watcher.watchers, []string{"testdata"}) {
		t.Fatalf("Expected watchers be equal to %s, but got %s", watcher.watchers, []string{"testdata"})
	}
	if err := watcher.UnWatch(d1); err != nil {
		t.Fatalf("Couldn' UnWatch %s : %s", d1, err)
	}
	if !equal(watcher.watchers, []string{name}) {
		t.Errorf("Expected watchers be equal to %s, but got %s", watcher.watchers, []string{name})
	}
}

func TestUnWatchOneOfSubscribers(t *testing.T) {
	name := "testdata/dummy.txt"
	d1 := &dummy{name}
	d2 := &dummy{name}
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	if err := watcher.Watch(d1); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d1, err)
	}
	if err := watcher.Watch(d2); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d2, err)
	}
	if len(watcher.watched[name]) != 2 {
		t.Fatalf("Expected watched[%s] length be %d, but got %d", name, 2, len(watcher.watched[name]))
	}
	if err := watcher.UnWatch(d1); err != nil {
		t.Fatalf("Couldn' UnWatch %s : %s", d1, err)
	}
	if !equal(watcher.watchers, []string{name}) {
		t.Errorf("Expected watchers be equal to %s, but got %s", watcher.watchers, []string{name})
	}
	if len(watcher.watched[name]) != 1 {
		t.Errorf("Expected watched[%s] length be %d, but got %d", name, 1, len(watcher.watched[name]))
	}
}

type dumView struct {
	text string
	name string
	lock sync.Mutex
}

func (d *dumView) Reload() {
	d.lock.Lock()
	defer d.lock.Unlock()
	d.text = "Reloaded"
}

func (d *dumView) Name() string {
	return d.name
}

func (d *dumView) Text() string {
	d.lock.Lock()
	defer d.lock.Unlock()
	return d.text
}

func TestObserve(t *testing.T) {
	name := "testdata/test.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: name}
	watcher.Watch(v)
	go watcher.Observe()

	if err := ioutil.WriteFile(name, []byte("test"), 0644); err != nil {
		t.Fatalf("WriteFile error: %s", err)
	}
	time.Sleep(time.Millisecond * 50)
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	ioutil.WriteFile(name, []byte(""), 0644)
}

func TestObserveDirectory(t *testing.T) {
	dir := "testdata"
	name := "testdata/test.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: dir}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	if !equal(watcher.watchers, []string{"testdata"}) {
		t.Errorf("Expected watchers be equal to %v, but got %v", []string{"testdata"}, watcher.watchers)
	}
	if err := ioutil.WriteFile(name, []byte("test"), 0644); err != nil {
		t.Fatalf("WriteFile error: %s", err)
	}
	time.Sleep(time.Millisecond * 50)
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	ioutil.WriteFile(name, []byte(""), 0644)
}

func TestCreateEvent(t *testing.T) {
	name := "testdata/new.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: name}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	if !equal(watcher.watchers, []string{"testdata"}) {
		t.Errorf("Expected watchers be equal to %v, but got %v", []string{name}, watcher.watchers)
	}
	if err := ioutil.WriteFile(name, []byte("test"), 0644); err != nil {
		t.Fatalf("WriteFile error: %s", err)
	}
	time.Sleep(time.Millisecond * 50)
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	os.Remove(name)
}

func TestDeleteEvent(t *testing.T) {
	name := "testdata/dummy.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: name}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	os.Remove(name)
	time.Sleep(time.Millisecond * 50)
	watcher.lock.Lock()
	if !equal(watcher.watchers, []string{"testdata"}) {
		t.Errorf("Expected watchers be equal to %v, but got %v", []string{"testdata"}, watcher.watchers)
	}
	watcher.lock.Unlock()
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	ioutil.WriteFile(name, []byte(""), 0644)
}

func TestRenameEvent(t *testing.T) {
	name := "testdata/dummy.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: name}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	os.Rename(name, "testdata/rename.txt")
	time.Sleep(time.Millisecond * 50)
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	os.Rename("testdata/rename.txt", name)
}

func TestExist(t *testing.T) {
	test := struct {
		array []string
		elms  []string
		exps  []bool
	}{
		[]string{"a", "b", "c", "d"},
		[]string{"a", "t", "A"},
		[]bool{true, false, false},
	}
	for i, exp := range test.exps {
		if exist(test.array, test.elms[i]) != exp {
			t.Errorf("Expected in %v exist result of element %s be %v, but got %v", test.array, test.elms[i], exp, exist(test.array, test.elms[i]))
		}
	}
}

func TestRemove(t *testing.T) {
	tests := []struct {
		slice  []string
		remove string
		exp    []string
	}{
		{
			[]string{"a", "b", "c"},
			"a",
			[]string{"c", "b"},
		},
		{
			[]string{"a", "b", "c"},
			"k",
			[]string{"a", "b", "c"},
		},
	}
	for i, test := range tests {
		if exp := remove(test.slice, test.remove); !equal(exp, test.exp) {
			t.Errorf("Test %d: Expected %v be equal to %v", i, exp, test.exp)
		}
	}
}
<commit_msg>Why is travis failing on TestDeleteEvent<commit_after>package watch

import (
	"io/ioutil"
	"os"
	"sync"
	"testing"
	"time"
)

func equal(a1, a2 []string) bool {
	if len(a1) != len(a2) {
		return false
	}
	for _, a := range a1 {
		if !exist(a2, a) {
			return false
		}
	}
	return true
}

type dummy struct {
	name string
}

func (d *dummy) Name() string {
	return d.name
}

func (d *dummy) Reload() {}

func TestWatch(t *testing.T) {
	tests := []struct {
		paths       []string
		expWatched  []string
		expWatchers []string
	}{
		{
			[]string{"testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata/dummy.txt", "testdata/test.txt"},
		},
		{
			[]string{"testdata", "testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata", "testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata"},
		},
		{
			[]string{"testdata/dummy.txt", "testdata/test.txt", "testdata"},
			[]string{"testdata", "testdata/dummy.txt", "testdata/test.txt"},
			[]string{"testdata"},
		},
		// 2 path refer same file or dir but different(e.g abs path and relative path)
	}
	for i, test := range tests {
		watcher, err := NewWatcher()
		if err != nil {
			t.Fatalf("Couldn't create watcher: %s", err)
		}
		for _, name := range test.paths {
			if err := watcher.Watch(&dummy{name}); err != nil {
				t.Fatalf("Couldn' Watch %s : %s", name, err)
			}
		}
		if len(watcher.watched) != len(test.expWatched) {
			t.Errorf("Test %d: Expected len of watched %d, but got %d", i, len(test.expWatched), len(watcher.watched))
		}
		for _, p := range test.expWatched {
			if _, exist := watcher.watched[p]; !exist {
				t.Errorf("Test %d: Expected %s exist in watched", i, p)
			}
		}
		if !equal(test.expWatchers, watcher.watchers) {
			t.Errorf("Test %d: Expected watchers %v, but got %v", i, test.expWatchers, watcher.watchers)
		}
	}
}

func TestUnWatch(t *testing.T) {
	name := "testdata/dummy.txt"
	d := &dummy{name}
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	if err := watcher.Watch(d); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d, err)
	}
	if err := watcher.UnWatch(d); err != nil {
		t.Fatalf("Couldn' UnWatch %s : %s", d, err)
	}
	if len(watcher.watched) != 0 {
		t.Errorf("Expected watcheds be empty, but got %s", watcher.watched)
	}
}

func TestUnWatchDirectory(t *testing.T) {
	name := "testdata/dummy.txt"
	dir := "testdata"
	d := &dummy{name}
	d1 := NewWatchedDir(dir)
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	if err := watcher.Watch(d); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d, err)
	}
	if err := watcher.Watch(d1); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d1, err)
	}
	if !equal(watcher.watchers, []string{"testdata"}) {
		t.Fatalf("Expected watchers be equal to %s, but got %s", watcher.watchers, []string{"testdata"})
	}
	if err := watcher.UnWatch(d1); err != nil {
		t.Fatalf("Couldn' UnWatch %s : %s", d1, err)
	}
	if !equal(watcher.watchers, []string{name}) {
		t.Errorf("Expected watchers be equal to %s, but got %s", watcher.watchers, []string{name})
	}
}

func TestUnWatchOneOfSubscribers(t *testing.T) {
	name := "testdata/dummy.txt"
	d1 := &dummy{name}
	d2 := &dummy{name}
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	if err := watcher.Watch(d1); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d1, err)
	}
	if err := watcher.Watch(d2); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", d2, err)
	}
	if len(watcher.watched[name]) != 2 {
		t.Fatalf("Expected watched[%s] length be %d, but got %d", name, 2, len(watcher.watched[name]))
	}
	if err := watcher.UnWatch(d1); err != nil {
		t.Fatalf("Couldn' UnWatch %s : %s", d1, err)
	}
	if !equal(watcher.watchers, []string{name}) {
		t.Errorf("Expected watchers be equal to %s, but got %s", watcher.watchers, []string{name})
	}
	if len(watcher.watched[name]) != 1 {
		t.Errorf("Expected watched[%s] length be %d, but got %d", name, 1, len(watcher.watched[name]))
	}
}

type dumView struct {
	text string
	name string
	lock sync.Mutex
}

func (d *dumView) Reload() {
	d.lock.Lock()
	defer d.lock.Unlock()
	d.text = "Reloaded"
}

func (d *dumView) Name() string {
	return d.name
}

func (d *dumView) Text() string {
	d.lock.Lock()
	defer d.lock.Unlock()
	return d.text
}

func TestObserve(t *testing.T) {
	name := "testdata/test.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: name}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	if err := ioutil.WriteFile(name, []byte("test"), 0644); err != nil {
		t.Fatalf("WriteFile error: %s", err)
	}
	time.Sleep(time.Millisecond * 50)
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	ioutil.WriteFile(name, []byte(""), 0644)
}

func TestObserveDirectory(t *testing.T) {
	dir := "testdata"
	name := "testdata/test.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: dir}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	if !equal(watcher.watchers, []string{"testdata"}) {
		t.Errorf("Expected watchers be equal to %v, but got %v", []string{"testdata"}, watcher.watchers)
	}
	if err := ioutil.WriteFile(name, []byte("test"), 0644); err != nil {
		t.Fatalf("WriteFile error: %s", err)
	}
	time.Sleep(time.Millisecond * 50)
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	ioutil.WriteFile(name, []byte(""), 0644)
}

func TestCreateEvent(t *testing.T) {
	name := "testdata/new.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: name}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	if !equal(watcher.watchers, []string{"testdata"}) {
		t.Errorf("Expected watchers be equal to %v, but got %v", []string{name}, watcher.watchers)
	}
	if err := ioutil.WriteFile(name, []byte("test"), 0644); err != nil {
		t.Fatalf("WriteFile error: %s", err)
	}
	time.Sleep(time.Millisecond * 50)
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	os.Remove(name)
}

func TestDeleteEvent(t *testing.T) {
	name := "testdata/dummy.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: name}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	if os.Remove(name); err != nil {
		t.Fatalf("Couldn't remove file %s: %s", name, err)
	}
	time.Sleep(time.Millisecond * 50)
	watcher.lock.Lock()
	if !equal(watcher.watchers, []string{"testdata"}) {
		t.Errorf("Expected watchers be equal to %v, but got %v", []string{"testdata"}, watcher.watchers)
	}
	watcher.lock.Unlock()
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	ioutil.WriteFile(name, []byte(""), 0644)
}

func TestRenameEvent(t *testing.T) {
	name := "testdata/dummy.txt"
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("Couldn't create watcher: %s", err)
	}
	v := &dumView{name: name}
	if err := watcher.Watch(v); err != nil {
		t.Fatalf("Couldn' Watch %s : %s", v, err)
	}
	go watcher.Observe()

	os.Rename(name, "testdata/rename.txt")
	time.Sleep(time.Millisecond * 50)
	if v.Text() != "Reloaded" {
		t.Errorf("Expected dumView Text %s, but got %s", "Reloaded", v.Text())
	}
	os.Rename("testdata/rename.txt", name)
}

func TestExist(t *testing.T) {
	test := struct {
		array []string
		elms  []string
		exps  []bool
	}{
		[]string{"a", "b", "c", "d"},
		[]string{"a", "t", "A"},
		[]bool{true, false, false},
	}
	for i, exp := range test.exps {
		if exist(test.array, test.elms[i]) != exp {
			t.Errorf("Expected in %v exist result of element %s be %v, but got %v", test.array, test.elms[i], exp, exist(test.array, test.elms[i]))
		}
	}
}

func TestRemove(t *testing.T) {
	tests := []struct {
		slice  []string
		remove string
		exp    []string
	}{
		{
			[]string{"a", "b", "c"},
			"a",
			[]string{"c", "b"},
		},
		{
			[]string{"a", "b", "c"},
			"k",
			[]string{"a", "b", "c"},
		},
	}
	for i, test := range tests {
		if exp := remove(test.slice, test.remove); !equal(exp, test.exp) {
			t.Errorf("Test %d: Expected %v be equal to %v", i, exp, test.exp)
		}
	}
}
<|endoftext|>