<commit_before>package subchal

import (
    "testing"
    "time"
)

func Test_Stoptime_DayLater(t *testing.T) {
    t.Parallel()
    SetTestLogger(t)

    initialTime, _ := time.Parse("15:04:05", "11:32:19")
    st := Stoptime{
        "A20131215WKD_WOLF_NS_01",
        initialTime,
        initialTime,
        nil,
        1,
        "",
    }
    newSt := st.DayLater()

    switch false {
    case newSt.TripID == st.TripID:
        t.Log("Stoptime.DayLater() didn't preserve TripID")
        t.FailNow()
    case 24 * time.Hour == newSt.ArrivalTime.Sub(st.ArrivalTime):
        t.Log("Stoptime.DayLater() didn't transform ArrivalTime")
        t.FailNow()
    case 24 * time.Hour == newSt.DepartureTime.Sub(st.DepartureTime):
        t.Log("Stoptime.DayLater() didn't transform DepartureTime")
        t.FailNow()
    }
}

func Test_LoadStoptimes(t *testing.T) {
    t.Parallel()
    SetTestLogger(t)

    stops, _, _ := LoadStops("../test-data/stops.txt")
    stoptimes, err := LoadStoptimes("../test-data/stop_times.txt", stops)

    switch false {
    case err == nil:
        t.Log("Got error from LoadStoptimes():", err)
        t.FailNow()
    case len(stoptimes) == len(stops):
        t.Log("Didn't load stoptimes for enough stops")
        t.FailNow()
    }

    for stopID, stSlice := range stoptimes {
        for _, st := range stSlice {
            if st.Stop.StopID != stopID {
                t.Log("Stoptime at stop", st.Stop.StopID, "doesn't match stoptimes key", stopID)
            }
            if st.Stop.IsStation() {
                t.Log("Stoptime at stop", st.Stop.StopID, "is a station rather than a stop")
            }
        }
    }
}
<commit_msg>Added test to make sure that Stoptimes get cycled past midnight<commit_after>package subchal

import (
    "testing"
    "time"
)

func Test_Stoptime_DayLater(t *testing.T) {
    t.Parallel()
    SetTestLogger(t)

    initialTime, _ := time.Parse("15:04:05", "11:32:19")
    st := Stoptime{
        "A20131215WKD_WOLF_NS_01",
        initialTime,
        initialTime,
        nil,
        1,
        "",
    }
    newSt := st.DayLater()

    switch false {
    case newSt.TripID == st.TripID:
        t.Log("Stoptime.DayLater() didn't preserve TripID")
        t.FailNow()
    case 24 * time.Hour == newSt.ArrivalTime.Sub(st.ArrivalTime):
        t.Log("Stoptime.DayLater() didn't transform ArrivalTime")
        t.FailNow()
    case 24 * time.Hour == newSt.DepartureTime.Sub(st.DepartureTime):
        t.Log("Stoptime.DayLater() didn't transform DepartureTime")
        t.FailNow()
    }
}

func Test_LoadStoptimes(t *testing.T) {
    t.Parallel()
    SetTestLogger(t)

    stops, _, _ := LoadStops("../test-data/stops.txt")
    stoptimes, err := LoadStoptimes("../test-data/stop_times.txt", stops)

    switch false {
    case err == nil:
        t.Log("Got error from LoadStoptimes():", err)
        t.FailNow()
    case len(stoptimes) == len(stops):
        t.Log("Didn't load stoptimes for enough stops")
        t.FailNow()
    }

    for stopID, stSlice := range stoptimes {
        firstSt := stSlice[0]
        lastSt := stSlice[len(stSlice) - 1]
        if lastSt.ArrivalTime.Sub(firstSt.ArrivalTime) < 24 * time.Hour {
            t.Log("Stoptimes for stop", stopID, "were not copied to the next day")
            t.FailNow()
        }

        for _, st := range stSlice {
            if st.Stop.StopID != stopID {
                t.Log("Stoptime at stop", st.Stop.StopID, "doesn't match stoptimes key", stopID)
                t.FailNow()
            }
            if st.Stop.IsStation() {
                t.Log("Stoptime at stop", st.Stop.StopID, "is a station rather than a stop")
                t.FailNow()
            }
        }
    }
}
<|endoftext|>


<commit_before>package libkbfs

import "golang.org/x/net/context"

// favReq represents a request to access the logged-in user's
// favorites list.  A single request can do one or more of the
// following: refresh the current cached list, add a favorite, remove
// a favorite, and get all the favorites.  When the request is done,
// the resulting error (or nil) is sent over the done channel.  The
// given ctx is used for all network operations.
type favReq struct {
	// Request types
	refresh bool
	toAdd   []Favorite
	toDel   []Favorite
	favs    chan<- []Favorite

	// Signaled when the request is done
	done chan<- error

	// Context
	ctx context.Context
}

// Favorites manages a user's favorite list.
type Favorites struct {
	config Config

	// Channels for interacting with the favorites cache
	reqChan chan favReq

	// cache tracks the favorites for this user, that we know about.
	// It may not be consistent with the server's view of the user's
	// favorites list, if other devices have modified the list since
	// the last refresh.
	cache map[Favorite]bool
}

// NewFavorites constructs a new Favorites instance.
func NewFavorites(config Config) *Favorites {
	f := &Favorites{
		config:  config,
		reqChan: make(chan favReq),
	}
	go f.loop()
	return f
}

func (f *Favorites) handleReq(req favReq) {
	kbpki := f.config.KBPKI()
	// Fetch a new list if:
	//  * The user asked us to refresh
	//  * We haven't fetched it before
	//  * The user wants the list of favorites.  TODO: use the cached list
	//    once we have proper invalidation from the server.
	if req.refresh || f.cache == nil || req.favs != nil {
		f.cache = make(map[Favorite]bool)
		folders, err := kbpki.FavoriteList(req.ctx)
		if err != nil {
			req.done <- err
			return
		}

		for _, folder := range folders {
			f.cache[*NewFavoriteFromFolder(folder)] = true
		}
		username, _, err := f.config.KBPKI().GetCurrentUserInfo(req.ctx)
		if err == nil {
			// Add favorites for the current user, that cannot be deleted.
			f.cache[Favorite{string(username), true}] = true
			f.cache[Favorite{string(username), false}] = true
		}
	}

	for _, fav := range req.toAdd {
		// TODO: once we have proper cache invalidation from the API
		// server, we should only call FavoriteAdd if the folder isn't
		// already favorited.
		err := kbpki.FavoriteAdd(req.ctx, fav.toKBFolder())
		if err != nil {
			req.done <- err
			return
		}
	}

	for _, fav := range req.toDel {
		// Since our cache isn't necessarily up-to-date, always delete
		// the favorite.
		err := kbpki.FavoriteDelete(req.ctx, fav.toKBFolder())
		if err != nil {
			req.done <- err
			return
		}
		delete(f.cache, fav)
	}

	if req.favs != nil {
		favorites := make([]Favorite, 0, len(f.cache))
		for fav := range f.cache {
			favorites = append(favorites, fav)
		}
		req.favs <- favorites
	}

	req.done <- nil
}

func (f *Favorites) loop() {
	for req := range f.reqChan {
		f.handleReq(req)
	}
}

// Shutdown shuts down this Favorites instance.
func (f *Favorites) Shutdown() {
	close(f.reqChan)
}

func (f *Favorites) sendReq(ctx context.Context, req favReq) error {
	errChan := make(chan error, 1)
	req.done = errChan
	req.ctx = ctx
	select {
	case f.reqChan <- req:
	case <-ctx.Done():
		return ctx.Err()
	}
	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-errChan:
		return err
	}
}

// Add adds a favorite to your favorites list, unless it
// already exists in the cached list of favorites.
func (f *Favorites) Add(ctx context.Context, fav Favorite) error {
	return f.sendReq(ctx, favReq{toAdd: []Favorite{fav}})
}

// Delete deletes a favorite from the favorites list.  It is
// idempotent.
func (f *Favorites) Delete(ctx context.Context, fav Favorite) error {
	return f.sendReq(ctx, favReq{toDel: []Favorite{fav}})
}

// RefreshCache refreshes the cached list of favorites.
func (f *Favorites) RefreshCache(ctx context.Context) {
	// This request is non-blocking, so use a throw-away done channel
	// and context.
	req := favReq{
		refresh: true,
		done:    make(chan error, 1),
		ctx:     context.Background(),
	}
	select {
	case f.reqChan <- req:
	case <-ctx.Done():
		return
	}
}

// Get returns the logged-in users list of favorites. It
// doesn't use the cache.
func (f *Favorites) Get(ctx context.Context) ([]Favorite, error) {
	favChan := make(chan []Favorite, 1)
	req := favReq{
		favs: favChan,
	}
	err := f.sendReq(ctx, req)
	if err != nil {
		return nil, err
	}
	return <-favChan, nil
}
<commit_msg>favorites: quick fix for removing public folders<commit_after>package libkbfs

import "golang.org/x/net/context"

// favReq represents a request to access the logged-in user's
// favorites list.  A single request can do one or more of the
// following: refresh the current cached list, add a favorite, remove
// a favorite, and get all the favorites.  When the request is done,
// the resulting error (or nil) is sent over the done channel.  The
// given ctx is used for all network operations.
type favReq struct {
	// Request types
	refresh bool
	toAdd   []Favorite
	toDel   []Favorite
	favs    chan<- []Favorite

	// Signaled when the request is done
	done chan<- error

	// Context
	ctx context.Context
}

// Favorites manages a user's favorite list.
type Favorites struct {
	config Config

	// Channels for interacting with the favorites cache
	reqChan chan favReq

	// cache tracks the favorites for this user, that we know about.
	// It may not be consistent with the server's view of the user's
	// favorites list, if other devices have modified the list since
	// the last refresh.
	cache map[Favorite]bool
}

// NewFavorites constructs a new Favorites instance.
func NewFavorites(config Config) *Favorites {
	f := &Favorites{
		config:  config,
		reqChan: make(chan favReq),
	}
	go f.loop()
	return f
}

func (f *Favorites) handleReq(req favReq) {
	kbpki := f.config.KBPKI()
	// Fetch a new list if:
	//  * The user asked us to refresh
	//  * We haven't fetched it before
	//  * The user wants the list of favorites.  TODO: use the cached list
	//    once we have proper invalidation from the server.
	if req.refresh || f.cache == nil || req.favs != nil {
		f.cache = make(map[Favorite]bool)
		folders, err := kbpki.FavoriteList(req.ctx)
		if err != nil {
			req.done <- err
			return
		}

		for _, folder := range folders {
			f.cache[*NewFavoriteFromFolder(folder)] = true
		}
		username, _, err := f.config.KBPKI().GetCurrentUserInfo(req.ctx)
		if err == nil {
			// Add favorites for the current user, that cannot be deleted.
			f.cache[Favorite{string(username), true}] = true
			f.cache[Favorite{string(username), false}] = true
		}
	}

	for _, fav := range req.toAdd {
		// TODO: once we have proper cache invalidation from the API
		// server, we should only call FavoriteAdd if the folder isn't
		// already favorited.
		err := kbpki.FavoriteAdd(req.ctx, fav.toKBFolder())
		if err != nil {
			req.done <- err
			return
		}
	}

	for _, fav := range req.toDel {
		// Since our cache isn't necessarily up-to-date, always delete
		// the favorite.
		folder := fav.toKBFolder()
		err := kbpki.FavoriteDelete(req.ctx, folder)
		if err != nil {
			req.done <- err
			return
		}
		if !folder.Private {
			// Public folders may be stored under a different name,
			// pending CORE-2695.  TODO: remove me!
			folder.Name = folder.Name + ReaderSep + "public"
			err := kbpki.FavoriteDelete(req.ctx, folder)
			if err != nil {
				req.done <- err
				return
			}
		}
		delete(f.cache, fav)
	}

	if req.favs != nil {
		favorites := make([]Favorite, 0, len(f.cache))
		for fav := range f.cache {
			favorites = append(favorites, fav)
		}
		req.favs <- favorites
	}

	req.done <- nil
}

func (f *Favorites) loop() {
	for req := range f.reqChan {
		f.handleReq(req)
	}
}

// Shutdown shuts down this Favorites instance.
func (f *Favorites) Shutdown() {
	close(f.reqChan)
}

func (f *Favorites) sendReq(ctx context.Context, req favReq) error {
	errChan := make(chan error, 1)
	req.done = errChan
	req.ctx = ctx
	select {
	case f.reqChan <- req:
	case <-ctx.Done():
		return ctx.Err()
	}
	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-errChan:
		return err
	}
}

// Add adds a favorite to your favorites list, unless it
// already exists in the cached list of favorites.
func (f *Favorites) Add(ctx context.Context, fav Favorite) error {
	return f.sendReq(ctx, favReq{toAdd: []Favorite{fav}})
}

// Delete deletes a favorite from the favorites list.  It is
// idempotent.
func (f *Favorites) Delete(ctx context.Context, fav Favorite) error {
	return f.sendReq(ctx, favReq{toDel: []Favorite{fav}})
}

// RefreshCache refreshes the cached list of favorites.
func (f *Favorites) RefreshCache(ctx context.Context) {
	// This request is non-blocking, so use a throw-away done channel
	// and context.
	req := favReq{
		refresh: true,
		done:    make(chan error, 1),
		ctx:     context.Background(),
	}
	select {
	case f.reqChan <- req:
	case <-ctx.Done():
		return
	}
}

