<commit_before>package plugins

import (
    "github.com/sn0w/discordgo"
    "git.lukas.moe/sn0w/Karen/helpers"
    "strings"
    "fmt"
    "regexp"
)

type Osu struct{}

func (o Osu) Commands() []string {
    return []string{
        "osu",
        "osu!mania",
        "osu!k",
        "osu!ctb",
        "osu!taiko",
    }
}

func (o Osu) Init(session *discordgo.Session) {

}

func (o Osu) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
    session.ChannelTyping(msg.ChannelID)

    user := strings.TrimSpace(content)

    var mode string
    switch command {
    case "osu":
        mode = "0"
        break

    case "osu!taiko":
        mode = "1"
        break

    case "osu!ctb":
        mode = "2"
        break

    case "osu!mania", "osu!k":
        mode = "3"
        break
    }

    jsonc, err := helpers.GetJSON(
        fmt.Sprintf(
            "https://osu.ppy.sh/api/get_user?k=%s&u=%s&type=u&m=%s",
            helpers.GetConfig().Path("osu").Data().(string),
            user,
            mode,
        ),
    ).Children()
    helpers.Relax(err)

    if len(jsonc) == 0 {
        session.ChannelMessageSend(msg.ChannelID, "User not found :frowning:")
        return
    }

    json := jsonc[0]
    html := string(helpers.NetGet("https://osu.ppy.sh/u/" + user))
    avatar := regexp.MustCompile(
        `"//a\.ppy\.sh/` + json.Path("user_id").Data().(string) + `_\d+\.\w{2,5}"`,
    ).FindString(html)

    if avatar == "" {
        avatar = "http://i.imgur.com/Ea1qmJX.png"
    } else {
        avatar = "https:" + avatar
    }

    avatar = strings.Replace(avatar, `"`, "", -1)

    if (!json.ExistsP("level")) || json.Path("level").Data() == nil {
        session.ChannelMessageSend(msg.ChannelID, "Seems like " + user + " didn't play this mode yet :thinking:")
        return
    }

    _, err = session.ChannelMessageSendEmbed(msg.ChannelID, &discordgo.MessageEmbed{
        Color: 0xEF77AF,
        Description: "Showing stats for " + user,
        Thumbnail: &discordgo.MessageEmbedThumbnail{
            URL: avatar,
        },
        Fields: []*discordgo.MessageEmbedField{
            {Name: "Name", Value: json.Path("username").Data().(string), Inline: true},
            {Name: "Country", Value: json.Path("country").Data().(string), Inline: true},
            {Name: "Level", Value: json.Path("level").Data().(string), Inline: true},
            {Name: "Playcount", Value: json.Path("playcount").Data().(string), Inline: true},
            {Name: "Accuracy", Value: json.Path("accuracy").Data().(string) + "%", Inline: true},
            {Name: "Rank (Country)", Value: json.Path("pp_country_rank").Data().(string) + "th", Inline: true},
            {Name: "Rank (Global)", Value: json.Path("pp_rank").Data().(string) + "th", Inline: true},
        },
        Footer: &discordgo.MessageEmbedFooter{
            Text:  "ppy powered :3",
        },
    })
}
<commit_msg>Remove unused assignment in osu.go<commit_after>package plugins

import (
    "github.com/sn0w/discordgo"
    "git.lukas.moe/sn0w/Karen/helpers"
    "strings"
    "fmt"
    "regexp"
)

type Osu struct{}

func (o Osu) Commands() []string {
    return []string{
        "osu",
        "osu!mania",
        "osu!k",
        "osu!ctb",
        "osu!taiko",
    }
}

func (o Osu) Init(session *discordgo.Session) {

}

func (o Osu) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
    session.ChannelTyping(msg.ChannelID)

    user := strings.TrimSpace(content)

    var mode string
    switch command {
    case "osu":
        mode = "0"
        break

    case "osu!taiko":
        mode = "1"
        break

    case "osu!ctb":
        mode = "2"
        break

    case "osu!mania", "osu!k":
        mode = "3"
        break
    }

    jsonc, err := helpers.GetJSON(
        fmt.Sprintf(
            "https://osu.ppy.sh/api/get_user?k=%s&u=%s&type=u&m=%s",
            helpers.GetConfig().Path("osu").Data().(string),
            user,
            mode,
        ),
    ).Children()
    helpers.Relax(err)

    if len(jsonc) == 0 {
        session.ChannelMessageSend(msg.ChannelID, "User not found :frowning:")
        return
    }

    json := jsonc[0]
    html := string(helpers.NetGet("https://osu.ppy.sh/u/" + user))
    avatar := regexp.MustCompile(
        `"//a\.ppy\.sh/` + json.Path("user_id").Data().(string) + `_\d+\.\w{2,5}"`,
    ).FindString(html)

    if avatar == "" {
        avatar = "http://i.imgur.com/Ea1qmJX.png"
    } else {
        avatar = "https:" + avatar
    }

    avatar = strings.Replace(avatar, `"`, "", -1)

    if (!json.ExistsP("level")) || json.Path("level").Data() == nil {
        session.ChannelMessageSend(msg.ChannelID, "Seems like " + user + " didn't play this mode yet :thinking:")
        return
    }

    session.ChannelMessageSendEmbed(msg.ChannelID, &discordgo.MessageEmbed{
        Color: 0xEF77AF,
        Description: "Showing stats for " + user,
        Thumbnail: &discordgo.MessageEmbedThumbnail{
            URL: avatar,
        },
        Fields: []*discordgo.MessageEmbedField{
            {Name: "Name", Value: json.Path("username").Data().(string), Inline: true},
            {Name: "Country", Value: json.Path("country").Data().(string), Inline: true},
            {Name: "Level", Value: json.Path("level").Data().(string), Inline: true},
            {Name: "Playcount", Value: json.Path("playcount").Data().(string), Inline: true},
            {Name: "Accuracy", Value: json.Path("accuracy").Data().(string) + "%", Inline: true},
            {Name: "Rank (Country)", Value: json.Path("pp_country_rank").Data().(string) + "th", Inline: true},
            {Name: "Rank (Global)", Value: json.Path("pp_rank").Data().(string) + "th", Inline: true},
        },
        Footer: &discordgo.MessageEmbedFooter{
            Text:  "ppy powered :3",
        },
    })
}
<|endoftext|>


<commit_before>package sudoku

import (
	"sort"
	"testing"
)

func TestBasicCellList(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(SOLVED_TEST_GRID)
	row := CellList(grid.Row(2))
	if !row.SameRow() {
		t.Log("The items of a row were not all of the same row.")
		t.Fail()
	}

	if row.SameCol() {
		t.Log("For some reason we thought all the cells in a row were in the same col")
		t.Fail()
	}

	var refs []cellRef

	for i := 0; i < DIM; i++ {
		refs = append(refs, cellRef{2, i})
	}

	if !row.sameAsRefs(refs) {
		t.Error("sameAsRefs didn't match values for row 2")
	}

	col := CellList(grid.Col(2))
	if !col.SameCol() {
		t.Log("The items in the col were not int he same col.")
		t.Fail()
	}

	if col.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	block := CellList(grid.Block(2))
	if !block.SameBlock() {
		t.Log("The items in the block were not int he same block.")
		t.Fail()
	}

	if block.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	if block.SameCol() {
		t.Log("For some reason we thought all the cells in a block were in the same col")
		t.Fail()
	}

	nums := row.CollectNums(func(cell *Cell) int {
		return cell.Row
	})

	if !nums.Same() {
		t.Log("Collecting rows gave us different numbers/.")
		t.Fail()
	}

	isZeroRow := func(cell *Cell) bool {
		return cell.Row == 0
	}

	cells := grid.Block(0).Filter(isZeroRow)

	if len(cells) != BLOCK_DIM {
		t.Log("We got back the wrong number of cells when filtering")
		t.Fail()
	}

	if !cells.SameRow() {
		t.Log("We got back cells not inthe same row.")
		t.Fail()
	}

	description := cells.Description()

	if description != "(0,0), (0,1), and (0,2)" {
		t.Log("Got wrong description of cellList: ", description)
		t.Fail()
	}

	unsortedList := CellList{grid.Cell(0, 1), grid.Cell(1, 2), grid.Cell(0, 0)}
	unsortedList.Sort()
	if unsortedList[0].Row != 0 || unsortedList[0].Col != 0 ||
		unsortedList[1].Row != 0 || unsortedList[1].Col != 1 ||
		unsortedList[2].Row != 1 || unsortedList[2].Col != 2 {
		t.Error("Cell List didn't get sorted: ", unsortedList)
	}

}

type chainTestConfiguration struct {
	name                 string
	one                  []cellRef
	two                  []cellRef
	equivalentToPrevious bool
}

type chainTestResult struct {
	name             string
	value            float64
	equivalenceGroup int
}

type chainTestResults []chainTestResult

func (self chainTestResults) Len() int {
	return len(self)
}

func (self chainTestResults) Less(i, j int) bool {
	return self[i].value < self[j].value
}

func (self chainTestResults) Swap(i, j int) {
	self[i], self[j] = self[j], self[i]
}

func TestChainDissimilarity(t *testing.T) {

	//The first bit is where we configure the tests.
	//We should add cases here in the order of similar to dissimilar. The test will then verify
	//they come out in that order.

	tests := []chainTestConfiguration{
		{
			"same row same block",
			[]cellRef{{0, 0}},
			[]cellRef{{0, 1}},
			false,
		},
		//this next one verifies that it doesn't matter which of self or other you do first.
		{
			"same row same block, just flipped self and other",
			[]cellRef{{0, 1}},
			[]cellRef{{0, 0}},
			true,
		},
		//These next two should be the same difficulty.
		{
			"same block 2 in same row 2 in same col 2 total",
			[]cellRef{{0, 0}},
			[]cellRef{{0, 1}, {1, 0}},
			false,
		},
		{
			"two full rows at opposite ends",
			[]cellRef{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}},
			[]cellRef{{7, 0}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}, {7, 7}, {7, 8}},
			true,
		},
		{
			"same row different blocks",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}},
			true,
		},
		{
			"same col different blocks",
			[]cellRef{{0, 0}, {1, 0}},
			[]cellRef{{3, 0}, {4, 0}},
			true,
		},
		{
			"same row different blocks, 2 vs 3",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}, {0, 5}},
			true,
		},
		{
			"single cell opposite corners",
			[]cellRef{{0, 0}},
			[]cellRef{{8, 8}},
			false,
		},
	}

	//Now run the tests

	grid := NewGrid()

	var results chainTestResults

	equivalenceGroup := -1

	for _, test := range tests {
		if !test.equivalentToPrevious {
			equivalenceGroup++
		}
		var listOne CellList
		var listTwo CellList
		for _, ref := range test.one {
			listOne = append(listOne, ref.Cell(grid))
		}
		for _, ref := range test.two {
			listTwo = append(listTwo, ref.Cell(grid))
		}
		dissimilarity := listOne.ChainDissimilarity(listTwo)
		if dissimilarity < 0.0 {
			t.Fatal(test.name, "failed with a dissimilarity less than 0.0: ", dissimilarity)
		}
		if dissimilarity > 1.0 {
			t.Fatal(test.name, "failed with a dissimilarity great than 1.0:", dissimilarity)
		}
		result := chainTestResult{test.name, dissimilarity, equivalenceGroup}
		results = append(results, result)
	}

	//sort them and see if their originalIndexes are now now in order.
	sort.Sort(results)

	lastEquivalenceGroup := 0
	for _, result := range results {
		if result.equivalenceGroup < lastEquivalenceGroup {
			t.Error(result.name, "was in equivalence group", result.equivalenceGroup, " but it was smaller than last group seen:", equivalenceGroup, ". Value:", result.value)
		}
		lastEquivalenceGroup = result.equivalenceGroup
	}

}

func TestFilledNums(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	if !grid.LoadFromFile(puzzlePath("nakedpairblock1.sdk")) {
		t.Fatal("Couldn't load file")
	}

	filledNums := grid.Row(0).FilledNums()

	if !filledNums.SameContentAs(IntSlice{3, 7, 8, 9}) {
		t.Error("Filled nums had wrong nums", filledNums)
	}

}

