<commit_before>package gopdf

import (
	"bytes"
	"fmt"
	"log"
	"strconv"
)

type ContentObj struct { //impl IObj
	buffer bytes.Buffer
	stream bytes.Buffer

	//text bytes.Buffer
	getRoot func() *GoPdf
}

func (me *ContentObj) Init(funcGetRoot func() *GoPdf) {
	me.getRoot = funcGetRoot
}

func (me *ContentObj) Build() error {
	streamlen := me.stream.Len()
	me.buffer.WriteString("<<\n")
	me.buffer.WriteString("/Length " + strconv.Itoa(streamlen) + "\n")
	me.buffer.WriteString(">>\n")
	me.buffer.WriteString("stream\n")
	me.buffer.Write(me.stream.Bytes())
	me.buffer.WriteString("endstream\n")
	return nil
}

func (me *ContentObj) GetType() string {
	return "Content"
}

func (me *ContentObj) GetObjBuff() *bytes.Buffer {
	return &(me.buffer)
}

func (me *ContentObj) AppendStreamSubsetFont(rectangle *Rect, text string) {

	sumWidth := uint64(0)
	var buff bytes.Buffer
	for _, r := range text {
		index, err := me.getRoot().Curr.Font_ISubset.CharIndex(r)
		if err != nil {
			log.Fatalf("err:%s", err.Error())
		}
		buff.WriteString(fmt.Sprintf("%04X", index))
		width, err := me.getRoot().Curr.Font_ISubset.CharWidth(r)
		if err != nil {
			log.Fatalf("err:%s", err.Error())
		}
		sumWidth += width
	}

	fontSize := me.getRoot().Curr.Font_Size
	x := fmt.Sprintf("%0.2f", me.getRoot().Curr.X)
	y := fmt.Sprintf("%0.2f", me.getRoot().config.PageSize.H-me.getRoot().Curr.Y-(float64(fontSize)*0.7))

	me.stream.WriteString("BT\n")
	me.stream.WriteString(x + " " + y + " TD\n")
	me.stream.WriteString("/F" + strconv.Itoa(me.getRoot().Curr.Font_FontCount+1) + " " + strconv.Itoa(fontSize) + " Tf\n")
	me.stream.WriteString("<" + buff.String() + "> Tj\n")
	me.stream.WriteString("ET\n")
	if rectangle == nil {
		fontSize := me.getRoot().Curr.Font_Size
		me.getRoot().Curr.X += float64(sumWidth) * (float64(fontSize) / 1000.0)
	} else {
		me.getRoot().Curr.X += rectangle.W
	}
}

func (me *ContentObj) AppendStream(rectangle *Rect, text string) {

	fontSize := me.getRoot().Curr.Font_Size

	x := fmt.Sprintf("%0.2f", me.getRoot().Curr.X)
	y := fmt.Sprintf("%0.2f", me.getRoot().config.PageSize.H-me.getRoot().Curr.Y-(float64(fontSize)*0.7))

	me.stream.WriteString("BT\n")
	me.stream.WriteString(x + " " + y + " TD\n")
	me.stream.WriteString("/F" + strconv.Itoa(me.getRoot().Curr.Font_FontCount+1) + " " + strconv.Itoa(fontSize) + " Tf\n")
	me.stream.WriteString("(" + text + ") Tj\n")
	me.stream.WriteString("ET\n")
	if rectangle == nil {
		me.getRoot().Curr.X += StrHelperGetStringWidth(text, fontSize, me.getRoot().Curr.Font_IFont)
	} else {
		me.getRoot().Curr.X += rectangle.W
	}

}

func (me *ContentObj) AppendStreamLine(x1 float64, y1 float64, x2 float64, y2 float64) {

	h := me.getRoot().config.PageSize.H
	me.stream.WriteString(fmt.Sprintf("%0.2f %0.2f m %0.2f %0.2f l s\n", x1, h-y1, x2, h-y2))
}

func (me *ContentObj) AppendUnderline(startX float64, y float64, endX float64, endY float64, text string) {

	h := me.getRoot().config.PageSize.H
	ut := int(0)
	if me.getRoot().Curr.Font_IFont != nil {
		ut = me.getRoot().Curr.Font_IFont.GetUt()
	} else if me.getRoot().Curr.Font_ISubset != nil {
		ut = int(me.getRoot().Curr.Font_ISubset.GetUt())
	} else {
		log.Fatal("error AppendUnderline not found font")
	}

	textH := ContentObj_CalTextHeight(me.getRoot().Curr.Font_Size)
	arg3 := float64(h) - float64(y) - textH - textH*0.07
	arg4 := (float64(ut) / 1000.00) * float64(me.getRoot().Curr.Font_Size)
	me.stream.WriteString(fmt.Sprintf("%0.2f %0.2f %0.2f -%0.2f re f\n", startX, arg3, endX-startX, arg4))
}

func (me *ContentObj) AppendStreamSetLineWidth(w float64) {

	me.stream.WriteString(fmt.Sprintf("%.2f w\n", w))

}

//  Set the grayscale fills
func (me *ContentObj) AppendStreamSetGrayFill(w float64) {
	me.stream.WriteString(fmt.Sprintf("%.2f g\n", w))
}

//  Set the grayscale stroke
func (me *ContentObj) AppendStreamSetGrayStroke(w float64) {
	me.stream.WriteString(fmt.Sprintf("%.2f G\n", w))
}

func (me *ContentObj) AppendStreamImage(index int, x float64, y float64, rect *Rect) {
	//fmt.Printf("index = %d",index)
	h := me.getRoot().config.PageSize.H
	me.stream.WriteString(fmt.Sprintf("q %0.2f 0 0 %0.2f %0.2f %0.2f cm /I%d Do Q\n", rect.W, rect.H, x, h-(y+rect.H), index+1))
}

//cal text height
func ContentObj_CalTextHeight(fontsize int) float64 {
	return (float64(fontsize) * 0.7)
}
<commit_msg>Added a func, fixRange10, to content_obj.go to ensure the number passed to the stream.WriteString is between 0.0 and 1.0<commit_after>package gopdf

import (
	"bytes"
	"fmt"
	"log"
	"strconv"
)

type ContentObj struct { //impl IObj
	buffer bytes.Buffer
	stream bytes.Buffer

	//text bytes.Buffer
	getRoot func() *GoPdf
}

func (me *ContentObj) Init(funcGetRoot func() *GoPdf) {
	me.getRoot = funcGetRoot
}

func (me *ContentObj) Build() error {
	streamlen := me.stream.Len()
	me.buffer.WriteString("<<\n")
	me.buffer.WriteString("/Length " + strconv.Itoa(streamlen) + "\n")
	me.buffer.WriteString(">>\n")
	me.buffer.WriteString("stream\n")
	me.buffer.Write(me.stream.Bytes())
	me.buffer.WriteString("endstream\n")
	return nil
}

func (me *ContentObj) GetType() string {
	return "Content"
}

func (me *ContentObj) GetObjBuff() *bytes.Buffer {
	return &(me.buffer)
}

func (me *ContentObj) AppendStreamSubsetFont(rectangle *Rect, text string) {

	sumWidth := uint64(0)
	var buff bytes.Buffer
	for _, r := range text {
		index, err := me.getRoot().Curr.Font_ISubset.CharIndex(r)
		if err != nil {
			log.Fatalf("err:%s", err.Error())
		}
		buff.WriteString(fmt.Sprintf("%04X", index))
		width, err := me.getRoot().Curr.Font_ISubset.CharWidth(r)
		if err != nil {
			log.Fatalf("err:%s", err.Error())
		}
		sumWidth += width
	}

	fontSize := me.getRoot().Curr.Font_Size
	x := fmt.Sprintf("%0.2f", me.getRoot().Curr.X)
	y := fmt.Sprintf("%0.2f", me.getRoot().config.PageSize.H-me.getRoot().Curr.Y-(float64(fontSize)*0.7))

	me.stream.WriteString("BT\n")
	me.stream.WriteString(x + " " + y + " TD\n")
	me.stream.WriteString("/F" + strconv.Itoa(me.getRoot().Curr.Font_FontCount+1) + " " + strconv.Itoa(fontSize) + " Tf\n")
	me.stream.WriteString("<" + buff.String() + "> Tj\n")
	me.stream.WriteString("ET\n")
	if rectangle == nil {
		fontSize := me.getRoot().Curr.Font_Size
		me.getRoot().Curr.X += float64(sumWidth) * (float64(fontSize) / 1000.0)
	} else {
		me.getRoot().Curr.X += rectangle.W
	}
}

func (me *ContentObj) AppendStream(rectangle *Rect, text string) {

	fontSize := me.getRoot().Curr.Font_Size

	x := fmt.Sprintf("%0.2f", me.getRoot().Curr.X)
	y := fmt.Sprintf("%0.2f", me.getRoot().config.PageSize.H-me.getRoot().Curr.Y-(float64(fontSize)*0.7))

	me.stream.WriteString("BT\n")
	me.stream.WriteString(x + " " + y + " TD\n")
	me.stream.WriteString("/F" + strconv.Itoa(me.getRoot().Curr.Font_FontCount+1) + " " + strconv.Itoa(fontSize) + " Tf\n")
	me.stream.WriteString("(" + text + ") Tj\n")
	me.stream.WriteString("ET\n")
	if rectangle == nil {
		me.getRoot().Curr.X += StrHelperGetStringWidth(text, fontSize, me.getRoot().Curr.Font_IFont)
	} else {
		me.getRoot().Curr.X += rectangle.W
	}

}

func (me *ContentObj) AppendStreamLine(x1 float64, y1 float64, x2 float64, y2 float64) {

	h := me.getRoot().config.PageSize.H
	me.stream.WriteString(fmt.Sprintf("%0.2f %0.2f m %0.2f %0.2f l s\n", x1, h-y1, x2, h-y2))
}

func (me *ContentObj) AppendUnderline(startX float64, y float64, endX float64, endY float64, text string) {

	h := me.getRoot().config.PageSize.H
	ut := int(0)
	if me.getRoot().Curr.Font_IFont != nil {
		ut = me.getRoot().Curr.Font_IFont.GetUt()
	} else if me.getRoot().Curr.Font_ISubset != nil {
		ut = int(me.getRoot().Curr.Font_ISubset.GetUt())
	} else {
		log.Fatal("error AppendUnderline not found font")
	}

	textH := ContentObj_CalTextHeight(me.getRoot().Curr.Font_Size)
	arg3 := float64(h) - float64(y) - textH - textH*0.07
	arg4 := (float64(ut) / 1000.00) * float64(me.getRoot().Curr.Font_Size)
	me.stream.WriteString(fmt.Sprintf("%0.2f %0.2f %0.2f -%0.2f re f\n", startX, arg3, endX-startX, arg4))
}