// Get returns the logged-in users list of favorites. It
// doesn't use the cache.
func (f *Favorites) Get(ctx context.Context) ([]Favorite, error) {
	favChan := make(chan []Favorite, 1)
	req := favReq{
		favs: favChan,
	}
	err := f.sendReq(ctx, req)
	if err != nil {
		return nil, err
	}
	return <-favChan, nil
}
<|endoftext|>


<commit_before>package jobs

import (
	"strings"

	log "github.com/meifamily/logrus"
	"github.com/meifamily/ptt-alertor/models"
	"github.com/meifamily/ptt-alertor/models/article"
	"github.com/meifamily/ptt-alertor/models/author"
	"github.com/meifamily/ptt-alertor/models/board"
	"github.com/meifamily/ptt-alertor/models/keyword"
	"github.com/meifamily/ptt-alertor/models/pushsum"
)

type migrateBoard struct{}

func NewMigrateBoard() *migrateBoard {
	return &migrateBoard{}
}

func (m migrateBoard) Run(boardMap map[string]string) {
	for pre, post := range boardMap {
		m.RunSingle(pre, post)
	}
}

func (migrateBoard) RunSingle(preBoard string, postBoard string) {
	// board list
	if postBoard != "" {
		addBoard(postBoard)
	}
	bd := board.NewBoard()
	bd.Name = preBoard
	bd.Delete()
	log.Info("Board List Migrated")

	// keyword
	if postBoard != "" {
		subs := keyword.Subscribers(preBoard)
		for _, sub := range subs {
			keyword.AddSubscriber(postBoard, sub)
		}
	}
	keyword.Destroy(preBoard)
	log.Info("Keyword Migrated")

	// author
	if postBoard != "" {
		subs := author.Subscribers(preBoard)
		for _, sub := range subs {
			author.AddSubscriber(postBoard, sub)
		}
	}
	author.Destroy(preBoard)
	log.Info("Author Migrated")

	// pushsum
	if postBoard != "" {
		pushsum.Add(postBoard)
		subs := pushsum.ListSubscribers(preBoard)
		for _, sub := range subs {
			pushsum.AddSubscriber(postBoard, sub)
		}
	}
	pushsum.Remove(preBoard)
	pushsum.Destroy(preBoard)
	pushsum.RenameDiffListKeys(preBoard, postBoard)
	log.Info("Pushsum Migrated")

	// articles
	codes := new(article.Articles).List()
	for _, code := range codes {
		a := new(article.Article).Find(code)
		if strings.EqualFold(a.Board, preBoard) {
			if postBoard == "" {
				a.Destroy()
			} else {
				a.Board = postBoard
				a.Save()
			}
			log.WithField("code", code).Info("Article Migrated")
		}
	}
	log.Info("Articles Migrated")

	// user
	for _, u := range models.User.All() {
		for _, sub := range u.Subscribes {
			if strings.EqualFold(sub.Board, preBoard) {
				u.Subscribes.Delete(sub)
				if postBoard != "" {
					for _, postSub := range u.Subscribes {
						if strings.EqualFold(postSub.Board, postBoard) {
							if postSub.PushSum.Up == 0 && postSub.PushSum.Down == 0 {
								postSub.PushSum.Up, postSub.PushSum.Down = sub.PushSum.Up, sub.PushSum.Down
								u.Subscribes.Update(postSub)
							}
						}
					}
					sub.Board = postBoard
					u.Subscribes.Add(sub)
				}
				u.Update()
				log.WithField("account", u.Account).Info("User Subscription Migrated")
			}
		}
	}
	log.Info("Board Migrated")
}
<commit_msg>:bug: move boardMap from parameter to migrateBoard constructor<commit_after>package jobs

import (
	"strings"

	log "github.com/meifamily/logrus"
	"github.com/meifamily/ptt-alertor/models"
	"github.com/meifamily/ptt-alertor/models/article"
	"github.com/meifamily/ptt-alertor/models/author"
	"github.com/meifamily/ptt-alertor/models/board"
	"github.com/meifamily/ptt-alertor/models/keyword"
	"github.com/meifamily/ptt-alertor/models/pushsum"
)

type migrateBoard struct {
	boardMap map[string]string
}

func newMigrateBoard(boardMap map[string]string) *migrateBoard {
	return &migrateBoard{boardMap: boardMap}
}

func (m migrateBoard) Run() {
	for pre, post := range m.boardMap {
		m.RunSingle(pre, post)
	}
}

func (migrateBoard) RunSingle(preBoard string, postBoard string) {
	// board list
	if postBoard != "" {
		addBoard(postBoard)
	}
	bd := board.NewBoard()
	bd.Name = preBoard
	bd.Delete()
	log.Info("Board List Migrated")

	// keyword
	if postBoard != "" {
		subs := keyword.Subscribers(preBoard)
		for _, sub := range subs {
			keyword.AddSubscriber(postBoard, sub)
		}
	}
	keyword.Destroy(preBoard)
	log.Info("Keyword Migrated")

	// author
	if postBoard != "" {
		subs := author.Subscribers(preBoard)
		for _, sub := range subs {
			author.AddSubscriber(postBoard, sub)
		}
	}
	author.Destroy(preBoard)
	log.Info("Author Migrated")

	// pushsum
	if postBoard != "" {
		pushsum.Add(postBoard)
		subs := pushsum.ListSubscribers(preBoard)
		for _, sub := range subs {
			pushsum.AddSubscriber(postBoard, sub)
		}
	}
	pushsum.Remove(preBoard)
	pushsum.Destroy(preBoard)
	pushsum.RenameDiffListKeys(preBoard, postBoard)
	log.Info("Pushsum Migrated")

	// articles
	codes := new(article.Articles).List()
	for _, code := range codes {
		a := new(article.Article).Find(code)
		if strings.EqualFold(a.Board, preBoard) {
			if postBoard == "" {
				a.Destroy()
			} else {
				a.Board = postBoard
				a.Save()
			}
			log.WithField("code", code).Info("Article Migrated")
		}
	}
	log.Info("Articles Migrated")

	// user
	for _, u := range models.User.All() {
		for _, sub := range u.Subscribes {
			if strings.EqualFold(sub.Board, preBoard) {
				u.Subscribes.Delete(sub)
				if postBoard != "" {
					for _, postSub := range u.Subscribes {
						if strings.EqualFold(postSub.Board, postBoard) {
							if postSub.PushSum.Up == 0 && postSub.PushSum.Down == 0 {
								postSub.PushSum.Up, postSub.PushSum.Down = sub.PushSum.Up, sub.PushSum.Down
								u.Subscribes.Update(postSub)
							}
						}
					}
					sub.Board = postBoard
					u.Subscribes.Add(sub)
				}
				u.Update()
				log.WithField("account", u.Account).Info("User Subscription Migrated")
			}
		}
	}
	log.Info("Board Migrated")
}
<|endoftext|>


<commit_before>package userController

import (
	"strconv"
	"time"
	"fmt"

	"net/http"

	"github.com/NyaaPantsu/nyaa/controllers/router"
	"github.com/NyaaPantsu/nyaa/models"
	"github.com/NyaaPantsu/nyaa/models/notifications"
	"github.com/NyaaPantsu/nyaa/models/users"
	"github.com/NyaaPantsu/nyaa/templates"
	"github.com/NyaaPantsu/nyaa/utils/cookies"
	"github.com/NyaaPantsu/nyaa/utils/crypto"
	"github.com/NyaaPantsu/nyaa/utils/email"
	msg "github.com/NyaaPantsu/nyaa/utils/messages"
	"github.com/NyaaPantsu/nyaa/utils/publicSettings"
	"github.com/NyaaPantsu/nyaa/utils/validator"
	"github.com/NyaaPantsu/nyaa/utils/validator/user"
	"github.com/gin-gonic/gin"
)

// UserProfileDelete :  Deleting User Profile
func UserProfileDelete(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)

	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser == nil{
		currentUser := router.GetUser(c)
		if (currentUser.CurrentOrAdmin(userProfile.ID)) {
			_, err := userProfile.Delete(currentUser)
			if err == nil && currentUser.CurrentUserIdentical(userProfile.ID) {
				cookies.Clear(c)
			}
		}
		templates.Static(c, "site/static/delete_success.jet.html")
	}
}

// UserProfileHandler :  Getting User Profile
func UserProfileHandler(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(c)
	messages := msg.GetMessages(c)

	if c.Param("id") != "0" && id == 0 && ContainsNonNumbersChars(c.Param("id")) {
		c.Redirect(http.StatusSeeOther, fmt.Sprintf("/username/%s", c.Param("id")))
		return
	}

	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser == nil {
		currentUser := router.GetUser(c)
		follow := c.Request.URL.Query()["followed"]
		unfollow := c.Request.URL.Query()["unfollowed"]
		deleteVar := c.Request.URL.Query()["delete"]

		if !((deleteVar != nil) && (currentUser.CurrentOrAdmin(userProfile.ID))) {
			if follow != nil {
				messages.AddInfof("infos", Ts("user_followed_msg"), userProfile.Username)
			}
			if unfollow != nil {
				messages.AddInfof("infos", Ts("user_unfollowed_msg"), userProfile.Username)
			}
			userProfile.ParseSettings()

			templates.UserProfile(c, userProfile)
		}
	} else {
		variables := templates.Commonvariables(c)
		templates.Render(c, "errors/user_not_found.jet.html", variables)
	}
}

func ContainsNonNumbersChars(source string) bool {
	for char := range source {
		if char < 30 || char > 39 {
			return true
		}
	}
	return false
}

func UserGetFromName(c *gin.Context) {
	username := c.Param("username")

	Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(c)
	messages := msg.GetMessages(c)

	userProfile, _, _, err := users.FindByUsername(username)
	if err == nil {
		currentUser := router.GetUser(c)
		follow := c.Request.URL.Query()["followed"]
		unfollow := c.Request.URL.Query()["unfollowed"]
		deleteVar := c.Request.URL.Query()["delete"]

		if (deleteVar != nil) && (currentUser.CurrentOrAdmin(userProfile.ID)) {
			_, err := userProfile.Delete(currentUser)
			if err == nil && currentUser.CurrentUserIdentical(userProfile.ID) {
				cookies.Clear(c)
			}
			templates.Static(c, "site/static/delete_success.jet.html")
		} else {
			if follow != nil {
				messages.AddInfof("infos", Ts("user_followed_msg"), userProfile.Username)
			}
			if unfollow != nil {
				messages.AddInfof("infos", Ts("user_unfollowed_msg"), userProfile.Username)
			}
			userProfile.ParseSettings()

			templates.UserProfile(c, userProfile)
		}
	} else {
		variables := templates.Commonvariables(c)
		searchForm := templates.NewSearchForm(c)
		searchForm.User = username
		variables.Set("Search", searchForm)
		templates.Render(c, "errors/user_not_found.jet.html", variables)
	}
}

func RedirectToUserSearch(c *gin.Context) {
	username := c.Query("username")

	if username == "" {
		variables := templates.Commonvariables(c)
		templates.Render(c, "errors/user_not_found.jet.html", variables)
	} else {
		c.Redirect(http.StatusSeeOther, fmt.Sprintf("/username/%s", username))
	}
}

// UserDetailsHandler : Getting User Profile Details View
func UserDetailsHandler(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	currentUser := router.GetUser(c)

	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser == nil && currentUser.CurrentOrAdmin(userProfile.ID) {
		b := userValidator.UserForm{}
		c.Bind(&b)
		availableLanguages := publicSettings.GetAvailableLanguages()
		userProfile.ParseSettings()
		templates.UserProfileEdit(c, userProfile, b, availableLanguages)
	} else {
		variables := templates.Commonvariables(c)
		templates.Render(c, "errors/user_not_found.jet.html", variables)
	}
}

// UserProfileFormHandler : Getting View User Profile Update
func UserProfileFormHandler(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	currentUser := router.GetUser(c)
	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser != nil || !currentUser.CurrentOrAdmin(userProfile.ID) || userProfile.ID == 0 {
		c.Status(http.StatusNotFound)
		return
	}
	userProfile.ParseSettings()
	messages := msg.GetMessages(c)
	userForm := userValidator.UserForm{}
	userSettingsForm := userValidator.UserSettingsForm{}

	if len(c.PostForm("email")) > 0 {
		if !userValidator.EmailValidation(c.PostForm("email")) {
			messages.AddErrorT("email", "email_not_valid")
		}
	}
	if len(c.PostForm("username")) > 0 {
		if !userValidator.ValidateUsername(c.PostForm("username")) {
			messages.AddErrorT("username", "username_illegal")
		}
	}

	if !messages.HasErrors() {
		c.Bind(&userForm)
		c.Bind(&userSettingsForm)
		if !currentUser.HasAdmin() {
			userForm.Username = userProfile.Username
			userForm.Status = userProfile.Status
		} else {
			if userProfile.Status != userForm.Status && userForm.Status == 2 {
				messages.AddErrorT("errors", "elevating_user_error")
			}
		}
		validator.ValidateForm(&userForm, messages)
		if !messages.HasErrors() {
			if userForm.Email != userProfile.Email {
				email.SendVerificationToUser(currentUser, userForm.Email)
				messages.AddInfoTf("infos", "email_changed", userForm.Email)
				userForm.Email = userProfile.Email // reset, it will be set when user clicks verification
			}
			user, _, err := users.UpdateFromRequest(c, &userForm, &userSettingsForm, currentUser, uint(id))
			if err != nil {
				messages.Error(err)
			}
			if userForm.Email != user.Email {
				// send verification to new email and keep old
				email.SendVerificationToUser(user, userForm.Email)
			}
			if !messages.HasErrors() {
				messages.AddInfoT("infos", "profile_updated")
			}
		}
	}
	availableLanguages := publicSettings.GetAvailableLanguages()
	templates.UserProfileEdit(c, userProfile, userForm, availableLanguages)
}