func TestIntList(t *testing.T) {
	numArr := [...]int{1, 1, 1}
	if !IntSlice(numArr[:]).Same() {
		t.Log("We didn't think that a num list with all of the same ints was the same.")
		t.Fail()
	}
	differentNumArr := [...]int{1, 2, 1}
	if IntSlice(differentNumArr[:]).Same() {
		t.Log("We thought a list of different ints were the same")
		t.Fail()
	}
	description := IntSlice(numArr[:]).Description()
	if description != "1, 1, and 1" {
		t.Log("Didn't get right description: ", description)
		t.Fail()
	}

	unsortedList := IntSlice{3, 2, 1}
	unsortedList.Sort()
	if !unsortedList.SameAs(IntSlice{1, 2, 3}) {
		t.Error("IntSlice.Sort did not sort the list.")
	}

	oneList := IntSlice{1}

	description = oneList.Description()

	if description != "1" {
		t.Log("Didn't get the right description for a short intlist: ", description)
		t.Fail()
	}

	twoList := IntSlice{1, 1}

	description = twoList.Description()

	if description != "1 and 1" {
		t.Log("Did'get the the right description for a two-item intList: ", description)
		t.Fail()
	}
}

func TestInverseSubset(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	cells := grid.Row(0)

	indexes := IntSlice([]int{4, 6, 2})

	subset := cells.InverseSubset(indexes)

	if len(subset) != DIM-3 {
		t.Error("Inverse subset gave wrong number of results")
	}

	for _, cell := range subset {
		if cell.Col == 2 || cell.Col == 4 || cell.Col == 6 {
			t.Error("Inverse subset included cells it shouldn't have.")
		}
	}

}

func TestIntSliceIntersection(t *testing.T) {
	one := IntSlice([]int{1, 3, 2, 5})
	two := IntSlice([]int{2, 7, 6, 5})

	result := one.Intersection(two)

	if len(result) != 2 {
		t.Error("Intersection had wrong number of items")
	}

	sort.Ints(result)

	if result[0] != 2 || result[1] != 5 {
		t.Error("Intersection result was wrong.")
	}
}

func TestIntSliceDifference(t *testing.T) {
	one := IntSlice([]int{1, 2, 3, 4, 5, 6})
	two := IntSlice([]int{3, 4, 7})

	result := one.Difference(two)

	if !result.SameContentAs(IntSlice([]int{1, 2, 5, 6})) {
		t.Error("Int slice difference gave wrong result: ", result)
	}
}

func TestSameContentAs(t *testing.T) {
	one := IntSlice([]int{2, 3, 1})
	two := IntSlice([]int{2, 1, 3})

	if !one.SameContentAs(two) {
		t.Log("Didn't think two equivalent slices were the same.")
		t.Fail()
	}

	if !one.SameAs([]int{2, 3, 1}) {
		t.Log("We mutated one")
		t.Fail()
	}

	if !two.SameAs([]int{2, 1, 3}) {
		t.Log("We mutated two")
		t.Fail()
	}

	onePair := IntSlice([]int{3, 2})
	twoPair := IntSlice([]int{2, 3})

	if !onePair.SameContentAs(twoPair) {
		t.Log("Didn't think two equivalent pairs were the same.")
		t.Fail()
	}

}
<commit_msg>Another test case for ChainDissimilarity.<commit_after>package sudoku

import (
	"sort"
	"testing"
)

func TestBasicCellList(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(SOLVED_TEST_GRID)
	row := CellList(grid.Row(2))
	if !row.SameRow() {
		t.Log("The items of a row were not all of the same row.")
		t.Fail()
	}

	if row.SameCol() {
		t.Log("For some reason we thought all the cells in a row were in the same col")
		t.Fail()
	}

	var refs []cellRef

	for i := 0; i < DIM; i++ {
		refs = append(refs, cellRef{2, i})
	}

	if !row.sameAsRefs(refs) {
		t.Error("sameAsRefs didn't match values for row 2")
	}

	col := CellList(grid.Col(2))
	if !col.SameCol() {
		t.Log("The items in the col were not int he same col.")
		t.Fail()
	}

	if col.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	block := CellList(grid.Block(2))
	if !block.SameBlock() {
		t.Log("The items in the block were not int he same block.")
		t.Fail()
	}

	if block.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	if block.SameCol() {
		t.Log("For some reason we thought all the cells in a block were in the same col")
		t.Fail()
	}

	nums := row.CollectNums(func(cell *Cell) int {
		return cell.Row
	})

	if !nums.Same() {
		t.Log("Collecting rows gave us different numbers/.")
		t.Fail()
	}

	isZeroRow := func(cell *Cell) bool {
		return cell.Row == 0
	}

	cells := grid.Block(0).Filter(isZeroRow)

	if len(cells) != BLOCK_DIM {
		t.Log("We got back the wrong number of cells when filtering")
		t.Fail()
	}

	if !cells.SameRow() {
		t.Log("We got back cells not inthe same row.")
		t.Fail()
	}

	description := cells.Description()

	if description != "(0,0), (0,1), and (0,2)" {
		t.Log("Got wrong description of cellList: ", description)
		t.Fail()
	}

	unsortedList := CellList{grid.Cell(0, 1), grid.Cell(1, 2), grid.Cell(0, 0)}
	unsortedList.Sort()
	if unsortedList[0].Row != 0 || unsortedList[0].Col != 0 ||
		unsortedList[1].Row != 0 || unsortedList[1].Col != 1 ||
		unsortedList[2].Row != 1 || unsortedList[2].Col != 2 {
		t.Error("Cell List didn't get sorted: ", unsortedList)
	}

}

type chainTestConfiguration struct {
	name                 string
	one                  []cellRef
	two                  []cellRef
	equivalentToPrevious bool
}

type chainTestResult struct {
	name             string
	value            float64
	equivalenceGroup int
}

type chainTestResults []chainTestResult

func (self chainTestResults) Len() int {
	return len(self)
}

func (self chainTestResults) Less(i, j int) bool {
	return self[i].value < self[j].value
}

func (self chainTestResults) Swap(i, j int) {
	self[i], self[j] = self[j], self[i]
}

func TestChainDissimilarity(t *testing.T) {

	//The first bit is where we configure the tests.
	//We should add cases here in the order of similar to dissimilar. The test will then verify
	//they come out in that order.

	//TODO: test more cases

	tests := []chainTestConfiguration{
		{
			"same row same block",
			[]cellRef{{0, 0}},
			[]cellRef{{0, 1}},
			false,
		},
		//this next one verifies that it doesn't matter which of self or other you do first.
		{
			"same row same block, just flipped self and other",
			[]cellRef{{0, 1}},
			[]cellRef{{0, 0}},
			true,
		},
		//These next two should be the same difficulty.
		{
			"same block 2 in same row 2 in same col 2 total",
			[]cellRef{{0, 0}},
			[]cellRef{{0, 1}, {1, 0}},
			false,
		},
		{
			"two full rows at opposite ends",
			[]cellRef{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}},
			[]cellRef{{7, 0}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}, {7, 7}, {7, 8}},
			true,
		},
		{
			"same row different blocks",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}},
			true,
		},
		{
			"same col different blocks",
			[]cellRef{{0, 0}, {1, 0}},
			[]cellRef{{3, 0}, {4, 0}},
			true,
		},
		{
			"same row different blocks, 2 vs 3",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}, {0, 5}},
			true,
		},
		{
			"same block opposite corners 1 x 1",
			[]cellRef{{0, 0}},
			[]cellRef{{2, 2}},
			true,
		},
		{
			"single cell opposite corners",
			[]cellRef{{0, 0}},
			[]cellRef{{8, 8}},
			false,
		},
	}

	//Now run the tests

	grid := NewGrid()

	var results chainTestResults

	equivalenceGroup := -1

	for _, test := range tests {
		if !test.equivalentToPrevious {
			equivalenceGroup++
		}
		var listOne CellList
		var listTwo CellList
		for _, ref := range test.one {
			listOne = append(listOne, ref.Cell(grid))
		}
		for _, ref := range test.two {
			listTwo = append(listTwo, ref.Cell(grid))
		}
		dissimilarity := listOne.ChainDissimilarity(listTwo)
		if dissimilarity < 0.0 {
			t.Fatal(test.name, "failed with a dissimilarity less than 0.0: ", dissimilarity)
		}
		if dissimilarity > 1.0 {
			t.Fatal(test.name, "failed with a dissimilarity great than 1.0:", dissimilarity)
		}
		result := chainTestResult{test.name, dissimilarity, equivalenceGroup}
		results = append(results, result)
	}

	//sort them and see if their originalIndexes are now now in order.
	sort.Sort(results)

	lastEquivalenceGroup := 0
	for _, result := range results {
		if result.equivalenceGroup < lastEquivalenceGroup {
			t.Error(result.name, "was in equivalence group", result.equivalenceGroup, " but it was smaller than last group seen:", equivalenceGroup, ". Value:", result.value)
		}
		lastEquivalenceGroup = result.equivalenceGroup
	}

}

func TestFilledNums(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	if !grid.LoadFromFile(puzzlePath("nakedpairblock1.sdk")) {
		t.Fatal("Couldn't load file")
	}

	filledNums := grid.Row(0).FilledNums()

	if !filledNums.SameContentAs(IntSlice{3, 7, 8, 9}) {
		t.Error("Filled nums had wrong nums", filledNums)
	}

}

func TestIntList(t *testing.T) {
	numArr := [...]int{1, 1, 1}
	if !IntSlice(numArr[:]).Same() {
		t.Log("We didn't think that a num list with all of the same ints was the same.")
		t.Fail()
	}
	differentNumArr := [...]int{1, 2, 1}
	if IntSlice(differentNumArr[:]).Same() {
		t.Log("We thought a list of different ints were the same")
		t.Fail()
	}
	description := IntSlice(numArr[:]).Description()
	if description != "1, 1, and 1" {
		t.Log("Didn't get right description: ", description)
		t.Fail()
	}

	unsortedList := IntSlice{3, 2, 1}
	unsortedList.Sort()
	if !unsortedList.SameAs(IntSlice{1, 2, 3}) {
		t.Error("IntSlice.Sort did not sort the list.")
	}

	oneList := IntSlice{1}

	description = oneList.Description()

	if description != "1" {
		t.Log("Didn't get the right description for a short intlist: ", description)
		t.Fail()
	}

	twoList := IntSlice{1, 1}

	description = twoList.Description()

	if description != "1 and 1" {
		t.Log("Did'get the the right description for a two-item intList: ", description)
		t.Fail()
	}
}

func TestInverseSubset(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	cells := grid.Row(0)

	indexes := IntSlice([]int{4, 6, 2})

	subset := cells.InverseSubset(indexes)

	if len(subset) != DIM-3 {
		t.Error("Inverse subset gave wrong number of results")
	}

	for _, cell := range subset {
		if cell.Col == 2 || cell.Col == 4 || cell.Col == 6 {
			t.Error("Inverse subset included cells it shouldn't have.")
		}
	}

}

func TestIntSliceIntersection(t *testing.T) {
	one := IntSlice([]int{1, 3, 2, 5})
	two := IntSlice([]int{2, 7, 6, 5})

	result := one.Intersection(two)

	if len(result) != 2 {
		t.Error("Intersection had wrong number of items")
	}

	sort.Ints(result)

	if result[0] != 2 || result[1] != 5 {
		t.Error("Intersection result was wrong.")
	}
}

func TestIntSliceDifference(t *testing.T) {
	one := IntSlice([]int{1, 2, 3, 4, 5, 6})
	two := IntSlice([]int{3, 4, 7})

	result := one.Difference(two)

	if !result.SameContentAs(IntSlice([]int{1, 2, 5, 6})) {
		t.Error("Int slice difference gave wrong result: ", result)
	}
}

func TestSameContentAs(t *testing.T) {
	one := IntSlice([]int{2, 3, 1})
	two := IntSlice([]int{2, 1, 3})

	if !one.SameContentAs(two) {
		t.Log("Didn't think two equivalent slices were the same.")
		t.Fail()
	}

	if !one.SameAs([]int{2, 3, 1}) {
		t.Log("We mutated one")
		t.Fail()
	}

	if !two.SameAs([]int{2, 1, 3}) {
		t.Log("We mutated two")
		t.Fail()
	}

	onePair := IntSlice([]int{3, 2})
	twoPair := IntSlice([]int{2, 3})

	if !onePair.SameContentAs(twoPair) {
		t.Log("Didn't think two equivalent pairs were the same.")
		t.Fail()
	}

}
<|endoftext|>


<commit_before>package sudoku

import (
	"github.com/davecgh/go-spew/spew"
	"sort"
	"testing"
)