func (me *ContentObj) AppendStreamSetLineWidth(w float64) {

	me.stream.WriteString(fmt.Sprintf("%.2f w\n", w))

}

//  Set the grayscale fills
func (me *ContentObj) AppendStreamSetGrayFill(w float64) {
	w = fixRange10(w)
	me.stream.WriteString(fmt.Sprintf("%.2f g\n", w))
}

//  Set the grayscale stroke
func (me *ContentObj) AppendStreamSetGrayStroke(w float64) {
	w = fixRange10(w)
	me.stream.WriteString(fmt.Sprintf("%.2f G\n", w))
}

func (me *ContentObj) AppendStreamImage(index int, x float64, y float64, rect *Rect) {
	//fmt.Printf("index = %d",index)
	h := me.getRoot().config.PageSize.H
	me.stream.WriteString(fmt.Sprintf("q %0.2f 0 0 %0.2f %0.2f %0.2f cm /I%d Do Q\n", rect.W, rect.H, x, h-(y+rect.H), index+1))
}

//cal text height
func ContentObj_CalTextHeight(fontsize int) float64 {
	return (float64(fontsize) * 0.7)
}

// When setting colour and grayscales the value has to be between 0.00 and 1.00
// This function takes a float64 and returns 0.0 if it is less than 0.0 and 1.0 if it
// is more than 1.0
func fixRange10(val float64) float64 {
	if val < 0.0 {
		return 0.0
	}
	if val > 1.0 {
		return 1.0
	}
	return val
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gin-gonic/gin"
	"net/http"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
)

type SiteData struct {
	Ib          uint
	Api         string
	Img         string
	Title       string
	Desc        string
	Nsfw        bool
	Style       string
	Logo        string
	Imageboards []Imageboard
}

type Imageboard struct {
	Title   string
	Address string
}

// gets the details from the request for the page handler variables
func Details() gin.HandlerFunc {
	return func(c *gin.Context) {

		host := c.Request.Host

		mu.RLock()
		site := sitemap[host]
		mu.RUnlock()

		if site == nil {

			sitedata := &SiteData{}

			// Get Database handle
			dbase, err := db.GetDb()
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			err = dbase.QueryRow(`SELECT ib_id,ib_title,ib_description,ib_nsfw,ib_api,ib_img,ib_style,ib_logo FROM imageboards WHERE ib_domain = ?`, host).Scan(&sitedata.Ib, &sitedata.Title, &sitedata.Desc, &sitedata.Nsfw, &sitedata.Api, &sitedata.Img, &sitedata.Style, &sitedata.Logo)
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			rows, err := dbase.Query(`SELECT ib_title,ib_domain FROM imageboards WHERE ib_id != ?`, sitedata.Ib)
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}
			defer rows.Close()

			for rows.Next() {

				ib := Imageboard{}

				err := rows.Scan(&ib.Title, &ib.Address)
				if err != nil {
					return err
				}

				sitedata.Imageboards = append(sitedata.Imageboards, ib)
			}
			err = rows.Err()
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			mu.Lock()
			sitemap[host] = sitedata
			mu.Unlock()

		}

		c.Next()

	}
}

// Handles index page generation
func IndexController(c *gin.Context) {

	host := c.Request.Host

	mu.RLock()
	site := sitemap[host]
	mu.RUnlock()

	c.HTML(http.StatusOK, "index", gin.H{
		"primjs":  config.Settings.Prim.Js,
		"primcss": config.Settings.Prim.Css,
		"ib":      site.Ib,
		"apisrv":  site.Api,
		"imgsrv":  site.Img,
		"title":   site.Title,
		"desc":    site.Desc,
		"nsfw":    site.Nsfw,
		"style":   site.Style,
		"logo":    site.Logo,
	})

	return

}

// Handles error messages for wrong routes
func ErrorController(c *gin.Context) {

	c.String(http.StatusNotFound, "Not Found")

	return

}
<commit_msg>loop through imageboards for auto nav menu<commit_after>package main

import (
	"github.com/gin-gonic/gin"
	"net/http"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
)

type SiteData struct {
	Ib          uint
	Api         string
	Img         string
	Title       string
	Desc        string
	Nsfw        bool
	Style       string
	Logo        string
	Imageboards []Imageboard
}

type Imageboard struct {
	Title   string
	Address string
}

// gets the details from the request for the page handler variables
func Details() gin.HandlerFunc {
	return func(c *gin.Context) {

		host := c.Request.Host

		mu.RLock()
		site := sitemap[host]
		mu.RUnlock()

		if site == nil {

			sitedata := &SiteData{}

			// Get Database handle
			dbase, err := db.GetDb()
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			err = dbase.QueryRow(`SELECT ib_id,ib_title,ib_description,ib_nsfw,ib_api,ib_img,ib_style,ib_logo FROM imageboards WHERE ib_domain = ?`, host).Scan(&sitedata.Ib, &sitedata.Title, &sitedata.Desc, &sitedata.Nsfw, &sitedata.Api, &sitedata.Img, &sitedata.Style, &sitedata.Logo)
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			rows, err := dbase.Query(`SELECT ib_title,ib_domain FROM imageboards WHERE ib_id != ?`, sitedata.Ib)
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}
			defer rows.Close()

			for rows.Next() {

				ib := Imageboard{}

				err := rows.Scan(&ib.Title, &ib.Address)
				if err != nil {
					return
				}

				sitedata.Imageboards = append(sitedata.Imageboards, ib)
			}
			err = rows.Err()
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			mu.Lock()
			sitemap[host] = sitedata
			mu.Unlock()

		}

		c.Next()

	}
}

// Handles index page generation
func IndexController(c *gin.Context) {

	host := c.Request.Host

	mu.RLock()
	site := sitemap[host]
	mu.RUnlock()

	c.HTML(http.StatusOK, "index", gin.H{
		"primjs":  config.Settings.Prim.Js,
		"primcss": config.Settings.Prim.Css,
		"ib":      site.Ib,
		"apisrv":  site.Api,
		"imgsrv":  site.Img,
		"title":   site.Title,
		"desc":    site.Desc,
		"nsfw":    site.Nsfw,
		"style":   site.Style,
		"logo":    site.Logo,
	})

	return

}

// Handles error messages for wrong routes
func ErrorController(c *gin.Context) {

	c.String(http.StatusNotFound, "Not Found")

	return

}
<|endoftext|>


<commit_before>package metafora

// CoordinatorContext is the context passed to coordinators by the core
// consumer.
type CoordinatorContext interface {
	Logger
}

// Coordinator is the core interface Metafora uses to discover, claim, and
// tasks as well as receive commands.
type Coordinator interface {
	// Init is called once by the consumer to provide a Logger to Coordinator
	// implementations.
	Init(CoordinatorContext)

	// Watch should do a blocking watch on the broker and return a task ID that
	// can be claimed.
	Watch() (taskID string, err error)

	// Claim is called by the Consumer when a Balancer has determined that a task
	// ID can be claimed. Claim returns false if another consumer has already
	// claimed the ID.
	Claim(taskID string) bool

	// Release a task for other consumers to claim.
	Release(taskID string)

	// Command blocks until a command for this node is received from the broker
	// by the coordinator.
	Command() (cmd string, err error)

	// Close indicates the Coordinator should stop watching and receiving
	// commands. It is called during Consumer.Shutdown().
	Close() error
}
<commit_msg>Make return values for Watch/Command clear in interface docs<commit_after>package metafora

// CoordinatorContext is the context passed to coordinators by the core
// consumer.
type CoordinatorContext interface {
	Logger
}

// Coordinator is the core interface Metafora uses to discover, claim, and
// tasks as well as receive commands.
type Coordinator interface {
	// Init is called once by the consumer to provide a Logger to Coordinator
	// implementations.
	Init(CoordinatorContext)

	// Watch should do a blocking watch on the broker and return a task ID that
	// can be claimed. Watch must return ("", nil) when Close is called.
	Watch() (taskID string, err error)

	// Claim is called by the Consumer when a Balancer has determined that a task
	// ID can be claimed. Claim returns false if another consumer has already
	// claimed the ID.
	Claim(taskID string) bool

	// Release a task for other consumers to claim.
	Release(taskID string)

	// Command blocks until a command for this node is received from the broker
	// by the coordinator. Command must return ("", nil) when Close is called.
	Command() (cmd string, err error)

	// Close indicates the Coordinator should stop watching and receiving
	// commands. It is called during Consumer.Shutdown().
	Close() error
}
<|endoftext|>


<commit_before>package copier_test

import (
	"errors"
	"reflect"
	"testing"
	"time"

	"github.com/jinzhu/copier"
)

type User struct {
	Name     string
	Birthday *time.Time
	Nickname string
	Role     string
	Age      int32
	FakeAge  *int32
	Notes    []string
	flags    []byte
}

func (user User) DoubleAge() int32 {
	return 2 * user.Age
}

type Employee struct {
	Name      string
	Birthday  *time.Time
	Nickname  *string
	Age       int64
	FakeAge   int
	EmployeID int64
	DoubleAge int32
	SuperRule string
	Notes     []string
	flags     []byte
}

func (employee *Employee) Role(role string) {
	employee.SuperRule = "Super " + role
}

func checkEmployee(employee Employee, user User, t *testing.T, testCase string) {
	if employee.Name != user.Name {
		t.Errorf("%v: Name haven't been copied correctly.", testCase)
	}
	if employee.Nickname == nil || *employee.Nickname != user.Nickname {
		t.Errorf("%v: NickName haven't been copied correctly.", testCase)
	}
	if employee.Birthday == nil && user.Birthday != nil {
		t.Errorf("%v: Birthday haven't been copied correctly.", testCase)
	}
	if employee.Birthday != nil && user.Birthday == nil {
		t.Errorf("%v: Birthday haven't been copied correctly.", testCase)
	}
	if employee.Birthday != nil && user.Birthday != nil &&
		!employee.Birthday.Equal(*(user.Birthday)) {
		t.Errorf("%v: Birthday haven't been copied correctly.", testCase)
	}
	if employee.Age != int64(user.Age) {
		t.Errorf("%v: Age haven't been copied correctly.", testCase)
	}
	if user.FakeAge != nil && employee.FakeAge != int(*user.FakeAge) {
		t.Errorf("%v: FakeAge haven't been copied correctly.", testCase)
	}
	if employee.DoubleAge != user.DoubleAge() {
		t.Errorf("%v: Copy from method doesn't work", testCase)
	}
	if employee.SuperRule != "Super "+user.Role {
		t.Errorf("%v: Copy to method doesn't work", testCase)
	}
	if !reflect.DeepEqual(employee.Notes, user.Notes) {
		t.Errorf("%v: Copy from slice doen't work", testCase)
	}
}