// UserNotificationsHandler : Controller to show user notifications
func UserNotificationsHandler(c *gin.Context) {
	currentUser := router.GetUser(c)
	if currentUser.ID > 0 {
		messages := msg.GetMessages(c)
		if c.Request.URL.Query()["clear"] != nil {
			notifications.DeleteNotifications(currentUser.ID, false)
			messages.AddInfoT("infos", "notifications_cleared")
			NewNotifications := []models.Notification{}
			for _, notif := range currentUser.Notifications {
				if !notif.Read {
					NewNotifications = append(NewNotifications, notif)
				}
			}
			currentUser.Notifications = NewNotifications

		} else if c.Request.URL.Query()["clear_all"] != nil {
			notifications.DeleteNotifications(currentUser.ID, true)
			messages.AddInfoT("infos", "notifications_cleared")
			currentUser.Notifications = []models.Notification{}
		}
		templates.UserProfileNotifications(c, currentUser)
	} else {
		c.Status(http.StatusNotFound)
	}
}

// UserAPIKeyResetHandler : Controller to reset user api key
func UserAPIKeyResetHandler(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	currentUser := router.GetUser(c)

	messages := msg.GetMessages(c)
	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser != nil || !currentUser.CurrentOrAdmin(userProfile.ID) || userProfile.ID == 0 {
		c.Status(http.StatusNotFound)
		return
	}
	userProfile.APIToken, _ = crypto.GenerateRandomToken32()
	userProfile.APITokenExpiry = time.Unix(0, 0)
	_, errorUser = userProfile.UpdateRaw()
	if errorUser != nil {
		messages.Error(errorUser)
	} else {
		messages.AddInfoT("infos", "profile_updated")
	}
	UserDetailsHandler(c)
}
<commit_msg>Update profile.go<commit_after>package userController

import (
	"strconv"
	"time"
	"fmt"

	"net/http"

	"github.com/NyaaPantsu/nyaa/controllers/router"
	"github.com/NyaaPantsu/nyaa/models"
	"github.com/NyaaPantsu/nyaa/models/notifications"
	"github.com/NyaaPantsu/nyaa/models/users"
	"github.com/NyaaPantsu/nyaa/templates"
	"github.com/NyaaPantsu/nyaa/utils/cookies"
	"github.com/NyaaPantsu/nyaa/utils/crypto"
	"github.com/NyaaPantsu/nyaa/utils/email"
	msg "github.com/NyaaPantsu/nyaa/utils/messages"
	"github.com/NyaaPantsu/nyaa/utils/publicSettings"
	"github.com/NyaaPantsu/nyaa/utils/validator"
	"github.com/NyaaPantsu/nyaa/utils/validator/user"
	"github.com/gin-gonic/gin"
)

// UserProfileDelete :  Deleting User Profile
func UserProfileDelete(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)

	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser == nil{
		currentUser := router.GetUser(c)
		if (currentUser.CurrentOrAdmin(userProfile.ID)) {
			_, err := userProfile.Delete(currentUser)
			if err == nil && currentUser.CurrentUserIdentical(userProfile.ID) {
				cookies.Clear(c)
			}
		}
		templates.Static(c, "site/static/delete_success.jet.html")
	}
}

// UserProfileHandler :  Getting User Profile
func UserProfileHandler(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(c)
	messages := msg.GetMessages(c)

	if c.Param("id") != "0" && id == 0 && ContainsNonNumbersChars(c.Param("id")) {
		c.Redirect(http.StatusSeeOther, fmt.Sprintf("/username/%s", c.Param("id")))
		return
	}

	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser == nil {
		currentUser := router.GetUser(c)
		follow := c.Request.URL.Query()["followed"]
		unfollow := c.Request.URL.Query()["unfollowed"]
		deleteVar := c.Request.URL.Query()["delete"]

		if !((deleteVar != nil) && (currentUser.CurrentOrAdmin(userProfile.ID))) {
			if follow != nil {
				messages.AddInfof("infos", Ts("user_followed_msg"), userProfile.Username)
			}
			if unfollow != nil {
				messages.AddInfof("infos", Ts("user_unfollowed_msg"), userProfile.Username)
			}
			userProfile.ParseSettings()

			templates.UserProfile(c, userProfile)
		}
	} else {
		variables := templates.Commonvariables(c)
		templates.Render(c, "errors/user_not_found.jet.html", variables)
	}
}

func ContainsNonNumbersChars(source string) bool {
	for char := range source {
		if char < 30 || char > 39 {
			return true
		}
	}
	return false
}

func UserGetFromName(c *gin.Context) {
	username := c.Param("username")

	Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(c)
	messages := msg.GetMessages(c)

	userProfile, _, _, err := users.FindByUsername(username)
	if err == nil {
		currentUser := router.GetUser(c)
		follow := c.Request.URL.Query()["followed"]
		unfollow := c.Request.URL.Query()["unfollowed"]
		deleteVar := c.Request.URL.Query()["delete"]

		if (deleteVar != nil) && (currentUser.CurrentOrAdmin(userProfile.ID)) {
			_, err := userProfile.Delete(currentUser)
			if err == nil && currentUser.CurrentUserIdentical(userProfile.ID) {
				cookies.Clear(c)
			}
			templates.Static(c, "site/static/delete_success.jet.html")
		} else {
			if follow != nil {
				messages.AddInfof("infos", Ts("user_followed_msg"), userProfile.Username)
			}
			if unfollow != nil {
				messages.AddInfof("infos", Ts("user_unfollowed_msg"), userProfile.Username)
			}
			userProfile.ParseSettings()

			templates.UserProfile(c, userProfile)
		}
	} else {
		variables := templates.Commonvariables(c)
		searchForm := templates.NewSearchForm(c)
		searchForm.User = username
		variables.Set("Search", searchForm)
		templates.Render(c, "errors/user_not_found.jet.html", variables)
	}
}

func RedirectToUserSearch(c *gin.Context) {
	username := c.Query("username")

	if username == "" {
		variables := templates.Commonvariables(c)
		templates.Render(c, "errors/user_not_found.jet.html", variables)
	} else {
		c.Redirect(http.StatusSeeOther, fmt.Sprintf("/username/%s", username))
	}
}

// UserDetailsHandler : Getting User Profile Details View
func UserDetailsHandler(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	currentUser := router.GetUser(c)

	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser == nil && currentUser.CurrentOrAdmin(userProfile.ID) {
		b := userValidator.UserForm{}
		c.Bind(&b)
		availableLanguages := publicSettings.GetAvailableLanguages()
		userProfile.ParseSettings()
		templates.UserProfileEdit(c, userProfile, b, availableLanguages)
	} else {
		variables := templates.Commonvariables(c)
		templates.Render(c, "errors/user_not_found.jet.html", variables)
	}
}

// UserProfileFormHandler : Getting View User Profile Update
func UserProfileFormHandler(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	currentUser := router.GetUser(c)
	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser != nil || !currentUser.CurrentOrAdmin(userProfile.ID) || userProfile.ID == 0 {
		c.Status(http.StatusNotFound)
		return
	}
	userProfile.ParseSettings()
	messages := msg.GetMessages(c)
	userForm := userValidator.UserForm{}
	userSettingsForm := userValidator.UserSettingsForm{}

	if len(c.PostForm("email")) > 0 {
		if !userValidator.EmailValidation(c.PostForm("email")) {
			messages.AddErrorT("email", "email_not_valid")
		}
	}
	if len(c.PostForm("username")) > 0 {
		if !userValidator.ValidateUsername(c.PostForm("username")) {
			messages.AddErrorT("username", "username_illegal")
		}
	}

	if !messages.HasErrors() {
		c.Bind(&userForm)
		c.Bind(&userSettingsForm)
		if !currentUser.HasAdmin() {
			userForm.Username = userProfile.Username
			userForm.Status = userProfile.Status
		} else {
			if userProfile.Status != userForm.Status && userForm.Status == 2 {
				messages.AddErrorT("errors", "elevating_user_error")
			}
		}
		validator.ValidateForm(&userForm, messages)
		if !messages.HasErrors() {
			if userForm.Email != userProfile.Email {
				email.SendVerificationToUser(currentUser, userForm.Email)
				messages.AddInfoTf("infos", "email_changed", userForm.Email)
				userForm.Email = userProfile.Email // reset, it will be set when user clicks verification
			}
			user, _, err := users.UpdateFromRequest(c, &userForm, &userSettingsForm, currentUser, uint(id))
			if err != nil {
				messages.Error(err)
			}
			if userForm.Email != user.Email {
				// send verification to new email and keep old
				email.SendVerificationToUser(user, userForm.Email)
			}
			if !messages.HasErrors() {
				messages.AddInfoT("infos", "profile_updated")
				userProfile = user
			}
		}
	}
	availableLanguages := publicSettings.GetAvailableLanguages()
	templates.UserProfileEdit(c, userProfile, userForm, availableLanguages)
}

// UserNotificationsHandler : Controller to show user notifications
func UserNotificationsHandler(c *gin.Context) {
	currentUser := router.GetUser(c)
	if currentUser.ID > 0 {
		messages := msg.GetMessages(c)
		if c.Request.URL.Query()["clear"] != nil {
			notifications.DeleteNotifications(currentUser.ID, false)
			messages.AddInfoT("infos", "notifications_cleared")
			NewNotifications := []models.Notification{}
			for _, notif := range currentUser.Notifications {
				if !notif.Read {
					NewNotifications = append(NewNotifications, notif)
				}
			}
			currentUser.Notifications = NewNotifications

		} else if c.Request.URL.Query()["clear_all"] != nil {
			notifications.DeleteNotifications(currentUser.ID, true)
			messages.AddInfoT("infos", "notifications_cleared")
			currentUser.Notifications = []models.Notification{}
		}
		templates.UserProfileNotifications(c, currentUser)
	} else {
		c.Status(http.StatusNotFound)
	}
}

// UserAPIKeyResetHandler : Controller to reset user api key
func UserAPIKeyResetHandler(c *gin.Context) {
	id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
	currentUser := router.GetUser(c)

	messages := msg.GetMessages(c)
	userProfile, _, errorUser := users.FindForAdmin(uint(id))
	if errorUser != nil || !currentUser.CurrentOrAdmin(userProfile.ID) || userProfile.ID == 0 {
		c.Status(http.StatusNotFound)
		return
	}
	userProfile.APIToken, _ = crypto.GenerateRandomToken32()
	userProfile.APITokenExpiry = time.Unix(0, 0)
	_, errorUser = userProfile.UpdateRaw()
	if errorUser != nil {
		messages.Error(errorUser)
	} else {
		messages.AddInfoT("infos", "profile_updated")
	}
	UserDetailsHandler(c)
}
<|endoftext|>


<commit_before>package aws

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

	"github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEip() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEipCreate,
		Read:   resourceAwsEipRead,
		Update: resourceAwsEipUpdate,
		Delete: resourceAwsEipDelete,

		Schema: map[string]*schema.Schema{
			"vpc": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
			},

			"instance": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"allocation_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"association_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"domain": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"public_ip": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"private_ip": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsEipCreate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2SDKconn

	// By default, we're not in a VPC
	domainOpt := ""
	if v := d.Get("vpc"); v != nil && v.(bool) {
		domainOpt = "vpc"
	}

	allocOpts := &ec2.AllocateAddressInput{
		Domain: aws.String(domainOpt),
	}

	log.Printf("[DEBUG] EIP create configuration: %#v", allocOpts)
	allocResp, err := ec2conn.AllocateAddress(allocOpts)
	if err != nil {
		return fmt.Errorf("Error creating EIP: %s", err)
	}

	// The domain tells us if we're in a VPC or not
	d.Set("domain", allocResp.Domain)

	// Assign the eips (unique) allocation id for use later
	// the EIP api has a conditional unique ID (really), so
	// if we're in a VPC we need to save the ID as such, otherwise
	// it defaults to using the public IP
	log.Printf("[DEBUG] EIP Allocate: %#v", allocResp)
	if d.Get("domain").(string) == "vpc" {
		d.SetId(*allocResp.AllocationID)
	} else {
		d.SetId(*allocResp.PublicIP)
	}

	log.Printf("[INFO] EIP ID: %s (domain: %v)", d.Id(), *allocResp.Domain)
	return resourceAwsEipUpdate(d, meta)
}

