<commit_before>package importer

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"sync"

	"github.com/sgeisbacher/photogallery-api/media"
)

type ImportMediaData struct {
	size        int64
	path        string
	galleryName string
}

type ImportManager struct {
	MediaService   *media.MediaService
	GalleryService *media.GalleryService
}

func (mgr ImportManager) ScanFolder(path string) error {
	var wg sync.WaitGroup
	imagesChan := make(chan ImportMediaData)

	// start worker threads
	go mgr.handleImageFile(imagesChan, &wg)
	go mgr.handleImageFile(imagesChan, &wg)

	path = addSlash(path)

	files, err := ioutil.ReadDir(path)
	if err != nil {
		return errors.New(fmt.Sprintf("error while reading dir: %v", err))
	}
	for _, file := range files {
		if !file.IsDir() {
			fmt.Printf("skipping file '%v' (not allowed here), because its on gallery-folder-level\n", path+file.Name())
			continue
		}
		scanGalleryFolder(file.Name(), addSlash(path+file.Name()), imagesChan, &wg)
	}

	close(imagesChan)
	wg.Wait()

	return nil
}

func scanGalleryFolder(galleryName, path string, imagesChan chan ImportMediaData, wg *sync.WaitGroup) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Printf("error while reading dir: %v\n", err)
		return
	}
	for _, file := range files {
		if file.IsDir() {
			fmt.Printf("skipping directory '%v' (not allowed here), because its on image-level\n", addSlash(path+file.Name()))
			continue
		}
		wg.Add(1)
		importMediaData := ImportMediaData{
			path:        path + file.Name(),
			galleryName: galleryName,
			size:        file.Size(),
		}
		imagesChan <- importMediaData
	}
}

func (mgr ImportManager) handleImageFile(imagesChan <-chan ImportMediaData, wg *sync.WaitGroup) {
	for importMediaData := range imagesChan {
		fileHash, err := hashFile(importMediaData.path)
		if err != nil {
			fmt.Printf("skipping file '%v' due to an error: %v\n", importMediaData.path, err)
			continue
		}

		media := media.Media{
			Hash:      fileHash,
			OrigPath:  importMediaData.path,
			Size:      importMediaData.size,
			MediaType: media.MEDIA_TYPE_PHOTO,
		}
		mgr.MediaService.Add(media)
		err = mgr.GalleryService.AddMediaToGallery(importMediaData.galleryName, media)
		if err != nil {
			fmt.Printf("error while putting media to gallery '%v': %v\n", importMediaData.galleryName, err)
			// TODO delete media!!!
		}
		wg.Done()
	}
}

func hashFile(filename string) (string, error) {
	var md5ChkSum string
	file, err := os.Open(filename)
	if err != nil {
		fmt.Println("could not open file:", filename)
		return md5ChkSum, err
	}
	defer file.Close()
	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		fmt.Println("could not hash file:", filename)
		return md5ChkSum, err
	}
	md5ChkSum = hex.EncodeToString(hash.Sum(nil))
	return md5ChkSum, nil
}

func addSlash(path string) string {
	path = strings.TrimSpace(path)
	if !strings.HasSuffix(path, "/") {
		path = path + "/"
	}
	return path
}
<commit_msg>added some verbosity to importer<commit_after>package importer

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"sync"

	"github.com/sgeisbacher/photogallery-api/media"
)

type ImportMediaData struct {
	size        int64
	path        string
	galleryName string
}

type ImportManager struct {
	MediaService   *media.MediaService
	GalleryService *media.GalleryService
}

func (mgr ImportManager) ScanFolder(path string) error {
	fmt.Printf("running import in '%v' ...\n", path)
	var wg sync.WaitGroup
	imagesChan := make(chan ImportMediaData)

	// start worker threads
	go mgr.handleImageFile(imagesChan, &wg)
	go mgr.handleImageFile(imagesChan, &wg)

	path = addSlash(path)

	files, err := ioutil.ReadDir(path)
	if err != nil {
		return errors.New(fmt.Sprintf("error while reading dir: %v", err))
	}
	for _, file := range files {
		if !file.IsDir() {
			fmt.Printf("skipping file '%v' (not allowed here), because its on gallery-folder-level\n", path+file.Name())
			continue
		}
		scanGalleryFolder(file.Name(), addSlash(path+file.Name()), imagesChan, &wg)
	}

	close(imagesChan)
	wg.Wait()

	fmt.Println("Importer ... done")
	return nil
}

func scanGalleryFolder(galleryName, path string, imagesChan chan ImportMediaData, wg *sync.WaitGroup) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Printf("error while reading dir: %v\n", err)
		return
	}
	for _, file := range files {
		if file.IsDir() {
			fmt.Printf("skipping directory '%v' (not allowed here), because its on image-level\n", addSlash(path+file.Name()))
			continue
		}
		wg.Add(1)
		importMediaData := ImportMediaData{
			path:        path + file.Name(),
			galleryName: galleryName,
			size:        file.Size(),
		}
		imagesChan <- importMediaData
	}
}

func (mgr ImportManager) handleImageFile(imagesChan <-chan ImportMediaData, wg *sync.WaitGroup) {
	for importMediaData := range imagesChan {
		fileHash, err := hashFile(importMediaData.path)
		if err != nil {
			fmt.Printf("skipping file '%v' due to an error: %v\n", importMediaData.path, err)
			continue
		}

		media := media.Media{
			Hash:      fileHash,
			OrigPath:  importMediaData.path,
			Size:      importMediaData.size,
			MediaType: media.MEDIA_TYPE_PHOTO,
		}
		mgr.MediaService.Add(media)
		err = mgr.GalleryService.AddMediaToGallery(importMediaData.galleryName, media)
		if err != nil {
			fmt.Printf("error while putting media to gallery '%v': %v\n", importMediaData.galleryName, err)
			// TODO delete media!!!
		}
		wg.Done()
	}
}

func hashFile(filename string) (string, error) {
	var md5ChkSum string
	file, err := os.Open(filename)
	if err != nil {
		fmt.Println("could not open file:", filename)
		return md5ChkSum, err
	}
	defer file.Close()
	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		fmt.Println("could not hash file:", filename)
		return md5ChkSum, err
	}
	md5ChkSum = hex.EncodeToString(hash.Sum(nil))
	return md5ChkSum, nil
}

func addSlash(path string) string {
	path = strings.TrimSpace(path)
	if !strings.HasSuffix(path, "/") {
		path = path + "/"
	}
	return path
}
<|endoftext|>


<commit_before>package main

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

	"github.com/oinume/lekcije/server/bootstrap"
	"github.com/oinume/lekcije/server/config"
	"github.com/oinume/lekcije/server/emailer"
	"github.com/oinume/lekcije/server/logger"
	"github.com/oinume/lekcije/server/model"
	"github.com/uber-go/zap"
)

var (
	dryRun     = flag.Bool("dry-run", false, "Don't update database with fetched lessons")
	logLevel   = flag.String("log-level", "info", "Log level")
	targetDate = flag.String("target-date", "", "Specify registration date of users")
)

func main() {
	flag.Parse()
	if err := run(); err != nil {
		log.Fatalf("err = %v", err) // TODO: Error handling
	}
	os.Exit(0)
}

func run() error {
	bootstrap.CheckCLIEnvVars()
	startedAt := time.Now().UTC()
	if *logLevel != "" {
		logger.App.SetLevel(logger.NewLevel(*logLevel))
	}
	logger.App.Info("follow_reminder started")
	defer func() {
		elapsed := time.Now().UTC().Sub(startedAt) / time.Millisecond
		logger.App.Info("follow_reminder finished", zap.Int("elapsed", int(elapsed)))
	}()

	db, err := model.OpenDB(bootstrap.CLIEnvVars.DBURL, 1, !config.IsProductionEnv())
	if err != nil {
		return err
	}
	defer db.Close()

	var date time.Time
	if *targetDate == "" {
		date = time.Now().UTC().Add(-1 * 24 * time.Hour)
	} else {
		date, err = time.Parse("2006-01-02", *targetDate)
		if err != nil {
			return fmt.Errorf("Failed to parse 'target-date': %v", *targetDate)
		}
	}
	users, err := model.NewUserService(db).FindAllFollowedTeacherAtIsNull(date)
	if err != nil {
		return err
	}

	sender := emailer.NewSendGridSender(http.DefaultClient)
	templateText := getEmailTemplate()
	for _, user := range users {
		t := emailer.NewTemplate("follow_reminder", templateText)
		data := struct {
			To   string
			Name string
		}{
			To:   user.Email.Raw(),
			Name: user.Name,
		}
		mail, err := emailer.NewEmailFromTemplate(t, data)
		if err != nil {
			return err
		}

		if !*dryRun {
			if err := sender.Send(mail); err != nil {
				return err
			}
			logger.App.Info("followReminder", zap.String("email", user.Email.Raw()))
		}
	}

	return nil
}

func getEmailTemplate() string {
	return strings.TrimSpace(`
From: lekcije@lekcije.com
To: {{ .To }}
Subject: lekcijeでお気に入りの講師をフォローしましょう
Body: text/html
lekcijeをご利用いただきありがとうございます。
lekcijeでお気入りのDMM英会話の講師をフォローしてみましょう。
フォローすると、講師の空きレッスンが登録された時にメールでお知らせが届きます。

フォローの仕方がわからない場合は下記をチェック！
PC
Mobile

今後ともlekcijeをよろしくお願いいたします。
	`)
}
<commit_msg>Add userID to log<commit_after>package main

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

	"github.com/oinume/lekcije/server/bootstrap"
	"github.com/oinume/lekcije/server/config"
	"github.com/oinume/lekcije/server/emailer"
	"github.com/oinume/lekcije/server/logger"
	"github.com/oinume/lekcije/server/model"
	"github.com/uber-go/zap"
)

var (
	dryRun     = flag.Bool("dry-run", false, "Don't update database with fetched lessons")
	logLevel   = flag.String("log-level", "info", "Log level")
	targetDate = flag.String("target-date", "", "Specify registration date of users")
)

func main() {
	flag.Parse()
	if err := run(); err != nil {
		log.Fatalf("err = %v", err) // TODO: Error handling
	}
	os.Exit(0)
}

func run() error {
	bootstrap.CheckCLIEnvVars()
	startedAt := time.Now().UTC()
	if *logLevel != "" {
		logger.App.SetLevel(logger.NewLevel(*logLevel))
	}
	logger.App.Info("follow_reminder started")
	defer func() {
		elapsed := time.Now().UTC().Sub(startedAt) / time.Millisecond
		logger.App.Info("follow_reminder finished", zap.Int("elapsed", int(elapsed)))
	}()

	db, err := model.OpenDB(bootstrap.CLIEnvVars.DBURL, 1, !config.IsProductionEnv())
	if err != nil {
		return err
	}
	defer db.Close()

	var date time.Time
	if *targetDate == "" {
		date = time.Now().UTC().Add(-1 * 24 * time.Hour)
	} else {
		date, err = time.Parse("2006-01-02", *targetDate)
		if err != nil {
			return fmt.Errorf("Failed to parse 'target-date': %v", *targetDate)
		}
	}
	users, err := model.NewUserService(db).FindAllFollowedTeacherAtIsNull(date)
	if err != nil {
		return err
	}

	sender := emailer.NewSendGridSender(http.DefaultClient)
	templateText := getEmailTemplate()
	for _, user := range users {
		t := emailer.NewTemplate("follow_reminder", templateText)
		data := struct {
			To   string
			Name string
		}{
			To:   user.Email.Raw(),
			Name: user.Name,
		}
		mail, err := emailer.NewEmailFromTemplate(t, data)
		if err != nil {
			return err
		}

		if !*dryRun {
			if err := sender.Send(mail); err != nil {
				return err
			}
			logger.App.Info("followReminder", zap.Uint("userID", uint(user.ID)), zap.String("email", user.Email.Raw()))
		}
	}

	return nil
}