func TestCopySameStructWithPointerField(t *testing.T) {
	var fakeAge int32 = 12
	var currentTime time.Time = time.Now()
	user := &User{Birthday: &currentTime, Name: "Jinzhu", Nickname: "jinzhu", Age: 18, FakeAge: &fakeAge, Role: "Admin", Notes: []string{"hello world", "welcome"}, flags: []byte{'x'}}
	newUser := &User{}
	copier.Copy(newUser, user)
	if user.Birthday == newUser.Birthday {
		t.Errorf("TestCopySameStructWithPointerField: copy Birthday failed since they need to have different address")
	}

	if user.FakeAge == newUser.FakeAge {
		t.Errorf("TestCopySameStructWithPointerField: copy FakeAge failed since they need to have different address")
	}
}

func checkEmployee2(employee Employee, user *User, t *testing.T, testCase string) {
	if user == nil {
		if employee.Name != "" || employee.Nickname != nil || employee.Birthday != nil || employee.Age != 0 ||
			employee.DoubleAge != 0 || employee.FakeAge != 0 || employee.SuperRule != "" || employee.Notes != nil {
			t.Errorf("%v : employee should be empty", testCase)
		}
		return
	}

	checkEmployee(employee, *user, t, testCase)
}

func TestCopyStruct(t *testing.T) {
	var fakeAge int32 = 12
	user := User{Name: "Jinzhu", Nickname: "jinzhu", Age: 18, FakeAge: &fakeAge, Role: "Admin", Notes: []string{"hello world", "welcome"}, flags: []byte{'x'}}
	employee := Employee{}

	if err := copier.Copy(employee, &user); err == nil {
		t.Errorf("Copy to unaddressable value should get error")
	}

	copier.Copy(&employee, &user)
	checkEmployee(employee, user, t, "Copy From Ptr To Ptr")

	employee2 := Employee{}
	copier.Copy(&employee2, user)
	checkEmployee(employee2, user, t, "Copy From Struct To Ptr")

	employee3 := Employee{}
	ptrToUser := &user
	copier.Copy(&employee3, &ptrToUser)
	checkEmployee(employee3, user, t, "Copy From Double Ptr To Ptr")

	employee4 := &Employee{}
	copier.Copy(&employee4, user)
	checkEmployee(*employee4, user, t, "Copy From Ptr To Double Ptr")
}

func TestCopyFromStructToSlice(t *testing.T) {
	user := User{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: []string{"hello world"}}
	employees := []Employee{}

	if err := copier.Copy(employees, &user); err != nil && len(employees) != 0 {
		t.Errorf("Copy to unaddressable value should get error")
	}

	if copier.Copy(&employees, &user); len(employees) != 1 {
		t.Errorf("Should only have one elem when copy struct to slice")
	} else {
		checkEmployee(employees[0], user, t, "Copy From Struct To Slice Ptr")
	}

	employees2 := &[]Employee{}
	if copier.Copy(&employees2, user); len(*employees2) != 1 {
		t.Errorf("Should only have one elem when copy struct to slice")
	} else {
		checkEmployee((*employees2)[0], user, t, "Copy From Struct To Double Slice Ptr")
	}

	employees3 := []*Employee{}
	if copier.Copy(&employees3, user); len(employees3) != 1 {
		t.Errorf("Should only have one elem when copy struct to slice")
	} else {
		checkEmployee(*(employees3[0]), user, t, "Copy From Struct To Ptr Slice Ptr")
	}

	employees4 := &[]*Employee{}
	if copier.Copy(&employees4, user); len(*employees4) != 1 {
		t.Errorf("Should only have one elem when copy struct to slice")
	} else {
		checkEmployee(*((*employees4)[0]), user, t, "Copy From Struct To Double Ptr Slice Ptr")
	}
}

func TestCopyFromSliceToSlice(t *testing.T) {
	users := []User{User{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: []string{"hello world"}}, User{Name: "Jinzhu2", Age: 22, Role: "Dev", Notes: []string{"hello world", "hello"}}}
	employees := []Employee{}

	if copier.Copy(&employees, users); len(employees) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee(employees[0], users[0], t, "Copy From Slice To Slice Ptr @ 1")
		checkEmployee(employees[1], users[1], t, "Copy From Slice To Slice Ptr @ 2")
	}

	employees2 := &[]Employee{}
	if copier.Copy(&employees2, &users); len(*employees2) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee((*employees2)[0], users[0], t, "Copy From Slice Ptr To Double Slice Ptr @ 1")
		checkEmployee((*employees2)[1], users[1], t, "Copy From Slice Ptr To Double Slice Ptr @ 2")
	}

	employees3 := []*Employee{}
	if copier.Copy(&employees3, users); len(employees3) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee(*(employees3[0]), users[0], t, "Copy From Slice To Ptr Slice Ptr @ 1")
		checkEmployee(*(employees3[1]), users[1], t, "Copy From Slice To Ptr Slice Ptr @ 2")
	}

	employees4 := &[]*Employee{}
	if copier.Copy(&employees4, users); len(*employees4) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee(*((*employees4)[0]), users[0], t, "Copy From Slice Ptr To Double Ptr Slice Ptr @ 1")
		checkEmployee(*((*employees4)[1]), users[1], t, "Copy From Slice Ptr To Double Ptr Slice Ptr @ 2")
	}
}

func TestCopyFromSliceToSlice2(t *testing.T) {
	users := []*User{{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: []string{"hello world"}}, nil}
	employees := []Employee{}

	if copier.Copy(&employees, users); len(employees) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee2(employees[0], users[0], t, "Copy From Slice To Slice Ptr @ 1")
		checkEmployee2(employees[1], users[1], t, "Copy From Slice To Slice Ptr @ 2")
	}

	employees2 := &[]Employee{}
	if copier.Copy(&employees2, &users); len(*employees2) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee2((*employees2)[0], users[0], t, "Copy From Slice Ptr To Double Slice Ptr @ 1")
		checkEmployee2((*employees2)[1], users[1], t, "Copy From Slice Ptr To Double Slice Ptr @ 2")
	}

	employees3 := []*Employee{}
	if copier.Copy(&employees3, users); len(employees3) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee2(*(employees3[0]), users[0], t, "Copy From Slice To Ptr Slice Ptr @ 1")
		checkEmployee2(*(employees3[1]), users[1], t, "Copy From Slice To Ptr Slice Ptr @ 2")
	}

	employees4 := &[]*Employee{}
	if copier.Copy(&employees4, users); len(*employees4) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee2(*((*employees4)[0]), users[0], t, "Copy From Slice Ptr To Double Ptr Slice Ptr @ 1")
		checkEmployee2(*((*employees4)[1]), users[1], t, "Copy From Slice Ptr To Double Ptr Slice Ptr @ 2")
	}
}

func TestEmbeddedAndBase(t *testing.T) {
	type Base struct {
		BaseField1 int
		BaseField2 int
		User *User
	}

	type Embed struct {
		EmbedField1 int
		EmbedField2 int
		Base
	}

	base := Base{}
	embeded := Embed{}
	embeded.BaseField1 = 1
	embeded.BaseField2 = 2
	embeded.EmbedField1 = 3
	embeded.EmbedField2 = 4

	user:=User{
		Name:"testName",
	}
	embeded.User=&user

	copier.Copy(&base, &embeded)

	if base.BaseField1 != 1 || base.User.Name!="testName"{
		t.Error("Embedded fields not copied")
	}

	base.BaseField1=11
	base.BaseField2=12
	user1:=User{
		Name:"testName1",
	}
	base.User=&user1

	copier.Copy(&embeded,&base)

	if embeded.BaseField1 != 11 || embeded.User.Name!="testName1" {
		t.Error("base fields not copied")
	}
}

type structSameName1 struct {
	A string
	B int64
	C time.Time
}

type structSameName2 struct {
	A string
	B time.Time
	C int64
}

func TestCopyFieldsWithSameNameButDifferentTypes(t *testing.T) {
	obj1 := structSameName1{A: "123", B: 2, C: time.Now()}
	obj2 := &structSameName2{}
	err := copier.Copy(obj2, &obj1)
	if err != nil {
		t.Error("Should not raise error")
	}

	if obj2.A != obj1.A {
		t.Errorf("Field A should be copied")
	}
}

type ScannerValue struct {
	V int
}

func (s *ScannerValue) Scan(src interface{}) error {
	return errors.New("I failed")
}

type ScannerStruct struct {
	V *ScannerValue
}

type ScannerStructTo struct {
	V *ScannerValue
}

func TestScanner(t *testing.T) {
	s := &ScannerStruct{
		V: &ScannerValue{
			V: 12,
		},
	}

	s2 := &ScannerStructTo{}

	err := copier.Copy(s2, s)
	if err != nil {
		t.Error("Should not raise error")
	}

	if s.V.V != s2.V.V {
		t.Errorf("Field V should be copied")
	}
}
<commit_msg>Correct typos in copier_test.go<commit_after>package copier_test

import (
	"errors"
	"reflect"
	"testing"
	"time"

	"github.com/jinzhu/copier"
)

type User struct {
	Name     string
	Birthday *time.Time
	Nickname string
	Role     string
	Age      int32
	FakeAge  *int32
	Notes    []string
	flags    []byte
}

func (user User) DoubleAge() int32 {
	return 2 * user.Age
}

type Employee struct {
	Name      string
	Birthday  *time.Time
	Nickname  *string
	Age       int64
	FakeAge   int
	EmployeID int64
	DoubleAge int32
	SuperRule string
	Notes     []string
	flags     []byte
}

func (employee *Employee) Role(role string) {
	employee.SuperRule = "Super " + role
}

func checkEmployee(employee Employee, user User, t *testing.T, testCase string) {
	if employee.Name != user.Name {
		t.Errorf("%v: Name haven't been copied correctly.", testCase)
	}
	if employee.Nickname == nil || *employee.Nickname != user.Nickname {
		t.Errorf("%v: NickName haven't been copied correctly.", testCase)
	}
	if employee.Birthday == nil && user.Birthday != nil {
		t.Errorf("%v: Birthday haven't been copied correctly.", testCase)
	}
	if employee.Birthday != nil && user.Birthday == nil {
		t.Errorf("%v: Birthday haven't been copied correctly.", testCase)
	}
	if employee.Birthday != nil && user.Birthday != nil &&
		!employee.Birthday.Equal(*(user.Birthday)) {
		t.Errorf("%v: Birthday haven't been copied correctly.", testCase)
	}
	if employee.Age != int64(user.Age) {
		t.Errorf("%v: Age haven't been copied correctly.", testCase)
	}
	if user.FakeAge != nil && employee.FakeAge != int(*user.FakeAge) {
		t.Errorf("%v: FakeAge haven't been copied correctly.", testCase)
	}
	if employee.DoubleAge != user.DoubleAge() {
		t.Errorf("%v: Copy from method doesn't work", testCase)
	}
	if employee.SuperRule != "Super "+user.Role {
		t.Errorf("%v: Copy to method doesn't work", testCase)
	}
	if !reflect.DeepEqual(employee.Notes, user.Notes) {
		t.Errorf("%v: Copy from slice doesn't work", testCase)
	}
}