func resourceAwsEipRead(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2SDKconn

	domain := resourceAwsEipDomain(d)
	id := d.Id()

	assocIds := []*string{}
	publicIps := []*string{}
	if domain == "vpc" {
		assocIds = []*string{aws.String(id)}
	} else {
		publicIps = []*string{aws.String(id)}
	}

	log.Printf(
		"[DEBUG] EIP describe configuration: %#v, %#v (domain: %s)",
		assocIds, publicIps, domain)

	req := &ec2.DescribeAddressesInput{
		AllocationIDs: assocIds,
		PublicIPs:     publicIps,
	}
	describeAddresses, err := ec2conn.DescribeAddresses(req)
	if err != nil {
		if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidAllocationID.NotFound" {
			d.SetId("")
			return nil
		}

		return fmt.Errorf("Error retrieving EIP: %s", err)
	}

	// Verify AWS returned our EIP
	if len(describeAddresses.Addresses) != 1 ||
		*describeAddresses.Addresses[0].AllocationID != id ||
		*describeAddresses.Addresses[0].PublicIP != id {
		if err != nil {
			return fmt.Errorf("Unable to find EIP: %#v", describeAddresses.Addresses)
		}
	}

	address := describeAddresses.Addresses[0]

	d.Set("association_id", address.AssociationID)
	d.Set("instance", address.InstanceID)
	d.Set("private_ip", address.PrivateIPAddress)
	d.Set("public_ip", address.PublicIP)

	return nil
}

func resourceAwsEipUpdate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2SDKconn

	domain := resourceAwsEipDomain(d)

	// Only register with an instance if we have one
	if v, ok := d.GetOk("instance"); ok {
		instanceId := v.(string)

		assocOpts := &ec2.AssociateAddressInput{
			InstanceID: aws.String(instanceId),
			PublicIP:   aws.String(d.Id()),
		}

		// more unique ID conditionals
		if domain == "vpc" {
			assocOpts = &ec2.AssociateAddressInput{
				InstanceID:   aws.String(instanceId),
				AllocationID: aws.String(d.Id()),
				PublicIP:     aws.String(""),
			}
		}

		log.Printf("[DEBUG] EIP associate configuration: %#v (domain: %v)", assocOpts, domain)
		_, err := ec2conn.AssociateAddress(assocOpts)
		if err != nil {
			return fmt.Errorf("Failure associating instances: %s", err)
		}
	}

	return resourceAwsEipRead(d, meta)
}

func resourceAwsEipDelete(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2SDKconn

	if err := resourceAwsEipRead(d, meta); err != nil {
		return err
	}
	if d.Id() == "" {
		// This might happen from the read
		return nil
	}

	// If we are attached to an instance, detach first.
	if d.Get("instance").(string) != "" {
		log.Printf("[DEBUG] Disassociating EIP: %s", d.Id())
		var err error
		switch resourceAwsEipDomain(d) {
		case "vpc":
			_, err = ec2conn.DisassociateAddress(&ec2.DisassociateAddressInput{
				AssociationID: aws.String(d.Get("association_id").(string)),
			})
		case "standard":
			_, err = ec2conn.DisassociateAddress(&ec2.DisassociateAddressInput{
				PublicIP: aws.String(d.Get("public_ip").(string)),
			})
		}
		if err != nil {
			return err
		}
	}

	domain := resourceAwsEipDomain(d)
	return resource.Retry(3*time.Minute, func() error {
		var err error
		switch domain {
		case "vpc":
			log.Printf(
				"[DEBUG] EIP release (destroy) address allocation: %v",
				d.Id())
			_, err = ec2conn.ReleaseAddress(&ec2.ReleaseAddressInput{
				AllocationID: aws.String(d.Id()),
			})
		case "standard":
			log.Printf("[DEBUG] EIP release (destroy) address: %v", d.Id())
			_, err = ec2conn.ReleaseAddress(&ec2.ReleaseAddressInput{
				PublicIP: aws.String(d.Id()),
			})
		}

		if err == nil {
			return nil
		}
		if _, ok := err.(aws.APIError); !ok {
			return resource.RetryError{Err: err}
		}

		return err
	})
}

func resourceAwsEipDomain(d *schema.ResourceData) string {
	if v, ok := d.GetOk("domain"); ok {
		return v.(string)
	} else if strings.Contains(d.Id(), "eipalloc") {
		// We have to do this for backwards compatibility since TF 0.1
		// didn't have the "domain" computed attribute.
		return "vpc"
	}

	return "standard"
}
<commit_msg>providers/aws: check allocationId only if it's vpc, fixes #1345<commit_after>package aws

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

	"github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEip() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEipCreate,
		Read:   resourceAwsEipRead,
		Update: resourceAwsEipUpdate,
		Delete: resourceAwsEipDelete,

		Schema: map[string]*schema.Schema{
			"vpc": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				ForceNew: true,
			},

			"instance": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},

			"allocation_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"association_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"domain": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"public_ip": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"private_ip": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsEipCreate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2SDKconn

	// By default, we're not in a VPC
	domainOpt := ""
	if v := d.Get("vpc"); v != nil && v.(bool) {
		domainOpt = "vpc"
	}

	allocOpts := &ec2.AllocateAddressInput{
		Domain: aws.String(domainOpt),
	}

	log.Printf("[DEBUG] EIP create configuration: %#v", allocOpts)
	allocResp, err := ec2conn.AllocateAddress(allocOpts)
	if err != nil {
		return fmt.Errorf("Error creating EIP: %s", err)
	}

	// The domain tells us if we're in a VPC or not
	d.Set("domain", allocResp.Domain)

	// Assign the eips (unique) allocation id for use later
	// the EIP api has a conditional unique ID (really), so
	// if we're in a VPC we need to save the ID as such, otherwise
	// it defaults to using the public IP
	log.Printf("[DEBUG] EIP Allocate: %#v", allocResp)
	if d.Get("domain").(string) == "vpc" {
		d.SetId(*allocResp.AllocationID)
	} else {
		d.SetId(*allocResp.PublicIP)
	}

	log.Printf("[INFO] EIP ID: %s (domain: %v)", d.Id(), *allocResp.Domain)
	return resourceAwsEipUpdate(d, meta)
}

func resourceAwsEipRead(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2SDKconn

	domain := resourceAwsEipDomain(d)
	id := d.Id()

	assocIds := []*string{}
	publicIps := []*string{}
	if domain == "vpc" {
		assocIds = []*string{aws.String(id)}
	} else {
		publicIps = []*string{aws.String(id)}
	}

	log.Printf(
		"[DEBUG] EIP describe configuration: %#v, %#v (domain: %s)",
		assocIds, publicIps, domain)

	req := &ec2.DescribeAddressesInput{
		AllocationIDs: assocIds,
		PublicIPs:     publicIps,
	}
	describeAddresses, err := ec2conn.DescribeAddresses(req)
	if err != nil {
		if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidAllocationID.NotFound" {
			d.SetId("")
			return nil
		}

		return fmt.Errorf("Error retrieving EIP: %s", err)
	}

	// Verify AWS returned our EIP
	if len(describeAddresses.Addresses) != 1 ||
		(domain == "vpc" && *describeAddresses.Addresses[0].AllocationID != id) ||
		*describeAddresses.Addresses[0].PublicIP != id {
		if err != nil {
			return fmt.Errorf("Unable to find EIP: %#v", describeAddresses.Addresses)
		}
	}

	address := describeAddresses.Addresses[0]

	d.Set("association_id", address.AssociationID)
	d.Set("instance", address.InstanceID)
	d.Set("private_ip", address.PrivateIPAddress)
	d.Set("public_ip", address.PublicIP)

	return nil
}

func resourceAwsEipUpdate(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2SDKconn

	domain := resourceAwsEipDomain(d)

	// Only register with an instance if we have one
	if v, ok := d.GetOk("instance"); ok {
		instanceId := v.(string)

		assocOpts := &ec2.AssociateAddressInput{
			InstanceID: aws.String(instanceId),
			PublicIP:   aws.String(d.Id()),
		}

		// more unique ID conditionals
		if domain == "vpc" {
			assocOpts = &ec2.AssociateAddressInput{
				InstanceID:   aws.String(instanceId),
				AllocationID: aws.String(d.Id()),
				PublicIP:     aws.String(""),
			}
		}

		log.Printf("[DEBUG] EIP associate configuration: %#v (domain: %v)", assocOpts, domain)
		_, err := ec2conn.AssociateAddress(assocOpts)
		if err != nil {
			return fmt.Errorf("Failure associating instances: %s", err)
		}
	}

	return resourceAwsEipRead(d, meta)
}

func resourceAwsEipDelete(d *schema.ResourceData, meta interface{}) error {
	ec2conn := meta.(*AWSClient).ec2SDKconn

	if err := resourceAwsEipRead(d, meta); err != nil {
		return err
	}
	if d.Id() == "" {
		// This might happen from the read
		return nil
	}

	// If we are attached to an instance, detach first.
	if d.Get("instance").(string) != "" {
		log.Printf("[DEBUG] Disassociating EIP: %s", d.Id())
		var err error
		switch resourceAwsEipDomain(d) {
		case "vpc":
			_, err = ec2conn.DisassociateAddress(&ec2.DisassociateAddressInput{
				AssociationID: aws.String(d.Get("association_id").(string)),
			})
		case "standard":
			_, err = ec2conn.DisassociateAddress(&ec2.DisassociateAddressInput{
				PublicIP: aws.String(d.Get("public_ip").(string)),
			})
		}
		if err != nil {
			return err
		}
	}

	domain := resourceAwsEipDomain(d)
	return resource.Retry(3*time.Minute, func() error {
		var err error
		switch domain {
		case "vpc":
			log.Printf(
				"[DEBUG] EIP release (destroy) address allocation: %v",
				d.Id())
			_, err = ec2conn.ReleaseAddress(&ec2.ReleaseAddressInput{
				AllocationID: aws.String(d.Id()),
			})
		case "standard":
			log.Printf("[DEBUG] EIP release (destroy) address: %v", d.Id())
			_, err = ec2conn.ReleaseAddress(&ec2.ReleaseAddressInput{
				PublicIP: aws.String(d.Id()),
			})
		}

		if err == nil {
			return nil
		}
		if _, ok := err.(aws.APIError); !ok {
			return resource.RetryError{Err: err}
		}

		return err
	})
}

func resourceAwsEipDomain(d *schema.ResourceData) string {
	if v, ok := d.GetOk("domain"); ok {
		return v.(string)
	} else if strings.Contains(d.Id(), "eipalloc") {
		// We have to do this for backwards compatibility since TF 0.1
		// didn't have the "domain" computed attribute.
		return "vpc"
	}

	return "standard"
}
<|endoftext|>


<commit_before>package triton

import (
	"errors"
	"strconv"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/joyent/gosdc/cloudapi"
)

func resourceVLAN() *schema.Resource {
	return &schema.Resource{
		Create: resourceVLANCreate,
		Exists: resourceVLANExists,
		Read:   resourceVLANRead,
		Update: resourceVLANUpdate,
		Delete: resourceVLANDelete,

		Schema: map[string]*schema.Schema{
			"vlan_id": {
				Description: "number between 0-4095 indicating VLAN ID",
				Required:    true,
				ForceNew:    true,
				Type:        schema.TypeInt,
				ValidateFunc: func(val interface{}, field string) (warn []string, err []error) {
					value := val.(int)
					if value < 0 || value > 4095 {
						err = append(err, errors.New("vlan_id must be between 0 and 4095"))
					}
					return
				},
			},
			"name": {
				Description: "Unique name to identify VLAN",
				Required:    true,
				Type:        schema.TypeString,
			},
			"description": {
				Description: "Optional description of the VLAN",
				Optional:    true,
				Type:        schema.TypeString,
			},
		},
	}
}

func resourceVLANCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*cloudapi.Client)

	vlan, err := client.CreateFabricVLAN(cloudapi.FabricVLAN{
		Id:          int16(d.Get("vlan_id").(int)),
		Name:        d.Get("name").(string),
		Description: d.Get("description").(string),
	})
	if err != nil {
		return err
	}

	d.SetId(resourceVLANIDString(vlan.Id))
	return resourceVLANRead(d, meta)
}

func resourceVLANExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	client := meta.(*cloudapi.Client)

	id, err := resourceVLANIDInt16(d.Id())
	if err != nil {
		return false, err
	}

	vlan, err := client.GetFabricVLAN(id)

	return vlan != nil && err == nil, err
}

func resourceVLANRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*cloudapi.Client)

	vlan, err := client.GetFabricVLAN(int16(d.Get("vlan_id").(int)))
	if err != nil {
		return err
	}

	d.SetId(resourceVLANIDString(vlan.Id))
	d.Set("vlan_id", vlan.Id)
	d.Set("name", vlan.Name)
	d.Set("description", vlan.Description)

	return nil
}

func resourceVLANUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*cloudapi.Client)

	vlan, err := client.UpdateFabricVLAN(cloudapi.FabricVLAN{
		Id:          int16(d.Get("vlan_id").(int)),
		Name:        d.Get("name").(string),
		Description: d.Get("description").(string),
	})
	if err != nil {
		return err
	}

	d.SetId(resourceVLANIDString(vlan.Id))
	return resourceVLANRead(d, meta)
}

func resourceVLANDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*cloudapi.Client)

	id, err := resourceVLANIDInt16(d.Id())
	if err != nil {
		return err
	}

	return client.DeleteFabricVLAN(id)
}

// convenience conversion functions

func resourceVLANIDString(id int16) string {
	return strconv.Itoa(int(id))
}