func getEmailTemplate() string {
	return strings.TrimSpace(`
From: lekcije@lekcije.com
To: {{ .To }}
Subject: lekcijeでお気に入りの講師をフォローしましょう
Body: text/html
lekcijeをご利用いただきありがとうございます。
lekcijeでお気入りのDMM英会話の講師をフォローしてみましょう。
フォローすると、講師の空きレッスンが登録された時にメールでお知らせが届きます。

フォローの仕方がわからない場合は下記をチェック！
PC
Mobile

今後ともlekcijeをよろしくお願いいたします。
	`)
}
<|endoftext|>


<commit_before>// Same copyright and license as the rest of the files in this project
// This file contains accelerator related functions and structures

package gtk

// #include <gtk/gtk.h>
// #include "gtk.go.h"
import "C"
import (
	"unsafe"

	"github.com/gotk3/gotk3/glib"
)

/*
 * GtkTreeViewColumn
 */

// TreeViewColumns is a representation of GTK's GtkTreeViewColumn.
type TreeViewColumn struct {
	glib.InitiallyUnowned
}

// native returns a pointer to the underlying GtkTreeViewColumn.
func (v *TreeViewColumn) native() *C.GtkTreeViewColumn {
	if v == nil || v.GObject == nil {
		return nil
	}
	p := unsafe.Pointer(v.GObject)
	return C.toGtkTreeViewColumn(p)
}

func marshalTreeViewColumn(p uintptr) (interface{}, error) {
	c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
	obj := glib.Take(unsafe.Pointer(c))
	return wrapTreeViewColumn(obj), nil
}

func wrapTreeViewColumn(obj *glib.Object) *TreeViewColumn {
	return &TreeViewColumn{glib.InitiallyUnowned{obj}}
}

// TreeViewColumnNew() is a wrapper around gtk_tree_view_column_new().
func TreeViewColumnNew() (*TreeViewColumn, error) {
	c := C.gtk_tree_view_column_new()
	if c == nil {
		return nil, nilPtrErr
	}
	return wrapTreeViewColumn(glib.Take(unsafe.Pointer(c))), nil
}

// TreeViewColumnNewWithAttribute() is a wrapper around
// gtk_tree_view_column_new_with_attributes() that only sets one
// attribute for one column.
func TreeViewColumnNewWithAttribute(title string, renderer ICellRenderer, attribute string, column int) (*TreeViewColumn, error) {
	t_cstr := C.CString(title)
	defer C.free(unsafe.Pointer(t_cstr))
	a_cstr := C.CString(attribute)
	defer C.free(unsafe.Pointer(a_cstr))
	c := C._gtk_tree_view_column_new_with_attributes_one((*C.gchar)(t_cstr),
		renderer.toCellRenderer(), (*C.gchar)(a_cstr), C.gint(column))
	if c == nil {
		return nil, nilPtrErr
	}
	return wrapTreeViewColumn(glib.Take(unsafe.Pointer(c))), nil
}

// AddAttribute() is a wrapper around gtk_tree_view_column_add_attribute().
func (v *TreeViewColumn) AddAttribute(renderer ICellRenderer, attribute string, column int) {
	cstr := C.CString(attribute)
	defer C.free(unsafe.Pointer(cstr))
	C.gtk_tree_view_column_add_attribute(v.native(),
		renderer.toCellRenderer(), (*C.gchar)(cstr), C.gint(column))
}

// SetExpand() is a wrapper around gtk_tree_view_column_set_expand().
func (v *TreeViewColumn) SetExpand(expand bool) {
	C.gtk_tree_view_column_set_expand(v.native(), gbool(expand))
}

// GetExpand() is a wrapper around gtk_tree_view_column_get_expand().
func (v *TreeViewColumn) GetExpand() bool {
	c := C.gtk_tree_view_column_get_expand(v.native())
	return gobool(c)
}

// SetMinWidth() is a wrapper around gtk_tree_view_column_set_min_width().
func (v *TreeViewColumn) SetMinWidth(minWidth int) {
	C.gtk_tree_view_column_set_min_width(v.native(), C.gint(minWidth))
}

// GetMinWidth() is a wrapper around gtk_tree_view_column_get_min_width().
func (v *TreeViewColumn) GetMinWidth() int {
	c := C.gtk_tree_view_column_get_min_width(v.native())
	return int(c)
}

// PackStart() is a wrapper around gtk_tree_view_column_pack_start().
func (v *TreeViewColumn) PackStart(cell *CellRenderer, expand bool) {
	C.gtk_tree_view_column_pack_start(v.native(), cell.native(), gbool(expand))
}

// PackEnd() is a wrapper around gtk_tree_view_column_pack_end().
func (v *TreeViewColumn) PackEnd(cell *CellRenderer, expand bool) {
	C.gtk_tree_view_column_pack_end(v.native(), cell.native(), gbool(expand))
}

// Clear() is a wrapper around gtk_tree_view_column_clear().
func (v *TreeViewColumn) Clear() {
	C.gtk_tree_view_column_clear(v.native())
}

// ClearAttributes() is a wrapper around gtk_tree_view_column_clear_attributes().
func (v *TreeViewColumn) ClearAttributes(cell *CellRenderer) {
	C.gtk_tree_view_column_clear_attributes(v.native(), cell.native())
}

// SetSpacing() is a wrapper around gtk_tree_view_column_set_spacing().
func (v *TreeViewColumn) SetSpacing(spacing int) {
	C.gtk_tree_view_column_set_spacing(v.native(), C.gint(spacing))
}

// GetSpacing() is a wrapper around gtk_tree_view_column_get_spacing().
func (v *TreeViewColumn) GetSpacing() int {
	return int(C.gtk_tree_view_column_get_spacing(v.native()))
}

// SetVisible() is a wrapper around gtk_tree_view_column_set_visible().
func (v *TreeViewColumn) SetVisible(visible bool) {
	C.gtk_tree_view_column_set_visible(v.native(), gbool(visible))
}

// GetVisible() is a wrapper around gtk_tree_view_column_get_visible().
func (v *TreeViewColumn) GetVisible() bool {
	return gobool(C.gtk_tree_view_column_get_visible(v.native()))
}

// SetResizable() is a wrapper around gtk_tree_view_column_set_resizable().
func (v *TreeViewColumn) SetResizable(resizable bool) {
	C.gtk_tree_view_column_set_resizable(v.native(), gbool(resizable))
}

// GetResizable() is a wrapper around gtk_tree_view_column_get_resizable().
func (v *TreeViewColumn) GetResizable() bool {
	return gobool(C.gtk_tree_view_column_get_resizable(v.native()))
}

// GetWidth() is a wrapper around gtk_tree_view_column_get_width().
func (v *TreeViewColumn) GetWidth() int {
	return int(C.gtk_tree_view_column_get_width(v.native()))
}

// SetFixedWidth() is a wrapper around gtk_tree_view_column_set_fixed_width().
func (v *TreeViewColumn) SetFixedWidth(w int) {
	C.gtk_tree_view_column_set_fixed_width(v.native(), C.gint(w))
}

// GetFixedWidth() is a wrapper around gtk_tree_view_column_get_fixed_width().
func (v *TreeViewColumn) GetFixedWidth() int {
	return int(C.gtk_tree_view_column_get_fixed_width(v.native()))
}

// SetMaxWidth() is a wrapper around gtk_tree_view_column_set_max_width().
func (v *TreeViewColumn) SetMaxWidth(w int) {
	C.gtk_tree_view_column_set_max_width(v.native(), C.gint(w))
}

// GetMaxWidth() is a wrapper around gtk_tree_view_column_get_max_width().
func (v *TreeViewColumn) GetMaxWidth() int {
	return int(C.gtk_tree_view_column_get_max_width(v.native()))
}

// Clicked() is a wrapper around gtk_tree_view_column_clicked().
func (v *TreeViewColumn) Clicked() {
	C.gtk_tree_view_column_clicked(v.native())
}

// SetTitle() is a wrapper around gtk_tree_view_column_set_title().
func (v *TreeViewColumn) SetTitle(t string) {
	cstr := (*C.gchar)(C.CString(t))
	defer C.free(unsafe.Pointer(cstr))
	C.gtk_tree_view_column_set_title(v.native(), cstr)
}

// GetTitle() is a wrapper around gtk_tree_view_column_get_title().
func (v *TreeViewColumn) GetTitle() string {
	return C.GoString((*C.char)(C.gtk_tree_view_column_get_title(v.native())))
}

// SetClickable() is a wrapper around gtk_tree_view_column_set_clickable().
func (v *TreeViewColumn) SetClickable(clickable bool) {
	C.gtk_tree_view_column_set_clickable(v.native(), gbool(clickable))
}

// GetClickable() is a wrapper around gtk_tree_view_column_get_clickable().
func (v *TreeViewColumn) GetClickable() bool {
	return gobool(C.gtk_tree_view_column_get_clickable(v.native()))
}

// SetReorderable() is a wrapper around gtk_tree_view_column_set_reorderable().
func (v *TreeViewColumn) SetReorderable(reorderable bool) {
	C.gtk_tree_view_column_set_reorderable(v.native(), gbool(reorderable))
}

// GetReorderable() is a wrapper around gtk_tree_view_column_get_reorderable().
func (v *TreeViewColumn) GetReorderable() bool {
	return gobool(C.gtk_tree_view_column_get_reorderable(v.native()))
}

// SetSortIndicator() is a wrapper around gtk_tree_view_column_set_sort_indicator().
func (v *TreeViewColumn) SetSortIndicator(reorderable bool) {
	C.gtk_tree_view_column_set_sort_indicator(v.native(), gbool(reorderable))
}

// GetSortIndicator() is a wrapper around gtk_tree_view_column_get_sort_indicator().
func (v *TreeViewColumn) GetSortIndicator() bool {
	return gobool(C.gtk_tree_view_column_get_sort_indicator(v.native()))
}

// SetSortColumnID() is a wrapper around gtk_tree_view_column_set_sort_column_id().
func (v *TreeViewColumn) SetSortColumnID(w int) {
	C.gtk_tree_view_column_set_sort_column_id(v.native(), C.gint(w))
}

// GetSortColumnID() is a wrapper around gtk_tree_view_column_get_sort_column_id().
func (v *TreeViewColumn) GetSortColumnID() int {
	return int(C.gtk_tree_view_column_get_sort_column_id(v.native()))
}

// CellIsVisible() is a wrapper around gtk_tree_view_column_cell_is_visible().
func (v *TreeViewColumn) CellIsVisible() bool {
	return gobool(C.gtk_tree_view_column_cell_is_visible(v.native()))
}

// FocusCell() is a wrapper around gtk_tree_view_column_focus_cell().
func (v *TreeViewColumn) FocusCell(cell *CellRenderer) {
	C.gtk_tree_view_column_focus_cell(v.native(), cell.native())
}

// QueueResize() is a wrapper around gtk_tree_view_column_queue_resize().
func (v *TreeViewColumn) QueueResize() {
	C.gtk_tree_view_column_queue_resize(v.native())
}

// GetXOffset() is a wrapper around gtk_tree_view_column_get_x_offset().
func (v *TreeViewColumn) GetXOffset() int {
	return int(C.gtk_tree_view_column_get_x_offset(v.native()))
}