func TestCopySameStructWithPointerField(t *testing.T) {
	var fakeAge int32 = 12
	var currentTime time.Time = time.Now()
	user := &User{Birthday: &currentTime, Name: "Jinzhu", Nickname: "jinzhu", Age: 18, FakeAge: &fakeAge, Role: "Admin", Notes: []string{"hello world", "welcome"}, flags: []byte{'x'}}
	newUser := &User{}
	copier.Copy(newUser, user)
	if user.Birthday == newUser.Birthday {
		t.Errorf("TestCopySameStructWithPointerField: copy Birthday failed since they need to have different address")
	}

	if user.FakeAge == newUser.FakeAge {
		t.Errorf("TestCopySameStructWithPointerField: copy FakeAge failed since they need to have different address")
	}
}

func checkEmployee2(employee Employee, user *User, t *testing.T, testCase string) {
	if user == nil {
		if employee.Name != "" || employee.Nickname != nil || employee.Birthday != nil || employee.Age != 0 ||
			employee.DoubleAge != 0 || employee.FakeAge != 0 || employee.SuperRule != "" || employee.Notes != nil {
			t.Errorf("%v : employee should be empty", testCase)
		}
		return
	}

	checkEmployee(employee, *user, t, testCase)
}

func TestCopyStruct(t *testing.T) {
	var fakeAge int32 = 12
	user := User{Name: "Jinzhu", Nickname: "jinzhu", Age: 18, FakeAge: &fakeAge, Role: "Admin", Notes: []string{"hello world", "welcome"}, flags: []byte{'x'}}
	employee := Employee{}

	if err := copier.Copy(employee, &user); err == nil {
		t.Errorf("Copy to unaddressable value should get error")
	}

	copier.Copy(&employee, &user)
	checkEmployee(employee, user, t, "Copy From Ptr To Ptr")

	employee2 := Employee{}
	copier.Copy(&employee2, user)
	checkEmployee(employee2, user, t, "Copy From Struct To Ptr")

	employee3 := Employee{}
	ptrToUser := &user
	copier.Copy(&employee3, &ptrToUser)
	checkEmployee(employee3, user, t, "Copy From Double Ptr To Ptr")

	employee4 := &Employee{}
	copier.Copy(&employee4, user)
	checkEmployee(*employee4, user, t, "Copy From Ptr To Double Ptr")
}

func TestCopyFromStructToSlice(t *testing.T) {
	user := User{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: []string{"hello world"}}
	employees := []Employee{}

	if err := copier.Copy(employees, &user); err != nil && len(employees) != 0 {
		t.Errorf("Copy to unaddressable value should get error")
	}

	if copier.Copy(&employees, &user); len(employees) != 1 {
		t.Errorf("Should only have one elem when copy struct to slice")
	} else {
		checkEmployee(employees[0], user, t, "Copy From Struct To Slice Ptr")
	}

	employees2 := &[]Employee{}
	if copier.Copy(&employees2, user); len(*employees2) != 1 {
		t.Errorf("Should only have one elem when copy struct to slice")
	} else {
		checkEmployee((*employees2)[0], user, t, "Copy From Struct To Double Slice Ptr")
	}

	employees3 := []*Employee{}
	if copier.Copy(&employees3, user); len(employees3) != 1 {
		t.Errorf("Should only have one elem when copy struct to slice")
	} else {
		checkEmployee(*(employees3[0]), user, t, "Copy From Struct To Ptr Slice Ptr")
	}

	employees4 := &[]*Employee{}
	if copier.Copy(&employees4, user); len(*employees4) != 1 {
		t.Errorf("Should only have one elem when copy struct to slice")
	} else {
		checkEmployee(*((*employees4)[0]), user, t, "Copy From Struct To Double Ptr Slice Ptr")
	}
}

func TestCopyFromSliceToSlice(t *testing.T) {
	users := []User{User{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: []string{"hello world"}}, User{Name: "Jinzhu2", Age: 22, Role: "Dev", Notes: []string{"hello world", "hello"}}}
	employees := []Employee{}

	if copier.Copy(&employees, users); len(employees) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee(employees[0], users[0], t, "Copy From Slice To Slice Ptr @ 1")
		checkEmployee(employees[1], users[1], t, "Copy From Slice To Slice Ptr @ 2")
	}

	employees2 := &[]Employee{}
	if copier.Copy(&employees2, &users); len(*employees2) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee((*employees2)[0], users[0], t, "Copy From Slice Ptr To Double Slice Ptr @ 1")
		checkEmployee((*employees2)[1], users[1], t, "Copy From Slice Ptr To Double Slice Ptr @ 2")
	}

	employees3 := []*Employee{}
	if copier.Copy(&employees3, users); len(employees3) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee(*(employees3[0]), users[0], t, "Copy From Slice To Ptr Slice Ptr @ 1")
		checkEmployee(*(employees3[1]), users[1], t, "Copy From Slice To Ptr Slice Ptr @ 2")
	}

	employees4 := &[]*Employee{}
	if copier.Copy(&employees4, users); len(*employees4) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee(*((*employees4)[0]), users[0], t, "Copy From Slice Ptr To Double Ptr Slice Ptr @ 1")
		checkEmployee(*((*employees4)[1]), users[1], t, "Copy From Slice Ptr To Double Ptr Slice Ptr @ 2")
	}
}

func TestCopyFromSliceToSlice2(t *testing.T) {
	users := []*User{{Name: "Jinzhu", Age: 18, Role: "Admin", Notes: []string{"hello world"}}, nil}
	employees := []Employee{}

	if copier.Copy(&employees, users); len(employees) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee2(employees[0], users[0], t, "Copy From Slice To Slice Ptr @ 1")
		checkEmployee2(employees[1], users[1], t, "Copy From Slice To Slice Ptr @ 2")
	}

	employees2 := &[]Employee{}
	if copier.Copy(&employees2, &users); len(*employees2) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee2((*employees2)[0], users[0], t, "Copy From Slice Ptr To Double Slice Ptr @ 1")
		checkEmployee2((*employees2)[1], users[1], t, "Copy From Slice Ptr To Double Slice Ptr @ 2")
	}

	employees3 := []*Employee{}
	if copier.Copy(&employees3, users); len(employees3) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee2(*(employees3[0]), users[0], t, "Copy From Slice To Ptr Slice Ptr @ 1")
		checkEmployee2(*(employees3[1]), users[1], t, "Copy From Slice To Ptr Slice Ptr @ 2")
	}

	employees4 := &[]*Employee{}
	if copier.Copy(&employees4, users); len(*employees4) != 2 {
		t.Errorf("Should have two elems when copy slice to slice")
	} else {
		checkEmployee2(*((*employees4)[0]), users[0], t, "Copy From Slice Ptr To Double Ptr Slice Ptr @ 1")
		checkEmployee2(*((*employees4)[1]), users[1], t, "Copy From Slice Ptr To Double Ptr Slice Ptr @ 2")
	}
}

func TestEmbeddedAndBase(t *testing.T) {
	type Base struct {
		BaseField1 int
		BaseField2 int
		User *User
	}

	type Embed struct {
		EmbedField1 int
		EmbedField2 int
		Base
	}

	base := Base{}
	embedded := Embed{}
	embedded.BaseField1 = 1
	embedded.BaseField2 = 2
	embedded.EmbedField1 = 3
	embedded.EmbedField2 = 4

	user:=User{
		Name:"testName",
	}
	embedded.User=&user

	copier.Copy(&base, &embedded)

	if base.BaseField1 != 1 || base.User.Name!="testName"{
		t.Error("Embedded fields not copied")
	}

	base.BaseField1=11
	base.BaseField2=12
	user1:=User{
		Name:"testName1",
	}
	base.User=&user1

	copier.Copy(&embedded,&base)

	if embedded.BaseField1 != 11 || embedded.User.Name!="testName1" {
		t.Error("base fields not copied")
	}
}

type structSameName1 struct {
	A string
	B int64
	C time.Time
}

type structSameName2 struct {
	A string
	B time.Time
	C int64
}

func TestCopyFieldsWithSameNameButDifferentTypes(t *testing.T) {
	obj1 := structSameName1{A: "123", B: 2, C: time.Now()}
	obj2 := &structSameName2{}
	err := copier.Copy(obj2, &obj1)
	if err != nil {
		t.Error("Should not raise error")
	}

	if obj2.A != obj1.A {
		t.Errorf("Field A should be copied")
	}
}

type ScannerValue struct {
	V int
}

func (s *ScannerValue) Scan(src interface{}) error {
	return errors.New("I failed")
}

type ScannerStruct struct {
	V *ScannerValue
}

type ScannerStructTo struct {
	V *ScannerValue
}

func TestScanner(t *testing.T) {
	s := &ScannerStruct{
		V: &ScannerValue{
			V: 12,
		},
	}

	s2 := &ScannerStructTo{}

	err := copier.Copy(s2, s)
	if err != nil {
		t.Error("Should not raise error")
	}

	if s.V.V != s2.V.V {
		t.Errorf("Field V should be copied")
	}
}
<|endoftext|>


<commit_before>package automata

import (
	"testing"
)