func resourceVLANIDInt16(id string) (int16, error) {
	result, err := strconv.ParseInt(id, 10, 16)
	if err != nil {
		return 0, err
	}

	return int16(result), nil
}
<commit_msg>provider/triton: Import triton_vlan resources<commit_after>package triton

import (
	"errors"
	"strconv"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/joyent/gosdc/cloudapi"
)

func resourceVLAN() *schema.Resource {
	return &schema.Resource{
		Create: resourceVLANCreate,
		Exists: resourceVLANExists,
		Read:   resourceVLANRead,
		Update: resourceVLANUpdate,
		Delete: resourceVLANDelete,
		Importer: &schema.ResourceImporter{
			State: resourceVLANImporter,
		},

		Schema: map[string]*schema.Schema{
			"vlan_id": {
				Description: "number between 0-4095 indicating VLAN ID",
				Required:    true,
				ForceNew:    true,
				Type:        schema.TypeInt,
				ValidateFunc: func(val interface{}, field string) (warn []string, err []error) {
					value := val.(int)
					if value < 0 || value > 4095 {
						err = append(err, errors.New("vlan_id must be between 0 and 4095"))
					}
					return
				},
			},
			"name": {
				Description: "Unique name to identify VLAN",
				Required:    true,
				Type:        schema.TypeString,
			},
			"description": {
				Description: "Optional description of the VLAN",
				Optional:    true,
				Type:        schema.TypeString,
			},
		},
	}
}

func resourceVLANCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*cloudapi.Client)

	vlan, err := client.CreateFabricVLAN(cloudapi.FabricVLAN{
		Id:          int16(d.Get("vlan_id").(int)),
		Name:        d.Get("name").(string),
		Description: d.Get("description").(string),
	})
	if err != nil {
		return err
	}

	d.SetId(resourceVLANIDString(vlan.Id))
	return resourceVLANRead(d, meta)
}

func resourceVLANExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	client := meta.(*cloudapi.Client)

	id, err := resourceVLANIDInt16(d.Id())
	if err != nil {
		return false, err
	}

	vlan, err := client.GetFabricVLAN(id)

	return vlan != nil && err == nil, err
}

func resourceVLANRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*cloudapi.Client)

	vlan, err := client.GetFabricVLAN(int16(d.Get("vlan_id").(int)))
	if err != nil {
		return err
	}

	d.SetId(resourceVLANIDString(vlan.Id))
	d.Set("vlan_id", vlan.Id)
	d.Set("name", vlan.Name)
	d.Set("description", vlan.Description)

	return nil
}

func resourceVLANUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*cloudapi.Client)

	vlan, err := client.UpdateFabricVLAN(cloudapi.FabricVLAN{
		Id:          int16(d.Get("vlan_id").(int)),
		Name:        d.Get("name").(string),
		Description: d.Get("description").(string),
	})
	if err != nil {
		return err
	}

	d.SetId(resourceVLANIDString(vlan.Id))
	return resourceVLANRead(d, meta)
}

func resourceVLANDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*cloudapi.Client)

	id, err := resourceVLANIDInt16(d.Id())
	if err != nil {
		return err
	}

	return client.DeleteFabricVLAN(id)
}

// convenience conversion functions

func resourceVLANIDString(id int16) string {
	return strconv.Itoa(int(id))
}

func resourceVLANIDInt16(id string) (int16, error) {
	result, err := strconv.ParseInt(id, 10, 16)
	if err != nil {
		return 0, err
	}

	return int16(result), nil
}

func resourceVLANImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	return []*schema.ResourceData{d}, nil
}
<|endoftext|>


<commit_before>package golang

import (
	"fmt"
	"time"

	"github.com/ellcrys/util"
	"github.com/ncodes/cocoon/core/common"
	"github.com/ncodes/cocoon/core/connector/server/connector_proto"
	"github.com/ncodes/cocoon/core/types"
)

// Link provides access to external services
// like ledgers, cocoon codes, event and messaging services.
type Link struct {
	cocoonID      string
	defaultLedger string
	native        bool
}

// NewLink creates a new link to a cocoon
func NewLink(cocoonID string) *Link {
	return &Link{
		cocoonID: cocoonID,
	}
}

// NewNativeLink create a new native link to a cocoon
func newNativeLink(cocoonID string) *Link {
	return &Link{
		cocoonID: cocoonID,
		native:   true,
	}
}

// IsNative checks whether the link is a native link
func (link *Link) IsNative() bool {
	return link.native
}

// SetDefaultLedger sets this link's default ledger
func (link *Link) SetDefaultLedger(name string) *Link {
	link.defaultLedger = name
	return link
}

// GetDefaultLedger returns the link's default ledger
func (link *Link) GetDefaultLedger() string {
	return link.defaultLedger
}

// GetCocoonID returns the cocoon id attached to this link
func (link *Link) GetCocoonID() string {
	return link.cocoonID
}

// NewRangeGetter creates an instance of a RangeGetter bounded to the default ledger
// and cocoon id of this link.
func (link *Link) NewRangeGetter(start, end string, inclusive bool) *RangeGetter {
	return NewRangeGetter(link.GetDefaultLedger(), link.GetCocoonID(), start, end, inclusive)
}

// NewRangeGetterFrom creates an instance of a RangeGetter for a specified ledger.
func (link *Link) NewRangeGetterFrom(ledgerName, start, end string, inclusive bool) *RangeGetter {
	return NewRangeGetter(ledgerName, link.GetCocoonID(), start, end, inclusive)
}

// CreateLedger creates a new ledger by sending an
// invoke transaction (TxCreateLedger) to the connector.
// If chained is set to true, a blockchain is created and subsequent
// PUT operations to the ledger will be included in the types. Otherwise,
// PUT operations will only be included in the types.
func (link *Link) CreateLedger(name string, chained, public bool) (*types.Ledger, error) {

	if !common.IsValidResName(name) {
		return nil, fmt.Errorf("invalid ledger name")
	}

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxCreateLedger,
		LinkTo: link.GetCocoonID(),
		Params: []string{name, fmt.Sprintf("%t", chained), fmt.Sprintf("%t", public)},
	})

	if err != nil {
		return nil, err
	}

	var ledger types.Ledger
	if err = util.FromJSON(result, &ledger); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	return &ledger, nil
}

// GetLedger fetches a ledger
func (link *Link) GetLedger(ledgerName string) (*types.Ledger, error) {

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxGetLedger,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName},
	})

	if err != nil {
		return nil, err
	}

	var ledger types.Ledger
	if err = util.FromJSON(result, &ledger); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	return &ledger, nil
}

// PutIn adds a new transaction to a ledger
func (link *Link) PutIn(ledgerName string, key string, value []byte) (*types.Transaction, error) {

	start := time.Now()

	ledger, err := link.GetLedger(ledgerName)
	if err != nil {
		return nil, err
	}

	tx := &types.Transaction{
		ID:             util.UUID4(),
		Ledger:         ledger.Name,
		LedgerInternal: types.MakeLedgerName(link.GetCocoonID(), ledger.Name),
		Key:            key,
		KeyInternal:    types.MakeTxKey(link.GetCocoonID(), key),
		Value:          string(value),
		CreatedAt:      time.Now().Unix(),
	}

	tx.Hash = tx.MakeHash()

	if ledger.Chained {
		respChan := make(chan interface{})
		blockMaker.Add(&Entry{
			Tx:       tx,
			RespChan: respChan,
			LinkTo:   link.GetCocoonID(),
		})
		result := <-respChan

		log.Debug("Put(): Time taken: ", time.Since(start))

		switch v := result.(type) {
		case error:
			return nil, v
		case *types.Block:
			tx.Block = v
			return tx, err
		default:
			return nil, fmt.Errorf("unexpected response %s", err)
		}
	}

	txJSON, _ := util.ToJSON([]*types.Transaction{tx})
	_, err = sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxPut,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName},
		Body:   txJSON,
	})

	if err != nil {
		return nil, fmt.Errorf("failed to put transaction: %s", err)
	}

	log.Debug("Put(): Time taken: ", time.Since(start))

	return tx, nil
}

// Put adds a new transaction into the default ledger
func (link *Link) Put(key string, value []byte) (*types.Transaction, error) {
	return link.PutIn(link.GetDefaultLedger(), key, value)
}

// GetFrom returns a transaction by its key and the ledger it belongs to
func (link *Link) GetFrom(ledgerName, key string) (*types.Transaction, error) {

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxGet,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName, key},
	})

	if err != nil {
		return nil, fmt.Errorf("failed to get transaction: %s", err)
	}

	var tx types.Transaction
	if err = util.FromJSON(result, &tx); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	if tx.Block.ID == "" {
		tx.Block = nil
	}

	return &tx, nil
}

// Get returns a transaction that belongs to the default legder by its key.
func (link *Link) Get(key string) (*types.Transaction, error) {
	return link.GetFrom(link.GetDefaultLedger(), key)
}

// GetByIDFrom returns a transaction by its id and the ledger it belongs to
func (link *Link) GetByIDFrom(ledgerName, id string) (*types.Transaction, error) {

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxGetByID,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName, id},
	})

	if err != nil {
		return nil, fmt.Errorf("failed to get transaction: %s", err)
	}

	var tx types.Transaction
	if err = util.FromJSON(result, &tx); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	if tx.Block.ID == "" {
		tx.Block = nil
	}

	return &tx, nil
}

// GetByID returns a transaction that belongs to the default legder by its id.
func (link *Link) GetByID(id string) (*types.Transaction, error) {
	return link.GetByIDFrom(link.GetDefaultLedger(), id)
}

// GetBlockFrom returns a block from a ledger by its block id
func (link *Link) GetBlockFrom(ledgerName, id string) (*types.Block, error) {

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxGetBlockByID,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName, id},
	})

	if err != nil {
		return nil, fmt.Errorf("failed to get block: %s", err)
	}

	var blk types.Block
	if err = util.FromJSON(result, &blk); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	return &blk, nil
}

// GetBlock returns a block from the default ledger by its block id
func (link *Link) GetBlock(id string) (*types.Block, error) {
	return link.GetBlockFrom(link.GetDefaultLedger(), id)
}
<commit_msg>Returns error if default ledger is not set<commit_after>package golang

import (
	"fmt"
	"time"

	"github.com/ellcrys/util"
	"github.com/ncodes/cocoon/core/common"
	"github.com/ncodes/cocoon/core/connector/server/connector_proto"
	"github.com/ncodes/cocoon/core/types"
)

// Link provides access to external services
// like ledgers, cocoon codes, event and messaging services.
type Link struct {
	cocoonID      string
	defaultLedger string
	native        bool
}

// NewLink creates a new link to a cocoon
func NewLink(cocoonID string) *Link {
	return &Link{
		cocoonID: cocoonID,
	}
}

// NewNativeLink create a new native link to a cocoon
func newNativeLink(cocoonID string) *Link {
	return &Link{
		cocoonID: cocoonID,
		native:   true,
	}
}

// IsNative checks whether the link is a native link
func (link *Link) IsNative() bool {
	return link.native
}

// SetDefaultLedger sets this link's default ledger
func (link *Link) SetDefaultLedger(name string) *Link {
	link.defaultLedger = name
	return link
}

// GetDefaultLedger returns the link's default ledger
func (link *Link) GetDefaultLedger() string {
	return link.defaultLedger
}

// GetCocoonID returns the cocoon id attached to this link
func (link *Link) GetCocoonID() string {
	return link.cocoonID
}

// NewRangeGetter creates an instance of a RangeGetter bounded to the default ledger
// and cocoon id of this link.
func (link *Link) NewRangeGetter(start, end string, inclusive bool) *RangeGetter {
	return NewRangeGetter(link.GetDefaultLedger(), link.GetCocoonID(), start, end, inclusive)
}

// NewRangeGetterFrom creates an instance of a RangeGetter for a specified ledger.
func (link *Link) NewRangeGetterFrom(ledgerName, start, end string, inclusive bool) *RangeGetter {
	return NewRangeGetter(ledgerName, link.GetCocoonID(), start, end, inclusive)
}

// CreateLedger creates a new ledger by sending an
// invoke transaction (TxCreateLedger) to the connector.
// If chained is set to true, a blockchain is created and subsequent
// PUT operations to the ledger will be included in the types. Otherwise,
// PUT operations will only be included in the types.
func (link *Link) CreateLedger(name string, chained, public bool) (*types.Ledger, error) {

	if !common.IsValidResName(name) {
		return nil, fmt.Errorf("invalid ledger name")
	}

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxCreateLedger,
		LinkTo: link.GetCocoonID(),
		Params: []string{name, fmt.Sprintf("%t", chained), fmt.Sprintf("%t", public)},
	})

	if err != nil {
		return nil, err
	}

	var ledger types.Ledger
	if err = util.FromJSON(result, &ledger); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	return &ledger, nil
}

// GetLedger fetches a ledger
func (link *Link) GetLedger(ledgerName string) (*types.Ledger, error) {

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxGetLedger,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName},
	})

	if err != nil {
		return nil, err
	}

	var ledger types.Ledger
	if err = util.FromJSON(result, &ledger); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	return &ledger, nil
}