func TestBasicCellList(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(SOLVED_TEST_GRID)
	row := CellList(grid.Row(2))
	if !row.SameRow() {
		t.Log("The items of a row were not all of the same row.")
		t.Fail()
	}

	if row.SameCol() {
		t.Log("For some reason we thought all the cells in a row were in the same col")
		t.Fail()
	}

	var refs []cellRef

	for i := 0; i < DIM; i++ {
		refs = append(refs, cellRef{2, i})
	}

	if !row.sameAsRefs(refs) {
		t.Error("sameAsRefs didn't match values for row 2")
	}

	col := CellList(grid.Col(2))
	if !col.SameCol() {
		t.Log("The items in the col were not int he same col.")
		t.Fail()
	}

	if col.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	block := CellList(grid.Block(2))
	if !block.SameBlock() {
		t.Log("The items in the block were not int he same block.")
		t.Fail()
	}

	if block.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	if block.SameCol() {
		t.Log("For some reason we thought all the cells in a block were in the same col")
		t.Fail()
	}

	nums := row.CollectNums(func(cell *Cell) int {
		return cell.Row
	})

	if !nums.Same() {
		t.Log("Collecting rows gave us different numbers/.")
		t.Fail()
	}

	isZeroRow := func(cell *Cell) bool {
		return cell.Row == 0
	}

	cells := grid.Block(0).Filter(isZeroRow)

	if len(cells) != BLOCK_DIM {
		t.Log("We got back the wrong number of cells when filtering")
		t.Fail()
	}

	if !cells.SameRow() {
		t.Log("We got back cells not inthe same row.")
		t.Fail()
	}

	description := cells.Description()

	if description != "(0,0), (0,1), and (0,2)" {
		t.Log("Got wrong description of cellList: ", description)
		t.Fail()
	}

	unsortedList := CellList{grid.Cell(0, 1), grid.Cell(1, 2), grid.Cell(0, 0)}
	unsortedList.Sort()
	if unsortedList[0].Row != 0 || unsortedList[0].Col != 0 ||
		unsortedList[1].Row != 0 || unsortedList[1].Col != 1 ||
		unsortedList[2].Row != 1 || unsortedList[2].Col != 2 {
		t.Error("Cell List didn't get sorted: ", unsortedList)
	}

}

type chainTestConfiguration struct {
	name string
	one  []cellRef
	two  []cellRef
}

type chainTestResult struct {
	name          string
	originalIndex int
	value         float64
}

type chainTestResults []chainTestResult

func (self chainTestResults) Len() int {
	return len(self)
}

func (self chainTestResults) Less(i, j int) bool {
	return self[i].value < self[j].value
}

func (self chainTestResults) Swap(i, j int) {
	self[i], self[j] = self[j], self[i]
}

func TestChainDissimilarity(t *testing.T) {

	//The first bit is where we configure the tests.
	//We should add cases here in the order of similar to dissimilar. The test will then verify
	//they come out in that order.

	tests := []chainTestConfiguration{
		{
			"same row same block",
			[]cellRef{{0, 0}},
			[]cellRef{{0, 1}},
		},
		//this next one verifies that it doesn't matter which of self or other you do first.
		{
			"same row same block, just flipped self and other",
			[]cellRef{{0, 1}},
			[]cellRef{{0, 0}},
		},
		//These next two should be the same difficulty.
		//TODO: might need to generalize the test to allow me to say
		//that two can be equivalent.
		{
			"same block 2 in same row 2 in same col 2 total",
			[]cellRef{{0, 0}},
			[]cellRef{{0, 1}, {1, 0}},
		},
		{
			"two full rows at opposite ends",
			[]cellRef{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}},
			[]cellRef{{7, 0}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}, {7, 7}, {7, 8}},
		},
		{
			"same row different blocks",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}},
		},
		{
			"same col different blocks",
			[]cellRef{{0, 0}, {1, 0}},
			[]cellRef{{3, 0}, {4, 0}},
		},
		{
			"same row different blocks, 2 vs 3",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}, {0, 5}},
		},
		{
			"single cell opposite corners",
			[]cellRef{{0, 0}},
			[]cellRef{{8, 8}},
		},
	}

	//Now run the tests

	grid := NewGrid()

	var results chainTestResults

	for i, test := range tests {
		var listOne CellList
		var listTwo CellList
		for _, ref := range test.one {
			listOne = append(listOne, ref.Cell(grid))
		}
		for _, ref := range test.two {
			listTwo = append(listTwo, ref.Cell(grid))
		}
		dissimilarity := listOne.ChainDissimilarity(listTwo)
		if dissimilarity < 0.0 {
			t.Fatal(test.name, "failed with a dissimilarity less than 0.0: ", dissimilarity)
		}
		if dissimilarity > 1.0 {
			t.Fatal(test.name, "failed with a dissimilarity great than 1.0:", dissimilarity)
		}
		result := chainTestResult{test.name, i, dissimilarity}
		results = append(results, result)
	}

	//sort them and see if their originalIndexes are now now in order.
	sort.Sort(results)

	spew.Dump(results)

	for i, result := range results {
		if result.originalIndex != i {
			t.Error(result.name, "was in position", i, " but it was supposed to be in position", result.originalIndex, ". Value:", result.value)
		}
	}

}

func TestFilledNums(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	if !grid.LoadFromFile(puzzlePath("nakedpairblock1.sdk")) {
		t.Fatal("Couldn't load file")
	}

	filledNums := grid.Row(0).FilledNums()

	if !filledNums.SameContentAs(IntSlice{3, 7, 8, 9}) {
		t.Error("Filled nums had wrong nums", filledNums)
	}

}

func TestIntList(t *testing.T) {
	numArr := [...]int{1, 1, 1}
	if !IntSlice(numArr[:]).Same() {
		t.Log("We didn't think that a num list with all of the same ints was the same.")
		t.Fail()
	}
	differentNumArr := [...]int{1, 2, 1}
	if IntSlice(differentNumArr[:]).Same() {
		t.Log("We thought a list of different ints were the same")
		t.Fail()
	}
	description := IntSlice(numArr[:]).Description()
	if description != "1, 1, and 1" {
		t.Log("Didn't get right description: ", description)
		t.Fail()
	}

	unsortedList := IntSlice{3, 2, 1}
	unsortedList.Sort()
	if !unsortedList.SameAs(IntSlice{1, 2, 3}) {
		t.Error("IntSlice.Sort did not sort the list.")
	}

	oneList := IntSlice{1}

	description = oneList.Description()

	if description != "1" {
		t.Log("Didn't get the right description for a short intlist: ", description)
		t.Fail()
	}

	twoList := IntSlice{1, 1}

	description = twoList.Description()

	if description != "1 and 1" {
		t.Log("Did'get the the right description for a two-item intList: ", description)
		t.Fail()
	}
}

func TestInverseSubset(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	cells := grid.Row(0)

	indexes := IntSlice([]int{4, 6, 2})

	subset := cells.InverseSubset(indexes)

	if len(subset) != DIM-3 {
		t.Error("Inverse subset gave wrong number of results")
	}

	for _, cell := range subset {
		if cell.Col == 2 || cell.Col == 4 || cell.Col == 6 {
			t.Error("Inverse subset included cells it shouldn't have.")
		}
	}

}

func TestIntSliceIntersection(t *testing.T) {
	one := IntSlice([]int{1, 3, 2, 5})
	two := IntSlice([]int{2, 7, 6, 5})

	result := one.Intersection(two)

	if len(result) != 2 {
		t.Error("Intersection had wrong number of items")
	}

	sort.Ints(result)

	if result[0] != 2 || result[1] != 5 {
		t.Error("Intersection result was wrong.")
	}
}

func TestIntSliceDifference(t *testing.T) {
	one := IntSlice([]int{1, 2, 3, 4, 5, 6})
	two := IntSlice([]int{3, 4, 7})

	result := one.Difference(two)

	if !result.SameContentAs(IntSlice([]int{1, 2, 5, 6})) {
		t.Error("Int slice difference gave wrong result: ", result)
	}
}

func TestSameContentAs(t *testing.T) {
	one := IntSlice([]int{2, 3, 1})
	two := IntSlice([]int{2, 1, 3})

	if !one.SameContentAs(two) {
		t.Log("Didn't think two equivalent slices were the same.")
		t.Fail()
	}

	if !one.SameAs([]int{2, 3, 1}) {
		t.Log("We mutated one")
		t.Fail()
	}

	if !two.SameAs([]int{2, 1, 3}) {
		t.Log("We mutated two")
		t.Fail()
	}

	onePair := IntSlice([]int{3, 2})
	twoPair := IntSlice([]int{2, 3})

	if !onePair.SameContentAs(twoPair) {
		t.Log("Didn't think two equivalent pairs were the same.")
		t.Fail()
	}

}
<commit_msg>TESTS FAIL still. Removed the spew debug output.<commit_after>package sudoku

import (
	"sort"
	"testing"
)

func TestBasicCellList(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	grid.Load(SOLVED_TEST_GRID)
	row := CellList(grid.Row(2))
	if !row.SameRow() {
		t.Log("The items of a row were not all of the same row.")
		t.Fail()
	}

	if row.SameCol() {
		t.Log("For some reason we thought all the cells in a row were in the same col")
		t.Fail()
	}

	var refs []cellRef

	for i := 0; i < DIM; i++ {
		refs = append(refs, cellRef{2, i})
	}

	if !row.sameAsRefs(refs) {
		t.Error("sameAsRefs didn't match values for row 2")
	}

	col := CellList(grid.Col(2))
	if !col.SameCol() {
		t.Log("The items in the col were not int he same col.")
		t.Fail()
	}

	if col.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	block := CellList(grid.Block(2))
	if !block.SameBlock() {
		t.Log("The items in the block were not int he same block.")
		t.Fail()
	}

	if block.SameRow() {
		t.Log("For some reason we thought all the cells in a col were in the same row")
		t.Fail()
	}

	if block.SameCol() {
		t.Log("For some reason we thought all the cells in a block were in the same col")
		t.Fail()
	}

	nums := row.CollectNums(func(cell *Cell) int {
		return cell.Row
	})

	if !nums.Same() {
		t.Log("Collecting rows gave us different numbers/.")
		t.Fail()
	}

	isZeroRow := func(cell *Cell) bool {
		return cell.Row == 0
	}

	cells := grid.Block(0).Filter(isZeroRow)

	if len(cells) != BLOCK_DIM {
		t.Log("We got back the wrong number of cells when filtering")
		t.Fail()
	}

	if !cells.SameRow() {
		t.Log("We got back cells not inthe same row.")
		t.Fail()
	}

	description := cells.Description()

	if description != "(0,0), (0,1), and (0,2)" {
		t.Log("Got wrong description of cellList: ", description)
		t.Fail()
	}

	unsortedList := CellList{grid.Cell(0, 1), grid.Cell(1, 2), grid.Cell(0, 0)}
	unsortedList.Sort()
	if unsortedList[0].Row != 0 || unsortedList[0].Col != 0 ||
		unsortedList[1].Row != 0 || unsortedList[1].Col != 1 ||
		unsortedList[2].Row != 1 || unsortedList[2].Col != 2 {
		t.Error("Cell List didn't get sorted: ", unsortedList)
	}

}

type chainTestConfiguration struct {
	name string
	one  []cellRef
	two  []cellRef
}

type chainTestResult struct {
	name          string
	originalIndex int
	value         float64
}

type chainTestResults []chainTestResult

func (self chainTestResults) Len() int {
	return len(self)
}

func (self chainTestResults) Less(i, j int) bool {
	return self[i].value < self[j].value
}

func (self chainTestResults) Swap(i, j int) {
	self[i], self[j] = self[j], self[i]
}