func TestCrossEntropyCost(t *testing.T) {
	ce := CrossEntropyCost{}
	output := ce.Cost([]float64{0, 0.5, 1}, []float64{1, 0.5, 0})
	want := 69.66613905215368
	if output != want {
		t.Errorf("Cost([0, 0.5, 1], [1, 0.5, 0]) : want %f, got %f", want, output)
	}

	output = ce.Cost([]float64{0, 0.5, 1}, []float64{0, 0.5, 1})
	want = 0.693147180559941
	if output != want {
		t.Errorf("Cost([0, 0.5, 1], [0, 0.5, 1]) : want %f, got %f", want, output)
	}
}
<commit_msg>Add MSE test (#9)<commit_after>package automata

import (
	"testing"
)

func TestMeanSquaredErrorCost(t *testing.T) {
	mse := MeanSquaredErrorCost{}
	output := mse.Cost([]float64{0, 0.5, 1}, []float64{1, 0.5, 0})
	want := 0.66666666666666666666
	if output != want {
		t.Errorf("Cost([0, 0.5, 1], [1, 0.5, 0]) : want %f, got %f", want, output)
	}

	output = mse.Cost([]float64{0, 0.5, 1}, []float64{0, 0.5, 1})
	want = 0
	if output != want {
		t.Errorf("Cost([0, 0.5, 1], [0, 0.5, 1]) : want %f, got %f", want, output)
	}
}

func TestCrossEntropyCost(t *testing.T) {
	ce := CrossEntropyCost{}
	output := ce.Cost([]float64{0, 0.5, 1}, []float64{1, 0.5, 0})
	want := 69.66613905215368
	if output != want {
		t.Errorf("Cost([0, 0.5, 1], [1, 0.5, 0]) : want %f, got %f", want, output)
	}

	output = ce.Cost([]float64{0, 0.5, 1}, []float64{0, 0.5, 1})
	want = 0.693147180559941
	if output != want {
		t.Errorf("Cost([0, 0.5, 1], [0, 0.5, 1]) : want %f, got %f", want, output)
	}
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"sort"
	"time"

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

func dataSourceAwsAvailabilityZones() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsAvailabilityZonesRead,

		Schema: map[string]*schema.Schema{
			"all_availability_zones": {
				Type:     schema.TypeBool,
				Optional: true,
			},
			"exclude_names": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"exclude_zone_ids": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"filter": ec2CustomFiltersSchema(),
			"group_names": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"names": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"state": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.StringInSlice([]string{
					ec2.AvailabilityZoneStateAvailable,
					ec2.AvailabilityZoneStateInformation,
					ec2.AvailabilityZoneStateImpaired,
					ec2.AvailabilityZoneStateUnavailable,
				}, false),
			},
			"zone_ids": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
		},
	}
}

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

	log.Printf("[DEBUG] Reading Availability Zones.")
	d.SetId(time.Now().UTC().String())

	request := &ec2.DescribeAvailabilityZonesInput{}

	if v, ok := d.GetOk("all_availability_zones"); ok {
		request.AllAvailabilityZones = aws.Bool(v.(bool))
	}

	if v, ok := d.GetOk("state"); ok {
		request.Filters = []*ec2.Filter{
			{
				Name:   aws.String("state"),
				Values: []*string{aws.String(v.(string))},
			},
		}
	}

	if filters, filtersOk := d.GetOk("filter"); filtersOk {
		request.Filters = append(request.Filters, buildEC2CustomFilterList(
			filters.(*schema.Set),
		)...)
	}

	if len(request.Filters) == 0 {
		// Don't send an empty filters list; the EC2 API won't accept it.
		request.Filters = nil
	}

	log.Printf("[DEBUG] Reading Availability Zones: %s", request)
	resp, err := conn.DescribeAvailabilityZones(request)
	if err != nil {
		return fmt.Errorf("Error fetching Availability Zones: %s", err)
	}

	sort.Slice(resp.AvailabilityZones, func(i, j int) bool {
		return aws.StringValue(resp.AvailabilityZones[i].ZoneName) < aws.StringValue(resp.AvailabilityZones[j].ZoneName)
	})

	excludeNames := d.Get("exclude_names").(*schema.Set)
	excludeZoneIDs := d.Get("exclude_zone_ids").(*schema.Set)

	groupNames := schema.NewSet(schema.HashString, nil)
	names := []string{}
	zoneIds := []string{}
	for _, v := range resp.AvailabilityZones {
		groupName := aws.StringValue(v.GroupName)
		name := aws.StringValue(v.ZoneName)
		zoneID := aws.StringValue(v.ZoneId)

		if excludeNames.Contains(name) {
			continue
		}

		if excludeZoneIDs.Contains(zoneID) {
			continue
		}

		if !groupNames.Contains(groupName) {
			groupNames.Add(groupName)
		}

		names = append(names, name)
		zoneIds = append(zoneIds, zoneID)
	}

	if err := d.Set("group_names", groupNames); err != nil {
		return fmt.Errorf("error setting group_names: %s", err)
	}
	if err := d.Set("names", names); err != nil {
		return fmt.Errorf("Error setting Availability Zone names: %s", err)
	}
	if err := d.Set("zone_ids", zoneIds); err != nil {
		return fmt.Errorf("Error setting Availability Zone IDs: %s", err)
	}

	return nil
}
<commit_msg>data-source/aws_availability_zones: Fix group_names attribute to be Computed instead of Optional (#14412)<commit_after>package aws

import (
	"fmt"
	"log"
	"sort"
	"time"

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

func dataSourceAwsAvailabilityZones() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsAvailabilityZonesRead,

		Schema: map[string]*schema.Schema{
			"all_availability_zones": {
				Type:     schema.TypeBool,
				Optional: true,
			},
			"exclude_names": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"exclude_zone_ids": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"filter": ec2CustomFiltersSchema(),
			"group_names": {
				Type:     schema.TypeSet,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"names": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"state": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.StringInSlice([]string{
					ec2.AvailabilityZoneStateAvailable,
					ec2.AvailabilityZoneStateInformation,
					ec2.AvailabilityZoneStateImpaired,
					ec2.AvailabilityZoneStateUnavailable,
				}, false),
			},
			"zone_ids": {
				Type:     schema.TypeList,
				Computed: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
		},
	}
}

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

	log.Printf("[DEBUG] Reading Availability Zones.")
	d.SetId(time.Now().UTC().String())

	request := &ec2.DescribeAvailabilityZonesInput{}

	if v, ok := d.GetOk("all_availability_zones"); ok {
		request.AllAvailabilityZones = aws.Bool(v.(bool))
	}

	if v, ok := d.GetOk("state"); ok {
		request.Filters = []*ec2.Filter{
			{
				Name:   aws.String("state"),
				Values: []*string{aws.String(v.(string))},
			},
		}
	}

	if filters, filtersOk := d.GetOk("filter"); filtersOk {
		request.Filters = append(request.Filters, buildEC2CustomFilterList(
			filters.(*schema.Set),
		)...)
	}

	if len(request.Filters) == 0 {
		// Don't send an empty filters list; the EC2 API won't accept it.
		request.Filters = nil
	}

	log.Printf("[DEBUG] Reading Availability Zones: %s", request)
	resp, err := conn.DescribeAvailabilityZones(request)
	if err != nil {
		return fmt.Errorf("Error fetching Availability Zones: %s", err)
	}

	sort.Slice(resp.AvailabilityZones, func(i, j int) bool {
		return aws.StringValue(resp.AvailabilityZones[i].ZoneName) < aws.StringValue(resp.AvailabilityZones[j].ZoneName)
	})

	excludeNames := d.Get("exclude_names").(*schema.Set)
	excludeZoneIDs := d.Get("exclude_zone_ids").(*schema.Set)

	groupNames := schema.NewSet(schema.HashString, nil)
	names := []string{}
	zoneIds := []string{}
	for _, v := range resp.AvailabilityZones {
		groupName := aws.StringValue(v.GroupName)
		name := aws.StringValue(v.ZoneName)
		zoneID := aws.StringValue(v.ZoneId)

		if excludeNames.Contains(name) {
			continue
		}

		if excludeZoneIDs.Contains(zoneID) {
			continue
		}

		if !groupNames.Contains(groupName) {
			groupNames.Add(groupName)
		}

		names = append(names, name)
		zoneIds = append(zoneIds, zoneID)
	}

	if err := d.Set("group_names", groupNames); err != nil {
		return fmt.Errorf("error setting group_names: %s", err)
	}
	if err := d.Set("names", names); err != nil {
		return fmt.Errorf("Error setting Availability Zone names: %s", err)
	}
	if err := d.Set("zone_ids", zoneIds); err != nil {
		return fmt.Errorf("Error setting Availability Zone IDs: %s", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"log"
	"time"

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

func resourceAwsEcrRepositoryPolicy() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEcrRepositoryPolicyCreate,
		Read:   resourceAwsEcrRepositoryPolicyRead,
		Update: resourceAwsEcrRepositoryPolicyUpdate,
		Delete: resourceAwsEcrRepositoryPolicyDelete,

		Schema: map[string]*schema.Schema{
			"repository": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"policy": {
				Type:             schema.TypeString,
				Required:         true,
				DiffSuppressFunc: suppressEquivalentJsonDiffs,
			},
			"registry_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsEcrRepositoryPolicyCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	input := ecr.SetRepositoryPolicyInput{
		RepositoryName: aws.String(d.Get("repository").(string)),
		PolicyText:     aws.String(d.Get("policy").(string)),
	}

	log.Printf("[DEBUG] Creating ECR resository policy: %s", input)

	// Retry due to IAM eventual consistency
	var out *ecr.SetRepositoryPolicyOutput
	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
		var err error
		out, err = conn.SetRepositoryPolicy(&input)

		if isAWSErr(err, "InvalidParameterException", "Invalid repository policy provided") {
			return resource.RetryableError(err)

		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return err
	}

	repositoryPolicy := *out

	log.Printf("[DEBUG] ECR repository policy created: %s", *repositoryPolicy.RepositoryName)

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)

	return resourceAwsEcrRepositoryPolicyRead(d, meta)
}

func resourceAwsEcrRepositoryPolicyRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	log.Printf("[DEBUG] Reading repository policy %s", d.Id())
	out, err := conn.GetRepositoryPolicy(&ecr.GetRepositoryPolicyInput{
		RegistryId:     aws.String(d.Get("registry_id").(string)),
		RepositoryName: aws.String(d.Id()),
	})
	if err != nil {
		if ecrerr, ok := err.(awserr.Error); ok {
			switch ecrerr.Code() {
			case "RepositoryNotFoundException", "RepositoryPolicyNotFoundException":
				d.SetId("")
				return nil
			default:
				return err
			}
		}
		return err
	}

	log.Printf("[DEBUG] Received repository policy %s", out)

	repositoryPolicy := out

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)
	d.Set("policy", repositoryPolicy.PolicyText)

	return nil
}

func resourceAwsEcrRepositoryPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	if !d.HasChange("policy") {
		return nil
	}

	input := ecr.SetRepositoryPolicyInput{
		RepositoryName: aws.String(d.Get("repository").(string)),
		RegistryId:     aws.String(d.Get("registry_id").(string)),
		PolicyText:     aws.String(d.Get("policy").(string)),
	}

	log.Printf("[DEBUG] Updating ECR resository policy: %s", input)

	// Retry due to IAM eventual consistency
	var out *ecr.SetRepositoryPolicyOutput
	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
		var err error
		out, err = conn.SetRepositoryPolicy(&input)

		if isAWSErr(err, "InvalidParameterException", "Invalid repository policy provided") {
			return resource.RetryableError(err)

		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return err
	}

	repositoryPolicy := *out

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)

	return nil
}

func resourceAwsEcrRepositoryPolicyDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	_, err := conn.DeleteRepositoryPolicy(&ecr.DeleteRepositoryPolicyInput{
		RepositoryName: aws.String(d.Id()),
		RegistryId:     aws.String(d.Get("registry_id").(string)),
	})
	if err != nil {
		if ecrerr, ok := err.(awserr.Error); ok {
			switch ecrerr.Code() {
			case "RepositoryNotFoundException", "RepositoryPolicyNotFoundException":
				return nil
			default:
				return err
			}
		}
		return err
	}

	log.Printf("[DEBUG] repository policy %s deleted.", d.Id())

	return nil
}
<commit_msg>resource/aws_ecr_repository_policy: Switch policy DiffSuppressFunc from suppressEquivalentJsonDiffs to suppressEquivalentAwsPolicyDiffs<commit_after>package aws

import (
	"log"
	"time"

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

func resourceAwsEcrRepositoryPolicy() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEcrRepositoryPolicyCreate,
		Read:   resourceAwsEcrRepositoryPolicyRead,
		Update: resourceAwsEcrRepositoryPolicyUpdate,
		Delete: resourceAwsEcrRepositoryPolicyDelete,

		Schema: map[string]*schema.Schema{
			"repository": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"policy": {
				Type:             schema.TypeString,
				Required:         true,
				DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
			},
			"registry_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceAwsEcrRepositoryPolicyCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	input := ecr.SetRepositoryPolicyInput{
		RepositoryName: aws.String(d.Get("repository").(string)),
		PolicyText:     aws.String(d.Get("policy").(string)),
	}

	log.Printf("[DEBUG] Creating ECR resository policy: %s", input)

	// Retry due to IAM eventual consistency
	var out *ecr.SetRepositoryPolicyOutput
	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
		var err error
		out, err = conn.SetRepositoryPolicy(&input)

		if isAWSErr(err, "InvalidParameterException", "Invalid repository policy provided") {
			return resource.RetryableError(err)

		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return err
	}

	repositoryPolicy := *out

	log.Printf("[DEBUG] ECR repository policy created: %s", *repositoryPolicy.RepositoryName)

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)

	return resourceAwsEcrRepositoryPolicyRead(d, meta)
}

func resourceAwsEcrRepositoryPolicyRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	log.Printf("[DEBUG] Reading repository policy %s", d.Id())
	out, err := conn.GetRepositoryPolicy(&ecr.GetRepositoryPolicyInput{
		RegistryId:     aws.String(d.Get("registry_id").(string)),
		RepositoryName: aws.String(d.Id()),
	})
	if err != nil {
		if ecrerr, ok := err.(awserr.Error); ok {
			switch ecrerr.Code() {
			case "RepositoryNotFoundException", "RepositoryPolicyNotFoundException":
				d.SetId("")
				return nil
			default:
				return err
			}
		}
		return err
	}

	log.Printf("[DEBUG] Received repository policy %s", out)

	repositoryPolicy := out

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)
	d.Set("policy", repositoryPolicy.PolicyText)

	return nil
}

func resourceAwsEcrRepositoryPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	if !d.HasChange("policy") {
		return nil
	}

	input := ecr.SetRepositoryPolicyInput{
		RepositoryName: aws.String(d.Get("repository").(string)),
		RegistryId:     aws.String(d.Get("registry_id").(string)),
		PolicyText:     aws.String(d.Get("policy").(string)),
	}

	log.Printf("[DEBUG] Updating ECR resository policy: %s", input)

	// Retry due to IAM eventual consistency
	var out *ecr.SetRepositoryPolicyOutput
	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
		var err error
		out, err = conn.SetRepositoryPolicy(&input)

		if isAWSErr(err, "InvalidParameterException", "Invalid repository policy provided") {
			return resource.RetryableError(err)

		}
		return resource.NonRetryableError(err)
	})
	if err != nil {
		return err
	}

	repositoryPolicy := *out

	d.SetId(*repositoryPolicy.RepositoryName)
	d.Set("registry_id", repositoryPolicy.RegistryId)

	return nil
}

func resourceAwsEcrRepositoryPolicyDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ecrconn

	_, err := conn.DeleteRepositoryPolicy(&ecr.DeleteRepositoryPolicyInput{
		RepositoryName: aws.String(d.Id()),
		RegistryId:     aws.String(d.Get("registry_id").(string)),
	})
	if err != nil {
		if ecrerr, ok := err.(awserr.Error); ok {
			switch ecrerr.Code() {
			case "RepositoryNotFoundException", "RepositoryPolicyNotFoundException":
				return nil
			default:
				return err
			}
		}
		return err
	}

	log.Printf("[DEBUG] repository policy %s deleted.", d.Id())

	return nil
}
<|endoftext|>


<commit_before>package reactive

import (
	"reflect"
	"sync/atomic"
	"time"
)

//ImmutableChain provides a means of locking the start and end chain between a specific area
func ImmutableChain(r, t Immutable) *MList {
	return &MList{root: r, tail: t}
}

//Immutables returns a new list with an open-ended chain
func Immutables(m Immutable) *MList {
	return ImmutableChain(m, m)
}

//Allowed calls the tail allowed function
func (m *MList) Allowed(v interface{}) bool {
	return m.tail.Allowed(v)
}

//Tail returns the tail Immutable for this list
func (m *MList) Tail() Immutable {
	return m.tail
}

//Root returns the root Immutable for this list
func (m *MList) Root() Immutable {
	return m.root
}

//Size returns the size of the list
func (m *MList) Size() int {
	return int(m.size)
}

//Stamp returns the time of creation
func (m *MList) Stamp() time.Time {
	return m.tail.Stamp()
}

//Mutate returns a new Immutable of that type
func (m *MList) Mutate(v interface{}) (Immutable, bool) {
	mc, b := m.tail.Mutate(v)
	if b {
		atomic.AddInt64(&m.size, 1)
	}
	m.tail = mc
	return mc, b
}

//GetKind returns the kind of the value
func GetKind(m interface{}) reflect.Kind {
	return reflect.TypeOf(m).Kind()
}

//InfiniteEventIterator returns an instance of MIterator
func InfiniteEventIterator(r Immutable) *MIterator {
	return &MIterator{
		from:    r,
		endless: true,
	}
}

//FiniteEventIterator returns an instance of MIterator
func FiniteEventIterator(r Immutable, end time.Time) *MIterator {
	return &MIterator{
		from:    r,
		end:     end,
		endless: false,
	}
}

//Previous walks to the next Immutable
func (m *MIterator) Previous() error {
	if m.started <= 0 && !m.endless {
		return ErrEndIndex
	}

	if !m.endless && m.current == m.from {
		return ErrEndIndex
	}

	atomic.StoreInt64(&m.started, 1)
	prv := m.current.previous()

	if prv == nil {
		// atomic.StoreInt64(&m.started, 2)
		return ErrEndIndex
	}

	m.current = prv
	return nil
}

//Reset resets the iterator for reuse
func (m *MIterator) Reset() {
	m.current = nil
	m.started = 0
}

//Next walks to the next Immutable
func (m *MIterator) Next() error {
	if int(m.started) > 1 {
		return ErrEndIndex
	}

	var nx Immutable

	if m.started <= 0 {
		atomic.StoreInt64(&m.started, 1)
		m.current = m.from
		nx = m.from
	} else {
		nx = m.current.next()
	}

	if nx == nil {
		atomic.StoreInt64(&m.started, 2)
		return ErrEndIndex
	}

	if !m.endless {

		diff := m.end.UTC().Sub(nx.Stamp().UTC())

		// log.Printf("diff: %s", diff)

		if diff <= 0 {
			atomic.StoreInt64(&m.started, 2)
			return ErrEndIndex
		}
	}

	m.current = nx
	return nil
}

//Event walks to the next Immutable
func (m *MIterator) Event() Immutable {
	if int(m.started) > 1 {
		return nil
	}
	return m.current
}

//NewManager returns a new MListManager instance
func NewManager(m Immutable, mcap int) *MListManager {
	return &MListManager{
		maxrange: mcap,
		mranges:  []*MList{Immutables(m)},
	}
}

//ForceSave saves the current list into the datastore timestamps
func (m *MListManager) ForceSave() {
	sz := len(m.mranges)
	lm := m.mranges[sz-1]

	//get the timestamps so we can store the range
	so, eo := lm.Root().Stamp(), lm.Tail().Stamp()

	tm := &TimeRange{Index: sz, Min: so, Max: eo}

	m.stamps = append(m.stamps, tm)

	//make another mlist,set the tail to be the root of it
	nm := Immutables(lm.Tail())

	m.mranges = append(m.mranges, nm)
}

//Mutate builds on the capability of storing the mutations
func (m *MListManager) Mutate(v interface{}) (Immutable, bool) {
	sz := len(m.mranges)
	lm := m.mranges[sz-1]

	if lm.Size() < m.maxrange {
		return lm.Mutate(v)
	}

	// //get the timestamps so we can store the range
	// so, eo := lm.Root().Stamp(), lm.Tail().Stamp()
	//
	// tm := &TimeRange{Index: sz, Min: so, Max: eo}
	//
	// m.stamps = append(m.stamps, tm)
	//
	// //make another mlist,set the tail to be the root of it
	// nm := Immutables(lm.Tail())
	m.ForceSave()

	return m.mranges[sz].Mutate(v)
}

//SnapFrom returns the MutationList that matches the range from the specified period
func (m *MListManager) SnapFrom(e time.Time) (EventIterator, error) {

	for _, tm := range m.stamps {

		if e.UTC().Sub(tm.Min.UTC()) < 0 {
			continue
		}

		iml := m.mranges[tm.Index]

		return InfiniteEventIterator(iml.Root()), nil
	}

	return nil, ErrEventNotFound
}

//SnapRange returns the MutationList that matches the range from the specified period
func (m *MListManager) SnapRange(s, e time.Time) (EventIterator, error) {
	for _, tm := range m.stamps {

		if s.UTC().Sub(tm.Min.UTC()) < 0 {
			continue
		}

		iml := m.mranges[tm.Index]

		return FiniteEventIterator(iml.Root(), e), nil
	}

	return nil, ErrEventNotFound
}

//All returns an iterator for all immutables or an error
func (m *MListManager) All() (EventIterator, error) {
	if len(m.mranges) <= 0 {
		return nil, ErrEndIndex
	}
	return InfiniteEventIterator((m.mranges[0]).Root()), nil
}