// PutIn adds a new transaction to a ledger
func (link *Link) PutIn(ledgerName string, key string, value []byte) (*types.Transaction, error) {

	start := time.Now()

	ledger, err := link.GetLedger(ledgerName)
	if err != nil {
		return nil, err
	}

	tx := &types.Transaction{
		ID:             util.UUID4(),
		Ledger:         ledger.Name,
		LedgerInternal: types.MakeLedgerName(link.GetCocoonID(), ledger.Name),
		Key:            key,
		KeyInternal:    types.MakeTxKey(link.GetCocoonID(), key),
		Value:          string(value),
		CreatedAt:      time.Now().Unix(),
	}

	tx.Hash = tx.MakeHash()

	if ledger.Chained {
		respChan := make(chan interface{})
		blockMaker.Add(&Entry{
			Tx:       tx,
			RespChan: respChan,
			LinkTo:   link.GetCocoonID(),
		})
		result := <-respChan

		log.Debug("Put(): Time taken: ", time.Since(start))

		switch v := result.(type) {
		case error:
			return nil, v
		case *types.Block:
			tx.Block = v
			return tx, err
		default:
			return nil, fmt.Errorf("unexpected response %s", err)
		}
	}

	txJSON, _ := util.ToJSON([]*types.Transaction{tx})
	_, err = sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxPut,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName},
		Body:   txJSON,
	})

	if err != nil {
		return nil, fmt.Errorf("failed to put transaction: %s", err)
	}

	log.Debug("Put(): Time taken: ", time.Since(start))

	return tx, nil
}

// Put adds a new transaction into the default ledger
func (link *Link) Put(key string, value []byte) (*types.Transaction, error) {
	if link.GetDefaultLedger() == "" {
		return nil, fmt.Errorf("default ledger not set")
	}
	return link.PutIn(link.GetDefaultLedger(), key, value)
}

// GetFrom returns a transaction by its key and the ledger it belongs to
func (link *Link) GetFrom(ledgerName, key string) (*types.Transaction, error) {

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxGet,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName, key},
	})

	if err != nil {
		return nil, fmt.Errorf("failed to get transaction: %s", err)
	}

	var tx types.Transaction
	if err = util.FromJSON(result, &tx); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	if tx.Block.ID == "" {
		tx.Block = nil
	}

	return &tx, nil
}

// Get returns a transaction that belongs to the default legder by its key.
func (link *Link) Get(key string) (*types.Transaction, error) {
	if link.GetDefaultLedger() == "" {
		return nil, fmt.Errorf("default ledger not set")
	}
	return link.GetFrom(link.GetDefaultLedger(), key)
}

// GetByIDFrom returns a transaction by its id and the ledger it belongs to
func (link *Link) GetByIDFrom(ledgerName, id string) (*types.Transaction, error) {

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxGetByID,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName, id},
	})

	if err != nil {
		return nil, fmt.Errorf("failed to get transaction: %s", err)
	}

	var tx types.Transaction
	if err = util.FromJSON(result, &tx); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	if tx.Block.ID == "" {
		tx.Block = nil
	}

	return &tx, nil
}

// GetByID returns a transaction that belongs to the default legder by its id.
func (link *Link) GetByID(id string) (*types.Transaction, error) {
	if link.GetDefaultLedger() == "" {
		return nil, fmt.Errorf("default ledger not set")
	}
	return link.GetByIDFrom(link.GetDefaultLedger(), id)
}

// GetBlockFrom returns a block from a ledger by its block id
func (link *Link) GetBlockFrom(ledgerName, id string) (*types.Block, error) {

	result, err := sendLedgerOp(&connector_proto.LedgerOperation{
		ID:     util.UUID4(),
		Name:   types.TxGetBlockByID,
		LinkTo: link.GetCocoonID(),
		Params: []string{ledgerName, id},
	})

	if err != nil {
		return nil, fmt.Errorf("failed to get block: %s", err)
	}

	var blk types.Block
	if err = util.FromJSON(result, &blk); err != nil {
		return nil, fmt.Errorf("failed to unmarshal response data")
	}

	return &blk, nil
}

// GetBlock returns a block from the default ledger by its block id
func (link *Link) GetBlock(id string) (*types.Block, error) {
	if link.GetDefaultLedger() == "" {
		return nil, fmt.Errorf("default ledger not set")
	}
	return link.GetBlockFrom(link.GetDefaultLedger(), id)
}
<|endoftext|>


<commit_before>// Package golang includes The runtime, which is just a stub that connects the cocoon code to the connector's RPC
// server. The runtime provides access to APIs for various operations.
package golang

import (
	"fmt"
	"net"
	"os"
	"strconv"
	"time"

	"strings"

	"github.com/ellcrys/util"
	"github.com/ncodes/cocoon/core/common"
	"github.com/ncodes/cocoon/core/runtime/golang/config"
	"github.com/ncodes/cocoon/core/runtime/golang/proto"
	"github.com/ncodes/cocoon/core/types"
	"github.com/op/go-logging"
	cmap "github.com/orcaman/concurrent-map"
	"google.golang.org/grpc"
)

var (

	// serverAddr to bind to
	serverAddr = util.Env("COCOON_ADDR", ":8000")

	// stub logger
	log *logging.Logger

	// default running server
	defaultServer *stubServer

	// stop channel to stop the server/cocoon code
	serverDone chan bool

	// Default runtime link
	defaultLink = NewNativeLink(GetID())

	// txChannels holds the channels to send transaction responses to
	txRespChannels = cmap.New()

	// ErrAlreadyExist represents an error about an already existing resource
	ErrAlreadyExist = fmt.Errorf("already exists")

	// ErrNotConnected represents an error about the cocoon code not
	// having an active connection with the connector.
	ErrNotConnected = fmt.Errorf("not connected to the connector")

	// Flag to help tell whether cocoon code is running
	running = false

	// Number of transactions per block
	txPerBlock = util.Env("TX_PER_BLOCK", "100")

	// Time between block creation (seconds)
	blockCreationInterval = util.Env("BLOCK_CREATION_INT", "5")

	// blockMaker creates a collection of blockchain transactions at interval
	blockMaker *BlockMaker

	// The cocoon code currently running
	ccode CocoonCode
)

// GetLogger returns the stubs logger.
func GetLogger() *logging.Logger {
	return log
}

// SetDebugLevel sets the default logger debug level
func SetDebugLevel(level logging.Level) {
	logging.SetLevel(level, log.Module)
}

func init() {
	defaultServer = new(stubServer)
	config.ConfigureLogger()
	log = logging.MustGetLogger("ccode.runtime")
}

// GetID returns the cocoon id. However, it will return the
// natively linked cocoon id if this cocoon is linked to another
// cocoon.
func GetID() string {
	return util.Env("COCOON_LINK", os.Getenv("COCOON_ID"))
}

// GetCocoonID returns the unique cocoon id
func GetCocoonID() string {
	return os.Getenv("COCOON_ID")
}

// Run starts the stub server, takes a cocoon code and attempts to initialize it..
func Run(cc CocoonCode) {

	if running {
		log.Info("cocoon code is already running")
		return
	}

	serverDone = make(chan bool, 1)

	lis, err := net.Listen("tcp", fmt.Sprintf("%s", serverAddr))
	if err != nil {
		log.Fatalf("failed to listen on port=%s", strings.Split(serverAddr, ":")[1])
	}

	log.Infof("Started stub service at port=%s", strings.Split(serverAddr, ":")[1])
	server := grpc.NewServer()
	proto.RegisterStubServer(server, defaultServer)
	go server.Serve(lis)

	intTxPerBlock, _ := strconv.Atoi(txPerBlock)
	intBlkCreationInt, _ := strconv.Atoi(blockCreationInterval)
	blockMaker = NewBlockMaker(intTxPerBlock, time.Duration(intBlkCreationInt)*time.Second)
	go blockMaker.Begin(blockCommitter)

	defaultLink.SetDefaultLedger(types.GetGlobalLedgerName())

	ccode = cc

	// run Init() after 1 second to give time for connector to connect
	time.AfterFunc(1*time.Second, func() {
		if err = cc.OnInit(defaultLink); err != nil {
			log.Errorf("cocoode OnInit() returned error: %s", err)
			Stop(1)
		} else {
			running = true
		}
	})

	<-serverDone
	log.Info("Cocoon code stopped")
	os.Exit(0)
}

// blockCommit creates a PUT operation which adds one or many
// transactions to the store and blockchain and returns the block if
// if succeed or error if otherwise.
func blockCommitter(entries []*Entry) interface{} {

	var block types.Block

	if len(entries) == 0 {
		return block
	}

	txs := make([]*types.Transaction, len(entries))
	for i, e := range entries {
		txs[i] = e.Tx
	}

	ledgerName := entries[0].Tx.Ledger
	txsJSON, _ := util.ToJSON(txs)

	var respCh = make(chan *proto.Tx)

	txID := util.UUID4()
	err := sendTx(&proto.Tx{
		Id:     txID,
		Invoke: true,
		Name:   types.TxPut,
		LinkTo: entries[0].To,
		Params: []string{ledgerName},
		Body:   txsJSON,
	}, respCh)
	if err != nil {
		return fmt.Errorf("failed to put block transaction. %s", err)
	}

	resp, err := common.AwaitTxChan(respCh)
	if err != nil {
		return err
	}

	if resp.Status != 200 {
		return fmt.Errorf("%s", common.GetRPCErrDesc(fmt.Errorf("%s", resp.Body)))
	}

	if err = util.FromJSON(resp.Body, &block); err != nil {
		return fmt.Errorf("failed to unmarshall response data")
	}

	return &block
}

// sendTx sends a transaction to the cocoon code
// and saves the response channel. The response channel will
// be passed a response when it is available in the Transact loop.
func sendTx(tx *proto.Tx, respCh chan *proto.Tx) error {
	txRespChannels.Set(tx.GetId(), respCh)
	if err := defaultServer.stream.Send(tx); err != nil {
		txRespChannels.Remove(tx.GetId())
		log.Errorf("failed to send transaction [%s] to connector. %s", tx.GetId(), err)
		return err
	}
	log.Debugf("Successfully sent transaction [%s] to connector", tx.GetId())
	return nil
}

// Stop stub and cocoon code
func Stop(exitCode int) {
	if blockMaker != nil {
		blockMaker.Stop()
	}
	defaultServer.stream = nil
	serverDone <- true
	log.Info("Cocoon code exiting with exit code %d", exitCode)
	os.Exit(exitCode)
}

// isConnected checks if connection with the connector
// is active.
func isConnected() bool {
	return defaultServer.stream != nil
}

// GetGlobalLedger returns the name of the global ledger.
func GetGlobalLedger() string {
	return types.GetGlobalLedgerName()
}
<commit_msg>debug: log when server stops<commit_after>// Package golang includes The runtime, which is just a stub that connects the cocoon code to the connector's RPC
// server. The runtime provides access to APIs for various operations.
package golang

import (
	"fmt"
	"net"
	"os"
	"strconv"
	"time"

	"strings"

	"github.com/ellcrys/util"
	"github.com/ncodes/cocoon/core/common"
	"github.com/ncodes/cocoon/core/runtime/golang/config"
	"github.com/ncodes/cocoon/core/runtime/golang/proto"
	"github.com/ncodes/cocoon/core/types"
	"github.com/op/go-logging"
	cmap "github.com/orcaman/concurrent-map"
	"google.golang.org/grpc"
)

var (

	// serverAddr to bind to
	serverAddr = util.Env("COCOON_ADDR", ":8000")

	// stub logger
	log *logging.Logger

	// default running server
	defaultServer *stubServer

	// stop channel to stop the server/cocoon code
	serverDone chan bool

	// Default runtime link
	defaultLink = NewNativeLink(GetID())

	// txChannels holds the channels to send transaction responses to
	txRespChannels = cmap.New()

	// ErrAlreadyExist represents an error about an already existing resource
	ErrAlreadyExist = fmt.Errorf("already exists")

	// ErrNotConnected represents an error about the cocoon code not
	// having an active connection with the connector.
	ErrNotConnected = fmt.Errorf("not connected to the connector")

	// Flag to help tell whether cocoon code is running
	running = false

	// Number of transactions per block
	txPerBlock = util.Env("TX_PER_BLOCK", "100")

	// Time between block creation (seconds)
	blockCreationInterval = util.Env("BLOCK_CREATION_INT", "5")

	// blockMaker creates a collection of blockchain transactions at interval
	blockMaker *BlockMaker

	// The cocoon code currently running
	ccode CocoonCode
)

// GetLogger returns the stubs logger.
func GetLogger() *logging.Logger {
	return log
}

// SetDebugLevel sets the default logger debug level
func SetDebugLevel(level logging.Level) {
	logging.SetLevel(level, log.Module)
}

func init() {
	defaultServer = new(stubServer)
	config.ConfigureLogger()
	log = logging.MustGetLogger("ccode.runtime")
}

// GetID returns the cocoon id. However, it will return the
// natively linked cocoon id if this cocoon is linked to another
// cocoon.
func GetID() string {
	return util.Env("COCOON_LINK", os.Getenv("COCOON_ID"))
}

// GetCocoonID returns the unique cocoon id
func GetCocoonID() string {
	return os.Getenv("COCOON_ID")
}