// GtkTreeViewColumn * 	gtk_tree_view_column_new_with_area ()
// void 	gtk_tree_view_column_set_attributes ()
// void 	gtk_tree_view_column_set_cell_data_func ()

type TreeViewColumnSizing int

const (
	TREE_VIEW_COLUMN_GROW_ONLY TreeViewColumnSizing = C.GTK_TREE_VIEW_COLUMN_GROW_ONLY
	TREE_VIEW_COLUMN_AUTOSIZE                       = C.GTK_TREE_VIEW_COLUMN_AUTOSIZE
	TREE_VIEW_COLUMN_FIXED                          = C.GTK_TREE_VIEW_COLUMN_FIXED
)

// void 	gtk_tree_view_column_set_sizing ()
func (v *TreeViewColumn) SetSizing(sizing TreeViewColumnSizing) {
	C.gtk_tree_view_column_set_sizing(v.native(), C.GtkTreeViewColumnSizing(sizing))
}

// GtkTreeViewColumnSizing 	gtk_tree_view_column_get_sizing ()
func (v *TreeViewColumn) GetSizing() TreeViewColumnSizing {
	return TreeViewColumnSizing(C.gtk_tree_view_column_get_sizing(v.native()))
}

// void 	gtk_tree_view_column_set_widget ()
// GtkWidget * 	gtk_tree_view_column_get_widget ()
// GtkWidget * 	gtk_tree_view_column_get_button ()
// void 	gtk_tree_view_column_set_alignment ()
// gfloat 	gtk_tree_view_column_get_alignment ()

type GtkSortType int

const (
	GTK_SORT_ASCENDING  GtkSortType = C.GTK_SORT_ASCENDING
	GTK_SORT_DESCENDING             = C.GTK_SORT_DESCENDING
)

// void 	gtk_tree_view_column_set_sort_order ()
func (v *TreeViewColumn) SetSortOrder(order GtkSortType) {
	C.gtk_tree_view_column_set_sort_order(v.native(), C.GtkSortType(order))
}

// GtkSortType 	gtk_tree_view_column_get_sort_order ()
func (v *TreeViewColumn) GetSortOrder() GtkSortType {
	return GtkSortType(C.gtk_tree_view_column_get_sort_order(v.native()))
}

// void 	gtk_tree_view_column_cell_set_cell_data ()
// void 	gtk_tree_view_column_cell_get_size ()
// gboolean 	gtk_tree_view_column_cell_get_position ()
// GtkWidget * 	gtk_tree_view_column_get_tree_view ()
<commit_msg>fix remove duplicate declaration of const GtkSortType<commit_after>// Same copyright and license as the rest of the files in this project
// This file contains accelerator related functions and structures

package gtk

// #include <gtk/gtk.h>
// #include "gtk.go.h"
import "C"
import (
	"unsafe"

	"github.com/gotk3/gotk3/glib"
)

/*
 * GtkTreeViewColumn
 */

// TreeViewColumns is a representation of GTK's GtkTreeViewColumn.
type TreeViewColumn struct {
	glib.InitiallyUnowned
}

// native returns a pointer to the underlying GtkTreeViewColumn.
func (v *TreeViewColumn) native() *C.GtkTreeViewColumn {
	if v == nil || v.GObject == nil {
		return nil
	}
	p := unsafe.Pointer(v.GObject)
	return C.toGtkTreeViewColumn(p)
}

func marshalTreeViewColumn(p uintptr) (interface{}, error) {
	c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
	obj := glib.Take(unsafe.Pointer(c))
	return wrapTreeViewColumn(obj), nil
}

func wrapTreeViewColumn(obj *glib.Object) *TreeViewColumn {
	return &TreeViewColumn{glib.InitiallyUnowned{obj}}
}

// TreeViewColumnNew() is a wrapper around gtk_tree_view_column_new().
func TreeViewColumnNew() (*TreeViewColumn, error) {
	c := C.gtk_tree_view_column_new()
	if c == nil {
		return nil, nilPtrErr
	}
	return wrapTreeViewColumn(glib.Take(unsafe.Pointer(c))), nil
}

// TreeViewColumnNewWithAttribute() is a wrapper around
// gtk_tree_view_column_new_with_attributes() that only sets one
// attribute for one column.
func TreeViewColumnNewWithAttribute(title string, renderer ICellRenderer, attribute string, column int) (*TreeViewColumn, error) {
	t_cstr := C.CString(title)
	defer C.free(unsafe.Pointer(t_cstr))
	a_cstr := C.CString(attribute)
	defer C.free(unsafe.Pointer(a_cstr))
	c := C._gtk_tree_view_column_new_with_attributes_one((*C.gchar)(t_cstr),
		renderer.toCellRenderer(), (*C.gchar)(a_cstr), C.gint(column))
	if c == nil {
		return nil, nilPtrErr
	}
	return wrapTreeViewColumn(glib.Take(unsafe.Pointer(c))), nil
}

// AddAttribute() is a wrapper around gtk_tree_view_column_add_attribute().
func (v *TreeViewColumn) AddAttribute(renderer ICellRenderer, attribute string, column int) {
	cstr := C.CString(attribute)
	defer C.free(unsafe.Pointer(cstr))
	C.gtk_tree_view_column_add_attribute(v.native(),
		renderer.toCellRenderer(), (*C.gchar)(cstr), C.gint(column))
}

// SetExpand() is a wrapper around gtk_tree_view_column_set_expand().
func (v *TreeViewColumn) SetExpand(expand bool) {
	C.gtk_tree_view_column_set_expand(v.native(), gbool(expand))
}

// GetExpand() is a wrapper around gtk_tree_view_column_get_expand().
func (v *TreeViewColumn) GetExpand() bool {
	c := C.gtk_tree_view_column_get_expand(v.native())
	return gobool(c)
}

// SetMinWidth() is a wrapper around gtk_tree_view_column_set_min_width().
func (v *TreeViewColumn) SetMinWidth(minWidth int) {
	C.gtk_tree_view_column_set_min_width(v.native(), C.gint(minWidth))
}

// GetMinWidth() is a wrapper around gtk_tree_view_column_get_min_width().
func (v *TreeViewColumn) GetMinWidth() int {
	c := C.gtk_tree_view_column_get_min_width(v.native())
	return int(c)
}

// PackStart() is a wrapper around gtk_tree_view_column_pack_start().
func (v *TreeViewColumn) PackStart(cell *CellRenderer, expand bool) {
	C.gtk_tree_view_column_pack_start(v.native(), cell.native(), gbool(expand))
}

// PackEnd() is a wrapper around gtk_tree_view_column_pack_end().
func (v *TreeViewColumn) PackEnd(cell *CellRenderer, expand bool) {
	C.gtk_tree_view_column_pack_end(v.native(), cell.native(), gbool(expand))
}

// Clear() is a wrapper around gtk_tree_view_column_clear().
func (v *TreeViewColumn) Clear() {
	C.gtk_tree_view_column_clear(v.native())
}

// ClearAttributes() is a wrapper around gtk_tree_view_column_clear_attributes().
func (v *TreeViewColumn) ClearAttributes(cell *CellRenderer) {
	C.gtk_tree_view_column_clear_attributes(v.native(), cell.native())
}

// SetSpacing() is a wrapper around gtk_tree_view_column_set_spacing().
func (v *TreeViewColumn) SetSpacing(spacing int) {
	C.gtk_tree_view_column_set_spacing(v.native(), C.gint(spacing))
}

// GetSpacing() is a wrapper around gtk_tree_view_column_get_spacing().
func (v *TreeViewColumn) GetSpacing() int {
	return int(C.gtk_tree_view_column_get_spacing(v.native()))
}

// SetVisible() is a wrapper around gtk_tree_view_column_set_visible().
func (v *TreeViewColumn) SetVisible(visible bool) {
	C.gtk_tree_view_column_set_visible(v.native(), gbool(visible))
}

// GetVisible() is a wrapper around gtk_tree_view_column_get_visible().
func (v *TreeViewColumn) GetVisible() bool {
	return gobool(C.gtk_tree_view_column_get_visible(v.native()))
}

// SetResizable() is a wrapper around gtk_tree_view_column_set_resizable().
func (v *TreeViewColumn) SetResizable(resizable bool) {
	C.gtk_tree_view_column_set_resizable(v.native(), gbool(resizable))
}

// GetResizable() is a wrapper around gtk_tree_view_column_get_resizable().
func (v *TreeViewColumn) GetResizable() bool {
	return gobool(C.gtk_tree_view_column_get_resizable(v.native()))
}

// GetWidth() is a wrapper around gtk_tree_view_column_get_width().
func (v *TreeViewColumn) GetWidth() int {
	return int(C.gtk_tree_view_column_get_width(v.native()))
}

// SetFixedWidth() is a wrapper around gtk_tree_view_column_set_fixed_width().
func (v *TreeViewColumn) SetFixedWidth(w int) {
	C.gtk_tree_view_column_set_fixed_width(v.native(), C.gint(w))
}

// GetFixedWidth() is a wrapper around gtk_tree_view_column_get_fixed_width().
func (v *TreeViewColumn) GetFixedWidth() int {
	return int(C.gtk_tree_view_column_get_fixed_width(v.native()))
}

// SetMaxWidth() is a wrapper around gtk_tree_view_column_set_max_width().
func (v *TreeViewColumn) SetMaxWidth(w int) {
	C.gtk_tree_view_column_set_max_width(v.native(), C.gint(w))
}

// GetMaxWidth() is a wrapper around gtk_tree_view_column_get_max_width().
func (v *TreeViewColumn) GetMaxWidth() int {
	return int(C.gtk_tree_view_column_get_max_width(v.native()))
}

// Clicked() is a wrapper around gtk_tree_view_column_clicked().
func (v *TreeViewColumn) Clicked() {
	C.gtk_tree_view_column_clicked(v.native())
}

// SetTitle() is a wrapper around gtk_tree_view_column_set_title().
func (v *TreeViewColumn) SetTitle(t string) {
	cstr := (*C.gchar)(C.CString(t))
	defer C.free(unsafe.Pointer(cstr))
	C.gtk_tree_view_column_set_title(v.native(), cstr)
}

// GetTitle() is a wrapper around gtk_tree_view_column_get_title().
func (v *TreeViewColumn) GetTitle() string {
	return C.GoString((*C.char)(C.gtk_tree_view_column_get_title(v.native())))
}

// SetClickable() is a wrapper around gtk_tree_view_column_set_clickable().
func (v *TreeViewColumn) SetClickable(clickable bool) {
	C.gtk_tree_view_column_set_clickable(v.native(), gbool(clickable))
}

// GetClickable() is a wrapper around gtk_tree_view_column_get_clickable().
func (v *TreeViewColumn) GetClickable() bool {
	return gobool(C.gtk_tree_view_column_get_clickable(v.native()))
}

// SetReorderable() is a wrapper around gtk_tree_view_column_set_reorderable().
func (v *TreeViewColumn) SetReorderable(reorderable bool) {
	C.gtk_tree_view_column_set_reorderable(v.native(), gbool(reorderable))
}

// GetReorderable() is a wrapper around gtk_tree_view_column_get_reorderable().
func (v *TreeViewColumn) GetReorderable() bool {
	return gobool(C.gtk_tree_view_column_get_reorderable(v.native()))
}

// SetSortIndicator() is a wrapper around gtk_tree_view_column_set_sort_indicator().
func (v *TreeViewColumn) SetSortIndicator(reorderable bool) {
	C.gtk_tree_view_column_set_sort_indicator(v.native(), gbool(reorderable))
}

// GetSortIndicator() is a wrapper around gtk_tree_view_column_get_sort_indicator().
func (v *TreeViewColumn) GetSortIndicator() bool {
	return gobool(C.gtk_tree_view_column_get_sort_indicator(v.native()))
}