//Last return the last Immutable
func (m *MListManager) Last() (Immutable, error) {
	sz := len(m.mranges)

	if sz <= 0 {
		return nil, ErrEndIndex
	}

	lm := m.mranges[sz-1]
	return lm.Tail(), nil
}
<commit_msg>file restructure<commit_after><|endoftext|>


<commit_before>// Copyright 2017 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package feed // import "miniflux.app/reader/feed"

import (
	"fmt"
	"time"

	"miniflux.app/errors"
	"miniflux.app/http/client"
	"miniflux.app/locale"
	"miniflux.app/logger"
	"miniflux.app/model"
	"miniflux.app/reader/browser"
	"miniflux.app/reader/filter"
	"miniflux.app/reader/icon"
	"miniflux.app/reader/parser"
	"miniflux.app/storage"
	"miniflux.app/timer"
)

var (
	errDuplicate        = "This feed already exists (%s)"
	errNotFound         = "Feed %d not found"
	errCategoryNotFound = "Category not found for this user"
)

// Handler contains all the logic to create and refresh feeds.
type Handler struct {
	store      *storage.Storage
}

// CreateFeed fetch, parse and store a new feed.
func (h *Handler) CreateFeed(userID, categoryID int64, url string, crawler bool, userAgent, username, password string) (*model.Feed, error) {
	defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[Handler:CreateFeed] feedUrl=%s", url))

	if !h.store.CategoryExists(userID, categoryID) {
		return nil, errors.NewLocalizedError(errCategoryNotFound)
	}

	request := client.New(url)
	request.WithCredentials(username, password)
	request.WithUserAgent(userAgent)
	response, requestErr := browser.Exec(request)
	if requestErr != nil {
		return nil, requestErr
	}

	if h.store.FeedURLExists(userID, response.EffectiveURL) {
		return nil, errors.NewLocalizedError(errDuplicate, response.EffectiveURL)
	}

	subscription, parseErr := parser.ParseFeed(response.String())
	if parseErr != nil {
		return nil, parseErr
	}

	subscription.UserID = userID
	subscription.WithCategoryID(categoryID)
	subscription.WithBrowsingParameters(crawler, userAgent, username, password)
	subscription.WithClientResponse(response)
	subscription.CheckedNow()

	filter.Apply(h.store, subscription)

	if storeErr := h.store.CreateFeed(subscription); storeErr != nil {
		return nil, storeErr
	}

	logger.Debug("[Handler:CreateFeed] Feed saved with ID: %d", subscription.ID)

	checkFeedIcon(h.store, subscription.ID, subscription.SiteURL)
	return subscription, nil
}

// RefreshFeed fetch and update a feed if necessary.
func (h *Handler) RefreshFeed(userID, feedID int64) error {
	defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[Handler:RefreshFeed] feedID=%d", feedID))
	userLanguage := h.store.UserLanguage(userID)
	printer := locale.NewPrinter(userLanguage)

	originalFeed, storeErr := h.store.FeedByID(userID, feedID)
	if storeErr != nil {
		return storeErr
	}

	if originalFeed == nil {
		return errors.NewLocalizedError(errNotFound, feedID)
	}

	originalFeed.CheckedNow()

	request := client.New(originalFeed.FeedURL)
	request.WithCredentials(originalFeed.Username, originalFeed.Password)
	request.WithCacheHeaders(originalFeed.EtagHeader, originalFeed.LastModifiedHeader)
	request.WithUserAgent(originalFeed.UserAgent)
	response, requestErr := browser.Exec(request)
	if requestErr != nil {
		originalFeed.WithError(requestErr.Localize(printer))
		h.store.UpdateFeed(originalFeed)
		return requestErr
	}

	if response.IsModified(originalFeed.EtagHeader, originalFeed.LastModifiedHeader) {
		logger.Debug("[Handler:RefreshFeed] Feed #%d has been modified", feedID)

		updatedFeed, parseErr := parser.ParseFeed(response.String())
		if parseErr != nil {
			originalFeed.WithError(parseErr.Localize(printer))
			h.store.UpdateFeed(originalFeed)
			return parseErr
		}

		originalFeed.Entries = updatedFeed.Entries
		filter.Apply(h.store, originalFeed)

		// We don't update existing entries when the crawler is enabled (we crawl only inexisting entries).
		if storeErr := h.store.UpdateEntries(originalFeed.UserID, originalFeed.ID, originalFeed.Entries, !originalFeed.Crawler); storeErr != nil {
			return storeErr
		}

		// We update caching headers only if the feed has been modified,
		// because some websites don't return the same headers when replying with a 304.
		originalFeed.WithClientResponse(response)
		checkFeedIcon(h.store, originalFeed.ID, originalFeed.SiteURL)
	} else {
		logger.Debug("[Handler:RefreshFeed] Feed #%d not modified", feedID)
	}

	originalFeed.ResetErrorCounter()
	return h.store.UpdateFeed(originalFeed)
}

// NewFeedHandler returns a feed handler.
func NewFeedHandler(store *storage.Storage) *Handler {
	return &Handler{store}
}

func checkFeedIcon(store *storage.Storage, feedID int64, websiteURL string) {
	if !store.HasIcon(feedID) {
		icon, err := icon.FindIcon(websiteURL)
		if err != nil {
			logger.Error("CheckFeedIcon: %v (feedID=%d websiteURL=%s)", err, feedID, websiteURL)
		} else if icon == nil {
			logger.Debug("CheckFeedIcon: No icon found (feedID=%d websiteURL=%s)", feedID, websiteURL)
		} else {
			if err := store.CreateFeedIcon(feedID, icon); err != nil {
				logger.Error("CheckFeedIcon: %v (feedID=%d websiteURL=%s)", err, feedID, websiteURL)
			}
		}
	}
}<commit_msg>Add entries storage error to feed errors count<commit_after>// Copyright 2017 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package feed // import "miniflux.app/reader/feed"

import (
	"fmt"
	"time"

	"miniflux.app/errors"
	"miniflux.app/http/client"
	"miniflux.app/locale"
	"miniflux.app/logger"
	"miniflux.app/model"
	"miniflux.app/reader/browser"
	"miniflux.app/reader/filter"
	"miniflux.app/reader/icon"
	"miniflux.app/reader/parser"
	"miniflux.app/storage"
	"miniflux.app/timer"
)

var (
	errDuplicate        = "This feed already exists (%s)"
	errNotFound         = "Feed %d not found"
	errCategoryNotFound = "Category not found for this user"
)

// Handler contains all the logic to create and refresh feeds.
type Handler struct {
	store      *storage.Storage
}

// CreateFeed fetch, parse and store a new feed.
func (h *Handler) CreateFeed(userID, categoryID int64, url string, crawler bool, userAgent, username, password string) (*model.Feed, error) {
	defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[Handler:CreateFeed] feedUrl=%s", url))

	if !h.store.CategoryExists(userID, categoryID) {
		return nil, errors.NewLocalizedError(errCategoryNotFound)
	}

	request := client.New(url)
	request.WithCredentials(username, password)
	request.WithUserAgent(userAgent)
	response, requestErr := browser.Exec(request)
	if requestErr != nil {
		return nil, requestErr
	}

	if h.store.FeedURLExists(userID, response.EffectiveURL) {
		return nil, errors.NewLocalizedError(errDuplicate, response.EffectiveURL)
	}

	subscription, parseErr := parser.ParseFeed(response.String())
	if parseErr != nil {
		return nil, parseErr
	}

	subscription.UserID = userID
	subscription.WithCategoryID(categoryID)
	subscription.WithBrowsingParameters(crawler, userAgent, username, password)
	subscription.WithClientResponse(response)
	subscription.CheckedNow()

	filter.Apply(h.store, subscription)

	if storeErr := h.store.CreateFeed(subscription); storeErr != nil {
		return nil, storeErr
	}

	logger.Debug("[Handler:CreateFeed] Feed saved with ID: %d", subscription.ID)

	checkFeedIcon(h.store, subscription.ID, subscription.SiteURL)
	return subscription, nil
}

// RefreshFeed fetch and update a feed if necessary.
func (h *Handler) RefreshFeed(userID, feedID int64) error {
	defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[Handler:RefreshFeed] feedID=%d", feedID))
	userLanguage := h.store.UserLanguage(userID)
	printer := locale.NewPrinter(userLanguage)

	originalFeed, storeErr := h.store.FeedByID(userID, feedID)
	if storeErr != nil {
		return storeErr
	}

	if originalFeed == nil {
		return errors.NewLocalizedError(errNotFound, feedID)
	}

	originalFeed.CheckedNow()

	request := client.New(originalFeed.FeedURL)
	request.WithCredentials(originalFeed.Username, originalFeed.Password)
	request.WithCacheHeaders(originalFeed.EtagHeader, originalFeed.LastModifiedHeader)
	request.WithUserAgent(originalFeed.UserAgent)
	response, requestErr := browser.Exec(request)
	if requestErr != nil {
		originalFeed.WithError(requestErr.Localize(printer))
		h.store.UpdateFeed(originalFeed)
		return requestErr
	}

	if response.IsModified(originalFeed.EtagHeader, originalFeed.LastModifiedHeader) {
		logger.Debug("[Handler:RefreshFeed] Feed #%d has been modified", feedID)

		updatedFeed, parseErr := parser.ParseFeed(response.String())
		if parseErr != nil {
			originalFeed.WithError(parseErr.Localize(printer))
			h.store.UpdateFeed(originalFeed)
			return parseErr
		}

		originalFeed.Entries = updatedFeed.Entries
		filter.Apply(h.store, originalFeed)

		// We don't update existing entries when the crawler is enabled (we crawl only inexisting entries).
		if storeErr := h.store.UpdateEntries(originalFeed.UserID, originalFeed.ID, originalFeed.Entries, !originalFeed.Crawler); storeErr != nil {
			originalFeed.WithError(storeErr.Error())
			h.store.UpdateFeed(originalFeed)
			return storeErr
		}

		// We update caching headers only if the feed has been modified,
		// because some websites don't return the same headers when replying with a 304.
		originalFeed.WithClientResponse(response)
		checkFeedIcon(h.store, originalFeed.ID, originalFeed.SiteURL)
	} else {
		logger.Debug("[Handler:RefreshFeed] Feed #%d not modified", feedID)
	}

	originalFeed.ResetErrorCounter()
	return h.store.UpdateFeed(originalFeed)
}

// NewFeedHandler returns a feed handler.
func NewFeedHandler(store *storage.Storage) *Handler {
	return &Handler{store}
}