// Run starts the stub server, takes a cocoon code and attempts to initialize it..
func Run(cc CocoonCode) {

	if running {
		log.Info("cocoon code is already running")
		return
	}

	serverDone = make(chan bool, 1)

	lis, err := net.Listen("tcp", fmt.Sprintf("%s", serverAddr))
	if err != nil {
		log.Fatalf("failed to listen on port=%s", strings.Split(serverAddr, ":")[1])
	}

	log.Infof("Started stub service at port=%s", strings.Split(serverAddr, ":")[1])
	server := grpc.NewServer()
	proto.RegisterStubServer(server, defaultServer)
	go func() {
		server.Serve(lis)
		log.Info("Server has stopped")
	}()

	intTxPerBlock, _ := strconv.Atoi(txPerBlock)
	intBlkCreationInt, _ := strconv.Atoi(blockCreationInterval)
	blockMaker = NewBlockMaker(intTxPerBlock, time.Duration(intBlkCreationInt)*time.Second)
	go blockMaker.Begin(blockCommitter)

	defaultLink.SetDefaultLedger(types.GetGlobalLedgerName())

	ccode = cc

	// run Init() after 1 second to give time for connector to connect
	time.AfterFunc(1*time.Second, func() {
		if err = cc.OnInit(defaultLink); err != nil {
			log.Errorf("cocoode OnInit() returned error: %s", err)
			Stop(1)
		} else {
			running = true
		}
	})

	<-serverDone
	log.Info("Cocoon code stopped")
	os.Exit(0)
}

// blockCommit creates a PUT operation which adds one or many
// transactions to the store and blockchain and returns the block if
// if succeed or error if otherwise.
func blockCommitter(entries []*Entry) interface{} {

	var block types.Block

	if len(entries) == 0 {
		return block
	}

	txs := make([]*types.Transaction, len(entries))
	for i, e := range entries {
		txs[i] = e.Tx
	}

	ledgerName := entries[0].Tx.Ledger
	txsJSON, _ := util.ToJSON(txs)

	var respCh = make(chan *proto.Tx)

	txID := util.UUID4()
	err := sendTx(&proto.Tx{
		Id:     txID,
		Invoke: true,
		Name:   types.TxPut,
		LinkTo: entries[0].To,
		Params: []string{ledgerName},
		Body:   txsJSON,
	}, respCh)
	if err != nil {
		return fmt.Errorf("failed to put block transaction. %s", err)
	}

	resp, err := common.AwaitTxChan(respCh)
	if err != nil {
		return err
	}

	if resp.Status != 200 {
		return fmt.Errorf("%s", common.GetRPCErrDesc(fmt.Errorf("%s", resp.Body)))
	}

	if err = util.FromJSON(resp.Body, &block); err != nil {
		return fmt.Errorf("failed to unmarshall response data")
	}

	return &block
}

// sendTx sends a transaction to the cocoon code
// and saves the response channel. The response channel will
// be passed a response when it is available in the Transact loop.
func sendTx(tx *proto.Tx, respCh chan *proto.Tx) error {
	txRespChannels.Set(tx.GetId(), respCh)
	if err := defaultServer.stream.Send(tx); err != nil {
		txRespChannels.Remove(tx.GetId())
		log.Errorf("failed to send transaction [%s] to connector. %s", tx.GetId(), err)
		return err
	}
	log.Debugf("Successfully sent transaction [%s] to connector", tx.GetId())
	return nil
}

// Stop stub and cocoon code
func Stop(exitCode int) {
	if blockMaker != nil {
		blockMaker.Stop()
	}
	defaultServer.stream = nil
	serverDone <- true
	log.Info("Cocoon code exiting with exit code %d", exitCode)
	os.Exit(exitCode)
}

// isConnected checks if connection with the connector
// is active.
func isConnected() bool {
	return defaultServer.stream != nil
}

// GetGlobalLedger returns the name of the global ledger.
func GetGlobalLedger() string {
	return types.GetGlobalLedgerName()
}
<|endoftext|>


<commit_before>package build_test

import (
	"fmt"
	"github.com/buildpack/libbuildpack"
	"github.com/cloudfoundry/libjavabuildpack/test"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"nodejs/v3/build"
	"path/filepath"
)

var _ = Describe("NewNode", func() {
	var stubNodeFixture = filepath.Join("v3", "stub-node.tar.gz")

	It("returns true if a build plan exists", func() {
		f := test.NewBuildFactory(T)
		f.AddBuildPlan(T, build.NodeDependency, libbuildpack.BuildPlanDependency{})
		f.AddDependency(T, build.NodeDependency, stubNodeFixture)

		_, ok, err := build.NewNode(f.Build)
		Expect(err).NotTo(HaveOccurred())
		Expect(ok).To(BeTrue())
	})

	It("returns false if a build plan does not exist", func() {
		f := test.NewBuildFactory(T)

		_, ok, err := build.NewNode(f.Build)
		Expect(err).NotTo(HaveOccurred())
		Expect(ok).To(BeFalse())
	})

	It("contributes node to the launch layer", func() {
		f := test.NewBuildFactory(T)
		f.AddBuildPlan(T, build.NodeDependency, libbuildpack.BuildPlanDependency{})
		f.AddDependency(T, build.NodeDependency, stubNodeFixture)

		nodeDep, _, err := build.NewNode(f.Build)
		Expect(err).NotTo(HaveOccurred())

		err = nodeDep.Contribute()
		Expect(err).NotTo(HaveOccurred())

		layerRoot := filepath.Join(f.Build.Launch.Root, "node")
		Expect(filepath.Join(layerRoot, "stub.txt")).To(BeARegularFile())
	})
})
<commit_msg>Remove unused import<commit_after>package build_test

import (
	"github.com/buildpack/libbuildpack"
	"github.com/cloudfoundry/libjavabuildpack/test"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"nodejs/v3/build"
	"path/filepath"
)

var _ = Describe("NewNode", func() {
	var stubNodeFixture = filepath.Join("v3", "stub-node.tar.gz")

	It("returns true if a build plan exists", func() {
		f := test.NewBuildFactory(T)
		f.AddBuildPlan(T, build.NodeDependency, libbuildpack.BuildPlanDependency{})
		f.AddDependency(T, build.NodeDependency, stubNodeFixture)

		_, ok, err := build.NewNode(f.Build)
		Expect(err).NotTo(HaveOccurred())
		Expect(ok).To(BeTrue())
	})

	It("returns false if a build plan does not exist", func() {
		f := test.NewBuildFactory(T)

		_, ok, err := build.NewNode(f.Build)
		Expect(err).NotTo(HaveOccurred())
		Expect(ok).To(BeFalse())
	})

	It("contributes node to the launch layer", func() {
		f := test.NewBuildFactory(T)
		f.AddBuildPlan(T, build.NodeDependency, libbuildpack.BuildPlanDependency{})
		f.AddDependency(T, build.NodeDependency, stubNodeFixture)

		nodeDep, _, err := build.NewNode(f.Build)
		Expect(err).NotTo(HaveOccurred())

		err = nodeDep.Contribute()
		Expect(err).NotTo(HaveOccurred())

		layerRoot := filepath.Join(f.Build.Launch.Root, "node")
		Expect(filepath.Join(layerRoot, "stub.txt")).To(BeARegularFile())
	})
})
<|endoftext|>


<commit_before>package commands

import (
	"testing"

	"github.com/garyburd/neovim-go/vim"
)

// func TestGuru(t *testing.T) {
// 	tests := []struct {
// 		// Parameters.
// 		v    *vim.Vim
// 		args []string
// 		eval *funcGuruEval
// 		// Expected results.
// 		wantErr bool
// 	}{
// 		{
// 			v:    testVim(t, gsftpMain),
// 			args: []string{"definition"},
// 			eval: &funcGuruEval{
// 				Cwd:      gsftp,
// 				File:     gsftpMain,
// 				Modified: 0,
// 			},
// 		},
// 	}
// 	for _, tt := range tests {
// 		if err := Guru(tt.v, tt.args, tt.eval); (err != nil) != tt.wantErr {
// 			t.Errorf("Guru(%v, %v, %v) error = %v, wantErr %v", tt.v, tt.args, tt.eval, err, tt.wantErr)
// 		}
// 	}
// }

func BenchmarkGuruDefinition(b *testing.B) {
	v := benchVim(b, gsftpMain)
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		if err := Guru(v, []string{"definition"}, &funcGuruEval{
			Cwd:      gsftp,
			File:     gsftpMain,
			Modified: 0,
			Offset:   2027, // client, err := sftp.|N|ewClient(conn)
		}); err != nil {
			b.Errorf("BenchmarkGuruDefinition: %v", err)
		}
	}
}

func BenchmarkGuruDefinitionFallback(b *testing.B) {
	v := benchVim(b, gsftpMain)
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		if err := Guru(v, []string{"definition"}, &funcGuruEval{
			Cwd:      gsftp,
			File:     gsftpMain,
			Modified: 0,
			Offset:   2132, // defer conn.|C|lose()
		}); err != nil {
			b.Errorf("BenchmarkGuruDefinitionFallback: %v", err)
		}
	}
}

// func TestParseResult(t *testing.T) {
// 	tests := []struct {
// 		// Parameters.
// 		mode string
// 		fset *token.FileSet
// 		data []byte
// 		cwd  string
// 		// Expected results.
// 		want    []*quickfix.ErrorlistData
// 		want1   string
// 		want2   int
// 		want3   int
// 		wantErr bool
// 	}{
// 	// TODO: Add test cases.
// 	}
// 	for _, tt := range tests {
// 		got, got1, got2, got3, err := parseResult(tt.mode, tt.fset, tt.data, tt.cwd)
// 		if (err != nil) != tt.wantErr {
// 			t.Errorf("parseResult(%v, %v, %v, %v) error = %v, wantErr %v", tt.mode, tt.fset, tt.data, tt.cwd, err, tt.wantErr)
// 			continue
// 		}
// 		if !reflect.DeepEqual(got, tt.want) {
// 			t.Errorf("parseResult(%v, %v, %v, %v) = %v, want %v", tt.mode, tt.fset, tt.data, tt.cwd, got, tt.want)
// 		}
// 		if !reflect.DeepEqual(got1, tt.want1) {
// 			t.Errorf("parseResult(%v, %v, %v, %v) = %v, want %v", tt.mode, tt.fset, tt.data, tt.cwd, got, tt.want1)
// 		}
// 		if !reflect.DeepEqual(got2, tt.want2) {
// 			t.Errorf("parseResult(%v, %v, %v, %v) = %v, want %v", tt.mode, tt.fset, tt.data, tt.cwd, got, tt.want2)
// 		}
// 		if !reflect.DeepEqual(got3, tt.want3) {
// 			t.Errorf("parseResult(%v, %v, %v, %v) = %v, want %v", tt.mode, tt.fset, tt.data, tt.cwd, got, tt.want3)
// 		}
// 	}
// }

func TestGuruHelp(t *testing.T) {
	tests := []struct {
		// Parameters.
		v    *vim.Vim
		mode string
		// Expected results.
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		if err := guruHelp(tt.v, tt.mode); (err != nil) != tt.wantErr {
			t.Errorf("guruHelp(%v, %v) error = %v, wantErr %v", tt.v, tt.mode, err, tt.wantErr)
		}
	}
}
<commit_msg>test/guru: Add some test and benchmark callees and callers<commit_after>package commands

import (
	"go/token"
	"reflect"
	"testing"

	"nvim-go/internal/guru"
	"nvim-go/internal/guru/serial"
	"nvim-go/nvim/quickfix"

	"github.com/garyburd/neovim-go/vim"
)

func TestGuru(t *testing.T) {
	tests := []struct {
		// Parameters.
		v    *vim.Vim
		args []string
		eval *funcGuruEval
		// Expected results.
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		if err := Guru(tt.v, tt.args, tt.eval); (err != nil) != tt.wantErr {
			t.Errorf("Guru(%v, %v, %v) error = %v, wantErr %v", tt.v, tt.args, tt.eval, err, tt.wantErr)
		}
	}
}

func BenchmarkGuruCallees(b *testing.B) {
	v := benchVim(b, gsftpMain)
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		if err := Guru(v, []string{"callees"}, &funcGuruEval{
			Cwd:      gsftp,
			File:     gsftpMain,
			Modified: 0,
			Offset:   2027, // client, err := sftp.|N|ewClient(conn)
		}); err != nil {
			b.Errorf(":BenchmarkGuruCallees %v", err)
		}
	}
}

func BenchmarkGuruCallers(b *testing.B) {
	v := benchVim(b, gsftpMain)
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		if err := Guru(v, []string{"callers"}, &funcGuruEval{
			Cwd:      gsftp,
			File:     gsftpMain,
			Modified: 0,
			Offset:   2027, // client, err := sftp.|N|ewClient(conn)
		}); err != nil {
			b.Errorf("BenchmarkGuruCallers: %v", err)
		}
	}
}

func TestDefinition(t *testing.T) {
	tests := []struct {
		// Parameters.
		q *guru.Query
		// Expected results.
		want    *serial.Definition
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		got, err := definition(tt.q)
		if (err != nil) != tt.wantErr {
			t.Errorf("definition(%v) error = %v, wantErr %v", tt.q, err, tt.wantErr)
			continue
		}
		if !reflect.DeepEqual(got, tt.want) {
			t.Errorf("definition(%v) = %v, want %v", tt.q, got, tt.want)
		}
	}
}