func TestChainDissimilarity(t *testing.T) {

	//The first bit is where we configure the tests.
	//We should add cases here in the order of similar to dissimilar. The test will then verify
	//they come out in that order.

	tests := []chainTestConfiguration{
		{
			"same row same block",
			[]cellRef{{0, 0}},
			[]cellRef{{0, 1}},
		},
		//this next one verifies that it doesn't matter which of self or other you do first.
		{
			"same row same block, just flipped self and other",
			[]cellRef{{0, 1}},
			[]cellRef{{0, 0}},
		},
		//These next two should be the same difficulty.
		//TODO: might need to generalize the test to allow me to say
		//that two can be equivalent.
		{
			"same block 2 in same row 2 in same col 2 total",
			[]cellRef{{0, 0}},
			[]cellRef{{0, 1}, {1, 0}},
		},
		{
			"two full rows at opposite ends",
			[]cellRef{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}},
			[]cellRef{{7, 0}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}, {7, 7}, {7, 8}},
		},
		{
			"same row different blocks",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}},
		},
		{
			"same col different blocks",
			[]cellRef{{0, 0}, {1, 0}},
			[]cellRef{{3, 0}, {4, 0}},
		},
		{
			"same row different blocks, 2 vs 3",
			[]cellRef{{0, 0}, {0, 1}},
			[]cellRef{{0, 3}, {0, 4}, {0, 5}},
		},
		{
			"single cell opposite corners",
			[]cellRef{{0, 0}},
			[]cellRef{{8, 8}},
		},
	}

	//Now run the tests

	grid := NewGrid()

	var results chainTestResults

	for i, test := range tests {
		var listOne CellList
		var listTwo CellList
		for _, ref := range test.one {
			listOne = append(listOne, ref.Cell(grid))
		}
		for _, ref := range test.two {
			listTwo = append(listTwo, ref.Cell(grid))
		}
		dissimilarity := listOne.ChainDissimilarity(listTwo)
		if dissimilarity < 0.0 {
			t.Fatal(test.name, "failed with a dissimilarity less than 0.0: ", dissimilarity)
		}
		if dissimilarity > 1.0 {
			t.Fatal(test.name, "failed with a dissimilarity great than 1.0:", dissimilarity)
		}
		result := chainTestResult{test.name, i, dissimilarity}
		results = append(results, result)
	}

	//sort them and see if their originalIndexes are now now in order.
	sort.Sort(results)

	for i, result := range results {
		if result.originalIndex != i {
			t.Error(result.name, "was in position", i, " but it was supposed to be in position", result.originalIndex, ". Value:", result.value)
		}
	}

}

func TestFilledNums(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	if !grid.LoadFromFile(puzzlePath("nakedpairblock1.sdk")) {
		t.Fatal("Couldn't load file")
	}

	filledNums := grid.Row(0).FilledNums()

	if !filledNums.SameContentAs(IntSlice{3, 7, 8, 9}) {
		t.Error("Filled nums had wrong nums", filledNums)
	}

}

func TestIntList(t *testing.T) {
	numArr := [...]int{1, 1, 1}
	if !IntSlice(numArr[:]).Same() {
		t.Log("We didn't think that a num list with all of the same ints was the same.")
		t.Fail()
	}
	differentNumArr := [...]int{1, 2, 1}
	if IntSlice(differentNumArr[:]).Same() {
		t.Log("We thought a list of different ints were the same")
		t.Fail()
	}
	description := IntSlice(numArr[:]).Description()
	if description != "1, 1, and 1" {
		t.Log("Didn't get right description: ", description)
		t.Fail()
	}

	unsortedList := IntSlice{3, 2, 1}
	unsortedList.Sort()
	if !unsortedList.SameAs(IntSlice{1, 2, 3}) {
		t.Error("IntSlice.Sort did not sort the list.")
	}

	oneList := IntSlice{1}

	description = oneList.Description()

	if description != "1" {
		t.Log("Didn't get the right description for a short intlist: ", description)
		t.Fail()
	}

	twoList := IntSlice{1, 1}

	description = twoList.Description()

	if description != "1 and 1" {
		t.Log("Did'get the the right description for a two-item intList: ", description)
		t.Fail()
	}
}

func TestInverseSubset(t *testing.T) {
	grid := NewGrid()
	defer grid.Done()
	cells := grid.Row(0)

	indexes := IntSlice([]int{4, 6, 2})

	subset := cells.InverseSubset(indexes)

	if len(subset) != DIM-3 {
		t.Error("Inverse subset gave wrong number of results")
	}

	for _, cell := range subset {
		if cell.Col == 2 || cell.Col == 4 || cell.Col == 6 {
			t.Error("Inverse subset included cells it shouldn't have.")
		}
	}

}

func TestIntSliceIntersection(t *testing.T) {
	one := IntSlice([]int{1, 3, 2, 5})
	two := IntSlice([]int{2, 7, 6, 5})

	result := one.Intersection(two)

	if len(result) != 2 {
		t.Error("Intersection had wrong number of items")
	}

	sort.Ints(result)

	if result[0] != 2 || result[1] != 5 {
		t.Error("Intersection result was wrong.")
	}
}

func TestIntSliceDifference(t *testing.T) {
	one := IntSlice([]int{1, 2, 3, 4, 5, 6})
	two := IntSlice([]int{3, 4, 7})

	result := one.Difference(two)

	if !result.SameContentAs(IntSlice([]int{1, 2, 5, 6})) {
		t.Error("Int slice difference gave wrong result: ", result)
	}
}

func TestSameContentAs(t *testing.T) {
	one := IntSlice([]int{2, 3, 1})
	two := IntSlice([]int{2, 1, 3})

	if !one.SameContentAs(two) {
		t.Log("Didn't think two equivalent slices were the same.")
		t.Fail()
	}

	if !one.SameAs([]int{2, 3, 1}) {
		t.Log("We mutated one")
		t.Fail()
	}

	if !two.SameAs([]int{2, 1, 3}) {
		t.Log("We mutated two")
		t.Fail()
	}

	onePair := IntSlice([]int{3, 2})
	twoPair := IntSlice([]int{2, 3})

	if !onePair.SameContentAs(twoPair) {
		t.Log("Didn't think two equivalent pairs were the same.")
		t.Fail()
	}

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
)

var _ = Describe("Checkout", func() {
	root := filepath.Join(os.TempDir(), "CheckoutTest")
	var oldwd string
	filenames := []string{
		"file1.dat",
		"file111.dat",
		"file112.dat",
		filepath.Join("some", "folder", "file2.dat"),
		filepath.Join("some", "folder", "file211.dat"),
		filepath.Join("some", "folder", "file212.dat"),
		filepath.Join("some", "folder", "nested", "file3.dat"),
		filepath.Join("some", "folder", "nested", "file31.dat"),
		filepath.Join("some", "folder", "nested", "file32.dat"),
		filepath.Join("second", "folder", "file4.dat"),
		filepath.Join("second", "folder", "file5.dat"),
		filepath.Join("second", "folder", "file6.dat"),
		filepath.Join("second", "folder", "file7.dat"),
		filepath.Join("spaced folder", "file8.dat"),
		filepath.Join("really", "really", "really", "really", "really", "really", "really", "really", "exceptionally", "very", "wow", "so", "much", "long", "folder", "withreallylongfilenameinit.barf"),
	}
	sizeForFile := func(i int) int64 {
		// Make a few files content exactly the same size as SHALineLen to test content check
		if i == 0 || i == 7 || i == 9 {
			return int64(SHALineLen)
		} else {
			return 500
		}
	}
	BeforeEach(func() {
		CreateGitRepoForTest(root)
		oldwd, _ = os.Getwd()
		os.Chdir(root)

		// In our test we have to actually create valid git commits referencing the data since
		// that's where checkout starts from
		// To avoid having to rely on clean filter setup when adding files, we'll manually store
		// the LOBs in the binary store then link them in files we add
		for i, file := range filenames {
			err := os.MkdirAll(filepath.Dir(file), 0755)
			if err != nil {
				Fail(err.Error())
			}
			sz := sizeForFile(i)
			CreateRandomFileForTest(sz, file)
			info, err := StoreLOBForTest(file)
			if err != nil {
				Fail("Error storing LOB: " + err.Error())
			}
			// Now manually overwrite the file with the SHA line, as if it hadn't been available when checked out
			err = ioutil.WriteFile(file, []byte(getLOBPlaceholderContent(info.SHA)), 0644)
			if err != nil {
				Fail("Error writing placeholder: " + err.Error())
			}
			// Need to commit the file (with placeholder)
			// If filter is enabled it should leave it alone anyway, but will also work if no filter is set up
			err = exec.Command("git", "add", file).Run()
			if err != nil {
				Fail("Error in git add: " + err.Error())
			}
			err = exec.Command("git", "commit", "-m", fmt.Sprintf("Commit %d", i)).Run()
			if err != nil {
				Fail("Error in git commit: " + err.Error())
			}

		}

	})
	AfterEach(func() {
		os.Chdir(oldwd)
		os.RemoveAll(root)
	})

	It("Checks out all missing data", func() {
		// In this case we just checkout everything
		var filesOK int
		var filesSkipped int
		var filesFailed int
		testCallback := func(t ProgressCallbackType, filelob *FileLOB, err error) {
			switch t {
			case ProgressTransferBytes:
				filesOK++
			case ProgressError:
				filesFailed++
			case ProgressSkip:
				filesSkipped++
			}

		}
		err := Checkout(nil, false, testCallback)
		Expect(err).To(BeNil(), "Shouldn't fail calling checkout")
		Expect(filesOK).To(BeEquivalentTo(len(filenames)), "All files should be updated")
		Expect(filesSkipped).To(BeEquivalentTo(0), "No files should be skipped")
		Expect(filesFailed).To(BeEquivalentTo(0), "No files should have failed")
		for i, file := range filenames {
			// All should be correct size
			sz := sizeForFile(i)
			stat, err := os.Stat(file)
			Expect(err).To(BeNil(), fmt.Sprintf("File %v should exist", file))
			Expect(stat.Size()).To(BeEquivalentTo(sz), fmt.Sprintf("File %v should be checked out & correct size", file))
		}
		// Second call should do nothing
		filesOK = 0
		filesSkipped = 0
		filesFailed = 0
		err = Checkout(nil, false, testCallback)
		Expect(err).To(BeNil(), "Shouldn't fail calling 2nd checkout")
		Expect(filesOK).To(BeEquivalentTo(0), "No files should be updated")
		Expect(filesSkipped).To(BeEquivalentTo(len(filenames)), "All files should be skipped")
		Expect(filesFailed).To(BeEquivalentTo(0), "No files should have failed")
		for i, file := range filenames {
			// All should be correct size
			sz := sizeForFile(i)
			stat, err := os.Stat(file)
			Expect(err).To(BeNil(), fmt.Sprintf("File %v should exist", file))
			Expect(stat.Size()).To(BeEquivalentTo(sz), fmt.Sprintf("File %v should be checked out & correct size", file))
		}

	})

})
<commit_msg>Add --dry-run test for checkout<commit_after>package main

import (
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
)