// SetSortColumnID() is a wrapper around gtk_tree_view_column_set_sort_column_id().
func (v *TreeViewColumn) SetSortColumnID(w int) {
	C.gtk_tree_view_column_set_sort_column_id(v.native(), C.gint(w))
}

// GetSortColumnID() is a wrapper around gtk_tree_view_column_get_sort_column_id().
func (v *TreeViewColumn) GetSortColumnID() int {
	return int(C.gtk_tree_view_column_get_sort_column_id(v.native()))
}

// CellIsVisible() is a wrapper around gtk_tree_view_column_cell_is_visible().
func (v *TreeViewColumn) CellIsVisible() bool {
	return gobool(C.gtk_tree_view_column_cell_is_visible(v.native()))
}

// FocusCell() is a wrapper around gtk_tree_view_column_focus_cell().
func (v *TreeViewColumn) FocusCell(cell *CellRenderer) {
	C.gtk_tree_view_column_focus_cell(v.native(), cell.native())
}

// QueueResize() is a wrapper around gtk_tree_view_column_queue_resize().
func (v *TreeViewColumn) QueueResize() {
	C.gtk_tree_view_column_queue_resize(v.native())
}

// GetXOffset() is a wrapper around gtk_tree_view_column_get_x_offset().
func (v *TreeViewColumn) GetXOffset() int {
	return int(C.gtk_tree_view_column_get_x_offset(v.native()))
}

// GtkTreeViewColumn * 	gtk_tree_view_column_new_with_area ()
// void 	gtk_tree_view_column_set_attributes ()
// void 	gtk_tree_view_column_set_cell_data_func ()

type TreeViewColumnSizing int

const (
	TREE_VIEW_COLUMN_GROW_ONLY TreeViewColumnSizing = C.GTK_TREE_VIEW_COLUMN_GROW_ONLY
	TREE_VIEW_COLUMN_AUTOSIZE                       = C.GTK_TREE_VIEW_COLUMN_AUTOSIZE
	TREE_VIEW_COLUMN_FIXED                          = C.GTK_TREE_VIEW_COLUMN_FIXED
)

// void 	gtk_tree_view_column_set_sizing ()
func (v *TreeViewColumn) SetSizing(sizing TreeViewColumnSizing) {
	C.gtk_tree_view_column_set_sizing(v.native(), C.GtkTreeViewColumnSizing(sizing))
}

// GtkTreeViewColumnSizing 	gtk_tree_view_column_get_sizing ()
func (v *TreeViewColumn) GetSizing() TreeViewColumnSizing {
	return TreeViewColumnSizing(C.gtk_tree_view_column_get_sizing(v.native()))
}

// void 	gtk_tree_view_column_set_widget ()
// GtkWidget * 	gtk_tree_view_column_get_widget ()
// GtkWidget * 	gtk_tree_view_column_get_button ()
// void 	gtk_tree_view_column_set_alignment ()
// gfloat 	gtk_tree_view_column_get_alignment ()

// void 	gtk_tree_view_column_set_sort_order ()
func (v *TreeViewColumn) SetSortOrder(order SortType) {
	C.gtk_tree_view_column_set_sort_order(v.native(), C.GtkSortType(order))
}

// GtkSortType 	gtk_tree_view_column_get_sort_order ()
func (v *TreeViewColumn) GetSortOrder() SortType {
	return SortType(C.gtk_tree_view_column_get_sort_order(v.native()))
}

// void 	gtk_tree_view_column_cell_set_cell_data ()
// void 	gtk_tree_view_column_cell_get_size ()
// gboolean 	gtk_tree_view_column_cell_get_position ()
// GtkWidget * 	gtk_tree_view_column_get_tree_view ()
<|endoftext|>


<commit_before>package faker

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

var imageCategories = []string{
	"abstract", "animals", "business", "cats", "city",
	"food", "nightlife", "fashion",
	"people", "nature", "sports",
	"technics", "transport",
}

type Image struct {
	Category string
	Width    int
	Height   int
	Url      string
}

func (image *Image) Image_(params ...interface{}) string {
	category := sample(imageCategories)

	switch category {
	case "abstract":
		image.Abstract_(params...)
	case "animals":
		image.Animals_(params...)
	case "business":
		image.Business_(params...)
	case "cats":
		image.Cats_(params...)
	case "city":
		image.City_(params...)
	case "food":
		image.Food_(params...)
	case "nightlife":
		image.Nightlife_(params...)
	case "fashion":
		image.Fashion_(params...)
	case "people":
		image.People_(params...)
	case "nature":
		image.Nature_(params...)
	case "sports":
		image.Sports_(params...)
	case "technics":
		image.Technics_(params...)
	case "transport":
		image.Transport_(params...)
	}

	return image.Url
}

func (image *Image) ImageURL(category string, params ...interface{}) string {
	randomize := false
	image.Width = 640
	image.Height = 480
	image.Category = category

	types := typeof(params...)

	if len(types) >= 1 && types[0] == reflect.Int {

		image.Width = params[0].(int)
	}

	if len(types) >= 2 && types[1] == reflect.Int {
		image.Height = params[1].(int)
	}

	if len(types) >= 3 && types[2] == reflect.Bool {
		randomize = params[2].(bool)
	}

	image.Url = "http://lorempixel.com/" +
		strconv.Itoa(image.Width) + "/" +
		strconv.Itoa(image.Height)

	if image.Category != "" {
		image.Url += "/" + image.Category
	}

	if randomize {
		image.Url += "?" + strconv.Itoa(rand.Int())
	}

	return image.Url
}

// TODO: Avatar from internet avatar
func (image *Image) Avatar_(params ...interface{}) string {
	//imageUrl(width, height, 'abstract', randomize);
	return ""
}

func (image *Image) Abstract_(params ...interface{}) string {
	image.ImageURL("abstract", params...)
	return image.Url
}

func (image *Image) Animals_(params ...interface{}) string {
	image.ImageURL("animals", params...)
	return image.Url
}

func (image *Image) Business_(params ...interface{}) string {
	image.ImageURL("business", params...)
	return image.Url
}

func (image *Image) Cats_(params ...interface{}) string {
	image.ImageURL("cats", params...)
	return image.Url
}

func (image *Image) City_(params ...interface{}) string {
	image.ImageURL("city", params...)
	return image.Url
}

func (image *Image) Food_(params ...interface{}) string {
	image.ImageURL("food", params...)
	return image.Url
}
func (image *Image) Nightlife_(params ...interface{}) string {
	image.ImageURL("nightlife", params...)
	return image.Url
}
func (image *Image) Fashion_(params ...interface{}) string {
	image.ImageURL("fashion", params...)
	return image.Url
}
func (image *Image) People_(params ...interface{}) string {
	image.ImageURL("people", params...)
	return image.Url
}
func (image *Image) Nature_(params ...interface{}) string {
	image.ImageURL("nature", params...)
	return image.Url
}
func (image *Image) Sports_(params ...interface{}) string {
	image.ImageURL("sports", params...)
	return image.Url
}
func (image *Image) Technics_(params ...interface{}) string {
	image.ImageURL("technics", params...)
	return image.Url
}
func (image *Image) Transport_(params ...interface{}) string {
	image.ImageURL("transport", params...)
	return image.Url
}
<commit_msg>fix image avatar<commit_after>package faker

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

var imageCategories = []string{
	"abstract", "animals", "business", "cats", "city",
	"food", "nightlife", "fashion",
	"people", "nature", "sports",
	"technics", "transport",
}

type Image struct {
	Category string
	Width    int
	Height   int
	Url      string
}

func (image *Image) Image_(params ...interface{}) string {
	category := sample(imageCategories)

	switch category {
	case "abstract":
		image.Abstract_(params...)
	case "animals":
		image.Animals_(params...)
	case "business":
		image.Business_(params...)
	case "cats":
		image.Cats_(params...)
	case "city":
		image.City_(params...)
	case "food":
		image.Food_(params...)
	case "nightlife":
		image.Nightlife_(params...)
	case "fashion":
		image.Fashion_(params...)
	case "people":
		image.People_(params...)
	case "nature":
		image.Nature_(params...)
	case "sports":
		image.Sports_(params...)
	case "technics":
		image.Technics_(params...)
	case "transport":
		image.Transport_(params...)
	}

	return image.Url
}

func (image *Image) ImageURL(category string, params ...interface{}) string {
	randomize := false
	image.Width = 640
	image.Height = 480
	image.Category = category

	types := typeof(params...)

	if len(types) >= 1 && types[0] == reflect.Int {

		image.Width = params[0].(int)
	}

	if len(types) >= 2 && types[1] == reflect.Int {
		image.Height = params[1].(int)
	}

	if len(types) >= 3 && types[2] == reflect.Bool {
		randomize = params[2].(bool)
	}

	image.Url = "http://lorempixel.com/" +
		strconv.Itoa(image.Width) + "/" +
		strconv.Itoa(image.Height)

	if image.Category != "" {
		image.Url += "/" + image.Category
	}

	if randomize {
		image.Url += "?" + strconv.Itoa(rand.Int())
	}

	return image.Url
}

func (image *Image) Avatar_(params ...interface{}) string {

	internet := Internet{}
	return internet.Avatar_()
}

func (image *Image) Abstract_(params ...interface{}) string {
	image.ImageURL("abstract", params...)
	return image.Url
}

func (image *Image) Animals_(params ...interface{}) string {
	image.ImageURL("animals", params...)
	return image.Url
}

func (image *Image) Business_(params ...interface{}) string {
	image.ImageURL("business", params...)
	return image.Url
}

func (image *Image) Cats_(params ...interface{}) string {
	image.ImageURL("cats", params...)
	return image.Url
}

func (image *Image) City_(params ...interface{}) string {
	image.ImageURL("city", params...)
	return image.Url
}

func (image *Image) Food_(params ...interface{}) string {
	image.ImageURL("food", params...)
	return image.Url
}
func (image *Image) Nightlife_(params ...interface{}) string {
	image.ImageURL("nightlife", params...)
	return image.Url
}
func (image *Image) Fashion_(params ...interface{}) string {
	image.ImageURL("fashion", params...)
	return image.Url
}
func (image *Image) People_(params ...interface{}) string {
	image.ImageURL("people", params...)
	return image.Url
}
func (image *Image) Nature_(params ...interface{}) string {
	image.ImageURL("nature", params...)
	return image.Url
}
func (image *Image) Sports_(params ...interface{}) string {
	image.ImageURL("sports", params...)
	return image.Url
}
func (image *Image) Technics_(params ...interface{}) string {
	image.ImageURL("technics", params...)
	return image.Url
}
func (image *Image) Transport_(params ...interface{}) string {
	image.ImageURL("transport", params...)
	return image.Url
}
<|endoftext|>


<commit_before>// Copyright 2016 Qiang Xue. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package auth provides a set of user authentication handlers for the ozzo routing package.
package auth

import (
	"encoding/base64"
	"net/http"
	"strings"

	"github.com/dgrijalva/jwt-go"
	"github.com/go-ozzo/ozzo-routing"
)

// User is the key used to store and retrieve the user identity information in routing.Context
const User = "User"

// Identity represents an authenticated user. If a user is successfully authenticated by
// an auth handler (Basic, Bearer, or Query), an Identity object will be made available for injection.
type Identity interface{}

// DefaultRealm is the default realm name for HTTP authentication. It is used by HTTP authentication based on
// Basic and Bearer.
var DefaultRealm = "API"

// BasicAuthFunc is the function that does the actual user authentication according to the given username and password.
type BasicAuthFunc func(c *routing.Context, username, password string) (Identity, error)