func BenchmarkGuruDefinition(b *testing.B) {
	v := benchVim(b, gsftpMain)
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		if err := Guru(v, []string{"definition"}, &funcGuruEval{
			Cwd:      gsftp,
			File:     gsftpMain,
			Modified: 0,
			Offset:   2027, // client, err := sftp.|N|ewClient(conn)
		}); err != nil {
			b.Errorf("BenchmarkGuruDefinition: %v", err)
		}
	}
}

func TestFallbackChan(t *testing.T) {
	tests := []struct {
		// Parameters.
		obj *serial.Definition
		err error
		// Expected results.
		want fallback
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		if got := fallbackChan(tt.obj, tt.err); !reflect.DeepEqual(got, tt.want) {
			t.Errorf("fallbackChan(%v, %v) = %v, want %v", tt.obj, tt.err, got, tt.want)
		}
	}
}

func TestDefinitionFallback(t *testing.T) {
	tests := []struct {
		// Parameters.
		q *guru.Query
		c chan fallback
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		definitionFallback(tt.q, tt.c)
	}
}

func BenchmarkGuruDefinitionFallback(b *testing.B) {
	v := benchVim(b, gsftpMain)
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		if err := Guru(v, []string{"definition"}, &funcGuruEval{
			Cwd:      gsftp,
			File:     gsftpMain,
			Modified: 0,
			Offset:   2132, // defer conn.|C|lose()
		}); err != nil {
			b.Errorf("BenchmarkGuruDefinitionFallback: %v", err)
		}
	}
}

func TestParseResult(t *testing.T) {
	tests := []struct {
		// Parameters.
		mode string
		fset *token.FileSet
		data []byte
		cwd  string
		// Expected results.
		want    []*quickfix.ErrorlistData
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		got, err := parseResult(tt.mode, tt.fset, tt.data, tt.cwd)
		if (err != nil) != tt.wantErr {
			t.Errorf("parseResult(%v, %v, %v, %v) error = %v, wantErr %v", tt.mode, tt.fset, tt.data, tt.cwd, err, tt.wantErr)
			continue
		}
		if !reflect.DeepEqual(got, tt.want) {
			t.Errorf("parseResult(%v, %v, %v, %v) = %v, want %v", tt.mode, tt.fset, tt.data, tt.cwd, got, tt.want)
		}
	}
}

func TestGuruHelp(t *testing.T) {
	tests := []struct {
		// Parameters.
		v    *vim.Vim
		mode string
		// Expected results.
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		if err := guruHelp(tt.v, tt.mode); (err != nil) != tt.wantErr {
			t.Errorf("guruHelp(%v, %v) error = %v, wantErr %v", tt.v, tt.mode, err, tt.wantErr)
		}
	}
}
<|endoftext|>


<commit_before>package brats_test

import (
	"flag"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"github.com/cloudfoundry/libbuildpack"
	"github.com/cloudfoundry/libbuildpack/bratshelper"
	"github.com/cloudfoundry/libbuildpack/cutlass"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func init() {
	flag.StringVar(&cutlass.DefaultMemory, "memory", "256M", "default memory for pushed apps")
	flag.StringVar(&cutlass.DefaultDisk, "disk", "384M", "default disk for pushed apps")
	flag.Parse()
}

var _ = SynchronizedBeforeSuite(func() []byte {
	// Run once
	return bratshelper.InitBpData().Marshal()
}, func(data []byte) {
	// Run on all nodes
	bratshelper.Data.Unmarshal(data)
	Expect(cutlass.CopyCfHome()).To(Succeed())
	cutlass.SeedRandom()
	cutlass.DefaultStdoutStderr = GinkgoWriter
})

var _ = SynchronizedAfterSuite(func() {
	// Run on all nodes
}, func() {
	// Run once
	_ = cutlass.DeleteOrphanedRoutes()
	Expect(cutlass.DeleteBuildpack(strings.Replace(bratshelper.Data.Cached, "_buildpack", "", 1))).To(Succeed())
	Expect(cutlass.DeleteBuildpack(strings.Replace(bratshelper.Data.Uncached, "_buildpack", "", 1))).To(Succeed())
	Expect(os.Remove(bratshelper.Data.CachedFile)).To(Succeed())
})

func TestBrats(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Brats Suite")
}

func FirstOfVersionLine(line string) string {
	bpDir, err := cutlass.FindRoot()
	if err != nil {
		panic(err)
	}
	manifest, err := libbuildpack.NewManifest(bpDir, nil, time.Now())
	if err != nil {
		panic(err)
	}
	deps := manifest.AllDependencyVersions("php")
	versions, err := libbuildpack.FindMatchingVersions(line, deps)
	if err != nil {
		panic(err)
	}
	return versions[0]
}

func CopyBratsWithFramework(phpVersion, webserver, webserverVersion string) *cutlass.App {
	manifest, err := libbuildpack.NewManifest(bratshelper.Data.BpDir, nil, time.Now())
	Expect(err).ToNot(HaveOccurred())

	if phpVersion == "" {
		phpVersion = "x"
	}
	if strings.Contains(phpVersion, "x") {
		deps := manifest.AllDependencyVersions("php")
		phpVersion, err = libbuildpack.FindMatchingVersion(phpVersion, deps)
		Expect(err).ToNot(HaveOccurred())
	}

	if webserver == "" {
		webserver = "httpd"
	}
	if webserverVersion == "" {
		webserverVersion = "x"
	}
	if strings.Contains(webserverVersion, "x") {
		deps := manifest.AllDependencyVersions(webserver)
		webserverVersion, err = libbuildpack.FindMatchingVersion(webserverVersion, deps)
		Expect(err).ToNot(HaveOccurred())
	}

	dir, err := cutlass.CopyFixture(filepath.Join(bratshelper.Data.BpDir, "fixtures", "brats"))
	Expect(err).ToNot(HaveOccurred())

	commonExtensions := []string{"amqp", "apcu", "bz2", "cassandra", "curl", "dba", "exif", "fileinfo", "ftp", "gd", "geoip", "gettext", "gmp", "imagick", "imap", "ldap", "lua", "mailparse", "mbstring", "mongodb", "msgpack", "mysqli", "openssl", "pcntl", "pdo", "pdo_mysql", "pdo_pgsql", "pdo_sqlite", "pgsql", "phpiredis", "protobuf", "pspell", "rdkafka", "redis", "soap", "sockets", "xsl", "yaf", "zip", "zlib"}
	extraExtensions := map[string][]string{
		"5.6": {"mcrypt", "solr", "gearman", "igbinary", "memcache", "memcached", "mongo", "mssql", "mysql", "pdo_dblib", "phalcon", "protocolbuffers", "readline", "suhosin", "sundown", "twig", "xcache", "xhprof"},
		"7.0": {"mcrypt", "phalcon", "solr"},
		"7.1": {"mcrypt", "solr"},
		"7.2": {},
	}
	zendExtensions := map[string][]string{
		"5.6": {"ioncube", "opcache", "xdebug"},
		"7.0": {"ioncube", "opcache", "xdebug"},
		"7.1": {"ioncube", "opcache", "xdebug"},
		"7.2": {"ioncube", "opcache", "xdebug"},
	}

	options := make(map[string]interface{})
	options["PHP_VM"] = "php"
	options["PHP_VERSION"] = phpVersion
	options["WEB_SERVER"] = webserver
	options[strings.ToUpper(webserver)+"_VERSION"] = webserverVersion
	options["PHP_EXTENSIONS"] = append(commonExtensions, extraExtensions[phpVersion[:3]]...)
	options["ZEND_EXTENSIONS"] = zendExtensions[phpVersion[:3]]
	Expect(libbuildpack.NewJSON().Write(filepath.Join(dir, ".bp-config", "options.json"), options)).To(Succeed())

	return cutlass.New(dir)
}

func CopyBrats(version string) *cutlass.App {
	return CopyBratsWithFramework(version, "", "")
}

func PushApp(app *cutlass.App) {
	Expect(app.Push()).To(Succeed())
	Eventually(app.InstanceStates, 20*time.Second).Should(Equal([]string{"RUNNING"}))
}
<commit_msg>Determine modules to test per PHP version from manifest.yml<commit_after>package brats_test

import (
	"flag"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"github.com/cloudfoundry/libbuildpack"
	"github.com/cloudfoundry/libbuildpack/bratshelper"
	"github.com/cloudfoundry/libbuildpack/cutlass"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func init() {
	flag.StringVar(&cutlass.DefaultMemory, "memory", "256M", "default memory for pushed apps")
	flag.StringVar(&cutlass.DefaultDisk, "disk", "384M", "default disk for pushed apps")
	flag.Parse()
}

var _ = SynchronizedBeforeSuite(func() []byte {
	// Run once
	return bratshelper.InitBpData().Marshal()
}, func(data []byte) {
	// Run on all nodes
	bratshelper.Data.Unmarshal(data)
	Expect(cutlass.CopyCfHome()).To(Succeed())
	cutlass.SeedRandom()
	cutlass.DefaultStdoutStderr = GinkgoWriter
})

var _ = SynchronizedAfterSuite(func() {
	// Run on all nodes
}, func() {
	// Run once
	_ = cutlass.DeleteOrphanedRoutes()
	Expect(cutlass.DeleteBuildpack(strings.Replace(bratshelper.Data.Cached, "_buildpack", "", 1))).To(Succeed())
	Expect(cutlass.DeleteBuildpack(strings.Replace(bratshelper.Data.Uncached, "_buildpack", "", 1))).To(Succeed())
	Expect(os.Remove(bratshelper.Data.CachedFile)).To(Succeed())
})

func TestBrats(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Brats Suite")
}

func FirstOfVersionLine(line string) string {
	bpDir, err := cutlass.FindRoot()
	if err != nil {
		panic(err)
	}
	manifest, err := libbuildpack.NewManifest(bpDir, nil, time.Now())
	if err != nil {
		panic(err)
	}
	deps := manifest.AllDependencyVersions("php")
	versions, err := libbuildpack.FindMatchingVersions(line, deps)
	if err != nil {
		panic(err)
	}
	return versions[0]
}

func CopyBratsWithFramework(phpVersion, webserver, webserverVersion string) *cutlass.App {
	manifest, err := libbuildpack.NewManifest(bratshelper.Data.BpDir, nil, time.Now())
	Expect(err).ToNot(HaveOccurred())

	if phpVersion == "" {
		phpVersion = "x"
	}
	if strings.Contains(phpVersion, "x") {
		deps := manifest.AllDependencyVersions("php")
		phpVersion, err = libbuildpack.FindMatchingVersion(phpVersion, deps)
		Expect(err).ToNot(HaveOccurred())
	}

	if webserver == "" {
		webserver = "httpd"
	}
	if webserverVersion == "" {
		webserverVersion = "x"
	}
	if strings.Contains(webserverVersion, "x") {
		deps := manifest.AllDependencyVersions(webserver)
		webserverVersion, err = libbuildpack.FindMatchingVersion(webserverVersion, deps)
		Expect(err).ToNot(HaveOccurred())
	}

	dir, err := cutlass.CopyFixture(filepath.Join(bratshelper.Data.BpDir, "fixtures", "brats"))
	Expect(err).ToNot(HaveOccurred())

	options := make(map[string]interface{})
	options["PHP_VM"] = "php"
	options["PHP_VERSION"] = phpVersion
	options["WEB_SERVER"] = webserver
	options[strings.ToUpper(webserver)+"_VERSION"] = webserverVersion

	options["PHP_EXTENSIONS"] = phpExtensions(phpVersion)
	options["ZEND_EXTENSIONS"] = zendExtensions(phpVersion)

	Expect(libbuildpack.NewJSON().Write(filepath.Join(dir, ".bp-config", "options.json"), options)).To(Succeed())
	return cutlass.New(dir)
}

func CopyBrats(version string) *cutlass.App {
	return CopyBratsWithFramework(version, "", "")
}

func PushApp(app *cutlass.App) {
	Expect(app.Push()).To(Succeed())
	Eventually(app.InstanceStates, 20*time.Second).Should(Equal([]string{"RUNNING"}))
}

func modulesForPHPVersion(version string) []string {
	manifest := struct {
		ManifestEntries []struct {
			Dependency struct {
				Name    string   `yaml:"name"`
				Version string   `yaml:"version"`
				Modules []string `yaml:"modules"`
			} `yaml:",inline"`
		} `yaml:"dependencies"`
	}{}

	manifestPath := filepath.Join(bratshelper.Data.BpDir, "manifest.yml")

	err := libbuildpack.NewYAML().Load(manifestPath, &manifest)
	Expect(err).ToNot(HaveOccurred())

	for _, entry := range manifest.ManifestEntries {
		if entry.Dependency.Name == "php" {
			if entry.Dependency.Version == version {
				return entry.Dependency.Modules
			}
		}
	}
	return []string{}
}

func zendExtensions(phpVersion string) (extensions []string) {
	for _, module := range modulesForPHPVersion(phpVersion) {
		if isZendExtension(module) {
			extensions = append(extensions, module)
		}
	}
	return
}

func phpExtensions(phpVersion string) (extensions []string) {
	for _, module := range modulesForPHPVersion(phpVersion) {
		if !isZendExtension(module) {
			extensions = append(extensions, module)
		}
	}
	return
}

func isZendExtension(moduleName string) bool {
	return moduleName == "ioncube" || moduleName == "opcache" || moduleName == "xdebug"
}
<|endoftext|>