var _ = Describe("Checkout", func() {
	root := filepath.Join(os.TempDir(), "CheckoutTest")
	var oldwd string
	filenames := []string{
		"file1.dat",
		"file111.dat",
		"file112.dat",
		filepath.Join("some", "folder", "file2.dat"),
		filepath.Join("some", "folder", "file211.dat"),
		filepath.Join("some", "folder", "file212.dat"),
		filepath.Join("some", "folder", "nested", "file3.dat"),
		filepath.Join("some", "folder", "nested", "file31.dat"),
		filepath.Join("some", "folder", "nested", "file32.dat"),
		filepath.Join("second", "folder", "file4.dat"),
		filepath.Join("second", "folder", "file5.dat"),
		filepath.Join("second", "folder", "file6.dat"),
		filepath.Join("second", "folder", "file7.dat"),
		filepath.Join("spaced folder", "file8.dat"),
		filepath.Join("really", "really", "really", "really", "really", "really", "really", "really", "exceptionally", "very", "wow", "so", "much", "long", "folder", "withreallylongfilenameinit.barf"),
	}
	sizeForFile := func(i int) int64 {
		// Make a few files content exactly the same size as SHALineLen to test content check
		if i == 0 || i == 7 || i == 9 {
			return int64(SHALineLen)
		} else {
			return 500
		}
	}
	BeforeEach(func() {
		CreateGitRepoForTest(root)
		oldwd, _ = os.Getwd()
		os.Chdir(root)

		// In our test we have to actually create valid git commits referencing the data since
		// that's where checkout starts from
		// To avoid having to rely on clean filter setup when adding files, we'll manually store
		// the LOBs in the binary store then link them in files we add
		for i, file := range filenames {
			err := os.MkdirAll(filepath.Dir(file), 0755)
			if err != nil {
				Fail(err.Error())
			}
			sz := sizeForFile(i)
			CreateRandomFileForTest(sz, file)
			info, err := StoreLOBForTest(file)
			if err != nil {
				Fail("Error storing LOB: " + err.Error())
			}
			// Now manually overwrite the file with the SHA line, as if it hadn't been available when checked out
			err = ioutil.WriteFile(file, []byte(getLOBPlaceholderContent(info.SHA)), 0644)
			if err != nil {
				Fail("Error writing placeholder: " + err.Error())
			}
			// Need to commit the file (with placeholder)
			// If filter is enabled it should leave it alone anyway, but will also work if no filter is set up
			err = exec.Command("git", "add", file).Run()
			if err != nil {
				Fail("Error in git add: " + err.Error())
			}
			err = exec.Command("git", "commit", "-m", fmt.Sprintf("Commit %d", i)).Run()
			if err != nil {
				Fail("Error in git commit: " + err.Error())
			}

		}

	})
	AfterEach(func() {
		os.Chdir(oldwd)
		os.RemoveAll(root)
	})

	It("Checks out all missing data", func() {
		// In this case we just checkout everything
		var filesOK int
		var filesSkipped int
		var filesFailed int
		testCallback := func(t ProgressCallbackType, filelob *FileLOB, err error) {
			switch t {
			case ProgressTransferBytes:
				filesOK++
			case ProgressError:
				filesFailed++
			case ProgressSkip:
				filesSkipped++
			}

		}
		// Dry run test
		err := Checkout(nil, true, testCallback)
		Expect(err).To(BeNil(), "Shouldn't fail calling checkout")
		Expect(filesOK).To(BeEquivalentTo(len(filenames)), "All files should need to be updated")
		Expect(filesSkipped).To(BeEquivalentTo(0), "No files should be skipped")
		Expect(filesFailed).To(BeEquivalentTo(0), "No files should have failed")
		for _, file := range filenames {
			// All should be unchanged, still placeholders
			stat, err := os.Stat(file)
			Expect(err).To(BeNil(), fmt.Sprintf("File %v should still exist", file))
			Expect(stat.Size()).To(BeEquivalentTo(SHALineLen), fmt.Sprintf("File %v should be unchanged", file))
		}
		// Now the real call
		filesOK = 0
		filesSkipped = 0
		filesFailed = 0
		err = Checkout(nil, false, testCallback)
		Expect(err).To(BeNil(), "Shouldn't fail calling checkout")
		Expect(filesOK).To(BeEquivalentTo(len(filenames)), "All files should be updated")
		Expect(filesSkipped).To(BeEquivalentTo(0), "No files should be skipped")
		Expect(filesFailed).To(BeEquivalentTo(0), "No files should have failed")
		for i, file := range filenames {
			// All should be correct size
			sz := sizeForFile(i)
			stat, err := os.Stat(file)
			Expect(err).To(BeNil(), fmt.Sprintf("File %v should exist", file))
			Expect(stat.Size()).To(BeEquivalentTo(sz), fmt.Sprintf("File %v should be checked out & correct size", file))
		}
		// Second call should do nothing
		filesOK = 0
		filesSkipped = 0
		filesFailed = 0
		err = Checkout(nil, false, testCallback)
		Expect(err).To(BeNil(), "Shouldn't fail calling 2nd checkout")
		Expect(filesOK).To(BeEquivalentTo(0), "No files should be updated")
		Expect(filesSkipped).To(BeEquivalentTo(len(filenames)), "All files should be skipped")
		Expect(filesFailed).To(BeEquivalentTo(0), "No files should have failed")
		for i, file := range filenames {
			// All should be correct size
			sz := sizeForFile(i)
			stat, err := os.Stat(file)
			Expect(err).To(BeNil(), fmt.Sprintf("File %v should exist", file))
			Expect(stat.Size()).To(BeEquivalentTo(sz), fmt.Sprintf("File %v should be checked out & correct size", file))
		}

	})
	It("Respects pathspecs", func() {
		// TODO

	})

})
<|endoftext|>


<commit_before>package deprecatedapirequest

import "k8s.io/apimachinery/pkg/runtime/schema"

var deprecatedApiRemovedRelease = map[schema.GroupVersionResource]string{
	// Kubernetes APIs
	{Group: "apps", Version: "v1beta1", Resource: "controllerrevisions"}:                                     "1.16",
	{Group: "apps", Version: "v1beta1", Resource: "deploymentrollbacks"}:                                     "1.16",
	{Group: "apps", Version: "v1beta1", Resource: "deployments"}:                                             "1.16",
	{Group: "apps", Version: "v1beta1", Resource: "scales"}:                                                  "1.16",
	{Group: "apps", Version: "v1beta1", Resource: "statefulsets"}:                                            "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "controllerrevisions"}:                                     "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "daemonsets"}:                                              "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "deployments"}:                                             "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "replicasets"}:                                             "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "scales"}:                                                  "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "statefulsets"}:                                            "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "daemonsets"}:                                        "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "deploymentrollbacks"}:                               "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "deployments"}:                                       "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "networkpolicies"}:                                   "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "podsecuritypolicies"}:                               "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "replicasets"}:                                       "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "scales"}:                                            "1.16",
	{Group: "flowcontrol.apiserver.k8s.io", Version: "v1alpha1", Resource: "flowschemas"}:                    "1.21",
	{Group: "flowcontrol.apiserver.k8s.io", Version: "v1alpha1", Resource: "prioritylevelconfigurations"}:    "1.21",
	{Group: "admissionregistration.k8s.io", Version: "v1beta1", Resource: "mutatingwebhookconfigurations"}:   "1.22",
	{Group: "admissionregistration.k8s.io", Version: "v1beta1", Resource: "validatingwebhookconfigurations"}: "1.22",
	{Group: "apiextensions.k8s.io", Version: "v1beta1", Resource: "customresourcedefinitions"}:               "1.22",
	{Group: "certificates.k8s.io", Version: "v1beta1", Resource: "certificatesigningrequests"}:               "1.22",
	{Group: "extensions", Version: "v1beta1", Resource: "ingresses"}:                                         "1.22",
	{Group: "networking.k8s.io", Version: "v1beta1", Resource: "ingresses"}:                                  "1.22",
	{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "clusterrolebindings"}:                "1.22",
	{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "clusterroles"}:                       "1.22",
	{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "rolebindings"}:                       "1.22",
	{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "roles"}:                              "1.22",
	{Group: "scheduling.k8s.io", Version: "v1beta1", Resource: "priorityclasses"}:                            "1.22",
	{Group: "storage.k8s.io", Version: "v1beta1", Resource: "csinodes"}:                                      "1.22",
	{Group: "batch", Version: "v1beta1", Resource: "cronjobs"}:                                               "1.25",
	{Group: "discovery.k8s.io", Version: "v1beta1", Resource: "endpointslices"}:                              "1.25",
	{Group: "events.k8s.io", Version: "v1beta1", Resource: "events"}:                                         "1.25",
	{Group: "autoscaling", Version: "v2beta1", Resource: "horizontalpodautoscalers"}:                         "1.25",
	{Group: "policy", Version: "v1beta1", Resource: "poddisruptionbudgets"}:                                  "1.25",
	{Group: "policy", Version: "v1beta1", Resource: "podsecuritypolicies"}:                                   "1.25",
	{Group: "node.k8s.io", Version: "v1beta1", Resource: "runtimeclasses"}:                                   "1.25",
	{Group: "autoscaling", Version: "v2beta2", Resource: "horizontalpodautoscalers"}:                         "1.26",
	{Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1", Resource: "flowschemas"}:                     "1.26",
	{Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1", Resource: "prioritylevelconfigurations"}:     "1.26",
	// OpenShift APIs
	{Group: "operator.openshift.io", Version: "v1beta1", Resource: "kubedeschedulers"}: "1.22",
}

// removedRelease of a specified resource.version.group.
func removedRelease(resource schema.GroupVersionResource) string {
	return deprecatedApiRemovedRelease[resource]
}
<commit_msg>UPSTREAM: <carry>: update list of deprecated apis<commit_after>package deprecatedapirequest

import "k8s.io/apimachinery/pkg/runtime/schema"

var deprecatedApiRemovedRelease = map[schema.GroupVersionResource]string{
	// Kubernetes APIs
	{Group: "apps", Version: "v1beta1", Resource: "controllerrevisions"}:                                     "1.16",
	{Group: "apps", Version: "v1beta1", Resource: "deploymentrollbacks"}:                                     "1.16",
	{Group: "apps", Version: "v1beta1", Resource: "deployments"}:                                             "1.16",
	{Group: "apps", Version: "v1beta1", Resource: "scales"}:                                                  "1.16",
	{Group: "apps", Version: "v1beta1", Resource: "statefulsets"}:                                            "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "controllerrevisions"}:                                     "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "daemonsets"}:                                              "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "deployments"}:                                             "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "replicasets"}:                                             "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "scales"}:                                                  "1.16",
	{Group: "apps", Version: "v1beta2", Resource: "statefulsets"}:                                            "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "daemonsets"}:                                        "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "deploymentrollbacks"}:                               "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "deployments"}:                                       "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "networkpolicies"}:                                   "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "podsecuritypolicies"}:                               "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "replicasets"}:                                       "1.16",
	{Group: "extensions", Version: "v1beta1", Resource: "scales"}:                                            "1.16",
	{Group: "flowcontrol.apiserver.k8s.io", Version: "v1alpha1", Resource: "flowschemas"}:                    "1.21",
	{Group: "flowcontrol.apiserver.k8s.io", Version: "v1alpha1", Resource: "prioritylevelconfigurations"}:    "1.21",
	{Group: "admissionregistration.k8s.io", Version: "v1beta1", Resource: "mutatingwebhookconfigurations"}:   "1.22",
	{Group: "admissionregistration.k8s.io", Version: "v1beta1", Resource: "validatingwebhookconfigurations"}: "1.22",
	{Group: "apiextensions.k8s.io", Version: "v1beta1", Resource: "customresourcedefinitions"}:               "1.22",
	{Group: "apiregistration.k8s.io", Version: "v1beta1", Resource: "apiservices"}:                           "1.22",
	{Group: "authentication.k8s.io", Version: "v1beta1", Resource: "tokenreviews"}:                           "1.22",
	{Group: "authorization.k8s.io", Version: "v1beta1", Resource: "localsubjectaccessreviews"}:               "1.22",
	{Group: "authorization.k8s.io", Version: "v1beta1", Resource: "selfsubjectaccessreviews"}:                "1.22",
	{Group: "authorization.k8s.io", Version: "v1beta1", Resource: "selfsubjectrulesreviews"}:                 "1.22",
	{Group: "authorization.k8s.io", Version: "v1beta1", Resource: "subjectaccessreviews"}:                    "1.22",
	{Group: "certificates.k8s.io", Version: "v1beta1", Resource: "certificatesigningrequests"}:               "1.22",
	{Group: "coordination.k8s.io", Version: "v1beta1", Resource: "leases"}:                                   "1.22",
	{Group: "extensions", Version: "v1beta1", Resource: "ingresses"}:                                         "1.22",
	{Group: "networking.k8s.io", Version: "v1beta1", Resource: "ingresses"}:                                  "1.22",
	{Group: "networking.k8s.io", Version: "v1beta1", Resource: "ingressclasses"}:                             "1.22",
	{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "clusterrolebindings"}:                "1.22",
	{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "clusterroles"}:                       "1.22",
	{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "rolebindings"}:                       "1.22",
	{Group: "rbac.authorization.k8s.io", Version: "v1beta1", Resource: "roles"}:                              "1.22",
	{Group: "scheduling.k8s.io", Version: "v1beta1", Resource: "priorityclasses"}:                            "1.22",
	{Group: "storage.k8s.io", Version: "v1beta1", Resource: "csidrivers"}:                                    "1.22",
	{Group: "storage.k8s.io", Version: "v1beta1", Resource: "csinodes"}:                                      "1.22",
	{Group: "storage.k8s.io", Version: "v1beta1", Resource: "storageclasses"}:                                "1.22",
	{Group: "storage.k8s.io", Version: "v1beta1", Resource: "volumeattachments"}:                             "1.22",
	{Group: "batch", Version: "v1beta1", Resource: "cronjobs"}:                                               "1.25",
	{Group: "discovery.k8s.io", Version: "v1beta1", Resource: "endpointslices"}:                              "1.25",
	{Group: "events.k8s.io", Version: "v1beta1", Resource: "events"}:                                         "1.25",
	{Group: "autoscaling", Version: "v2beta1", Resource: "horizontalpodautoscalers"}:                         "1.25",
	{Group: "policy", Version: "v1beta1", Resource: "poddisruptionbudgets"}:                                  "1.25",
	{Group: "policy", Version: "v1beta1", Resource: "podsecuritypolicies"}:                                   "1.25",
	{Group: "node.k8s.io", Version: "v1beta1", Resource: "runtimeclasses"}:                                   "1.25",
	{Group: "autoscaling", Version: "v2beta2", Resource: "horizontalpodautoscalers"}:                         "1.26",
	{Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1", Resource: "flowschemas"}:                     "1.26",
	{Group: "flowcontrol.apiserver.k8s.io", Version: "v1beta1", Resource: "prioritylevelconfigurations"}:     "1.26",
	// OpenShift APIs
	{Group: "operator.openshift.io", Version: "v1beta1", Resource: "kubedeschedulers"}: "1.22",
}