// Basic returns a routing.Handler that performs HTTP basic authentication.
// It can be used like the following:
//
//   import (
//     "errors"
//     "fmt"
//     "net/http"
//     "github.com/go-ozzo/ozzo-routing"
//     "github.com/go-ozzo/ozzo-routing/auth"
//   )
//   func main() {
//     r := routing.New()
//     r.Use(auth.Basic(func(c *routing.Context, username, password string) (auth.Identity, error) {
//       if username == "demo" && password == "foo" {
//         return auth.Identity(username), nil
//       }
//       return nil, errors.New("invalid credential")
//     }))
//     r.Get("/demo", func(c *routing.Context) error {
//       fmt.Fprintf(res, "Hello, %v", c.Get(auth.User))
//       return nil
//     })
//   }
//
// By default, the auth realm is named as "API". You may customize it by specifying the realm parameter.
//
// When authentication fails, a "WWW-Authenticate" header will be sent, and an http.StatusUnauthorized
// error will be returned.
func Basic(fn BasicAuthFunc, realm ...string) routing.Handler {
	name := DefaultRealm
	if len(realm) > 0 {
		name = realm[0]
	}
	return func(c *routing.Context) error {
		username, password := parseBasicAuth(c.Request.Header.Get("Authorization"))
		identity, e := fn(c, username, password)
		if e == nil {
			c.Set(User, identity)
			return nil
		}
		c.Response.Header().Set("WWW-Authenticate", `Basic realm="`+name+`"`)
		return routing.NewHTTPError(http.StatusUnauthorized, e.Error())
	}
}

func parseBasicAuth(auth string) (username, password string) {
	if strings.HasPrefix(auth, "Basic ") {
		if bytes, err := base64.StdEncoding.DecodeString(auth[6:]); err == nil {
			str := string(bytes)
			if i := strings.IndexByte(str, ':'); i >= 0 {
				return str[:i], str[i+1:]
			}
		}
	}
	return
}

// TokenAuthFunc is the function for authenticating a user based on a secret token.
type TokenAuthFunc func(c *routing.Context, token string) (Identity, error)

// Bearer returns a routing.Handler that performs HTTP authentication based on bearer token.
// It can be used like the following:
//
//   import (
//     "errors"
//     "fmt"
//     "net/http"
//     "github.com/go-ozzo/ozzo-routing"
//     "github.com/go-ozzo/ozzo-routing/auth"
//   )
//   func main() {
//     r := routing.New()
//     r.Use(auth.Bearer(func(c *routing.Context, token string) (auth.Identity, error) {
//       if token == "secret" {
//         return auth.Identity("demo"), nil
//       }
//       return nil, errors.New("invalid credential")
//     }))
//     r.Get("/demo", func(c *routing.Context) error {
//       fmt.Fprintf(res, "Hello, %v", c.Get(auth.User))
//       return nil
//     })
//   }
//
// By default, the auth realm is named as "API". You may customize it by specifying the realm parameter.
//
// When authentication fails, a "WWW-Authenticate" header will be sent, and an http.StatusUnauthorized
// error will be returned.
func Bearer(fn TokenAuthFunc, realm ...string) routing.Handler {
	name := DefaultRealm
	if len(realm) > 0 {
		name = realm[0]
	}
	return func(c *routing.Context) error {
		token := parseBearerAuth(c.Request.Header.Get("Authorization"))
		identity, e := fn(c, token)
		if e == nil {
			c.Set(User, identity)
			return nil
		}
		c.Response.Header().Set("WWW-Authenticate", `Bearer realm="`+name+`"`)
		return routing.NewHTTPError(http.StatusUnauthorized, e.Error())
	}
}

func parseBearerAuth(auth string) string {
	if strings.HasPrefix(auth, "Bearer ") {
		if bearer, err := base64.StdEncoding.DecodeString(auth[7:]); err == nil {
			return string(bearer)
		}
	}
	return ""
}

// TokenName is the query parameter name for auth token.
var TokenName = "access-token"

// Query returns a routing.Handler that performs authentication based on a token passed via a query parameter.
// It can be used like the following:
//
//   import (
//     "errors"
//     "fmt"
//     "net/http"
//     "github.com/go-ozzo/ozzo-routing"
//     "github.com/go-ozzo/ozzo-routing/auth"
//   )
//   func main() {
//     r := routing.New()
//     r.Use(auth.Query(func(token string) (auth.Identity, error) {
//       if token == "secret" {
//         return auth.Identity("demo"), nil
//       }
//       return nil, errors.New("invalid credential")
//     }))
//     r.Get("/demo", func(c *routing.Context) error {
//       fmt.Fprintf(res, "Hello, %v", c.Get(auth.User))
//       return nil
//     })
//   }
//
// When authentication fails, an http.StatusUnauthorized error will be returned.
func Query(fn TokenAuthFunc, tokenName ...string) routing.Handler {
	name := TokenName
	if len(tokenName) > 0 {
		name = tokenName[0]
	}
	return func(c *routing.Context) error {
		token := c.Request.URL.Query().Get(name)
		identity, err := fn(c, token)
		if err != nil {
			return routing.NewHTTPError(http.StatusUnauthorized, err.Error())
		}
		c.Set(User, identity)
		return nil
	}
}

// JWTTokenHandler handles the parsed JWT token.
type JWTTokenHandler func(*routing.Context, *jwt.Token) error

// JWTOptions represents the options that can be used with the JWT handler.
type JWTOptions struct {
	// auth realm. Defaults to "API".
	Realm string
	// the allowed signing method. This is required and should be the actual method that you use to create JWT token. It defaults to "HS256".
	SigningMethod string
	// a function that handles the parsed JWT token. Defaults to DefaultJWTTokenHandler, which stores the token in the routing context with the key "JWT".
	TokenHandler JWTTokenHandler
}

// DefaultJWTTokenHandler stores the parsed JWT token in the routing context with the key named "JWT".
func DefaultJWTTokenHandler(c *routing.Context, token *jwt.Token) error {
	c.Set("JWT", token)
	return nil
}

// JWT returns a JWT (JSON Web Token) handler which attempts to parse the Bearer header into a JWT token and validate it.
// If both are successful, it will call a JWTTokenHandler to further handle the token. By default, the token
// will be stored in the routing context with the key named "JWT". Other handlers can retrieve this token to obtain
// the user identity information.
// If the parsing or validation fails, a "WWW-Authenticate" header will be sent, and an http.StatusUnauthorized
// error will be returned.
//
// JWT can be used like the following:
//
//   import (
//     "errors"
//     "fmt"
//     "net/http"
//     "github.com/dgrijalva/jwt-go"
//     "github.com/go-ozzo/ozzo-routing"
//     "github.com/go-ozzo/ozzo-routing/auth"
//   )
//   func main() {
//     signingKey := "secret-key"
//     r := routing.New()
//
//     r.Get("/login", func(c *routing.Context) error {
//       id, err := authenticate(c)
//       if err != nil {
//         return err
//       }
//       token, err := auth.NewJWT(jwt.StandardClaims{
//         Id: id
//       }, signingKey)
//       if err != nil {
//         return err
//       }
//       return c.Write(token)
//     })
//
//     r.Use(auth.JWT(signingKey))
//     r.Get("/restricted", func(c *routing.Context) error {
//       claims := c.Get("JWT").(*jwt.Token).Claims.(jwt.StandardClaims)
//       return c.Write(fmt.Sprint("Welcome, %v!", claims.Id)
//     })
//   }
func JWT(verificationKey string, options ...JWTOptions) routing.Handler {
	var opt JWTOptions
	if len(options) > 0 {
		opt = options[0]
	}
	if opt.Realm == "" {
		opt.Realm = DefaultRealm
	}
	if opt.SigningMethod == "" {
		opt.SigningMethod = "HS256"
	}
	if opt.TokenHandler == nil {
		opt.TokenHandler = DefaultJWTTokenHandler
	}
	parser := &jwt.Parser{
		ValidMethods: []string{opt.SigningMethod},
	}
	return func(c *routing.Context) error {
		header := c.Request.Header.Get("Authorization")
		if strings.HasPrefix(header, "Bearer ") {
			token, err := parser.Parse(header[7:], func(t *jwt.Token) (interface{}, error) { return []byte(verificationKey), nil })
			if err == nil && token.Valid {
				return opt.TokenHandler(c, token)
			}
		}

		c.Response.Header().Set("WWW-Authenticate", `Bearer realm="`+opt.Realm+`"`)
		return routing.NewHTTPError(http.StatusUnauthorized)
	}
}

// NewJWT creates a new JWT token and returns it as a signed string that may be sent to the client side.
// The signingMethod parameter is optional. It defaults to the HS256 algorithm.
func NewJWT(claims jwt.MapClaims, signingKey string, signingMethod ...jwt.SigningMethod) (string, error) {
	var sm jwt.SigningMethod = jwt.SigningMethodHS256
	if len(signingMethod) > 0 {
		sm = signingMethod[0]
	}
	return jwt.NewWithClaims(sm, claims).SignedString([]byte(signingKey))
}
<commit_msg>add concrete error message to auth failure<commit_after>// Copyright 2016 Qiang Xue. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package auth provides a set of user authentication handlers for the ozzo routing package.
package auth

import (
	"encoding/base64"
	"net/http"
	"strings"

	"github.com/dgrijalva/jwt-go"
	"github.com/go-ozzo/ozzo-routing"
)

// User is the key used to store and retrieve the user identity information in routing.Context
const User = "User"

// Identity represents an authenticated user. If a user is successfully authenticated by
// an auth handler (Basic, Bearer, or Query), an Identity object will be made available for injection.
type Identity interface{}

// DefaultRealm is the default realm name for HTTP authentication. It is used by HTTP authentication based on
// Basic and Bearer.
var DefaultRealm = "API"

// BasicAuthFunc is the function that does the actual user authentication according to the given username and password.
type BasicAuthFunc func(c *routing.Context, username, password string) (Identity, error)

// Basic returns a routing.Handler that performs HTTP basic authentication.
// It can be used like the following:
//
//   import (
//     "errors"
//     "fmt"
//     "net/http"
//     "github.com/go-ozzo/ozzo-routing"
//     "github.com/go-ozzo/ozzo-routing/auth"
//   )
//   func main() {
//     r := routing.New()
//     r.Use(auth.Basic(func(c *routing.Context, username, password string) (auth.Identity, error) {
//       if username == "demo" && password == "foo" {
//         return auth.Identity(username), nil
//       }
//       return nil, errors.New("invalid credential")
//     }))
//     r.Get("/demo", func(c *routing.Context) error {
//       fmt.Fprintf(res, "Hello, %v", c.Get(auth.User))
//       return nil
//     })
//   }
//
// By default, the auth realm is named as "API". You may customize it by specifying the realm parameter.
//
// When authentication fails, a "WWW-Authenticate" header will be sent, and an http.StatusUnauthorized
// error will be returned.
func Basic(fn BasicAuthFunc, realm ...string) routing.Handler {
	name := DefaultRealm
	if len(realm) > 0 {
		name = realm[0]
	}
	return func(c *routing.Context) error {
		username, password := parseBasicAuth(c.Request.Header.Get("Authorization"))
		identity, e := fn(c, username, password)
		if e == nil {
			c.Set(User, identity)
			return nil
		}
		c.Response.Header().Set("WWW-Authenticate", `Basic realm="`+name+`"`)
		return routing.NewHTTPError(http.StatusUnauthorized, e.Error())
	}
}