func checkFeedIcon(store *storage.Storage, feedID int64, websiteURL string) {
	if !store.HasIcon(feedID) {
		icon, err := icon.FindIcon(websiteURL)
		if err != nil {
			logger.Error("CheckFeedIcon: %v (feedID=%d websiteURL=%s)", err, feedID, websiteURL)
		} else if icon == nil {
			logger.Debug("CheckFeedIcon: No icon found (feedID=%d websiteURL=%s)", feedID, websiteURL)
		} else {
			if err := store.CreateFeedIcon(feedID, icon); err != nil {
				logger.Error("CheckFeedIcon: %v (feedID=%d websiteURL=%s)", err, feedID, websiteURL)
			}
		}
	}
}<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"testing"

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

func TestMaxColLen(t *testing.T) {
	in := [][]string{
		{"123", "sdfgerwgeg", "sdf43terge", "sad", "tzutzutz"},
		{"hfghfgh", "3", "fghehjthjgfhjezthg", "sad", "tzutzutzttttttttttt"},
		{"545", "4554", "hgfhfg", "sad", "ghjtzj65hgfh"},
		{"fghfghfg", "fghfg", "tuzutzutzt", "hgjez565ztd", "tzutzutz"},
	}
	ex := []int{8, 10, 18, 11, 19}
	ac, err := maxColLen(in)
	assert.Nil(t, err)
	assert.Equal(t, ex, ac, "Result ist wrong")
}

func BenchmarkMaxColLen(b *testing.B) {
	a := [][]string{
		{"123", "sdfgerwgeg", "sdf43terge", "sad", "tzutzutz"},
		{"hfghfgh", "3", "fghehjthjgfhjezthg", "sad", "tzutzutzttttttttttt"},
		{"545", "4554", "hgfhfg", "sad", "ghjtzj65hgfh"},
		{"fghfghfg", "fghfg", "tuzutzutzt", "hgjez565ztd", "tzutzutz"},
	}
	for n := 0; n < b.N; n++ {
		maxColLen(a)
	}
}

func BenchmarkBuildMarkdown(b *testing.B) {
	table := [][]string{{"colA1", "colA2", "colA3", "colA4", "colA5"}, {"colB1", "colB2", "colB3", "colB4", "colB5"}, {"colC1", "colC2", "colC3", "colC4", "colC5"}}
	var buf bytes.Buffer
	for n := 0; n < b.N; n++ {
		buildMarkdown(&buf, table, false)
	}
}
<commit_msg>Full path<commit_after>package main

import (
	"bytes"
	"testing"

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

func TestMaxColLen(t *testing.T) {
	in := [][]string{
		{"123", "sdfgerwgeg", "sdf43terge", "sad", "tzutzutz"},
		{"hfghfgh", "3", "fghehjthjgfhjezthg", "sad", "tzutzutzttttttttttt"},
		{"545", "4554", "hgfhfg", "sad", "ghjtzj65hgfh"},
		{"fghfghfg", "fghfg", "tuzutzutzt", "hgjez565ztd", "tzutzutz"},
	}
	ex := []int{8, 10, 18, 11, 19}
	ac, err := maxColLen(in)
	assert.Nil(t, err)
	assert.Equal(t, ex, ac, "Result ist wrong")
	// test empty
	ac, err = maxColLen([][]string{})
	assert.Nil(t, ac)
	assert.Error(t, err)
}

func BenchmarkMaxColLen(b *testing.B) {
	a := [][]string{
		{"123", "sdfgerwgeg", "sdf43terge", "sad", "tzutzutz"},
		{"hfghfgh", "3", "fghehjthjgfhjezthg", "sad", "tzutzutzttttttttttt"},
		{"545", "4554", "hgfhfg", "sad", "ghjtzj65hgfh"},
		{"fghfghfg", "fghfg", "tuzutzutzt", "hgjez565ztd", "tzutzutz"},
	}
	for n := 0; n < b.N; n++ {
		maxColLen(a)
	}
}

func BenchmarkBuildMarkdown(b *testing.B) {
	table := [][]string{{"colA1", "colA2", "colA3", "colA4", "colA5"}, {"colB1", "colB2", "colB3", "colB4", "colB5"}, {"colC1", "colC2", "colC3", "colC4", "colC5"}}
	var buf bytes.Buffer
	for n := 0; n < b.N; n++ {
		buildMarkdown(&buf, table, false)
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 repr_test

import (
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
	"time"
)

func TestRoundtripTest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func makeLegalEntry() *fs.DirectoryEntry {
	entry := new(fs.DirectoryEntry)
	entry.Type = fs.TypeDirectory
	return entry
}

type RoundtripTest struct {
}

func init() { RegisterTestSuite(&RoundtripTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *RoundtripTest) NoEntries() {
	// Input
	in := []*fs.DirectoryEntry{}

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	ExpectThat(out, ElementsAre())
}

func (t *RoundtripTest) UnknownType() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[1].Type = 17

	// Marshal
	_, err := repr.Marshal(in)

	ExpectThat(err, Error(HasSubstr("EntryType")))
	ExpectThat(err, Error(HasSubstr("17")))
}

func (t *RoundtripTest) PreservesTypes() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Type = fs.TypeFile
	in[1].Type = fs.TypeDirectory
	in[2].Type = fs.TypeSymlink

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any(), Any()))

	ExpectEq(in[0].Type, out[0].Type)
	ExpectEq(in[1].Type, out[1].Type)
	ExpectEq(in[2].Type, out[2].Type)
}

func (t *RoundtripTest) PreservesNames() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Name = "taco"
	in[1].Name = "burrito"

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectEq(in[0].Name, out[0].Name)
	ExpectEq(in[1].Name, out[1].Name)
}

func (t *RoundtripTest) PreservesPermissions() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Permissions = 0644
	in[1].Permissions = 0755

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectEq(in[0].Permissions, out[0].Permissions)
	ExpectEq(in[1].Permissions, out[1].Permissions)
}

func (t *RoundtripTest) PreservesModTimes() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].MTime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	in[1].MTime = time.Date(1985, time.March, 18, 15, 33, 0, 0, time.UTC)

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectTrue(in[0].MTime.Equal(out[0].MTime), "%v", out[0].MTime)
	ExpectTrue(in[1].MTime.Equal(out[1].MTime), "%v", out[1].MTime)
}

func (t *RoundtripTest) PreservesScores() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	score00 := blob.ComputeScore([]byte("taco"))
	score01 := blob.ComputeScore([]byte("burrito"))
	score10 := blob.ComputeScore([]byte("enchilada"))

	in[0].Scores = []blob.Score{score00, score01}
	in[1].Scores = []blob.Score{score10}

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	AssertThat(out[0].Scores, ElementsAre(Any(), Any()))
	ExpectThat(out[0].Scores[0].Sha1Hash(), DeepEquals(score00.Sha1Hash()))
	ExpectThat(out[0].Scores[1].Sha1Hash(), DeepEquals(score01.Sha1Hash()))

	AssertThat(out[1].Scores, ElementsAre(Any()))
	ExpectThat(out[1].Scores[0].Sha1Hash(), DeepEquals(score10.Sha1Hash()))
}
<commit_msg>Updated round-trip test.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 repr_test

import (
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
	"time"
)

func TestRoundtripTest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func makeLegalEntry() *fs.DirectoryEntry {
	entry := new(fs.DirectoryEntry)
	entry.Type = fs.TypeDirectory
	return entry
}

type RoundtripTest struct {
}

func init() { RegisterTestSuite(&RoundtripTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *RoundtripTest) NoEntries() {
	// Input
	in := []*fs.DirectoryEntry{}

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	ExpectThat(out, ElementsAre())
}

func (t *RoundtripTest) UnknownType() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[1].Type = 17

	// Marshal
	_, err := repr.Marshal(in)

	ExpectThat(err, Error(HasSubstr("EntryType")))
	ExpectThat(err, Error(HasSubstr("17")))
}

func (t *RoundtripTest) PreservesTypes() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Type = fs.TypeFile
	in[1].Type = fs.TypeDirectory
	in[2].Type = fs.TypeSymlink

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any(), Any()))

	ExpectEq(in[0].Type, out[0].Type)
	ExpectEq(in[1].Type, out[1].Type)
	ExpectEq(in[2].Type, out[2].Type)
}

func (t *RoundtripTest) PreservesNames() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Name = "taco"
	in[1].Name = "burrito"

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectEq(in[0].Name, out[0].Name)
	ExpectEq(in[1].Name, out[1].Name)
}

func (t *RoundtripTest) PreservesPermissions() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Permissions = 0644|os.ModeSticky|os.ModeSetuid
	in[1].Permissions = 0755|os.ModeSetgid

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectEq(in[0].Permissions, out[0].Permissions)
	ExpectEq(in[1].Permissions, out[1].Permissions)
}

func (t *RoundtripTest) PreservesModTimes() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].MTime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	in[1].MTime = time.Date(1985, time.March, 18, 15, 33, 0, 0, time.UTC)

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectTrue(in[0].MTime.Equal(out[0].MTime), "%v", out[0].MTime)
	ExpectTrue(in[1].MTime.Equal(out[1].MTime), "%v", out[1].MTime)
}

func (t *RoundtripTest) PreservesScores() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	score00 := blob.ComputeScore([]byte("taco"))
	score01 := blob.ComputeScore([]byte("burrito"))
	score10 := blob.ComputeScore([]byte("enchilada"))

	in[0].Scores = []blob.Score{score00, score01}
	in[1].Scores = []blob.Score{score10}

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	AssertThat(out[0].Scores, ElementsAre(Any(), Any()))
	ExpectThat(out[0].Scores[0].Sha1Hash(), DeepEquals(score00.Sha1Hash()))
	ExpectThat(out[0].Scores[1].Sha1Hash(), DeepEquals(score01.Sha1Hash()))

	AssertThat(out[1].Scores, ElementsAre(Any()))
	ExpectThat(out[1].Scores[0].Sha1Hash(), DeepEquals(score10.Sha1Hash()))
}

func (t *RoundtripTest) PreservesTargets() {
	// Input
	in := []*fs.DirectoryEntry{
		makeLegalEntry(),
		makeLegalEntry(),
	}

	in[0].Target = "taco"
	in[1].Target = "burrito"

	// Marshal
	d, err := repr.Marshal(in)
	AssertEq(nil, err)
	AssertNe(nil, d)

	// Unmarshal
	out, err := repr.Unmarshal(d)
	AssertEq(nil, err)
	AssertNe(nil, out)

	// Output
	AssertThat(out, ElementsAre(Any(), Any()))

	ExpectEq(in[0].Target, out[0].Target)
	ExpectEq(in[1].Target, out[1].Target)
}
<|endoftext|>