// removedRelease of a specified resource.version.group.
func removedRelease(resource schema.GroupVersionResource) string {
	return deprecatedApiRemovedRelease[resource]
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppcalls_test

import (
	"testing"

	"github.com/ligato/cn-infra/logging/logrus"
	"github.com/ligato/vpp-agent/idxvpp/nametoidx"
	l2ba "github.com/ligato/vpp-agent/plugins/defaultplugins/common/bin_api/l2"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/common/model/l2"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/ifaceidx"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/l2plugin/vppcalls"
	"github.com/ligato/vpp-agent/tests/vppcallmock"
	. "github.com/onsi/gomega"
)

const (
	ifaceA = "A"
	ifaceB = "B"
	ifaceC = "C"
	ifaceD = "D"
	ifaceE = "E"

	swIndexA uint32 = 1
	swIndexB uint32 = 2
	swIndexC uint32 = 3
	swIndexD uint32 = 4

	splitHorizonGroupA = 2104
	splitHorizonGroupB = 1903

	dummyPluginName = "dummy plugin name"
	dummyRetVal     = 4
)

var testDataInDummySwIfIndex = initSwIfIndex().(ifaceidx.SwIfIndexRW)

var testDataIfaces = []*l2.BridgeDomains_BridgeDomain_Interfaces{
	{Name: ifaceA, BridgedVirtualInterface: true, SplitHorizonGroup: splitHorizonGroupA},
	{Name: ifaceB, BridgedVirtualInterface: false, SplitHorizonGroup: splitHorizonGroupA},
	{Name: ifaceC, BridgedVirtualInterface: false, SplitHorizonGroup: splitHorizonGroupB},
	{Name: ifaceD, BridgedVirtualInterface: false, SplitHorizonGroup: splitHorizonGroupB},
	{Name: ifaceE, BridgedVirtualInterface: false, SplitHorizonGroup: splitHorizonGroupB},
}

var testDataInBDIfaces = []*l2.BridgeDomains_BridgeDomain{
	{
		Name:       dummyBridgeDomainName,
		Interfaces: testDataIfaces,
	},
}

var testDataOutBDIfaces = []*l2ba.SwInterfaceSetL2Bridge{
	{
		BdID:        dummyBridgeDomain,
		RxSwIfIndex: swIndexA,
		Enable:      1,
		Bvi:         1,
	},
	{
		BdID:        dummyBridgeDomain,
		RxSwIfIndex: swIndexB,
		Enable:      1,
	},
	{
		BdID:        dummyBridgeDomain,
		RxSwIfIndex: swIndexA,
		Enable:      0,
	},
	{
		BdID:        dummyBridgeDomain,
		RxSwIfIndex: swIndexB,
		Enable:      0,
	},
}

/**
covers scenarios
- 5 provided interfaces - A..E
	- interface A - common interface
	- interface B - BVI interface
	- interface C - vpp binary call returns dummy ret value
	- interface D - vpp binary call returns incorrect return value
	- interface E - isn't specified sw index
*/
//TestVppSetAllInterfacesToBridgeDomainWithInterfaces tests method VppSetAllInterfacesToBridgeDomain
func TestVppSetAllInterfacesToBridgeDomainWithInterfaces(t *testing.T) {
	ctx := vppcallmock.SetupTestCtx(t)
	defer ctx.TeardownTestCtx()

	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{Retval: dummyRetVal})
	ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{})

	//call testing method
	vppcalls.SetInterfacesToBridgeDomain(testDataInBDIfaces[0], dummyBridgeDomain,
		testDataIfaces, testDataInDummySwIfIndex, logrus.DefaultLogger(), ctx.MockChannel, nil)

	//Four VPP call - only two of them are successfull
	Expect(ctx.MockChannel.Msgs).To(HaveLen(4))
	Expect(ctx.MockChannel.Msgs[0]).To(Equal(testDataOutBDIfaces[0]))
	Expect(ctx.MockChannel.Msgs[1]).To(Equal(testDataOutBDIfaces[1]))
}

/**
covers scenarios
- 5 provided interfaces - A..E
	- interface A - common interface
	- interface B - common interface
	- interface C - vpp binary call returns dummy ret value
	- interface D - vpp binary call returns incorrect return value
	- interface E - isn't specified sw index
*/
//TestVppUnsetAllInterfacesFromBridgeDomain tests method VppUnsetAllInterfacesFromBridgeDomain
func TestVppUnsetAllInterfacesFromBridgeDomain(t *testing.T) {
	ctx := vppcallmock.SetupTestCtx(t)
	defer ctx.TeardownTestCtx()

	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{Retval: dummyRetVal})
	ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{})

	//call testing method
	vppcalls.UnsetInterfacesFromBridgeDomain(testDataInBDIfaces[0], dummyBridgeDomain,
		testDataIfaces, testDataInDummySwIfIndex, logrus.DefaultLogger(), ctx.MockChannel, nil)

	Expect(ctx.MockChannel.Msgs).To(HaveLen(4))
	Expect(ctx.MockChannel.Msgs[0]).To(Equal(testDataOutBDIfaces[2]))
	Expect(ctx.MockChannel.Msgs[1]).To(Equal(testDataOutBDIfaces[3]))
}

var testDatasInInterfaceToBd = []struct {
	bdIndex   uint32
	swIfIndex uint32
	bvi       bool
}{
	{dummyBridgeDomain, 1, true},
	{dummyBridgeDomain, 1, false},
}

var testDatasOutInterfaceToBd = []*l2ba.SwInterfaceSetL2Bridge{

	{RxSwIfIndex: 1, BdID: dummyBridgeDomain, Bvi: 1, Enable: 1},
	{RxSwIfIndex: 1, BdID: dummyBridgeDomain, Bvi: 0, Enable: 1},
}

/**
scenarios:
- BVI - true
- BVI - false
*/
//TestVppSetInterfaceToBridgeDomain tests VppSetInterfaceToBridgeDomain method
func TestVppSetInterfaceToBridgeDomain(t *testing.T) {
	ctx := vppcallmock.SetupTestCtx(t)
	defer ctx.TeardownTestCtx()

	for idx, testDataIn := range testDatasInInterfaceToBd {
		ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
		vppcalls.SetInterfaceToBridgeDomain(testDataIn.bdIndex, testDataIn.swIfIndex, testDataIn.bvi,
			logrus.DefaultLogger(), ctx.MockChannel, nil)
		Expect(ctx.MockChannel.Msg).To(Equal(testDatasOutInterfaceToBd[idx]))
	}
}

func initSwIfIndex() interface{} {
	result := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), dummyPluginName,
		"sw_if_indexes", ifaceidx.IndexMetadata))
	result.RegisterName(ifaceA, swIndexA, nil)
	result.RegisterName(ifaceB, swIndexB, nil)
	result.RegisterName(ifaceC, swIndexC, nil)
	result.RegisterName(ifaceD, swIndexD, nil)
	return result
}
<commit_msg>fixed tests<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppcalls_test

import (
	"testing"

	"github.com/ligato/cn-infra/logging/logrus"
	"github.com/ligato/vpp-agent/idxvpp/nametoidx"
	l2ba "github.com/ligato/vpp-agent/plugins/defaultplugins/common/bin_api/l2"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/common/model/l2"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/ifplugin/ifaceidx"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/l2plugin/vppcalls"
	"github.com/ligato/vpp-agent/tests/vppcallmock"
	. "github.com/onsi/gomega"
)

const (
	ifaceA = "A"
	ifaceB = "B"
	ifaceC = "C"
	ifaceD = "D"
	ifaceE = "E"

	swIndexA uint32 = 1
	swIndexB uint32 = 2
	swIndexC uint32 = 3
	swIndexD uint32 = 4

	splitHorizonGroupA = 10
	splitHorizonGroupB = 100

	dummyPluginName = "dummy plugin name"
	dummyRetVal     = 4
)

var testDataInDummySwIfIndex = initSwIfIndex().(ifaceidx.SwIfIndexRW)

var testDataIfaces = []*l2.BridgeDomains_BridgeDomain_Interfaces{
	{Name: ifaceA, BridgedVirtualInterface: true, SplitHorizonGroup: splitHorizonGroupA},
	{Name: ifaceB, BridgedVirtualInterface: false, SplitHorizonGroup: splitHorizonGroupA},
	{Name: ifaceC, BridgedVirtualInterface: false, SplitHorizonGroup: splitHorizonGroupB},
	{Name: ifaceD, BridgedVirtualInterface: false, SplitHorizonGroup: splitHorizonGroupB},
	{Name: ifaceE, BridgedVirtualInterface: false, SplitHorizonGroup: splitHorizonGroupB},
}

var testDataInBDIfaces = []*l2.BridgeDomains_BridgeDomain{
	{
		Name:       dummyBridgeDomainName,
		Interfaces: testDataIfaces,
	},
}

var testDataOutBDIfaces = []*l2ba.SwInterfaceSetL2Bridge{
	{
		BdID:        dummyBridgeDomain,
		RxSwIfIndex: swIndexA,
		Shg:         splitHorizonGroupA,
		Enable:      1,
		Bvi:         1,
	},
	{
		BdID:        dummyBridgeDomain,
		RxSwIfIndex: swIndexB,
		Shg:         splitHorizonGroupA,
		Enable:      1,
	},
	{
		BdID:        dummyBridgeDomain,
		RxSwIfIndex: swIndexA,
		Shg:         splitHorizonGroupA,
		Enable:      0,
	},
	{
		BdID:        dummyBridgeDomain,
		RxSwIfIndex: swIndexB,
		Shg:         splitHorizonGroupA,
		Enable:      0,
	},
}

/**
covers scenarios
- 5 provided interfaces - A..E
	- interface A - common interface
	- interface B - BVI interface
	- interface C - vpp binary call returns dummy ret value
	- interface D - vpp binary call returns incorrect return value
	- interface E - isn't specified sw index
*/
//TestVppSetAllInterfacesToBridgeDomainWithInterfaces tests method VppSetAllInterfacesToBridgeDomain
func TestVppSetAllInterfacesToBridgeDomainWithInterfaces(t *testing.T) {
	ctx := vppcallmock.SetupTestCtx(t)
	defer ctx.TeardownTestCtx()

	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{Retval: dummyRetVal})
	ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{})

	//call testing method
	vppcalls.SetInterfacesToBridgeDomain(testDataInBDIfaces[0], dummyBridgeDomain,
		testDataIfaces, testDataInDummySwIfIndex, logrus.DefaultLogger(), ctx.MockChannel, nil)

	//Four VPP call - only two of them are successfull
	Expect(ctx.MockChannel.Msgs).To(HaveLen(4))
	Expect(ctx.MockChannel.Msgs[0]).To(Equal(testDataOutBDIfaces[0]))
	Expect(ctx.MockChannel.Msgs[1]).To(Equal(testDataOutBDIfaces[1]))
}

/**
covers scenarios
- 5 provided interfaces - A..E
	- interface A - common interface
	- interface B - common interface
	- interface C - vpp binary call returns dummy ret value
	- interface D - vpp binary call returns incorrect return value
	- interface E - isn't specified sw index
*/
//TestVppUnsetAllInterfacesFromBridgeDomain tests method VppUnsetAllInterfacesFromBridgeDomain
func TestVppUnsetAllInterfacesFromBridgeDomain(t *testing.T) {
	ctx := vppcallmock.SetupTestCtx(t)
	defer ctx.TeardownTestCtx()

	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
	ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{Retval: dummyRetVal})
	ctx.MockVpp.MockReply(&l2ba.BridgeDomainAddDelReply{})

	//call testing method
	vppcalls.UnsetInterfacesFromBridgeDomain(testDataInBDIfaces[0], dummyBridgeDomain,
		testDataIfaces, testDataInDummySwIfIndex, logrus.DefaultLogger(), ctx.MockChannel, nil)

	Expect(ctx.MockChannel.Msgs).To(HaveLen(4))
	Expect(ctx.MockChannel.Msgs[0]).To(Equal(testDataOutBDIfaces[2]))
	Expect(ctx.MockChannel.Msgs[1]).To(Equal(testDataOutBDIfaces[3]))
}

var testDatasInInterfaceToBd = []struct {
	bdIndex   uint32
	swIfIndex uint32
	bvi       bool
}{
	{dummyBridgeDomain, 1, true},
	{dummyBridgeDomain, 1, false},
}