func parseBasicAuth(auth string) (username, password string) {
	if strings.HasPrefix(auth, "Basic ") {
		if bytes, err := base64.StdEncoding.DecodeString(auth[6:]); err == nil {
			str := string(bytes)
			if i := strings.IndexByte(str, ':'); i >= 0 {
				return str[:i], str[i+1:]
			}
		}
	}
	return
}

// TokenAuthFunc is the function for authenticating a user based on a secret token.
type TokenAuthFunc func(c *routing.Context, token string) (Identity, error)

// Bearer returns a routing.Handler that performs HTTP authentication based on bearer token.
// It can be used like the following:
//
//   import (
//     "errors"
//     "fmt"
//     "net/http"
//     "github.com/go-ozzo/ozzo-routing"
//     "github.com/go-ozzo/ozzo-routing/auth"
//   )
//   func main() {
//     r := routing.New()
//     r.Use(auth.Bearer(func(c *routing.Context, token string) (auth.Identity, error) {
//       if token == "secret" {
//         return auth.Identity("demo"), nil
//       }
//       return nil, errors.New("invalid credential")
//     }))
//     r.Get("/demo", func(c *routing.Context) error {
//       fmt.Fprintf(res, "Hello, %v", c.Get(auth.User))
//       return nil
//     })
//   }
//
// By default, the auth realm is named as "API". You may customize it by specifying the realm parameter.
//
// When authentication fails, a "WWW-Authenticate" header will be sent, and an http.StatusUnauthorized
// error will be returned.
func Bearer(fn TokenAuthFunc, realm ...string) routing.Handler {
	name := DefaultRealm
	if len(realm) > 0 {
		name = realm[0]
	}
	return func(c *routing.Context) error {
		token := parseBearerAuth(c.Request.Header.Get("Authorization"))
		identity, e := fn(c, token)
		if e == nil {
			c.Set(User, identity)
			return nil
		}
		c.Response.Header().Set("WWW-Authenticate", `Bearer realm="`+name+`"`)
		return routing.NewHTTPError(http.StatusUnauthorized, e.Error())
	}
}

func parseBearerAuth(auth string) string {
	if strings.HasPrefix(auth, "Bearer ") {
		if bearer, err := base64.StdEncoding.DecodeString(auth[7:]); err == nil {
			return string(bearer)
		}
	}
	return ""
}

// TokenName is the query parameter name for auth token.
var TokenName = "access-token"

// Query returns a routing.Handler that performs authentication based on a token passed via a query parameter.
// It can be used like the following:
//
//   import (
//     "errors"
//     "fmt"
//     "net/http"
//     "github.com/go-ozzo/ozzo-routing"
//     "github.com/go-ozzo/ozzo-routing/auth"
//   )
//   func main() {
//     r := routing.New()
//     r.Use(auth.Query(func(token string) (auth.Identity, error) {
//       if token == "secret" {
//         return auth.Identity("demo"), nil
//       }
//       return nil, errors.New("invalid credential")
//     }))
//     r.Get("/demo", func(c *routing.Context) error {
//       fmt.Fprintf(res, "Hello, %v", c.Get(auth.User))
//       return nil
//     })
//   }
//
// When authentication fails, an http.StatusUnauthorized error will be returned.
func Query(fn TokenAuthFunc, tokenName ...string) routing.Handler {
	name := TokenName
	if len(tokenName) > 0 {
		name = tokenName[0]
	}
	return func(c *routing.Context) error {
		token := c.Request.URL.Query().Get(name)
		identity, err := fn(c, token)
		if err != nil {
			return routing.NewHTTPError(http.StatusUnauthorized, err.Error())
		}
		c.Set(User, identity)
		return nil
	}
}

// JWTTokenHandler handles the parsed JWT token.
type JWTTokenHandler func(*routing.Context, *jwt.Token) error

// JWTOptions represents the options that can be used with the JWT handler.
type JWTOptions struct {
	// auth realm. Defaults to "API".
	Realm string
	// the allowed signing method. This is required and should be the actual method that you use to create JWT token. It defaults to "HS256".
	SigningMethod string
	// a function that handles the parsed JWT token. Defaults to DefaultJWTTokenHandler, which stores the token in the routing context with the key "JWT".
	TokenHandler JWTTokenHandler
}

// DefaultJWTTokenHandler stores the parsed JWT token in the routing context with the key named "JWT".
func DefaultJWTTokenHandler(c *routing.Context, token *jwt.Token) error {
	c.Set("JWT", token)
	return nil
}

// JWT returns a JWT (JSON Web Token) handler which attempts to parse the Bearer header into a JWT token and validate it.
// If both are successful, it will call a JWTTokenHandler to further handle the token. By default, the token
// will be stored in the routing context with the key named "JWT". Other handlers can retrieve this token to obtain
// the user identity information.
// If the parsing or validation fails, a "WWW-Authenticate" header will be sent, and an http.StatusUnauthorized
// error will be returned.
//
// JWT can be used like the following:
//
//   import (
//     "errors"
//     "fmt"
//     "net/http"
//     "github.com/dgrijalva/jwt-go"
//     "github.com/go-ozzo/ozzo-routing"
//     "github.com/go-ozzo/ozzo-routing/auth"
//   )
//   func main() {
//     signingKey := "secret-key"
//     r := routing.New()
//
//     r.Get("/login", func(c *routing.Context) error {
//       id, err := authenticate(c)
//       if err != nil {
//         return err
//       }
//       token, err := auth.NewJWT(jwt.StandardClaims{
//         Id: id
//       }, signingKey)
//       if err != nil {
//         return err
//       }
//       return c.Write(token)
//     })
//
//     r.Use(auth.JWT(signingKey))
//     r.Get("/restricted", func(c *routing.Context) error {
//       claims := c.Get("JWT").(*jwt.Token).Claims.(jwt.StandardClaims)
//       return c.Write(fmt.Sprint("Welcome, %v!", claims.Id)
//     })
//   }
func JWT(verificationKey string, options ...JWTOptions) routing.Handler {
	var opt JWTOptions
	if len(options) > 0 {
		opt = options[0]
	}
	if opt.Realm == "" {
		opt.Realm = DefaultRealm
	}
	if opt.SigningMethod == "" {
		opt.SigningMethod = "HS256"
	}
	if opt.TokenHandler == nil {
		opt.TokenHandler = DefaultJWTTokenHandler
	}
	parser := &jwt.Parser{
		ValidMethods: []string{opt.SigningMethod},
	}
	return func(c *routing.Context) error {
		header := c.Request.Header.Get("Authorization")
		message := ""
		if strings.HasPrefix(header, "Bearer ") {
			token, err := parser.Parse(header[7:], func(t *jwt.Token) (interface{}, error) { return []byte(verificationKey), nil })
			if err == nil && token.Valid {
				err = opt.TokenHandler(c, token)
			}
			if err == nil {
				return nil
			}
			message = err.Error()
		}

		c.Response.Header().Set("WWW-Authenticate", `Bearer realm="`+opt.Realm+`"`)
		if message != "" {
			return routing.NewHTTPError(http.StatusUnauthorized, message)
		}
		return routing.NewHTTPError(http.StatusUnauthorized)
	}
}

// NewJWT creates a new JWT token and returns it as a signed string that may be sent to the client side.
// The signingMethod parameter is optional. It defaults to the HS256 algorithm.
func NewJWT(claims jwt.MapClaims, signingKey string, signingMethod ...jwt.SigningMethod) (string, error) {
	var sm jwt.SigningMethod = jwt.SigningMethodHS256
	if len(signingMethod) > 0 {
		sm = signingMethod[0]
	}
	return jwt.NewWithClaims(sm, claims).SignedString([]byte(signingKey))
}
<|endoftext|>


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

package parser

import (
	"bytes"
	"io/ioutil"
	"os"
	"path"
	"reflect"
	"strings"
	"testing"

	"github.com/qiniu/x/log"

	"github.com/goplus/gop/ast"
	"github.com/goplus/gop/parser/parsertest"
	"github.com/goplus/gop/scanner"
	"github.com/goplus/gop/token"
)

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

func init() {
	log.SetFlags(log.Llongfile)
	SetDebug(DbgFlagAll)
}

func TestReadSource(t *testing.T) {
	buf := bytes.NewBuffer(nil)
	if _, err := readSource(buf); err != nil {
		t.Fatal("readSource failed:", err)
	}
	sr := strings.NewReader("")
	if _, err := readSource(sr); err != nil {
		t.Fatal("readSource strings.Reader failed:", err)
	}
	if _, err := readSource(0); err == nil {
		t.Fatal("readSource int failed: no error?")
	}
}

func TestParseFile(t *testing.T) {
	fset := token.NewFileSet()
	if _, err := ParseFile(fset, "/foo/bar/not-exists", nil, PackageClauseOnly); err == nil {
		t.Fatal("ParseFile failed: no error?")
	}
}

func TestIparseFileInvalidSrc(t *testing.T) {
	fset := token.NewFileSet()
	if _, err := parseFile(fset, "/foo/bar/not-exists", 1, PackageClauseOnly); err != errInvalidSource {
		t.Fatal("ParseFile failed: not errInvalidSource?")
	}
}

func TestIparseFileNoFset(t *testing.T) {
	defer func() {
		if e := recover(); e == nil {
			t.Fatal("ParseFile failed: no error?")
		}
	}()
	parseFile(nil, "/foo/bar/not-exists", nil, PackageClauseOnly)
}

func TestParseDir(t *testing.T) {
	fset := token.NewFileSet()
	if _, err := ParseDir(fset, "/foo/bar/not-exists", nil, PackageClauseOnly); err == nil {
		t.Fatal("ParseDir failed: no error?")
	}
}

func testFrom(t *testing.T, pkgDir, sel string, exclude Mode) {
	if sel != "" && !strings.Contains(pkgDir, sel) {
		return
	}
	log.Println("Parsing", pkgDir)
	fset := token.NewFileSet()
	pkgs, err := ParseDir(fset, pkgDir, nil, (Trace|ParseGoFiles|ParseComments)&^exclude)
	if err != nil || len(pkgs) != 1 {
		if errs, ok := err.(scanner.ErrorList); ok {
			for _, e := range errs {
				t.Log(e)
			}
		}
		t.Fatal("ParseDir failed:", err, reflect.TypeOf(err), len(pkgs))
	}
	for _, pkg := range pkgs {
		b, err := ioutil.ReadFile(pkgDir + "/parser.expect")
		if err != nil {
			t.Fatal("Parsing", pkgDir, "-", err)
		}
		parsertest.Expect(t, pkg, string(b))
		return
	}
}

func TestParseGo(t *testing.T) {
	fset := token.NewFileSet()
	pkgs, err := ParseDir(fset, "./_testdata/functype", nil, Trace)
	if err != nil {
		t.Fatal("TestParseGo: ParseDir failed -", err)
	}
	if len(pkgs) != 0 {
		t.Fatal("TestParseGo failed: len(pkgs) =", len(pkgs))
	}
}

func TestFromTestdata(t *testing.T) {
	sel := ""
	dir, err := os.Getwd()
	if err != nil {
		t.Fatal("Getwd failed:", err)
	}
	dir = path.Join(dir, "./_testdata")
	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Fatal("ReadDir failed:", err)
	}
	for _, fi := range fis {
		name := fi.Name()
		if strings.HasPrefix(name, "_") {
			continue
		}
		testFrom(t, dir+"/"+name, sel, 0)
	}
}