var testDatasOutInterfaceToBd = []*l2ba.SwInterfaceSetL2Bridge{

	{RxSwIfIndex: 1, BdID: dummyBridgeDomain, Bvi: 1, Enable: 1},
	{RxSwIfIndex: 1, BdID: dummyBridgeDomain, Bvi: 0, Enable: 1},
}

/**
scenarios:
- BVI - true
- BVI - false
*/
//TestVppSetInterfaceToBridgeDomain tests VppSetInterfaceToBridgeDomain method
func TestVppSetInterfaceToBridgeDomain(t *testing.T) {
	ctx := vppcallmock.SetupTestCtx(t)
	defer ctx.TeardownTestCtx()

	for idx, testDataIn := range testDatasInInterfaceToBd {
		ctx.MockVpp.MockReply(&l2ba.SwInterfaceSetL2BridgeReply{})
		vppcalls.SetInterfaceToBridgeDomain(testDataIn.bdIndex, testDataIn.swIfIndex, testDataIn.bvi,
			logrus.DefaultLogger(), ctx.MockChannel, nil)
		Expect(ctx.MockChannel.Msg).To(Equal(testDatasOutInterfaceToBd[idx]))
	}
}

func initSwIfIndex() interface{} {
	result := ifaceidx.NewSwIfIndex(nametoidx.NewNameToIdx(logrus.DefaultLogger(), dummyPluginName,
		"sw_if_indexes", ifaceidx.IndexMetadata))
	result.RegisterName(ifaceA, swIndexA, nil)
	result.RegisterName(ifaceB, swIndexB, nil)
	result.RegisterName(ifaceC, swIndexC, nil)
	result.RegisterName(ifaceD, swIndexD, nil)
	return result
}
<|endoftext|>


<commit_before>package geometry

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"

	"github.com/gonum/matrix/mat64"
	"github.com/google/uuid"
)

// PointCloud Represents an array of vectors
type PointCloud struct {
	Vectors []*mat64.Vector
}

// Add adds a Vector to Pointcloud
func (pC *PointCloud) Add(vec ...*mat64.Vector) {
	pC.Vectors = append(pC.Vectors, vec...)
}

// FillRandom fills pointcloud with random vectors
func (pC *PointCloud) FillRandom(count int) {
	for i := 0; i < count; i++ {
		vec := mat64.NewVector(3, []float64{
			rand.Float64(),
			rand.Float64(),
			rand.Float64(),
		})
		pC.Vectors = append(pC.Vectors, vec)
	}
}

// Length returns the amount of vertices in PoinCloud
func (pC *PointCloud) Length() int {
	return len(pC.Vectors)
}

// ReadPCD reads in PCD data from Point Cloud Library
func (pC *PointCloud) ReadPCD(path string) error {
	fileHandle, err := os.Open(path)
	if err != nil {
		return err
	}
	defer fileHandle.Close()

	fileScanner := bufio.NewScanner(fileHandle)
	isPoint := false
	for fileScanner.Scan() {
		// line ist die jeweilige Zeile
		line := fileScanner.Text()

		if isPoint {
			// Die Punkte sind zeilenweise als "x y z" gespeichert und werden erstmal in ein unterarray gesplittet
			point := strings.Split(line, " ")

			// die unterarrays werden zu einem vektor zusammen geschrieben
			x, err := strconv.ParseFloat(point[0], 64)
			if err != nil {
				return err
			}
			y, err := strconv.ParseFloat(point[1], 64)
			if err != nil {
				return err
			}
			z, err := strconv.ParseFloat(point[2], 64)
			if err != nil {
				return err
			}

			vector := mat64.NewVector(3, []float64{
				x,
				y,
				z,
			})

			// der vector wird in die gesamte PointCloud ergänzt
			pC.Vectors = append(pC.Vectors, vector)
		}

		// Erst nach erkennen dieser Zeile werden Vectoren erstellt.
		if line == "DATA ascii" {
			isPoint = true
		}
	}
	return nil
}

// SavePLY saves a Pointcloud to PLY file
func (pC *PointCloud) SavePLY(path string) error {

	if pC.Vectors == nil {
		return errors.New("pointcloud is empty")
	}

	ply := []byte{}
	ply = append(ply, []byte("ply\n")...)
	ply = append(ply, []byte("format ascii 1.0\n")...)
	body := []byte{}

	var (
		x string
		y string
		z string
	)

	for _, vector := range pC.Vectors {
		x = strconv.FormatFloat(vector.At(0, 0), 'E', -1, 64)
		y = strconv.FormatFloat(vector.At(1, 0), 'E', -1, 64)
		z = strconv.FormatFloat(vector.At(2, 0), 'E', -1, 64)
		body = append(body, []byte(x+" "+y+" "+z+"\n")...)
	}

	ply = append(ply, []byte("element vertex "+strconv.Itoa(len(pC.Vectors))+"\n")...)
	ply = append(ply, []byte("property float x\n")...)
	ply = append(ply, []byte("property float y\n")...)
	ply = append(ply, []byte("property float z\n")...)
	ply = append(ply, []byte("end_header\n")...)
	ply = append(ply, body...)
	return ioutil.WriteFile(path, ply, 0644)

}

// Transform transforms pointcloud with transformation matrix
func (pC *PointCloud) Transform(transMat *TransMat) {
	for i, vector := range pC.Vectors {
		pC.Vectors[i] = transMat.Transform(vector)
	}
}

// ShowInMeshlab shows the Pointcloudobject in meshlab
func (pC *PointCloud) ShowInMeshlab() error {
	tmpPath := os.TempDir() + "/" + uuid.New().String() + ".ply"
	fmt.Println(tmpPath)
	err := pC.SavePLY(tmpPath)
	if err != nil {
		return err
	}

	meshlabExecPath := "meshlab"
	if runtime.GOOS == "windows" {
		meshlabExecPath = `C:\Program Files\VCG\MeshLab\meshlab.exe`
	}

	meshlab := exec.Command(meshlabExecPath, tmpPath)
	err = meshlab.Start()
	if err != nil {
		return errors.New("meshlab could not be started")
	}
	meshlab.Wait()
	return os.Remove(tmpPath)
}
<commit_msg>PCD oder PLY in ReadPCD<commit_after>package geometry

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"

	"github.com/gonum/matrix/mat64"
	"github.com/google/uuid"
)

// PointCloud Represents an array of vectors
type PointCloud struct {
	Vectors []*mat64.Vector
}

// Add adds a Vector to Pointcloud
func (pC *PointCloud) Add(vec ...*mat64.Vector) {
	pC.Vectors = append(pC.Vectors, vec...)
}

// FillRandom fills pointcloud with random vectors
func (pC *PointCloud) FillRandom(count int) {
	for i := 0; i < count; i++ {
		vec := mat64.NewVector(3, []float64{
			rand.Float64(),
			rand.Float64(),
			rand.Float64(),
		})
		pC.Vectors = append(pC.Vectors, vec)
	}
}

// Length returns the amount of vertices in PoinCloud
func (pC *PointCloud) Length() int {
	return len(pC.Vectors)
}

// ReadPCD reads in PCD data from Point Cloud Library
func (pC *PointCloud) ReadPCD(path string) error {
	fileHandle, err := os.Open(path)
	if err != nil {
		return err
	}
	defer fileHandle.Close()

	fileScanner := bufio.NewScanner(fileHandle)
	isPoint := false
	for fileScanner.Scan() {
		// line ist die jeweilige Zeile
		line := fileScanner.Text()

		if isPoint {
			// Die Punkte sind zeilenweise als "x y z" gespeichert und werden erstmal in ein unterarray gesplittet
			point := strings.Split(line, " ")

			// die unterarrays werden zu einem vektor zusammen geschrieben
			x, err := strconv.ParseFloat(point[0], 64)
			if err != nil {
				return err
			}
			y, err := strconv.ParseFloat(point[1], 64)
			if err != nil {
				return err
			}
			z, err := strconv.ParseFloat(point[2], 64)
			if err != nil {
				return err
			}

			vector := mat64.NewVector(3, []float64{
				x,
				y,
				z,
			})

			// der vector wird in die gesamte PointCloud ergänzt
			pC.Vectors = append(pC.Vectors, vector)
		}

		// Erst nach erkennen dieser Zeile werden Vectoren erstellt.
		if line == "DATA ascii" || line == "end_header" {
			isPoint = true
		}
	}
	return nil
}

// SavePLY saves a Pointcloud to PLY file
func (pC *PointCloud) SavePLY(path string) error {

	if pC.Vectors == nil {
		return errors.New("pointcloud is empty")
	}

	ply := []byte{}
	ply = append(ply, []byte("ply\n")...)
	ply = append(ply, []byte("format ascii 1.0\n")...)
	body := []byte{}

	var (
		x string
		y string
		z string
	)

	for _, vector := range pC.Vectors {
		x = strconv.FormatFloat(vector.At(0, 0), 'E', -1, 64)
		y = strconv.FormatFloat(vector.At(1, 0), 'E', -1, 64)
		z = strconv.FormatFloat(vector.At(2, 0), 'E', -1, 64)
		body = append(body, []byte(x+" "+y+" "+z+"\n")...)
	}

	ply = append(ply, []byte("element vertex "+strconv.Itoa(len(pC.Vectors))+"\n")...)
	ply = append(ply, []byte("property float x\n")...)
	ply = append(ply, []byte("property float y\n")...)
	ply = append(ply, []byte("property float z\n")...)
	ply = append(ply, []byte("end_header\n")...)
	ply = append(ply, body...)
	return ioutil.WriteFile(path, ply, 0644)

}

// Transform transforms pointcloud with transformation matrix
func (pC *PointCloud) Transform(transMat *TransMat) {
	for i, vector := range pC.Vectors {
		pC.Vectors[i] = transMat.Transform(vector)
	}
}

// ShowInMeshlab shows the Pointcloudobject in meshlab
func (pC *PointCloud) ShowInMeshlab() error {
	tmpPath := os.TempDir() + "/" + uuid.New().String() + ".ply"
	fmt.Println(tmpPath)
	err := pC.SavePLY(tmpPath)
	if err != nil {
		return err
	}

	meshlabExecPath := "meshlab"
	if runtime.GOOS == "windows" {
		meshlabExecPath = `C:\Program Files\VCG\MeshLab\meshlab.exe`
	}

	meshlab := exec.Command(meshlabExecPath, tmpPath)
	err = meshlab.Start()
	if err != nil {
		return errors.New("meshlab could not be started")
	}
	meshlab.Wait()
	return os.Remove(tmpPath)
}
<|endoftext|>


<commit_before>// Package mapreduce provides a simple abstraction for the general Map/Reduce
// pattern.
package mapreduce

import (
	"sync"
)

// In order to utilize this package you must create a struct that implements
// the following interface.
type MapReduce interface {
	Map(in chan interface{}, out chan interface{})
	Reduce(in chan interface{}) interface{}
}

// Configuration used by the Map Reducer.
type Configuration struct {
	MapperCount int
	InChan      chan interface{}
	OutChan     chan interface{}
}

// NewMapReduceConfig returns a MapReduce Configuration struct with sensible
// defaults.
func NewMapReduceConfig() *Configuration {
	inChan := make(chan interface{})
	outChan := make(chan interface{})

	return &Configuration{
		MapperCount: 1,
		InChan:      inChan,
		OutChan:     outChan,
	}
}

// Run executes the MapReduce process.
func Run(mr MapReduce, c *Configuration) (interface{}, error) {

	var wg sync.WaitGroup

	// Map
	for i := 0; i < c.MapperCount; i++ {
		go func(wg *sync.WaitGroup) {
			wg.Add(1)
			mr.Map(c.InChan, c.OutChan)
			wg.Done()
		}(&wg)
	}

	go func(w *sync.WaitGroup) {
		w.Wait()
		close(c.OutChan)
	}(&wg)

	// Reduce
	resultChan := make(chan interface{}, 1)
	go func(res chan interface{}) {
		res <- mr.Reduce(c.OutChan)
	}(resultChan)

	return <-resultChan, nil
}
<commit_msg>simplify return<commit_after>// Package mapreduce provides a simple abstraction for the general Map/Reduce
// pattern.
package mapreduce

import (
	"sync"
)

// In order to utilize this package you must create a struct that implements
// the following interface.
type MapReduce interface {
	Map(in chan interface{}, out chan interface{})
	Reduce(in chan interface{}) interface{}
}

// Configuration used by the Map Reducer.
type Configuration struct {
	MapperCount int
	InChan      chan interface{}
	OutChan     chan interface{}
}

// NewMapReduceConfig returns a MapReduce Configuration struct with sensible
// defaults.
func NewMapReduceConfig() *Configuration {
	inChan := make(chan interface{})
	outChan := make(chan interface{})

	return &Configuration{
		MapperCount: 1,
		InChan:      inChan,
		OutChan:     outChan,
	}
}

// Run executes the MapReduce process.
func Run(mr MapReduce, c *Configuration) (interface{}, error) {

	var wg sync.WaitGroup

	// Map
	for i := 0; i < c.MapperCount; i++ {
		go func(wg *sync.WaitGroup) {
			wg.Add(1)
			mr.Map(c.InChan, c.OutChan)
			wg.Done()
		}(&wg)
	}

	go func(w *sync.WaitGroup) {
		w.Wait()
		close(c.OutChan)
	}(&wg)

	// Reduce
	res := mr.Reduce(c.OutChan)
	return res, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 The Vermeer Light Tools Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package sample provides various sampling strategies and utilities.
*/
package sample

import (
	m "github.com/jamiec7919/vermeer/math"
	"math"
)

// CosineHemisphere returns a unit vector sampled from the cosine weighted hemisphere. Normal
// is [0,0,1]
// pdf is cos(v,N)/Pi
func CosineHemisphere(u0, u1 float64) m.Vec3 {
	r := math.Sqrt(u0)
	theta := 2 * math.Pi * u1

	x := r * math.Cos(theta)
	y := r * math.Sin(theta)

	return m.Vec3{float32(x), float32(y), float32(math.Sqrt(1 - u0))}

}

// UniformSphere returns a unit vector uniformly sampled from the sphere.
// pdf is 1/(4*Pi)
func UniformSphere(u0, u1 float64) m.Vec3 {
	theta := 2 * u0 * math.Pi
	z := -1.0 + 2*u1

	r := math.Sqrt(1 - z*z)
	x := r * math.Cos(theta)
	y := r * math.Sin(theta)

	return m.Vec3{float32(x), float32(y), float32(z)}
}

// UniformDisk2D returns a 2D point sampled from the disk with given radius.  Uses
// uniform warping.
// pdf is 1/Pi*radius^2
func UniformDisk2D(radius, r0, r1 float32) (xo, yo float32) {
	// Square to disk warp

	x := -1 + 2*r0
	y := -1 + 2*r1
	r, theta := float32(0), float32(0)
	if x > -y && x > y {
		r = x
		theta = (m.Pi / 4) * y / x
	} else if x > -y && x < y {
		r = y
		theta = (m.Pi / 4) * (2 - x/y)

	} else if x < y && x < -y {
		r = -x
		theta = (m.Pi / 4) * (4 + y/x)

	} else if x > y && x < -y {
		r = -y
		theta = (m.Pi / 4) * (6 - x/y)
	}
	xo = radius * r * m.Cos(theta)
	yo = radius * r * m.Sin(theta)
	return
}
<commit_msg>Added different cosine and uniform hemisphere warps.<commit_after>// Copyright 2016 The Vermeer Light Tools Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package sample provides various sampling strategies and utilities.
*/
package sample

import (
	m "github.com/jamiec7919/vermeer/math"
	"math"
)

// CosineHemisphere returns a unit vector sampled from the cosine weighted hemisphere. Normal
// is [0,0,1]
// pdf is cos(v,N)/Pi
func CosineHemisphere(u0, u1 float64) m.Vec3 {
	r := math.Sqrt(1 - u0)
	theta := 2 * math.Pi * u1

	x := r * math.Cos(theta)
	y := r * math.Sin(theta)

	return m.Vec3{float32(x), float32(y), float32(math.Sqrt(u0))}

}

// CosineHemisphere2 returns a unit vector sampled from the cosine weighted hemisphere. Normal
// is [0,0,1]
// pdf is cos(v,N)/Pi
func CosineHemisphere2(u0, u1 float64) m.Vec3 {
	r := math.Sqrt(u0)
	theta := 2 * math.Pi * u1

	x := r * math.Cos(theta)
	y := r * math.Sin(theta)

	return m.Vec3{float32(x), float32(y), float32(math.Sqrt(1 - u0))}

}

// CosineHemisphereConcentric returns a unit vector sampled from the cosine weighted hemisphere. Normal
// is [0,0,1].  Uses Concentric (Shirley) mapping.
// pdf is cos(v,N)/Pi
func CosineHemisphereConcentric(u0, u1 float64) m.Vec3 {
	var r, phi float64

	u0 = -1 + (u0 * 2)
	u1 = -1 + (u1 * 2)

	switch {
	case u0 > -u1 && u0 > u1:
		r = u0
		phi = (math.Pi / 4) * (u1 / u0)
	case u0 < u1 && u0 > -u1:
		r = u1
		phi = (math.Pi / 4) * (2 - u0/u1)
	case u0 < -u1 && u0 < u1:
		r = -u0
		phi = (math.Pi / 4) * (4 + u1/u0)
	case u0 > u1 && u0 < -u1:
		r = -u1
		phi = (math.Pi / 4) * (6 - u0/u1)

	}

	x := r * math.Cos(phi)
	y := r * math.Sin(phi)

	return m.Vec3{float32(x), float32(y), m.Sqrt(1 - float32(r*r))}

}

// UniformHemisphere returns a unit vector sampled from the cosine weighted hemisphere. Normal
// is [0,0,1]
// pdf is 1/2pi
func UniformHemisphere(u0, u1 float64) m.Vec3 {
	r := math.Sqrt(1 - u1*u1)
	theta := 2 * math.Pi * u0

	x := r * math.Cos(theta)
	y := r * math.Sin(theta)

	return m.Vec3{float32(x), float32(y), float32(u1)}

}

// UniformSphere returns a unit vector uniformly sampled from the sphere.
// pdf is 1/(4*Pi)
func UniformSphere(u0, u1 float64) m.Vec3 {
	theta := 2 * u0 * math.Pi
	z := -1.0 + 2*u1

	r := math.Sqrt(1 - z*z)
	x := r * math.Cos(theta)
	y := r * math.Sin(theta)

	return m.Vec3{float32(x), float32(y), float32(z)}
}

// UniformDisk2D returns a 2D point sampled from the disk with given radius.  Uses
// uniform warping.
// pdf is 1/Pi*radius^2
func UniformDisk2D(radius, r0, r1 float32) (xo, yo float32) {
	// Square to disk warp

	x := -1 + 2*r0
	y := -1 + 2*r1
	r, theta := float32(0), float32(0)
	if x > -y && x > y {
		r = x
		theta = (m.Pi / 4) * y / x
	} else if x > -y && x < y {
		r = y
		theta = (m.Pi / 4) * (2 - x/y)

	} else if x < y && x < -y {
		r = -x
		theta = (m.Pi / 4) * (4 + y/x)

	} else if x > y && x < -y {
		r = -y
		theta = (m.Pi / 4) * (6 - x/y)
	}
	xo = radius * r * m.Cos(theta)
	yo = radius * r * m.Sin(theta)
	return
}
<|endoftext|>


<commit_before>package lockfile

import (
	"io/ioutil"
	"os"
	"testing"

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

func makeTempFile() string {
	tempFile, err := ioutil.TempFile("", "")
	if err != nil {
		panic(err)
	}

	return tempFile.Name()
}

func TestAcquire(t *testing.T) {
	fileName := makeTempFile()
	defer os.Remove(fileName)

	lock := NewLock(fileName)
	defer lock.Release()

	assert.Nil(t, lock.Acquire())
	assert.NotNil(t, lock.Acquire())
}

func TestAcquireNotCreated(t *testing.T) {
	name := "TestAcquireNotCreated"

	lock := NewLock(name)
	defer os.Remove(name)
	defer lock.finish()

	assert.Nil(t, lock.Acquire())
	_, err := os.Stat(name)
	assert.Nil(t, err)

	assert.NotNil(t, lock.Acquire())
	_, err = os.Stat(name)
	assert.Nil(t, err)

	assert.Nil(t, lock.Release())
	_, err = os.Stat(name)
	assert.True(t, os.IsNotExist(err))
}

func TestReleaseOK(t *testing.T) {
	fileName := makeTempFile()
	defer os.Remove(fileName)

	lock := NewLock(fileName)
	defer lock.finish()

	assert.Nil(t, lock.Acquire())
	assert.Nil(t, lock.Release())

	_, err := os.Stat(fileName)
	assert.Nil(t, err)
}

func TestReleaseAbsentLock(t *testing.T) {
	lock := NewLock("WTF")

	assert.NotNil(t, lock.Release())
}

func TestLockFileIsNotHarmuful(t *testing.T) {
	content := []byte("content")
	fileName := makeTempFile()
	defer os.Remove(fileName)

	ioutil.WriteFile(fileName, content, os.FileMode(0666))

	lock := NewLock(fileName)
	defer lock.finish()

	lock.Acquire()

	readContent, err := ioutil.ReadFile(fileName)
	assert.Nil(t, err)
	assert.Equal(t, content, readContent)

	lock.Release()

	readContent, err = ioutil.ReadFile(fileName)
	assert.Nil(t, err)
	assert.Equal(t, content, readContent)
}

func TestCannotAcquireWithWrongPermissions(t *testing.T) {
	fileName := makeTempFile()
	defer os.Remove(fileName)

	os.Chmod(fileName, os.FileMode(0200))

	lock := NewLock(fileName)
	assert.NotNil(t, lock.Acquire())
}

func TestLockDirectory(t *testing.T) {
	tempDir, _ := ioutil.TempDir("", "")
	defer os.RemoveAll(tempDir)

	lock := NewLock(tempDir)
	assert.Nil(t, lock.Acquire())
	assert.Nil(t, lock.Release())
}
<commit_msg>Add test to check Stringer interface for the lock file<commit_after>package lockfile

import (
	"io/ioutil"
	"os"
	"testing"

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

func makeTempFile() string {
	tempFile, err := ioutil.TempFile("", "")
	if err != nil {
		panic(err)
	}

	return tempFile.Name()
}

func TestAcquire(t *testing.T) {
	fileName := makeTempFile()
	defer os.Remove(fileName)

	lock := NewLock(fileName)
	defer lock.Release()

	assert.Nil(t, lock.Acquire())
	assert.NotNil(t, lock.Acquire())
}

func TestAcquireNotCreated(t *testing.T) {
	name := "TestAcquireNotCreated"

	lock := NewLock(name)
	defer os.Remove(name)
	defer lock.finish()

	assert.Nil(t, lock.Acquire())
	_, err := os.Stat(name)
	assert.Nil(t, err)

	assert.NotNil(t, lock.Acquire())
	_, err = os.Stat(name)
	assert.Nil(t, err)

	assert.Nil(t, lock.Release())
	_, err = os.Stat(name)
	assert.True(t, os.IsNotExist(err))
}

func TestReleaseOK(t *testing.T) {
	fileName := makeTempFile()
	defer os.Remove(fileName)

	lock := NewLock(fileName)
	defer lock.finish()

	assert.Nil(t, lock.Acquire())
	assert.Nil(t, lock.Release())

	_, err := os.Stat(fileName)
	assert.Nil(t, err)
}

func TestReleaseAbsentLock(t *testing.T) {
	lock := NewLock("WTF")

	assert.NotNil(t, lock.Release())
}

func TestLockFileIsNotHarmuful(t *testing.T) {
	content := []byte("content")
	fileName := makeTempFile()
	defer os.Remove(fileName)

	ioutil.WriteFile(fileName, content, os.FileMode(0666))

	lock := NewLock(fileName)
	defer lock.finish()

	lock.Acquire()

	readContent, err := ioutil.ReadFile(fileName)
	assert.Nil(t, err)
	assert.Equal(t, content, readContent)

	lock.Release()

	readContent, err = ioutil.ReadFile(fileName)
	assert.Nil(t, err)
	assert.Equal(t, content, readContent)
}

func TestCannotAcquireWithWrongPermissions(t *testing.T) {
	fileName := makeTempFile()
	defer os.Remove(fileName)

	os.Chmod(fileName, os.FileMode(0200))

	lock := NewLock(fileName)
	assert.NotNil(t, lock.Acquire())
}

func TestLockDirectory(t *testing.T) {
	tempDir, _ := ioutil.TempDir("", "")
	defer os.RemoveAll(tempDir)

	lock := NewLock(tempDir)
	assert.Nil(t, lock.Acquire())
	assert.Nil(t, lock.Release())
}

func TestStringer(t *testing.T) {
	assert.True(t, NewLock("").String() != "")
}
<|endoftext|>