func TestRegisterFileType(t *testing.T) {
	RegisterFileType(".gsh", ast.FileTypeSpx)
	func() {
		defer func() {
			if e := recover(); e == nil {
				t.Fatal("TestRegisterFileType failed: no error?")
			}
		}()
		RegisterFileType(".gshx", ast.FileTypeGop)
	}()
	func() {
		defer func() {
			if e := recover(); e == nil {
				t.Fatal("TestRegisterFileType failed: no error?")
			}
		}()
		RegisterFileType(".gsh", ast.FileTypeGmx)
	}()
}

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

package parser

import (
	"bytes"
	"io/ioutil"
	"os"
	"path"
	"reflect"
	"runtime"
	"strings"
	"testing"

	"github.com/qiniu/x/log"

	"github.com/goplus/gop/ast"
	"github.com/goplus/gop/parser/parsertest"
	"github.com/goplus/gop/scanner"
	"github.com/goplus/gop/token"
)

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

func init() {
	log.SetFlags(log.Llongfile)
	SetDebug(DbgFlagAll)
}

func TestReadSource(t *testing.T) {
	buf := bytes.NewBuffer(nil)
	if _, err := readSource(buf); err != nil {
		t.Fatal("readSource failed:", err)
	}
	sr := strings.NewReader("")
	if _, err := readSource(sr); err != nil {
		t.Fatal("readSource strings.Reader failed:", err)
	}
	if _, err := readSource(0); err == nil {
		t.Fatal("readSource int failed: no error?")
	}
}

func TestParseFile(t *testing.T) {
	fset := token.NewFileSet()
	if _, err := ParseFile(fset, "/foo/bar/not-exists", nil, PackageClauseOnly); err == nil {
		t.Fatal("ParseFile failed: no error?")
	}
}

func TestIparseFileInvalidSrc(t *testing.T) {
	fset := token.NewFileSet()
	if _, err := parseFile(fset, "/foo/bar/not-exists", 1, PackageClauseOnly); err != errInvalidSource {
		t.Fatal("ParseFile failed: not errInvalidSource?")
	}
}

func TestIparseFileNoFset(t *testing.T) {
	defer func() {
		if e := recover(); e == nil {
			t.Fatal("ParseFile failed: no error?")
		}
	}()
	parseFile(nil, "/foo/bar/not-exists", nil, PackageClauseOnly)
}

func TestParseDir(t *testing.T) {
	fset := token.NewFileSet()
	if _, err := ParseDir(fset, "/foo/bar/not-exists", nil, PackageClauseOnly); err == nil {
		t.Fatal("ParseDir failed: no error?")
	}
}

func testFrom(t *testing.T, pkgDir, sel string, exclude Mode) {
	if sel != "" && !strings.Contains(pkgDir, sel) {
		return
	}
	log.Println("Parsing", pkgDir)
	fset := token.NewFileSet()
	pkgs, err := ParseDir(fset, pkgDir, nil, (Trace|ParseGoFiles|ParseComments)&^exclude)
	if err != nil || len(pkgs) != 1 {
		if errs, ok := err.(scanner.ErrorList); ok {
			for _, e := range errs {
				t.Log(e)
			}
		}
		t.Fatal("ParseDir failed:", err, reflect.TypeOf(err), len(pkgs))
	}
	for _, pkg := range pkgs {
		b, err := ioutil.ReadFile(pkgDir + "/parser.expect")
		if err != nil {
			t.Fatal("Parsing", pkgDir, "-", err)
		}
		parsertest.Expect(t, pkg, string(b))
		return
	}
}

func TestParseGo(t *testing.T) {
	fset := token.NewFileSet()
	pkgs, err := ParseDir(fset, "./_testdata/functype", nil, Trace)
	if err != nil {
		t.Fatal("TestParseGo: ParseDir failed -", err)
	}
	if len(pkgs) != 0 {
		t.Fatal("TestParseGo failed: len(pkgs) =", len(pkgs))
	}
}

func TestFromTestdata(t *testing.T) {
	if runtime.GOOS == "windows" {
		return // TODO: how to pass this testcase in windows
	}
	sel := ""
	dir, err := os.Getwd()
	if err != nil {
		t.Fatal("Getwd failed:", err)
	}
	dir = path.Join(dir, "./_testdata")
	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Fatal("ReadDir failed:", err)
	}
	for _, fi := range fis {
		name := fi.Name()
		if strings.HasPrefix(name, "_") {
			continue
		}
		testFrom(t, dir+"/"+name, sel, 0)
	}
}

func TestRegisterFileType(t *testing.T) {
	RegisterFileType(".gsh", ast.FileTypeSpx)
	func() {
		defer func() {
			if e := recover(); e == nil {
				t.Fatal("TestRegisterFileType failed: no error?")
			}
		}()
		RegisterFileType(".gshx", ast.FileTypeGop)
	}()
	func() {
		defer func() {
			if e := recover(); e == nil {
				t.Fatal("TestRegisterFileType failed: no error?")
			}
		}()
		RegisterFileType(".gsh", ast.FileTypeGmx)
	}()
}

// -----------------------------------------------------------------------------
<|endoftext|>


<commit_before>package wallaby

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

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

func createTestDir(t *testing.T) string {
	dir := "./tests"
	err := os.MkdirAll(dir, os.ModeDir|0700)
	assert.Nil(t, err, "Test dir could not be created")
	return dir
}

func TestIndexRecord(t *testing.T) {
	now := time.Now()

	unix := now.UnixNano()
	index, offset := uint64(0), int64(24)
	ir := BasicIndexRecord{unix, index, offset}

	// time
	assert.Equal(t, unix, ir.Time())

	// index
	assert.Equal(t, index, ir.Index())

	// offset
	assert.Equal(t, offset, ir.Offset())
}

func TestIndexHeader(t *testing.T) {

	var version uint8 = 128
	var flags uint32 = 0x377
	ih := BasicIndexHeader{version, flags}

	// version
	assert.Equal(t, version, ih.Version())

	// flags
	assert.Equal(t, flags, ih.Flags())
}

func TestVersionOneCreateIndex(t *testing.T) {
	dir := createTestDir(t)

	// open index file
	indexfile := filepath.Join(dir, "test001.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		t.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(FlagsDefault)

	assert.NotNil(t, index, "Index file could not be created")
	assert.Nil(t, err, "CreateIndex produced an error")

	// stat file header size
	info, err := os.Stat(indexfile)
	assert.Nil(t, err, "os.Stat call resulted in error")
	if info.Size() != 8 {
		t.Errorf("Invalid header size")
	}

	// test header
	header, err := index.Header()
	assert.Equal(t, 1, header.Version())
	assert.Equal(t, uint32(FlagsDefault), header.Flags())

	// test Size
	size, err := index.Size()
	assert.Equal(t, 0, size)
}

func TestVersionOneCreateIndexExisting(t *testing.T) {
	dir := createTestDir(t)

	// open index file
	indexfile := filepath.Join(dir, "test002.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		t.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(FlagsDefault)
	index.Close()

	// re-open file
	index, err = factory.GetOrCreateIndex(FlagsDefault)

	// test header
	header, err := index.Header()
	assert.Equal(t, 1, header.Version())
	assert.Equal(t, uint32(FlagsDefault), header.Flags())

	// test Size
	size, err := index.Size()
	assert.Equal(t, 0, size)
}

func TestVersionOneAppend(t *testing.T) {
	dir := createTestDir(t)

	// open index file
	indexfile := filepath.Join(dir, "test003.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		t.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(FlagsDefault)

	// test index file
	assert.NotNil(t, index, "Index file could not be created")
	assert.Nil(t, err, "CreateIndex produced an error")

	unix := time.Now().UnixNano()
	i, offset := uint64(0), int64(24)
	record := BasicIndexRecord{unix, i, offset}
	n, err := index.Append(record)
	assert.Equal(t, VersionOneIndexRecordSize, n, "Invalid index record size")

	size, _ := index.Size()
	assert.Equal(t, 1, size)

	for i := 2; i < 10; i++ {
		unix = time.Now().UnixNano()
		offset = int64(24)
		record := BasicIndexRecord{unix, uint64(i + 1), offset}
		n, err := index.Append(record)
		assert.Equal(t, VersionOneIndexRecordSize, n, "Invalid index record size")
		assert.Nil(t, err)

		size, _ := index.Size()
		assert.Equal(t, i, size)
	}
}

func TestVersionOneSlice(t *testing.T) {
	dir := createTestDir(t)

	// open index file
	indexfile := filepath.Join(dir, "test004.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		t.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(FlagsDefault)

	// offset out of range
	slice, err := index.Slice(1, 1)
	assert.Nil(t, slice, "Slice should be nil for invalid offset")
	assert.NotNil(t, err, "Expected ErrSliceOufOfBounds")

	// offset out of range
	slice, err = index.Slice(0, 1)
	assert.Nil(t, slice, "Slice should be nil for invalid offset")
	assert.NotNil(t, err, "Expected ErrSliceOufOfBounds")

	// limit out of range
	slice, err = index.Slice(1, 0)
	assert.Nil(t, slice, "Slice should be nil for invalid limit")
	assert.NotNil(t, err, "Expected ErrSliceOufOfBounds")

	// append records
	for i := 0; i < 100; i++ {
		unix := time.Now().UnixNano()
		offset := int64(24*i + 8)
		record := BasicIndexRecord{unix, uint64(i), offset}
		index.Append(record)
	}
	index.Flush()

	// read Slice
	slice, err = index.Slice(0, 5)
	assert.Equal(t, 5, slice.Size(), "Slice should contain 5 index records")

	var unix int64
	for i := 0; i < slice.Size(); i++ {
		record, err := slice.Get(i)
		assert.Nil(t, err, "Get should not produce an error")

		assert.Equal(t, int64(24*i+8), record.Offset(), "Record offset should equal 24")
		assert.Equal(t, uint64(i), record.Index(), "Invalid record index")
		assert.True(t, record.Time() > unix, "Each record's time should be greater than the last")
		unix = record.Time()

	}

	// close file
	index.Close()
}

func BenchmarkIndexAdd(b *testing.B) {

	dir := "./tests"
	os.MkdirAll(dir, os.ModeDir|0700)

	// open index file
	indexfile := filepath.Join(dir, "bench001.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		b.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(FlagsDefault)

	// var unix, offset int64
	var record BasicIndexRecord
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		record.nanos = time.Now().UnixNano()
		record.index = uint64(i)
		index.Append(record)
	}

	// flush to disk and close file
	index.Close()

	// stat file header size
	// info, err := os.Stat(indexfile)
	// b.Logf("Filesize: %d", info.Size())

	// number of bytes per iteration
	b.SetBytes(VersionOneIndexRecordSize)
}

func BenchmarkIndexSlice(b *testing.B) {
	dir := "./tests"
	os.MkdirAll(dir, os.ModeDir|0700)

	// open index file
	indexfile := filepath.Join(dir, "bench002.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		b.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(FlagsDefault)

	// append records
	for i := 0; i < b.N; i++ {
		unix := time.Now().UnixNano()
		offset := int64(24*i + 8)
		record := BasicIndexRecord{unix, uint64(i), offset}
		index.Append(record)
	}
	index.Flush()

	b.ResetTimer()

	// read slice
	var read int
	for read < b.N {
		index.Slice(int64(read), int64(MaximumIndexSlice))
		read += MaximumIndexSlice
		// read += slice.Size()
	}

	// for i := 0; i < slice.Size(); i++ {
	// 	slice.Get(i)
	// }

	// close file
	index.Close()

	// number of bytes per iteration
	b.SetBytes(VersionOneIndexRecordSize)
}
<commit_msg>renamed FlagsDefault to DefaultIndexFlags<commit_after>package wallaby

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

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

func createTestDir(t *testing.T) string {
	dir := "./tests"
	err := os.MkdirAll(dir, os.ModeDir|0700)
	assert.Nil(t, err, "Test dir could not be created")
	return dir
}

func TestIndexRecord(t *testing.T) {
	now := time.Now()

	unix := now.UnixNano()
	index, offset := uint64(0), int64(24)
	ir := BasicIndexRecord{unix, index, offset}

	// time
	assert.Equal(t, unix, ir.Time())

	// index
	assert.Equal(t, index, ir.Index())

	// offset
	assert.Equal(t, offset, ir.Offset())
}

func TestIndexHeader(t *testing.T) {

	var version uint8 = 128
	var flags uint32 = 0x377
	ih := BasicIndexHeader{version, flags}

	// version
	assert.Equal(t, version, ih.Version())

	// flags
	assert.Equal(t, flags, ih.Flags())
}

func TestVersionOneCreateIndex(t *testing.T) {
	dir := createTestDir(t)

	// open index file
	indexfile := filepath.Join(dir, "test001.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		t.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(DefaultIndexFlags)

	assert.NotNil(t, index, "Index file could not be created")
	assert.Nil(t, err, "CreateIndex produced an error")

	// stat file header size
	info, err := os.Stat(indexfile)
	assert.Nil(t, err, "os.Stat call resulted in error")
	if info.Size() != 8 {
		t.Errorf("Invalid header size")
	}

	// test header
	header, err := index.Header()
	assert.Equal(t, 1, header.Version())
	assert.Equal(t, uint32(DefaultIndexFlags), header.Flags())

	// test Size
	size, err := index.Size()
	assert.Equal(t, 0, size)
}

func TestVersionOneCreateIndexExisting(t *testing.T) {
	dir := createTestDir(t)

	// open index file
	indexfile := filepath.Join(dir, "test002.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		t.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(DefaultIndexFlags)
	index.Close()

	// re-open file
	index, err = factory.GetOrCreateIndex(DefaultIndexFlags)

	// test header
	header, err := index.Header()
	assert.Equal(t, 1, header.Version())
	assert.Equal(t, uint32(DefaultIndexFlags), header.Flags())

	// test Size
	size, err := index.Size()
	assert.Equal(t, 0, size)
}

func TestVersionOneAppend(t *testing.T) {
	dir := createTestDir(t)

	// open index file
	indexfile := filepath.Join(dir, "test003.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		t.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(DefaultIndexFlags)

	// test index file
	assert.NotNil(t, index, "Index file could not be created")
	assert.Nil(t, err, "CreateIndex produced an error")

	unix := time.Now().UnixNano()
	i, offset := uint64(0), int64(24)
	record := BasicIndexRecord{unix, i, offset}
	n, err := index.Append(record)
	assert.Equal(t, VersionOneIndexRecordSize, n, "Invalid index record size")

	size, _ := index.Size()
	assert.Equal(t, 1, size)

	for i := 2; i < 10; i++ {
		unix = time.Now().UnixNano()
		offset = int64(24)
		record := BasicIndexRecord{unix, uint64(i + 1), offset}
		n, err := index.Append(record)
		assert.Equal(t, VersionOneIndexRecordSize, n, "Invalid index record size")
		assert.Nil(t, err)

		size, _ := index.Size()
		assert.Equal(t, i, size)
	}
}

func TestVersionOneSlice(t *testing.T) {
	dir := createTestDir(t)

	// open index file
	indexfile := filepath.Join(dir, "test004.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		t.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(DefaultIndexFlags)

	// offset out of range
	slice, err := index.Slice(1, 1)
	assert.Nil(t, slice, "Slice should be nil for invalid offset")
	assert.NotNil(t, err, "Expected ErrSliceOufOfBounds")

	// offset out of range
	slice, err = index.Slice(0, 1)
	assert.Nil(t, slice, "Slice should be nil for invalid offset")
	assert.NotNil(t, err, "Expected ErrSliceOufOfBounds")

	// limit out of range
	slice, err = index.Slice(1, 0)
	assert.Nil(t, slice, "Slice should be nil for invalid limit")
	assert.NotNil(t, err, "Expected ErrSliceOufOfBounds")

	// append records
	for i := 0; i < 100; i++ {
		unix := time.Now().UnixNano()
		offset := int64(24*i + 8)
		record := BasicIndexRecord{unix, uint64(i), offset}
		index.Append(record)
	}
	index.Flush()

	// read Slice
	slice, err = index.Slice(0, 5)
	assert.Equal(t, 5, slice.Size(), "Slice should contain 5 index records")

	var unix int64
	for i := 0; i < slice.Size(); i++ {
		record, err := slice.Get(i)
		assert.Nil(t, err, "Get should not produce an error")

		assert.Equal(t, int64(24*i+8), record.Offset(), "Record offset should equal 24")
		assert.Equal(t, uint64(i), record.Index(), "Invalid record index")
		assert.True(t, record.Time() > unix, "Each record's time should be greater than the last")
		unix = record.Time()

	}

	// close file
	index.Close()
}

func BenchmarkIndexAdd(b *testing.B) {

	dir := "./tests"
	os.MkdirAll(dir, os.ModeDir|0700)

	// open index file
	indexfile := filepath.Join(dir, "bench001.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		b.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(DefaultIndexFlags)

	// var unix, offset int64
	var record BasicIndexRecord
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		record.nanos = time.Now().UnixNano()
		record.index = uint64(i)
		index.Append(record)
	}

	// flush to disk and close file
	index.Close()

	// stat file header size
	// info, err := os.Stat(indexfile)
	// b.Logf("Filesize: %d", info.Size())

	// number of bytes per iteration
	b.SetBytes(VersionOneIndexRecordSize)
}

func BenchmarkIndexSlice(b *testing.B) {
	dir := "./tests"
	os.MkdirAll(dir, os.ModeDir|0700)

	// open index file
	indexfile := filepath.Join(dir, "bench002.idx")

	// delete prior test file
	err := os.Remove(indexfile)
	if err != nil && !os.IsNotExist(err) {
		b.Error(err)
	}

	// create index factory
	factory := VersionOneIndexFactory{indexfile}
	index, err := factory.GetOrCreateIndex(DefaultIndexFlags)

	// append records
	for i := 0; i < b.N; i++ {
		unix := time.Now().UnixNano()
		offset := int64(24*i + 8)
		record := BasicIndexRecord{unix, uint64(i), offset}
		index.Append(record)
	}
	index.Flush()

	b.ResetTimer()

	// read slice
	var read int
	for read < b.N {
		index.Slice(int64(read), int64(MaximumIndexSlice))
		read += MaximumIndexSlice
		// read += slice.Size()
	}

	// for i := 0; i < slice.Size(); i++ {
	// 	slice.Get(i)
	// }

	// close file
	index.Close()

	// number of bytes per iteration
	b.SetBytes(VersionOneIndexRecordSize)
}
<|endoftext|>


<commit_before>package wikiparse

import (
	"io"
	"strings"
	"testing"
)

const testData = `499:10:AccessibleComputing
499:12:Anarchism
499:13:AfghanistanHistory
499:14:AfghanistanGeography
499:15:AfghanistanPeople
499:18:AfghanistanCommunications
499:19:AfghanistanTransportations
499:20:AfghanistanMilitary
499:21:AfghanistanTransnationalIssues
499:23:AssistiveTechnology
2147418907:2638569:William Earl Brown
2147418907:2638570:Lebuhraya Persekutuan
2147418907:2638571:St Francis of Paola
2147418907:2638573:Francesco di Paula
2147418907:2638575:Arapahoe Community College
2147418907:2638583:Francesco Borgia
-2147469295:2638585:Philadelphia Bulletin
-2147469295:2638588:Zrínyi Miklós
-2147469295:2638602:Privatize
-2147469295:2638604:Island of Montréal
`

const lastChunk = 2147498001

func TestIndexReader(t *testing.T) {
	r := strings.NewReader(testData)
	ir := NewIndexReader(r)

	e, err := ir.Next()
	if err != nil {
		t.Fatalf("Error parsing first entry: %v", err)
	}

	for {
		var tmp IndexEntry
		tmp, err = ir.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			t.Fatalf("Error reading stream:  %v", err)
		}
		e = tmp
	}
	if e.StreamOffset != lastChunk {
		t.Fatalf("Expected %v, got %v for the last chunk offset",
			int64(lastChunk), e.StreamOffset)
	}

}

func TestIndexSummary(t *testing.T) {
	r := strings.NewReader(testData)
	isr, err := NewIndexSummaryReader(r)
	if err != nil {
		t.Fatalf("Error initializing IndexSummaryReader: %v", err)
	}

	expected := []struct {
		offset int64
		count  int
		err    error
	}{
		{499, 10, nil},
		{2147418907, 6, nil},
		{lastChunk, 4, io.EOF},
		{0, 0, io.EOF},
	}

	for _, e := range expected {
		offset, count, err := isr.Next()
		if offset != e.offset {
			t.Fatalf("Expected offset %v, got %v", e.offset, offset)
		}
		if count != e.count {
			t.Fatalf("Expected count %v, got %v", e.count, count)
		}
		if err != e.err {
			t.Fatalf("Expected err %v, got %v", e.err, err)
		}
	}
}
<commit_msg>String validation of index entries<commit_after>package wikiparse

import (
	"io"
	"strings"
	"testing"
)

const testData = `499:10:AccessibleComputing
499:12:Anarchism
499:13:AfghanistanHistory
499:14:AfghanistanGeography
499:15:AfghanistanPeople
499:18:AfghanistanCommunications
499:19:AfghanistanTransportations
499:20:AfghanistanMilitary
499:21:AfghanistanTransnationalIssues
499:23:AssistiveTechnology
2147418907:2638569:William Earl Brown
2147418907:2638570:Lebuhraya Persekutuan
2147418907:2638571:St Francis of Paola
2147418907:2638573:Francesco di Paula
2147418907:2638575:Arapahoe Community College
2147418907:2638583:Francesco Borgia
-2147469295:2638585:Philadelphia Bulletin
-2147469295:2638588:Zrínyi Miklós
-2147469295:2638602:Privatize
-2147469295:2638604:Island of Montréal
`

const lastChunk = 2147498001

func TestIndexReader(t *testing.T) {
	r := strings.NewReader(testData)
	ir := NewIndexReader(r)

	e, err := ir.Next()
	if err != nil {
		t.Fatalf("Error parsing first entry: %v", err)
	}
	if e.String() != "499:10:AccessibleComputing" {
		t.Errorf("Error stringing first entry, got %v", e)
	}

	for {
		var tmp IndexEntry
		tmp, err = ir.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			t.Fatalf("Error reading stream:  %v", err)
		}
		e = tmp
	}
	if e.StreamOffset != lastChunk {
		t.Fatalf("Expected %v, got %v for the last chunk offset",
			int64(lastChunk), e.StreamOffset)
	}

}

func TestIndexSummary(t *testing.T) {
	r := strings.NewReader(testData)
	isr, err := NewIndexSummaryReader(r)
	if err != nil {
		t.Fatalf("Error initializing IndexSummaryReader: %v", err)
	}

	expected := []struct {
		offset int64
		count  int
		err    error
	}{
		{499, 10, nil},
		{2147418907, 6, nil},
		{lastChunk, 4, io.EOF},
		{0, 0, io.EOF},
	}

	for _, e := range expected {
		offset, count, err := isr.Next()
		if offset != e.offset {
			t.Fatalf("Expected offset %v, got %v", e.offset, offset)
		}
		if count != e.count {
			t.Fatalf("Expected count %v, got %v", e.count, count)
		}
		if err != e.err {
			t.Fatalf("Expected err %v, got %v", e.err, err)
		}
	}
}
<|endoftext|>