<commit_before>// Copyright 2013 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package util

import (
	"strings"
)

// Naive algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
func mDiff(av, bv []string) (ret []string) {
	matrix := make([]int, (len(av)+1)*(len(bv)+1))
	pitch := (len(bv) + 1)
	for i, a := range av {
		mp := (i+1)*pitch + 1

		for _, b := range bv {
			if a == b {
				matrix[mp] = matrix[mp-1-pitch] + 1
			} else if matrix[mp-1] > matrix[mp-pitch] {
				matrix[mp] = matrix[mp-1]
			} else {
				matrix[mp] = matrix[mp-pitch]
			}
			mp++
		}
	}
	var inner func(i, j int, context int)
	inner = func(i, j int, context int) {
		if i > 0 && j > 0 && av[i-1] == bv[j-1] {
			i--
			j--
			inner(i, j, context-1)
			if context > 0 {
				ret = append(ret, "  "+bv[j])
			}
		} else if j > 0 && (i == 0 || matrix[i*pitch+j-1] >= matrix[(i-1)*pitch+j]) {
			inner(i, j-1, 3)
			ret = append(ret, "+ "+bv[j-1])
		} else if i > 0 && (j == 0 || matrix[i*pitch+j-1] < matrix[(i-1)*pitch+j]) {
			inner(i-1, j, 3)
			ret = append(ret, "- "+av[i-1])
		}
	}
	inner(len(av), len(bv), 0)
	return
}

func Diff(a, b string) string {
	if a == b {
		return ""
	}
	a = strings.Replace(a, "\r\n", "\n", -1)
	b = strings.Replace(b, "\r\n", "\n", -1)
	if a == b {
		return ""
	}
	return strings.Join(mDiff(strings.Split(a, "\n"), strings.Split(b, "\n")), "\n")
}
<commit_msg>Add context to the beginning and the end of the diff.<commit_after>// Copyright 2013 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package util

import (
	"strings"
)

// Naive algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
func mDiff(av, bv []string, context int) (ret []string) {
	matrix := make([]int, (len(av)+1)*(len(bv)+1))
	pitch := (len(bv) + 1)
	for i, a := range av {
		mp := (i+1)*pitch + 1

		for _, b := range bv {
			if a == b {
				matrix[mp] = matrix[mp-1-pitch] + 1
			} else if matrix[mp-1] > matrix[mp-pitch] {
				matrix[mp] = matrix[mp-1]
			} else {
				matrix[mp] = matrix[mp-pitch]
			}
			mp++
		}
	}

	var innerContext func(i, count int)
	innerContext = func(i, count int) {
		i--
		count--
		if count > 0 {
			innerContext(i, count)
		}
		ret = append(ret, "  "+av[i])
	}

	var inner func(i, j, k, iLast, contextLast int)
	inner = func(i, j, k, iLast, contextLast int) {
		changed := false
		if i > 0 && j > 0 && av[i-1] == bv[j-1] {
			c := contextLast
			if k > 0 {
				c = i - 1
			}

			inner(i-1, j-1, k-1, iLast, c)

			// add context before the change
			if k > 0 {
				ret = append(ret, "  "+av[i-1])
			}
		} else if j > 0 && (i == 0 || matrix[i*pitch+j-1] >= matrix[(i-1)*pitch+j]) {
			changed = true
			inner(i, j-1, context, i, contextLast)
			ret = append(ret, "+ "+bv[j-1])
		} else if i > 0 && (j == 0 || matrix[i*pitch+j-1] < matrix[(i-1)*pitch+j]) {
			changed = true
			inner(i-1, j, context, i-1, contextLast)
			ret = append(ret, "- "+av[i-1])
		}

		if changed {
			// add context after the change
			l := iLast
			if l > contextLast {
				l = contextLast
			}

			m := l - i
			if m > 0 {
				if m > context {
					m = context
				}
				innerContext(i+m, m)
			}
		}
	}

	inner(len(av), len(bv), 0, len(av), len(av))
	return
}

func Diff(a, b string) string {
	if a == b {
		return ""
	}
	a = strings.Replace(a, "\r\n", "\n", -1)
	b = strings.Replace(b, "\r\n", "\n", -1)
	if a == b {
		return ""
	}
	return strings.Join(mDiff(strings.Split(a, "\n"), strings.Split(b, "\n"), 3), "\n")
}
<|endoftext|>


<commit_before>package plugin_repo_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	testcmd "github.com/cloudfoundry/cli/testhelpers/commands"
	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
	testreq "github.com/cloudfoundry/cli/testhelpers/requirements"
	testterm "github.com/cloudfoundry/cli/testhelpers/terminal"

	"github.com/cloudfoundry/cli/cf/command_registry"
	"github.com/cloudfoundry/cli/cf/configuration/core_config"
	"github.com/cloudfoundry/cli/cf/models"
	. "github.com/cloudfoundry/cli/testhelpers/matchers"

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

var _ = Describe("add-plugin-repo", func() {
	var (
		ui                  *testterm.FakeUI
		config              core_config.Repository
		requirementsFactory *testreq.FakeReqFactory
		testServer          *httptest.Server
		deps                command_registry.Dependency
	)

	updateCommandDependency := func(pluginCall bool) {
		deps.Ui = ui
		deps.Config = config
		command_registry.Commands.SetCommand(command_registry.Commands.FindCommand("add-plugin-repo").SetDependency(deps, pluginCall))
	}

	BeforeEach(func() {
		ui = &testterm.FakeUI{}
		requirementsFactory = &testreq.FakeReqFactory{}
		config = testconfig.NewRepositoryWithDefaults()
	})

	var callAddPluginRepo = func(args []string) bool {
		return testcmd.RunCliCommand("add-plugin-repo", args, requirementsFactory, updateCommandDependency, false)
	}

	Context("When repo server is valid", func() {
		BeforeEach(func() {

			h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				fmt.Fprintln(w, `{"plugins":[
				{
					"name":"echo",
					"description":"none",
					"version":"4",
					"binaries":[
						{
							"platform":"osx",
							"url":"https://github.com/simonleung8/cli-plugin-echo/raw/master/bin/osx/echo",
							"checksum":"2a087d5cddcfb057fbda91e611c33f46"
						}
					]
				}]
			}`)
			})
			testServer = httptest.NewServer(h)
		})

		AfterEach(func() {
			testServer.Close()
		})

		It("saves the repo url into config", func() {
			callAddPluginRepo([]string{"repo", testServer.URL})

			Ω(config.PluginRepos()[0].Name).To(Equal("repo"))
			Ω(config.PluginRepos()[0].Url).To(Equal(testServer.URL))
		})
	})

	Context("repo name already existing", func() {
		BeforeEach(func() {
			config.SetPluginRepo(models.PluginRepo{Name: "repo", Url: "http://repo.com"})
		})

		It("informs user of the already existing repo", func() {

			callAddPluginRepo([]string{"repo", "http://repo2.com"})

			Ω(ui.Outputs).To(ContainSubstrings(
				[]string{"Plugin repo named \"repo\"", " already exists"},
			))
		})
	})

	Context("repo address already existing", func() {
		BeforeEach(func() {
			config.SetPluginRepo(models.PluginRepo{Name: "repo1", Url: "http://repo.com"})
		})

		It("informs user of the already existing repo", func() {

			callAddPluginRepo([]string{"repo2", "http://repo.com"})

			Ω(ui.Outputs).To(ContainSubstrings(
				[]string{"http://repo.com (repo1)", " already exists."},
			))
		})
	})

	Context("When repo server is not valid", func() {

		Context("server url is invalid", func() {
			It("informs user of invalid url which does not has prefix http", func() {

				callAddPluginRepo([]string{"repo", "msn.com"})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"msn.com", "is not a valid url"},
				))
			})

			It("should not contain the tip", func() {
				callAddPluginRepo([]string{"repo", "msn.com"})

				Ω(ui.Outputs).To(Not(ContainSubstrings(
					[]string{"TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection."},
				)))
			})
		})

		Context("server does not has a '/list' endpoint", func() {
			It("informs user of invalid repo server", func() {

				callAddPluginRepo([]string{"repo", "https://google.com"})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"https://google.com/list", "is not responding."},
				))
			})
		})

		Context("server responses with invalid json", func() {
			BeforeEach(func() {

				h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					fmt.Fprintln(w, `"plugins":[]}`)
				})
				testServer = httptest.NewServer(h)
			})

			AfterEach(func() {
				testServer.Close()
			})

			It("informs user of invalid repo server", func() {
				callAddPluginRepo([]string{"repo", testServer.URL})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"Error processing data from server"},
				))
			})
		})

		Context("server responses with json without 'plugins' object", func() {
			BeforeEach(func() {

				h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					fmt.Fprintln(w, `{"bad_plugins":[
						{
							"name": "plugin1",
							"description": "none"
						}
					]}`)
				})
				testServer = httptest.NewServer(h)
			})

			AfterEach(func() {
				testServer.Close()
			})

			It("informs user of invalid repo server", func() {
				callAddPluginRepo([]string{"repo", testServer.URL})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"\"Plugins\" object not found in the responded data"},
				))
			})
		})

		Context("When connection could not be established", func() {
			It("prints a tip", func() {
				callAddPluginRepo([]string{"repo", "https://example.com:1234"})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection."},
				))
			})
		})

		Context("server responds with an http error", func() {
			BeforeEach(func() {
				h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					w.WriteHeader(http.StatusInternalServerError)
				})
				testServer = httptest.NewServer(h)
			})

			AfterEach(func() {
				testServer.Close()
			})

			It("does not print a tip", func() {
				callAddPluginRepo([]string{"repo", testServer.URL})

				Ω(ui.Outputs).NotTo(ContainSubstrings(
					[]string{"TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection."},
				))
			})
		})
	})
})
<commit_msg>Make add-plugin-repo test not take 15 seconds<commit_after>package plugin_repo_test

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	testcmd "github.com/cloudfoundry/cli/testhelpers/commands"
	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
	testreq "github.com/cloudfoundry/cli/testhelpers/requirements"
	testterm "github.com/cloudfoundry/cli/testhelpers/terminal"

	"github.com/cloudfoundry/cli/cf/command_registry"
	"github.com/cloudfoundry/cli/cf/configuration/core_config"
	"github.com/cloudfoundry/cli/cf/models"
	. "github.com/cloudfoundry/cli/testhelpers/matchers"

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

var _ = Describe("add-plugin-repo", func() {
	var (
		ui                  *testterm.FakeUI
		config              core_config.Repository
		requirementsFactory *testreq.FakeReqFactory
		testServer          *httptest.Server
		deps                command_registry.Dependency
	)

	updateCommandDependency := func(pluginCall bool) {
		deps.Ui = ui
		deps.Config = config
		command_registry.Commands.SetCommand(command_registry.Commands.FindCommand("add-plugin-repo").SetDependency(deps, pluginCall))
	}

	BeforeEach(func() {
		ui = &testterm.FakeUI{}
		requirementsFactory = &testreq.FakeReqFactory{}
		config = testconfig.NewRepositoryWithDefaults()
	})

	var callAddPluginRepo = func(args []string) bool {
		return testcmd.RunCliCommand("add-plugin-repo", args, requirementsFactory, updateCommandDependency, false)
	}

	Context("When repo server is valid", func() {
		BeforeEach(func() {

			h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				fmt.Fprintln(w, `{"plugins":[
				{
					"name":"echo",
					"description":"none",
					"version":"4",
					"binaries":[
						{
							"platform":"osx",
							"url":"https://github.com/simonleung8/cli-plugin-echo/raw/master/bin/osx/echo",
							"checksum":"2a087d5cddcfb057fbda91e611c33f46"
						}
					]
				}]
			}`)
			})
			testServer = httptest.NewServer(h)
		})

		AfterEach(func() {
			testServer.Close()
		})

		It("saves the repo url into config", func() {
			callAddPluginRepo([]string{"repo", testServer.URL})

			Ω(config.PluginRepos()[0].Name).To(Equal("repo"))
			Ω(config.PluginRepos()[0].Url).To(Equal(testServer.URL))
		})
	})

	Context("repo name already existing", func() {
		BeforeEach(func() {
			config.SetPluginRepo(models.PluginRepo{Name: "repo", Url: "http://repo.com"})
		})

		It("informs user of the already existing repo", func() {

			callAddPluginRepo([]string{"repo", "http://repo2.com"})

			Ω(ui.Outputs).To(ContainSubstrings(
				[]string{"Plugin repo named \"repo\"", " already exists"},
			))
		})
	})

	Context("repo address already existing", func() {
		BeforeEach(func() {
			config.SetPluginRepo(models.PluginRepo{Name: "repo1", Url: "http://repo.com"})
		})

		It("informs user of the already existing repo", func() {

			callAddPluginRepo([]string{"repo2", "http://repo.com"})

			Ω(ui.Outputs).To(ContainSubstrings(
				[]string{"http://repo.com (repo1)", " already exists."},
			))
		})
	})

	Context("When repo server is not valid", func() {

		Context("server url is invalid", func() {
			It("informs user of invalid url which does not has prefix http", func() {

				callAddPluginRepo([]string{"repo", "msn.com"})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"msn.com", "is not a valid url"},
				))
			})

			It("should not contain the tip", func() {
				callAddPluginRepo([]string{"repo", "msn.com"})

				Ω(ui.Outputs).To(Not(ContainSubstrings(
					[]string{"TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection."},
				)))
			})
		})

		Context("server does not has a '/list' endpoint", func() {
			It("informs user of invalid repo server", func() {

				callAddPluginRepo([]string{"repo", "https://google.com"})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"https://google.com/list", "is not responding."},
				))
			})
		})

		Context("server responses with invalid json", func() {
			BeforeEach(func() {

				h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					fmt.Fprintln(w, `"plugins":[]}`)
				})
				testServer = httptest.NewServer(h)
			})

			AfterEach(func() {
				testServer.Close()
			})

			It("informs user of invalid repo server", func() {
				callAddPluginRepo([]string{"repo", testServer.URL})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"Error processing data from server"},
				))
			})
		})

		Context("server responses with json without 'plugins' object", func() {
			BeforeEach(func() {

				h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					fmt.Fprintln(w, `{"bad_plugins":[
						{
							"name": "plugin1",
							"description": "none"
						}
					]}`)
				})
				testServer = httptest.NewServer(h)
			})

			AfterEach(func() {
				testServer.Close()
			})

			It("informs user of invalid repo server", func() {
				callAddPluginRepo([]string{"repo", testServer.URL})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"\"Plugins\" object not found in the responded data"},
				))
			})
		})

		Context("When connection could not be established", func() {
			It("prints a tip", func() {
				callAddPluginRepo([]string{"repo", "https://example.com:"})

				Ω(ui.Outputs).To(ContainSubstrings(
					[]string{"TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection."},
				))
			})
		})

		Context("server responds with an http error", func() {
			BeforeEach(func() {
				h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					w.WriteHeader(http.StatusInternalServerError)
				})
				testServer = httptest.NewServer(h)
			})

			AfterEach(func() {
				testServer.Close()
			})

			It("does not print a tip", func() {
				callAddPluginRepo([]string{"repo", testServer.URL})

				Ω(ui.Outputs).NotTo(ContainSubstrings(
					[]string{"TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection."},
				))
			})
		})
	})
})
<|endoftext|>


<commit_before>package linode

import (
	"encoding/json"
	"fmt"
	"sort"
	"strconv"
)

const (
	linodeListAction   = "linode.list"
	linodeIPListAction = "linode.ip.list"
)

func (c *Client) LinodeList() ([]Linode, error) {
	req := c.NewRequest().AddAction(linodeListAction, nil)
	var err error

	responses, err := req.GetJSON()
	if err != nil {
		return nil, err
	}
	if len(responses) != 1 {
		return nil, fmt.Errorf("unexpected number of responses: %d", len(responses))
	}

	var linodes sortedLinodes
	if responses[0].Action != linodeListAction {
		return nil, fmt.Errorf("unexpected api action %s", responses[0].Action)
	}
	if err = json.Unmarshal(responses[0].Data, &linodes); err != nil {
		return nil, err
	}
	sort.Sort(linodes)

	return []Linode(linodes), nil
}

func (c *Client) LinodeIPList(linodeIDs []int) (map[int][]LinodeIP, error) {
	req := c.NewRequest()
	var err error
	// batch all requests together
	for _, id := range linodeIDs {
		idVal := strconv.Itoa(id)
		req.AddAction(linodeIPListAction, map[string]string{"LinodeID": idVal})
	}

	responses, err := req.GetJSON()
	if err != nil {
		return nil, err
	}

	m := make(map[int][]LinodeIP, len(responses))
	for _, r := range responses {
		if r.Action != linodeIPListAction {
			return nil, fmt.Errorf("unexpected api action %s", r.Action)
		}
		var ips sortedLinodeIPs
		if err = json.Unmarshal(r.Data, &ips); err != nil {
			return nil, err
		}
		if len(ips) > 0 {
			sort.Sort(ips)
			m[ips[0].LinodeID] = []LinodeIP(ips)
		}
	}

	return m, nil
}

type Linode struct {
	ID           int    `json:"LINODEID"`
	Status       int    `json:"STATUS"`
	Label        string `json:"LABEL"`
	DisplayGroup string `json:"LPM_DISPLAYGROUP"`
	RAM          int    `json:"TOTALRAM"`
}

func (l Linode) IsRunning() bool {
	return l.Status == 1
}

type LinodeIP struct {
	LinodeID int    `json:"LINODEID"`
	Public   int    `json:"ISPUBLIC"`
	IP       string `json:"IPADDRESS"`
}

func (i LinodeIP) IsPublic() bool {
	return i.Public == 1
}

// Sort LinodeIPs by private IPs first
type sortedLinodeIPs []LinodeIP

func (sorted sortedLinodeIPs) Len() int {
	return len(sorted)
}
func (sorted sortedLinodeIPs) Swap(i, j int) {
	sorted[i], sorted[j] = sorted[j], sorted[i]
}

func (sorted sortedLinodeIPs) Less(i, j int) bool {
	return sorted[i].Public < sorted[j].Public
}

// Sort Linodes by DisplayGroup then Label
type sortedLinodes []Linode

func (sorted sortedLinodes) Len() int {
	return len(sorted)
}
func (sorted sortedLinodes) Swap(i, j int) {
	sorted[i], sorted[j] = sorted[j], sorted[i]
}

func (sorted sortedLinodes) Less(i, j int) bool {
	if sorted[i].DisplayGroup == sorted[j].DisplayGroup {
		return sorted[i].Label < sorted[j].Label
	} else {
		return sorted[i].DisplayGroup < sorted[j].DisplayGroup
	}
}
<commit_msg>more documenting and GoLinting<commit_after>package linode

import (
	"encoding/json"
	"fmt"
	"sort"
	"strconv"
)

const (
	linodeListAction   = "linode.list"
	linodeIPListAction = "linode.ip.list"
)

// LinodeList returns slice of Linodes
func (c *Client) LinodeList() ([]Linode, error) {
	req := c.NewRequest().AddAction(linodeListAction, nil)
	var err error

	responses, err := req.GetJSON()
	if err != nil {
		return nil, err
	}
	if len(responses) != 1 {
		return nil, fmt.Errorf("unexpected number of responses: %d", len(responses))
	}

	var linodes sortedLinodes
	if responses[0].Action != linodeListAction {
		return nil, fmt.Errorf("unexpected api action %s", responses[0].Action)
	}
	if err = json.Unmarshal(responses[0].Data, &linodes); err != nil {
		return nil, err
	}
	sort.Sort(linodes)

	return []Linode(linodes), nil
}

// LinodeIPList returns mapping of LinodeID to slice of its LinodeIPs
func (c *Client) LinodeIPList(linodeIDs []int) (map[int][]LinodeIP, error) {
	req := c.NewRequest()
	var err error
	// batch all requests together
	for _, id := range linodeIDs {
		idVal := strconv.Itoa(id)
		req.AddAction(linodeIPListAction, map[string]string{"LinodeID": idVal})
	}

	responses, err := req.GetJSON()
	if err != nil {
		return nil, err
	}

	m := make(map[int][]LinodeIP, len(responses))
	for _, r := range responses {
		if r.Action != linodeIPListAction {
			return nil, fmt.Errorf("unexpected api action %s", r.Action)
		}
		var ips sortedLinodeIPs
		if err = json.Unmarshal(r.Data, &ips); err != nil {
			return nil, err
		}
		if len(ips) > 0 {
			sort.Sort(ips)
			m[ips[0].LinodeID] = []LinodeIP(ips)
		}
	}

	return m, nil
}

// Linode represent a Linode as returned by the API
type Linode struct {
	ID           int    `json:"LINODEID"`
	Status       int    `json:"STATUS"`
	Label        string `json:"LABEL"`
	DisplayGroup string `json:"LPM_DISPLAYGROUP"`
	RAM          int    `json:"TOTALRAM"`
}

// IsRunning returns true if Status == 1
func (l Linode) IsRunning() bool {
	return l.Status == 1
}

// LinodeIP respresents a Linode.IP as returned by the API
type LinodeIP struct {
	LinodeID int    `json:"LINODEID"`
	Public   int    `json:"ISPUBLIC"`
	IP       string `json:"IPADDRESS"`
}

// IsPublic returns true if IP is public
func (i LinodeIP) IsPublic() bool {
	return i.Public == 1
}

// Sort LinodeIPs by private IPs first
type sortedLinodeIPs []LinodeIP

func (sorted sortedLinodeIPs) Len() int {
	return len(sorted)
}
func (sorted sortedLinodeIPs) Swap(i, j int) {
	sorted[i], sorted[j] = sorted[j], sorted[i]
}

func (sorted sortedLinodeIPs) Less(i, j int) bool {
	return sorted[i].Public < sorted[j].Public
}

// Sort Linodes by DisplayGroup then Label
type sortedLinodes []Linode

func (sorted sortedLinodes) Len() int {
	return len(sorted)
}
func (sorted sortedLinodes) Swap(i, j int) {
	sorted[i], sorted[j] = sorted[j], sorted[i]
}

func (sorted sortedLinodes) Less(i, j int) bool {
	if sorted[i].DisplayGroup == sorted[j].DisplayGroup {
		return sorted[i].Label < sorted[j].Label
	}
	return sorted[i].DisplayGroup < sorted[j].DisplayGroup
}
<|endoftext|>


<commit_before>package analyze

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"
)

type edge struct {
	target *Target
	dep    *Target
}

type Graph struct {
	TargetByWrite  map[string]*Target
	TargetByName   map[string]*Target
	CommandByID    map[string]*Command
	CommandByWrite map[string]*Command
	Errors         []Error
	UsedEdges      map[edge]struct{}
}

type Target struct {
	Name     string
	Reads    map[string]struct{}
	Deps     map[string]struct{}
	Writes   map[string]struct{}
	Duration time.Duration
	Commands []*Command
	Errors   []Error
}

func (a *Target) Start() time.Time {
	return a.Commands[0].Time
}

type Error interface {
	HTML(g *Graph) string
}

type dupWrite struct {
	write    string
	commands []*Command
}

func (d *dupWrite) HTML(g *Graph) string {
	s := ""
	for _, a := range d.commands {
		s += fmt.Sprintf("
%s\n", commandRef(a))
	}
	return fmt.Sprintf("file %q written by
%s
", d.write, s)
}

/* parse a "target: dep" file. */
func ParseDepFile(content []byte) ([]string, []string) {
	content = bytes.Replace(content, []byte("\\\n"), nil, -1)
	components := bytes.Split(content, []byte(":"))
	if len(components) != 2 {
		return nil, nil
	}

	targetStrs := bytes.Split(components[0], []byte(" "))
	depStrs := bytes.Split(components[1], []byte(" "))

	var targets, deps []string
	for _, t := range targetStrs {
		if len(t) > 0 {
			targets = append(targets, string(t))
		}
	}
	for _, d := range depStrs {
		if len(d) > 0 {
			deps = append(deps, string(d))
		}
	}

	return targets, deps
}

func ReadDir(dir string, depRe *regexp.Regexp) ([]*Command, error) {
	dir = filepath.Clean(dir)
	result := []*Command{}
	f, err := os.Open(dir)
	if err != nil {
		return nil, err
	}

	names, err := f.Readdirnames(-1)
	if err != nil {
		return nil, err
	}
	base := filepath.Dir(dir)
	for _, nm := range names {
		fn := filepath.Join(dir, nm)
		contents, err := ioutil.ReadFile(fn)
		if err != nil {
			return nil, fmt.Errorf("read(%q): %v", fn, err)
		}

		var a Command
		if err := json.Unmarshal(contents, &a); err != nil {
			return nil, fmt.Errorf("Unmarshal(%q): %v", fn, err)
		}

		a.Target, err = filepath.Rel(base, filepath.Join(a.Dir, a.Target))
		if err != nil {
			return nil, fmt.Errorf("rel: %v", a)
		}
		a.Target = filepath.Clean(a.Target)
		a.Filename = nm

		// add contents of .dep file to the command.
		for _, w := range a.Writes {
			if depRe == nil || !depRe.MatchString(w) {
				continue
			}
			c, err := ioutil.ReadFile(filepath.Join(base, w))
			if err != nil {
				continue
			}

			found := false
			targets, deps := ParseDepFile(c)
			if len(targets) == 0 {
				continue
			}
			for _, t := range targets {
				t = filepath.Clean(filepath.Join(a.Dir, t))
				if t == filepath.Join(base, a.Target) {
					found = true
				}
			}
			if !found {
				continue
			}

			for _, d := range deps {
				a.Deps = append(a.Deps, d)
			}
		}

		var clean []string
		for _, p := range a.Deps {
			p, err = filepath.Rel(base, filepath.Join(a.Dir, p))
			if err != nil {
				return nil, fmt.Errorf("rel %q %v", p, err)
			}

			clean = append(clean, p)
		}

		a.Deps = clean

		result = append(result, &a)
	}

	return result, nil
}

type annSlice []*Command

func (s annSlice) Len() int {
	return len(s)
}

func (s annSlice) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
func (s annSlice) Less(i, j int) bool {
	return s[i].Time.UnixNano() < s[j].Time.UnixNano()
}

func (g *Graph) computeTarget(target *Target) {
	target.Writes = map[string]struct{}{}
	target.Reads = map[string]struct{}{}
	target.Deps = map[string]struct{}{}
	sort.Sort(annSlice(target.Commands))

	yes := struct{}{}
	for _, a := range target.Commands {
		a.target = target
		target.Duration += a.Duration
		for _, f := range a.Deps {
			if f == "" {
				continue
			}
			target.Deps[f] = yes
		}
		for _, f := range a.Reads {
			if f == "" {
				continue
			}
			if strings.HasPrefix(f, "/") {
				continue
			}
			target.Reads[f] = yes
		}
		for _, f := range a.Deletions {
			if f == "" {
				continue
			}
			delete(target.Writes, f)
			delete(target.Reads, f)
		}
		for _, f := range a.Writes {
			if f == "" {
				continue
			}
			target.Writes[f] = yes
		}
		if a.Target != "" {
			target.Name = a.Target
		}

	}
}

func (g *Graph) addError(e Error) {
	g.Errors = append(g.Errors, e)
}

func (g *Graph) addCommand(ann *Command) {
	g.CommandByID[ann.ID()] = ann
	for _, w := range ann.Writes {
		if exist, ok := g.CommandByWrite[w]; ok {
			g.addError(&dupWrite{w, []*Command{exist, ann}})
		} else {
			g.CommandByWrite[w] = ann
		}
	}

	target := g.TargetByName[ann.Target]
	if target == nil {
		target = &Target{}
		g.TargetByName[ann.Target] = target
	}

	target.Commands = append(target.Commands, ann)
	for _, w := range ann.Writes {
		g.TargetByWrite[w] = target
	}
}

func NewGraph(anns []*Command) *Graph {
	g := Graph{
		TargetByName:   map[string]*Target{},
		TargetByWrite:  map[string]*Target{},
		CommandByWrite: map[string]*Command{},
		CommandByID:    map[string]*Command{},
		UsedEdges:      map[edge]struct{}{},
	}

	for _, ann := range anns {
		g.addCommand(ann)
	}

	for _, a := range g.TargetByName {
		g.computeTarget(a)
	}
	g.checkTargets()
	return &g
}
<commit_msg>Fix bug with absolute paths in dependencies.<commit_after>package analyze

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"
)

type edge struct {
	target *Target
	dep    *Target
}

type Graph struct {
	TargetByWrite  map[string]*Target
	TargetByName   map[string]*Target
	CommandByID    map[string]*Command
	CommandByWrite map[string]*Command
	Errors         []Error
	UsedEdges      map[edge]struct{}
}

type Target struct {
	Name     string
	Reads    map[string]struct{}
	Deps     map[string]struct{}
	Writes   map[string]struct{}
	Duration time.Duration
	Commands []*Command
	Errors   []Error
}

func (a *Target) Start() time.Time {
	return a.Commands[0].Time
}

type Error interface {
	HTML(g *Graph) string
}

type dupWrite struct {
	write    string
	commands []*Command
}

func (d *dupWrite) HTML(g *Graph) string {
	s := ""
	for _, a := range d.commands {
		s += fmt.Sprintf("
%s\n", commandRef(a))
	}
	return fmt.Sprintf("file %q written by
%s
", d.write, s)
}

/* parse a "target: dep" file. */
func ParseDepFile(content []byte) ([]string, []string) {
	content = bytes.Replace(content, []byte("\\\n"), nil, -1)
	components := bytes.Split(content, []byte(":"))
	if len(components) != 2 {
		return nil, nil
	}

	targetStrs := bytes.Split(components[0], []byte(" "))
	depStrs := bytes.Split(components[1], []byte(" "))

	var targets, deps []string
	for _, t := range targetStrs {
		if len(t) > 0 {
			targets = append(targets, string(t))
		}
	}
	for _, d := range depStrs {
		if len(d) > 0 {
			deps = append(deps, string(d))
		}
	}

	return targets, deps
}

func ReadDir(dir string, depRe *regexp.Regexp) ([]*Command, error) {
	dir = filepath.Clean(dir)
	result := []*Command{}
	f, err := os.Open(dir)
	if err != nil {
		return nil, err
	}

	names, err := f.Readdirnames(-1)
	if err != nil {
		return nil, err
	}
	base := filepath.Dir(dir)
	for _, nm := range names {
		fn := filepath.Join(dir, nm)
		contents, err := ioutil.ReadFile(fn)
		if err != nil {
			return nil, fmt.Errorf("read(%q): %v", fn, err)
		}

		var a Command
		if err := json.Unmarshal(contents, &a); err != nil {
			return nil, fmt.Errorf("Unmarshal(%q): %v", fn, err)
		}

		a.Target, err = filepath.Rel(base, filepath.Join(a.Dir, a.Target))
		if err != nil {
			return nil, fmt.Errorf("rel: %v", a)
		}
		a.Target = filepath.Clean(a.Target)
		a.Filename = nm

		// add contents of .dep file to the command.
		for _, w := range a.Writes {
			if depRe == nil || !depRe.MatchString(w) {
				continue
			}
			c, err := ioutil.ReadFile(filepath.Join(base, w))
			if err != nil {
				continue
			}

			found := false
			targets, deps := ParseDepFile(c)
			if len(targets) == 0 {
				continue
			}
			for _, t := range targets {
				t = filepath.Clean(filepath.Join(a.Dir, t))
				if t == filepath.Join(base, a.Target) {
					found = true
				}
			}
			if !found {
				continue
			}

			for _, d := range deps {
				a.Deps = append(a.Deps, d)
			}
		}

		var clean []string
		for _, p := range a.Deps {
			if !filepath.IsAbs(p) {
				p = filepath.Join(a.Dir, p)
			}
			p, err = filepath.Rel(base, p)
			if err != nil {
				return nil, fmt.Errorf("rel %q %v", p, err)
			}

			clean = append(clean, p)
		}

		a.Deps = clean

		result = append(result, &a)
	}

	return result, nil
}

type annSlice []*Command

func (s annSlice) Len() int {
	return len(s)
}

func (s annSlice) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
func (s annSlice) Less(i, j int) bool {
	return s[i].Time.UnixNano() < s[j].Time.UnixNano()
}

func (g *Graph) computeTarget(target *Target) {
	target.Writes = map[string]struct{}{}
	target.Reads = map[string]struct{}{}
	target.Deps = map[string]struct{}{}
	sort.Sort(annSlice(target.Commands))

	yes := struct{}{}
	for _, a := range target.Commands {
		a.target = target
		target.Duration += a.Duration
		for _, f := range a.Deps {
			if f == "" {
				continue
			}
			target.Deps[f] = yes
		}
		for _, f := range a.Reads {
			if f == "" {
				continue
			}
			if strings.HasPrefix(f, "/") {
				continue
			}
			target.Reads[f] = yes
		}
		for _, f := range a.Deletions {
			if f == "" {
				continue
			}
			delete(target.Writes, f)
			delete(target.Reads, f)
		}
		for _, f := range a.Writes {
			if f == "" {
				continue
			}
			target.Writes[f] = yes
		}
		if a.Target != "" {
			target.Name = a.Target
		}

	}
}

func (g *Graph) addError(e Error) {
	g.Errors = append(g.Errors, e)
}

func (g *Graph) addCommand(ann *Command) {
	g.CommandByID[ann.ID()] = ann
	for _, w := range ann.Writes {
		if exist, ok := g.CommandByWrite[w]; ok {
			g.addError(&dupWrite{w, []*Command{exist, ann}})
		} else {
			g.CommandByWrite[w] = ann
		}
	}

	target := g.TargetByName[ann.Target]
	if target == nil {
		target = &Target{}
		g.TargetByName[ann.Target] = target
	}

	target.Commands = append(target.Commands, ann)
	for _, w := range ann.Writes {
		g.TargetByWrite[w] = target
	}
}

func NewGraph(anns []*Command) *Graph {
	g := Graph{
		TargetByName:   map[string]*Target{},
		TargetByWrite:  map[string]*Target{},
		CommandByWrite: map[string]*Command{},
		CommandByID:    map[string]*Command{},
		UsedEdges:      map[edge]struct{}{},
	}

	for _, ann := range anns {
		g.addCommand(ann)
	}

	for _, a := range g.TargetByName {
		g.computeTarget(a)
	}
	g.checkTargets()
	return &g
}
<|endoftext|>


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

package sources

import (
	"fmt"
	"net/url"
	"time"

	. "k8s.io/heapster/core"
	"k8s.io/heapster/sources/api"

	"github.com/golang/glog"
	kube_api "k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/cache"
	kube_client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/fields"
)

// TODO: following constants are copied from k8s, change to use them directly
const (
	kubernetesPodNameLabel      = "io.kubernetes.pod.name"
	kubernetesPodNamespaceLabel = "io.kubernetes.pod.namespace"
	kubernetesPodUID            = "io.kubernetes.pod.uid"
)

// Kubelet-provided metrics for pod and system container.
type kubeletMetricsSource struct {
	host          Host
	kubeletClient *KubeletClient
	hostname      string
	hostId        string
}

func (this *kubeletMetricsSource) String() string {
	return fmt.Sprintf("kubelet:%s:%d", this.host.IP, this.host.Port)
}

func (this *kubeletMetricsSource) decodeMetrics(c *api.Container) (string, *MetricSet) {
	var metricSetKey string
	cMetrics := &MetricSet{
		MetricValues: map[string]MetricValue{},
		Labels:       map[string]string{},
	}

	for _, metric := range StandardMetrics {
		if metric.HasValue(&c.Spec) {
			cMetrics.MetricValues[metric.Name] = metric.GetValue(&c.Spec, c.Stats[0])
		}
	}

	if isNode(c) {
		metricSetKey = NodeKey(this.hostname)
		cMetrics.Labels[LabelMetricSetType.Key] = MetricSetTypeNode
	} else if isSysContainer(c) {
		cName := getSysContainerName(c)
		metricSetKey = NodeContainerKey(this.hostname, cName)
		cMetrics.Labels[LabelMetricSetType.Key] = MetricSetTypeSystemContainer
		cMetrics.Labels[LabelContainerName.Key] = cName
	} else {
		// TODO: figure out why "io.kubernetes.container.name" is not set
		cName := c.Name
		ns := c.Spec.Labels[kubernetesPodNamespaceLabel]
		podName := c.Spec.Labels[kubernetesPodNameLabel]
		metricSetKey = PodContainerKey(ns, podName, cName)
		cMetrics.Labels[LabelMetricSetType.Key] = MetricSetTypePodContainer
		cMetrics.Labels[LabelContainerName.Key] = cName
		cMetrics.Labels[LabelPodId.Key] = c.Spec.Labels[kubernetesPodUID]
		cMetrics.Labels[LabelPodName.Key] = podName
		cMetrics.Labels[LabelPodNamespace.Key] = ns
		cMetrics.Labels[LabelContainerBaseImage.Key] = c.Spec.Image
	}

	// common labels
	cMetrics.Labels[LabelHostname.Key] = this.hostname
	cMetrics.Labels[LabelHostID.Key] = this.hostId

	// TODO: add labels: LabelPodNamespaceUID, LabelLabels, LabelResourceID

	return metricSetKey, cMetrics
}

func (this *kubeletMetricsSource) ScrapeMetrics(start, end time.Time) *DataBatch {
	containers, err := this.kubeletClient.GetAllRawContainers(this.host, start, end)
	if err != nil {
		glog.Errorf("error while getting containers from Kubelet: %v", err)
	}
	glog.Infof("successfully obtained stats for %v containers", len(containers))

	result := &DataBatch{
		Timestamp:  end,
		MetricSets: map[string]*MetricSet{},
	}
	for _, c := range containers {
		name, metrics := this.decodeMetrics(&c)
		result.MetricSets[name] = metrics
	}
	return result
}

type kubeletProvider struct {
	nodeLister    *cache.StoreToNodeLister
	reflector     *cache.Reflector
	kubeletClient *KubeletClient
}

func (this *kubeletProvider) GetMetricsSources() []MetricsSource {
	sources := []MetricsSource{}
	nodes, err := this.nodeLister.List()
	if err != nil {
		glog.Errorf("error while listing nodes: %v", err)
		return sources
	}
	for _, node := range nodes.Items {
		hostname, ip, err := getNodeHostnameAndIP(&node)
		if err != nil {
			glog.Errorf("%v", err)
			continue
		}
		sources = append(sources, &kubeletMetricsSource{
			host:          Host{IP: ip, Port: this.kubeletClient.GetPort()},
			kubeletClient: this.kubeletClient,
			hostname:      hostname,
			hostId:        node.Spec.ExternalID,
		})
	}
	return sources
}

func getNodeHostnameAndIP(node *kube_api.Node) (string, string, error) {
	for _, c := range node.Status.Conditions {
		if c.Type == kube_api.NodeReady && c.Status != kube_api.ConditionTrue {
			return "", "", fmt.Errorf("Node %v is not ready", node.Name)
		}
	}
	hostname, ip := node.Name, ""
	for _, addr := range node.Status.Addresses {
		if addr.Type == kube_api.NodeHostName && addr.Address != "" {
			hostname = addr.Address
		}
		if addr.Type == kube_api.NodeInternalIP && addr.Address != "" {
			ip = addr.Address
		}
	}
	if ip != "" {
		return hostname, ip, nil
	}
	return "", "", fmt.Errorf("Node %v has no valid hostname and/or IP address: %v %v", node.Name, hostname, ip)
}

func NewKubeletProvider(uri *url.URL) (MetricsSourceProvider, error) {
	// create clients
	kubeConfig, kubeletConfig, err := getKubeConfigs(uri)
	if err != nil {
		return nil, err
	}
	kubeClient := kube_client.NewOrDie(kubeConfig)
	kubeletClient, err := NewKubeletClient(kubeletConfig)
	if err != nil {
		return nil, err
	}
	// watch nodes
	lw := cache.NewListWatchFromClient(kubeClient, "nodes", kube_api.NamespaceAll, fields.Everything())
	nodeLister := &cache.StoreToNodeLister{Store: cache.NewStore(cache.MetaNamespaceKeyFunc)}
	reflector := cache.NewReflector(lw, &kube_api.Node{}, nodeLister.Store, 0)
	reflector.Run()

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

package sources

import (
	"fmt"
	"net/url"
	"time"

	. "k8s.io/heapster/core"
	"k8s.io/heapster/sources/api"

	"github.com/golang/glog"
	kube_api "k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/client/cache"
	kube_client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/fields"
)

const (
	infraContainerName = "POD"
	// TODO: following constants are copied from k8s, change to use them directly
	kubernetesPodNameLabel      = "io.kubernetes.pod.name"
	kubernetesPodNamespaceLabel = "io.kubernetes.pod.namespace"
	kubernetesPodUID            = "io.kubernetes.pod.uid"
	kubernetesContainerLabel    = "io.kubernetes.container.name"
)

// Kubelet-provided metrics for pod and system container.
type kubeletMetricsSource struct {
	host          Host
	kubeletClient *KubeletClient
	hostname      string
	hostId        string
}

func (this *kubeletMetricsSource) String() string {
	return fmt.Sprintf("kubelet:%s:%d", this.host.IP, this.host.Port)
}

func (this *kubeletMetricsSource) decodeMetrics(c *api.Container) (string, *MetricSet) {
	var metricSetKey string
	cMetrics := &MetricSet{
		MetricValues: map[string]MetricValue{},
		Labels:       map[string]string{},
	}

	if isNode(c) {
		metricSetKey = NodeKey(this.hostname)
		cMetrics.Labels[LabelMetricSetType.Key] = MetricSetTypeNode
	} else if isSysContainer(c) {
		cName := getSysContainerName(c)
		metricSetKey = NodeContainerKey(this.hostname, cName)
		cMetrics.Labels[LabelMetricSetType.Key] = MetricSetTypeSystemContainer
		cMetrics.Labels[LabelContainerName.Key] = cName
	} else {
		cName := c.Spec.Labels[kubernetesContainerLabel]
		if cName == infraContainerName {
			return "", nil
		}
		ns := c.Spec.Labels[kubernetesPodNamespaceLabel]
		podName := c.Spec.Labels[kubernetesPodNameLabel]
		metricSetKey = PodContainerKey(ns, podName, cName)
		cMetrics.Labels[LabelMetricSetType.Key] = MetricSetTypePodContainer
		cMetrics.Labels[LabelContainerName.Key] = cName
		cMetrics.Labels[LabelPodId.Key] = c.Spec.Labels[kubernetesPodUID]
		cMetrics.Labels[LabelPodName.Key] = podName
		cMetrics.Labels[LabelPodNamespace.Key] = ns
		cMetrics.Labels[LabelContainerBaseImage.Key] = c.Spec.Image
	}

	for _, metric := range StandardMetrics {
		if metric.HasValue(&c.Spec) {
			cMetrics.MetricValues[metric.Name] = metric.GetValue(&c.Spec, c.Stats[0])
		}
	}

	// common labels
	cMetrics.Labels[LabelHostname.Key] = this.hostname
	cMetrics.Labels[LabelHostID.Key] = this.hostId

	// TODO: add labels: LabelPodNamespaceUID, LabelLabels, LabelResourceID

	return metricSetKey, cMetrics
}

func (this *kubeletMetricsSource) ScrapeMetrics(start, end time.Time) *DataBatch {
	containers, err := this.kubeletClient.GetAllRawContainers(this.host, start, end)
	if err != nil {
		glog.Errorf("error while getting containers from Kubelet: %v", err)
	}
	glog.Infof("successfully obtained stats for %v containers", len(containers))

	result := &DataBatch{
		Timestamp:  end,
		MetricSets: map[string]*MetricSet{},
	}
	for _, c := range containers {
		name, metrics := this.decodeMetrics(&c)
		if name == "" {
			continue
		}
		result.MetricSets[name] = metrics
	}
	return result
}

type kubeletProvider struct {
	nodeLister    *cache.StoreToNodeLister
	reflector     *cache.Reflector
	kubeletClient *KubeletClient
}

func (this *kubeletProvider) GetMetricsSources() []MetricsSource {
	sources := []MetricsSource{}
	nodes, err := this.nodeLister.List()
	if err != nil {
		glog.Errorf("error while listing nodes: %v", err)
		return sources
	}
	for _, node := range nodes.Items {
		hostname, ip, err := getNodeHostnameAndIP(&node)
		if err != nil {
			glog.Errorf("%v", err)
			continue
		}
		sources = append(sources, &kubeletMetricsSource{
			host:          Host{IP: ip, Port: this.kubeletClient.GetPort()},
			kubeletClient: this.kubeletClient,
			hostname:      hostname,
			hostId:        node.Spec.ExternalID,
		})
	}
	return sources
}

func getNodeHostnameAndIP(node *kube_api.Node) (string, string, error) {
	for _, c := range node.Status.Conditions {
		if c.Type == kube_api.NodeReady && c.Status != kube_api.ConditionTrue {
			return "", "", fmt.Errorf("Node %v is not ready", node.Name)
		}
	}
	hostname, ip := node.Name, ""
	for _, addr := range node.Status.Addresses {
		if addr.Type == kube_api.NodeHostName && addr.Address != "" {
			hostname = addr.Address
		}
		if addr.Type == kube_api.NodeInternalIP && addr.Address != "" {
			ip = addr.Address
		}
	}
	if ip != "" {
		return hostname, ip, nil
	}
	return "", "", fmt.Errorf("Node %v has no valid hostname and/or IP address: %v %v", node.Name, hostname, ip)
}

func NewKubeletProvider(uri *url.URL) (MetricsSourceProvider, error) {
	// create clients
	kubeConfig, kubeletConfig, err := getKubeConfigs(uri)
	if err != nil {
		return nil, err
	}
	kubeClient := kube_client.NewOrDie(kubeConfig)
	kubeletClient, err := NewKubeletClient(kubeletConfig)
	if err != nil {
		return nil, err
	}
	// watch nodes
	lw := cache.NewListWatchFromClient(kubeClient, "nodes", kube_api.NamespaceAll, fields.Everything())
	nodeLister := &cache.StoreToNodeLister{Store: cache.NewStore(cache.MetaNamespaceKeyFunc)}
	reflector := cache.NewReflector(lw, &kube_api.Node{}, nodeLister.Store, 0)
	reflector.Run()

	return &kubeletProvider{
		nodeLister:    nodeLister,
		reflector:     reflector,
		kubeletClient: kubeletClient,
	}, nil
}
<|endoftext|>


<commit_before>package goredis

import (
	"testing"
	"time"
)

func TestPublish(t *testing.T) {
	if _, err := r.Publish("channel", "message"); err != nil {
		t.Error(err)
	}
}

func TestSubscribe(t *testing.T) {
	quit := make(chan bool)
	sub, err := r.PubSub()
	if err != nil {
		t.Error(err)
	}
	defer sub.Close()
	go func() {
		if err := sub.Subscribe("channel"); err != nil {
			t.Error(err)
			quit <- true
			return
		}
		for {
			list, err := sub.Receive()
			if err != nil {
				t.Error(err)
				quit <- true
				break
			}
			if list[0] == "message" {
				if list[1] != "channel" || list[2] != "message" {
					t.Fail()
				}
				quit <- true
				break
			}
		}
	}()
	time.Sleep(100 * time.Millisecond)
	r.Publish("channel", "message")
	time.Sleep(100 * time.Millisecond)
	<-quit
}

func TestPSubscribe(t *testing.T) {
	quit := make(chan bool)
	psub, err := r.PubSub()
	if err != nil {
		t.Error(err)
	}
	defer psub.Close()
	go func() {
		if err := psub.PSubscribe("news.*"); err != nil {
			t.Error(err)
			quit <- true
			return
		}
		for {
			list, err := psub.Receive()
			if err != nil {
				t.Error(err)
				quit <- true
				break
			}
			if list[0] == "pmessage" {
				if list[1] != "news.*" || list[2] != "news.china" || list[3] != "message" {
					t.Fail()
				}
				quit <- true
				break
			}
		}
	}()
	time.Sleep(100 * time.Millisecond)
	r.Publish("news.china", "message")
	time.Sleep(100 * time.Millisecond)
	<-quit
}

func TestUnSubscribe(t *testing.T) {
	ch := make(chan bool)
	sub, err := r.PubSub()
	if err != nil {
		t.Error(err)
	}
	defer sub.Close()
	go func() {
		for {
			if _, err := sub.Receive(); err != nil {
				t.Error(err)
			}
			ch <- true
		}
	}()
	time.Sleep(100 * time.Millisecond)
	sub.Subscribe("channel")
	time.Sleep(100 * time.Millisecond)
	<-ch
	if len(sub.Channels) != 1 {
		t.Fail()
	}
	if err := sub.UnSubscribe("channel"); err != nil {
		t.Error(err)
	}
	time.Sleep(100 * time.Millisecond)
	<-ch
	time.Sleep(100 * time.Millisecond)
	if len(sub.Channels) != 0 {
		t.Fail()
	}
}

func TestPUnSubscribe(t *testing.T) {
	ch := make(chan bool)
	sub, err := r.PubSub()
	if err != nil {
		t.Error(err)
	}
	defer sub.Close()
	go func() {
		for {
			if _, err := sub.Receive(); err != nil {
				t.Error(err)
			}
			ch <- true
		}
	}()
	time.Sleep(100 * time.Millisecond)
	sub.PSubscribe("news.*")
	time.Sleep(100 * time.Millisecond)
	<-ch
	if len(sub.Patterns) != 1 {
		t.Fail()
	}
	if err := sub.PUnSubscribe("news.*"); err != nil {
		t.Error(err)
	}
	time.Sleep(100 * time.Millisecond)
	<-ch
	time.Sleep(100 * time.Millisecond)
	if len(sub.Patterns) != 0 {
		t.Fail()
	}
}
<commit_msg>pubsub: add quit(bool) var to prevent test fail<commit_after>package goredis

import (
	"testing"
	"time"
)

func TestPublish(t *testing.T) {
	if _, err := r.Publish("channel", "message"); err != nil {
		t.Error(err)
	}
}

func TestSubscribe(t *testing.T) {
	quit := make(chan bool)
	sub, err := r.PubSub()
	if err != nil {
		t.Error(err)
	}
	defer sub.Close()
	go func() {
		if err := sub.Subscribe("channel"); err != nil {
			t.Error(err)
			quit <- true
			return
		}
		for {
			list, err := sub.Receive()
			if err != nil {
				t.Error(err)
				quit <- true
				break
			}
			if list[0] == "message" {
				if list[1] != "channel" || list[2] != "message" {
					t.Fail()
				}
				quit <- true
				break
			}
		}
	}()
	time.Sleep(100 * time.Millisecond)
	r.Publish("channel", "message")
	time.Sleep(100 * time.Millisecond)
	<-quit
}

func TestPSubscribe(t *testing.T) {
	quit := make(chan bool)
	psub, err := r.PubSub()
	if err != nil {
		t.Error(err)
	}
	defer psub.Close()
	go func() {
		if err := psub.PSubscribe("news.*"); err != nil {
			t.Error(err)
			quit <- true
			return
		}
		for {
			list, err := psub.Receive()
			if err != nil {
				t.Error(err)
				quit <- true
				break
			}
			if list[0] == "pmessage" {
				if list[1] != "news.*" || list[2] != "news.china" || list[3] != "message" {
					t.Fail()
				}
				quit <- true
				break
			}
		}
	}()
	time.Sleep(100 * time.Millisecond)
	r.Publish("news.china", "message")
	time.Sleep(100 * time.Millisecond)
	<-quit
}

func TestUnSubscribe(t *testing.T) {
	quit := false
	ch := make(chan bool)
	sub, err := r.PubSub()
	if err != nil {
		t.Error(err)
	}
	defer sub.Close()
	go func() {
		for {
			if _, err := sub.Receive(); err != nil {
				if !quit {
					t.Error(err)
				}
			}
			ch <- true
		}
	}()
	time.Sleep(100 * time.Millisecond)
	sub.Subscribe("channel")
	time.Sleep(100 * time.Millisecond)
	<-ch
	if len(sub.Channels) != 1 {
		t.Fail()
	}
	if err := sub.UnSubscribe("channel"); err != nil {
		t.Error(err)
	}
	time.Sleep(100 * time.Millisecond)
	<-ch
	time.Sleep(100 * time.Millisecond)
	if len(sub.Channels) != 0 {
		t.Fail()
	}
	quit = true
}

func TestPUnSubscribe(t *testing.T) {
	quit := false
	ch := make(chan bool)
	sub, err := r.PubSub()
	if err != nil {
		t.Error(err)
	}
	defer sub.Close()
	go func() {
		for {
			if _, err := sub.Receive(); err != nil {
				if !quit {
					t.Error(err)
				}
			}
			ch <- true
		}
	}()
	time.Sleep(100 * time.Millisecond)
	sub.PSubscribe("news.*")
	time.Sleep(100 * time.Millisecond)
	<-ch
	if len(sub.Patterns) != 1 {
		t.Fail()
	}
	if err := sub.PUnSubscribe("news.*"); err != nil {
		t.Error(err)
	}
	time.Sleep(100 * time.Millisecond)
	<-ch
	time.Sleep(100 * time.Millisecond)
	if len(sub.Patterns) != 0 {
		t.Fail()
	}
	quit = true
}
<|endoftext|>


<commit_before>// Copyright 2012 Jesse Allen. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pubsub

import (
  "testing"
)

func TestNew(t *testing.T) {
  // nothing to test.
}

func TestRegister(t *testing.T) {
  t.Errorf("Tests not created")
}
<commit_msg>Test created for `New()`<commit_after>// Copyright 2012 Jesse Allen. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pubsub

import (
	"testing"
)

func TestNew(t *testing.T) {
	// almost too dumb to test, but we will anyhow
	ps := New()
	if ps == nil {
		t.Errorf("New() returned nil pointer")
	}
}

func TestRegister(t *testing.T) {
	t.Errorf("Tests not created")
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package samples

import (
	"os"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseutil"
	"github.com/jacobsa/gcsfuse/timeutil"
	"golang.org/x/net/context"
)

// A file system with a fixed structure that looks like this:
//
//     hello
//     dir/
//         world
//
// Each file contains the string "Hello, world!".
type HelloFS struct {
	fuseutil.NotImplementedFileSystem
	Clock timeutil.Clock

	// Set by Init.
	Uid uint32
	Gid uint32
}

var _ fuse.FileSystem = &HelloFS{}

const (
	rootInode fuse.InodeID = fuse.RootInodeID + iota
	helloInode
	dirInode
	worldInode
)

type inodeInfo struct {
	attributes fuse.InodeAttributes

	// File or directory?
	dir bool

	// For directories, children.
	children []fuseutil.Dirent
}

// We have a fixed directory structure.
var gInodeInfo = map[fuse.InodeID]inodeInfo{
	// root
	rootInode: inodeInfo{
		attributes: fuse.InodeAttributes{
			Mode: 0500 | os.ModeDir,
		},
		dir: true,
		children: []fuseutil.Dirent{
			fuseutil.Dirent{
				Offset: 1,
				Inode:  helloInode,
				Name:   "hello",
				Type:   fuseutil.DT_File,
			},
			fuseutil.Dirent{
				Offset: 2,
				Inode:  dirInode,
				Name:   "dir",
				Type:   fuseutil.DT_Directory,
			},
		},
	},

	// hello
	helloInode: inodeInfo{
		attributes: fuse.InodeAttributes{
			Mode: 0400,
			Size: uint64(len("Hello, world!")),
		},
	},

	// dir
	dirInode: inodeInfo{
		attributes: fuse.InodeAttributes{
			Mode: 0500 | os.ModeDir,
		},
		dir: true,
		children: []fuseutil.Dirent{
			fuseutil.Dirent{
				Offset: 1,
				Inode:  worldInode,
				Name:   "world",
				Type:   fuseutil.DT_File,
			},
		},
	},

	// world
	worldInode: inodeInfo{
		attributes: fuse.InodeAttributes{
			Mode: 0400,
			Size: uint64(len("Hello, world!")),
		},
	},
}

func findChildInode(
	name string,
	children []fuseutil.Dirent) (inode fuse.InodeID, err error) {
	for _, e := range children {
		if e.Name == name {
			inode = e.Inode
			return
		}
	}

	err = fuse.ENOENT
	return
}

func (fs *HelloFS) patchAttributes(
	attr *fuse.InodeAttributes) {
	now := fs.Clock.Now()
	attr.Uid = fs.Uid
	attr.Gid = fs.Gid
	attr.Atime = now
	attr.Mtime = now
	attr.Crtime = now
}

func (fs *HelloFS) Init(
	ctx context.Context,
	req *fuse.InitRequest) (
	resp *fuse.InitResponse, err error) {
	resp = &fuse.InitResponse{}
	fs.Uid = req.Uid
	fs.Gid = req.Gid
	return
}

func (fs *HelloFS) LookUpInode(
	ctx context.Context,
	req *fuse.LookUpInodeRequest) (
	resp *fuse.LookUpInodeResponse, err error) {
	resp = &fuse.LookUpInodeResponse{}

	// Find the info for the parent.
	parentInfo, ok := gInodeInfo[req.Parent]
	if !ok {
		err = fuse.ENOENT
		return
	}

	// Find the child within the parent.
	childInode, err := findChildInode(req.Name, parentInfo.children)
	if err != nil {
		return
	}

	// Copy over information.
	resp.Child = childInode
	resp.Attributes = gInodeInfo[childInode].attributes

	// Patch attributes.
	fs.patchAttributes(&resp.Attributes)

	return
}

func (fs *HelloFS) GetInodeAttributes(
	ctx context.Context,
	req *fuse.GetInodeAttributesRequest) (
	resp *fuse.GetInodeAttributesResponse, err error) {
	resp = &fuse.GetInodeAttributesResponse{}

	// Find the info for this inode.
	info, ok := gInodeInfo[req.Inode]
	if !ok {
		err = fuse.ENOENT
		return
	}

	// Copy over its attributes.
	resp.Attributes = info.attributes

	// Patch attributes.
	fs.patchAttributes(&resp.Attributes)

	return
}

func (fs *HelloFS) OpenDir(
	ctx context.Context,
	req *fuse.OpenDirRequest) (resp *fuse.OpenDirResponse, err error) {
	// Allow opening any directory.
	resp = &fuse.OpenDirResponse{}
	return
}

func (fs *HelloFS) ReadDir(
	ctx context.Context,
	req *fuse.ReadDirRequest) (resp *fuse.ReadDirResponse, err error) {
	resp = &fuse.ReadDirResponse{}

	// Find the info for this inode.
	info, ok := gInodeInfo[req.Inode]
	if !ok {
		err = fuse.ENOENT
		return
	}

	if !info.dir {
		err = fuse.EIO
		return
	}

	entries := info.children

	// Grab the range of interest.
	if req.Offset > fuse.DirOffset(len(entries)) {
		err = fuse.EIO
		return
	}

	entries = entries[req.Offset:]

	// Resume at the specified offset into the array.
	for _, e := range entries {
		resp.Data = fuseutil.AppendDirent(resp.Data, e)
		if len(resp.Data) > req.Size {
			resp.Data = resp.Data[:req.Size]
			break
		}
	}

	return
}
<commit_msg>Implemented OpenFile.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package samples

import (
	"os"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseutil"
	"github.com/jacobsa/gcsfuse/timeutil"
	"golang.org/x/net/context"
)

// A file system with a fixed structure that looks like this:
//
//     hello
//     dir/
//         world
//
// Each file contains the string "Hello, world!".
type HelloFS struct {
	fuseutil.NotImplementedFileSystem
	Clock timeutil.Clock

	// Set by Init.
	Uid uint32
	Gid uint32
}

var _ fuse.FileSystem = &HelloFS{}

const (
	rootInode fuse.InodeID = fuse.RootInodeID + iota
	helloInode
	dirInode
	worldInode
)

type inodeInfo struct {
	attributes fuse.InodeAttributes

	// File or directory?
	dir bool

	// For directories, children.
	children []fuseutil.Dirent
}

// We have a fixed directory structure.
var gInodeInfo = map[fuse.InodeID]inodeInfo{
	// root
	rootInode: inodeInfo{
		attributes: fuse.InodeAttributes{
			Mode: 0500 | os.ModeDir,
		},
		dir: true,
		children: []fuseutil.Dirent{
			fuseutil.Dirent{
				Offset: 1,
				Inode:  helloInode,
				Name:   "hello",
				Type:   fuseutil.DT_File,
			},
			fuseutil.Dirent{
				Offset: 2,
				Inode:  dirInode,
				Name:   "dir",
				Type:   fuseutil.DT_Directory,
			},
		},
	},

	// hello
	helloInode: inodeInfo{
		attributes: fuse.InodeAttributes{
			Mode: 0400,
			Size: uint64(len("Hello, world!")),
		},
	},

	// dir
	dirInode: inodeInfo{
		attributes: fuse.InodeAttributes{
			Mode: 0500 | os.ModeDir,
		},
		dir: true,
		children: []fuseutil.Dirent{
			fuseutil.Dirent{
				Offset: 1,
				Inode:  worldInode,
				Name:   "world",
				Type:   fuseutil.DT_File,
			},
		},
	},

	// world
	worldInode: inodeInfo{
		attributes: fuse.InodeAttributes{
			Mode: 0400,
			Size: uint64(len("Hello, world!")),
		},
	},
}

func findChildInode(
	name string,
	children []fuseutil.Dirent) (inode fuse.InodeID, err error) {
	for _, e := range children {
		if e.Name == name {
			inode = e.Inode
			return
		}
	}

	err = fuse.ENOENT
	return
}

func (fs *HelloFS) patchAttributes(
	attr *fuse.InodeAttributes) {
	now := fs.Clock.Now()
	attr.Uid = fs.Uid
	attr.Gid = fs.Gid
	attr.Atime = now
	attr.Mtime = now
	attr.Crtime = now
}

func (fs *HelloFS) Init(
	ctx context.Context,
	req *fuse.InitRequest) (
	resp *fuse.InitResponse, err error) {
	resp = &fuse.InitResponse{}
	fs.Uid = req.Uid
	fs.Gid = req.Gid
	return
}

func (fs *HelloFS) LookUpInode(
	ctx context.Context,
	req *fuse.LookUpInodeRequest) (
	resp *fuse.LookUpInodeResponse, err error) {
	resp = &fuse.LookUpInodeResponse{}

	// Find the info for the parent.
	parentInfo, ok := gInodeInfo[req.Parent]
	if !ok {
		err = fuse.ENOENT
		return
	}

	// Find the child within the parent.
	childInode, err := findChildInode(req.Name, parentInfo.children)
	if err != nil {
		return
	}

	// Copy over information.
	resp.Child = childInode
	resp.Attributes = gInodeInfo[childInode].attributes

	// Patch attributes.
	fs.patchAttributes(&resp.Attributes)

	return
}

func (fs *HelloFS) GetInodeAttributes(
	ctx context.Context,
	req *fuse.GetInodeAttributesRequest) (
	resp *fuse.GetInodeAttributesResponse, err error) {
	resp = &fuse.GetInodeAttributesResponse{}

	// Find the info for this inode.
	info, ok := gInodeInfo[req.Inode]
	if !ok {
		err = fuse.ENOENT
		return
	}

	// Copy over its attributes.
	resp.Attributes = info.attributes

	// Patch attributes.
	fs.patchAttributes(&resp.Attributes)

	return
}

func (fs *HelloFS) OpenDir(
	ctx context.Context,
	req *fuse.OpenDirRequest) (resp *fuse.OpenDirResponse, err error) {
	// Allow opening any directory.
	resp = &fuse.OpenDirResponse{}
	return
}

func (fs *HelloFS) ReadDir(
	ctx context.Context,
	req *fuse.ReadDirRequest) (resp *fuse.ReadDirResponse, err error) {
	resp = &fuse.ReadDirResponse{}

	// Find the info for this inode.
	info, ok := gInodeInfo[req.Inode]
	if !ok {
		err = fuse.ENOENT
		return
	}

	if !info.dir {
		err = fuse.EIO
		return
	}

	entries := info.children

	// Grab the range of interest.
	if req.Offset > fuse.DirOffset(len(entries)) {
		err = fuse.EIO
		return
	}

	entries = entries[req.Offset:]

	// Resume at the specified offset into the array.
	for _, e := range entries {
		resp.Data = fuseutil.AppendDirent(resp.Data, e)
		if len(resp.Data) > req.Size {
			resp.Data = resp.Data[:req.Size]
			break
		}
	}

	return
}

func (fs *HelloFS) OpenFile(
	ctx context.Context,
	req *fuse.OpenFileRequest) (resp *fuse.OpenFileResponse, err error) {
	// Allow opening any file.
	resp = &fuse.OpenFileResponse{}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/anatol/luks.go"
	"github.com/stretchr/testify/assert"
	"github.com/tych0/go-losetup" // fork of github.com/freddierice/go-losetup
	"golang.org/x/sys/unix"
)

// generate several LUKS disks, mount them as loop device and test end-to-end mount process
func runLuksTest(t *testing.T, name string, testPersistentFlags bool, formatArgs ...string) {
	t.Parallel()

	tmpImage, err := ioutil.TempFile("", "luks.go.img."+name)
	assert.NoError(t, err)
	defer tmpImage.Close()
	defer os.Remove(tmpImage.Name())

	assert.NoError(t, tmpImage.Truncate(24*1024*1024))

	mapperFile := "/dev/mapper/" + name
	password := "pwd." + name

	// format a new LUKS device
	args := []string{"luksFormat"}
	args = append(args, formatArgs...)
	args = append(args, "-q", tmpImage.Name())
	formatCmd := exec.Command("cryptsetup", args...)
	formatCmd.Stdin = strings.NewReader(password)
	if testing.Verbose() {
		formatCmd.Stdout = os.Stdout
		formatCmd.Stderr = os.Stderr
	}
	assert.NoError(t, formatCmd.Run())

	// attach the luks image to a loop device
	loopDev, err := losetup.Attach(tmpImage.Name(), 0, false)
	assert.NoError(t, err)
	defer loopDev.Detach()

	// open the loop device
	openCmd := exec.Command("cryptsetup", "open", loopDev.Path(), name)
	openCmd.Stdin = strings.NewReader(password)
	if testing.Verbose() {
		openCmd.Stdout = os.Stdout
		openCmd.Stderr = os.Stderr
	}
	assert.NoError(t, openCmd.Run())

	if testPersistentFlags {
		refreshCmd := exec.Command("cryptsetup", "refresh", "--persistent", "--allow-discards", name)
		refreshCmd.Stdin = strings.NewReader(password)
		if testing.Verbose() {
			refreshCmd.Stdout = os.Stdout
			refreshCmd.Stderr = os.Stderr
		}
		assert.NoError(t, refreshCmd.Run())
	}

	expectedUUID := "462c8bc5-f997-4aa5-b97e-6346f5275521"
	// format the crypt device with ext4 filesystem
	formatExt4Cmd := exec.Command("mkfs.ext4", "-q", "-U", expectedUUID, mapperFile)
	if testing.Verbose() {
		formatExt4Cmd.Stdout = os.Stdout
		formatExt4Cmd.Stderr = os.Stderr
	}
	assert.NoError(t, formatExt4Cmd.Run())

	// try to mount it to ext4 filesystem
	tmpMountpoint, err := ioutil.TempDir("", "luks.go.mount."+name)
	assert.NoError(t, err)
	if err := syscall.Mount(mapperFile, tmpMountpoint, "ext4", 0, ""); err != nil {
		assert.Error(t, os.NewSyscallError("mount", err))
	}

	emptyFile := filepath.Join(tmpMountpoint, "empty.txt")
	assert.NoError(t, ioutil.WriteFile(emptyFile, []byte("Hello, world!"), 0666))
	assert.NoError(t, syscall.Unmount(tmpMountpoint, 0))
	assert.NoError(t, os.RemoveAll(tmpMountpoint))

	// close the crypt device
	closeCmd := exec.Command("cryptsetup", "close", name)
	closeCmd.Stdin = strings.NewReader(password)
	if testing.Verbose() {
		closeCmd.Stdout = os.Stdout
		closeCmd.Stderr = os.Stderr
	}
	assert.NoError(t, closeCmd.Run())

	_, err = os.Stat(mapperFile)
	assert.False(t, err == nil || !os.IsNotExist(err), "It is expected file /dev/mapper/%v does not exist", name)

	dev, err := luks.Open(loopDev.Path())
	assert.NoError(t, err)
	defer dev.Close()

	assert.NoError(t, dev.FlagsAdd(luks.FlagNoReadWorkqueue, luks.FlagSubmitFromCryptCPUs, luks.FlagNoReadWorkqueue /* this is dup */))
	if testPersistentFlags {
		// test adding duplicated flag
		assert.NoError(t, dev.FlagsAdd(luks.FlagAllowDiscards))
	}

	// open the crypt device again, this time with our Golang API
	assert.NoError(t, dev.Unlock(0, []byte(password), name))
	defer luks.Lock(name)

	out, err := exec.Command("cryptsetup", "status", name).CombinedOutput()
	assert.NoError(t, err, "Unable to get status of volume %v", name)

	var expectedFlags string
	if testPersistentFlags {
		expectedFlags = "discards submit_from_crypt_cpus no_read_workqueue"
	} else {
		expectedFlags = "submit_from_crypt_cpus no_read_workqueue"
	}
	assert.Contains(t, string(out), "  flags:   "+expectedFlags+" \n", "expected LUKS flags '%v', got:\n%v", expectedFlags, string(out))

	// dm-crypt mount is an asynchronous process, we need to wait a bit until /dev/mapper/ file appears
	time.Sleep(200 * time.Millisecond)

	// try to mount it to ext4 filesystem
	tmpMountpoint2, err := ioutil.TempDir("", "luks.go.mount."+name)
	assert.NoError(t, err)
	defer os.RemoveAll(tmpMountpoint2)

	if err := syscall.Mount(mapperFile, tmpMountpoint2, "ext4", 0, ""); err != nil {
		assert.Error(t, os.NewSyscallError("mount", err))
	}
	defer syscall.Unmount(tmpMountpoint2, 0)

	data, err := ioutil.ReadFile(filepath.Join(tmpMountpoint2, "empty.txt"))
	assert.NoError(t, err)
	assert.Equal(t, "Hello, world!", string(data))

	if testing.Verbose() {
		stat, err := os.Stat(mapperFile)
		assert.NoError(t, err)
		sys, ok := stat.Sys().(*syscall.Stat_t)
		assert.True(t, ok, "Cannot determine the device major and minor numbers for %s", mapperFile)
		major := unix.Major(sys.Rdev)
		minor := unix.Minor(sys.Rdev)

		udevFile := fmt.Sprintf("/run/udev/data/b%d:%d", major, minor)

		fmt.Printf(">>> %s\n", udevFile)
		content, err := ioutil.ReadFile(udevFile)
		assert.NoError(t, err)
		fmt.Print(string(content))
	}

	out, err = exec.Command("/usr/bin/lsblk", "-rno", "UUID", mapperFile).CombinedOutput()
	assert.NoError(t, err)
	out = bytes.TrimRight(out, "\n")
	assert.Equal(t, expectedUUID, string(out))
}

func TestLUKS1(t *testing.T) {
	runLuksTest(t, "luks1", false, "--type", "luks1", "--iter-time", "5") // lower the unlock time to make tests faster
}

func TestLUKS2(t *testing.T) {
	runLuksTest(t, "luks2", true, "--type", "luks2", "--iter-time", "5")
}
<commit_msg>tests: simplify assert() condition<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/anatol/luks.go"
	"github.com/stretchr/testify/assert"
	"github.com/tych0/go-losetup" // fork of github.com/freddierice/go-losetup
	"golang.org/x/sys/unix"
)

// generate several LUKS disks, mount them as loop device and test end-to-end mount process
func runLuksTest(t *testing.T, name string, testPersistentFlags bool, formatArgs ...string) {
	t.Parallel()

	tmpImage, err := ioutil.TempFile("", "luks.go.img."+name)
	assert.NoError(t, err)
	defer tmpImage.Close()
	defer os.Remove(tmpImage.Name())

	assert.NoError(t, tmpImage.Truncate(24*1024*1024))

	mapperFile := "/dev/mapper/" + name
	password := "pwd." + name

	// format a new LUKS device
	args := []string{"luksFormat"}
	args = append(args, formatArgs...)
	args = append(args, "-q", tmpImage.Name())
	formatCmd := exec.Command("cryptsetup", args...)
	formatCmd.Stdin = strings.NewReader(password)
	if testing.Verbose() {
		formatCmd.Stdout = os.Stdout
		formatCmd.Stderr = os.Stderr
	}
	assert.NoError(t, formatCmd.Run())

	// attach the luks image to a loop device
	loopDev, err := losetup.Attach(tmpImage.Name(), 0, false)
	assert.NoError(t, err)
	defer loopDev.Detach()

	// open the loop device
	openCmd := exec.Command("cryptsetup", "open", loopDev.Path(), name)
	openCmd.Stdin = strings.NewReader(password)
	if testing.Verbose() {
		openCmd.Stdout = os.Stdout
		openCmd.Stderr = os.Stderr
	}
	assert.NoError(t, openCmd.Run())

	if testPersistentFlags {
		refreshCmd := exec.Command("cryptsetup", "refresh", "--persistent", "--allow-discards", name)
		refreshCmd.Stdin = strings.NewReader(password)
		if testing.Verbose() {
			refreshCmd.Stdout = os.Stdout
			refreshCmd.Stderr = os.Stderr
		}
		assert.NoError(t, refreshCmd.Run())
	}

	expectedUUID := "462c8bc5-f997-4aa5-b97e-6346f5275521"
	// format the crypt device with ext4 filesystem
	formatExt4Cmd := exec.Command("mkfs.ext4", "-q", "-U", expectedUUID, mapperFile)
	if testing.Verbose() {
		formatExt4Cmd.Stdout = os.Stdout
		formatExt4Cmd.Stderr = os.Stderr
	}
	assert.NoError(t, formatExt4Cmd.Run())

	// try to mount it to ext4 filesystem
	tmpMountpoint, err := ioutil.TempDir("", "luks.go.mount."+name)
	assert.NoError(t, err)
	if err := syscall.Mount(mapperFile, tmpMountpoint, "ext4", 0, ""); err != nil {
		assert.Error(t, os.NewSyscallError("mount", err))
	}

	emptyFile := filepath.Join(tmpMountpoint, "empty.txt")
	assert.NoError(t, ioutil.WriteFile(emptyFile, []byte("Hello, world!"), 0666))
	assert.NoError(t, syscall.Unmount(tmpMountpoint, 0))
	assert.NoError(t, os.RemoveAll(tmpMountpoint))

	// close the crypt device
	closeCmd := exec.Command("cryptsetup", "close", name)
	closeCmd.Stdin = strings.NewReader(password)
	if testing.Verbose() {
		closeCmd.Stdout = os.Stdout
		closeCmd.Stderr = os.Stderr
	}
	assert.NoError(t, closeCmd.Run())

	_, err = os.Stat(mapperFile)
	assert.True(t, os.IsNotExist(err), "/dev/mapper/%v: file exists", name)

	dev, err := luks.Open(loopDev.Path())
	assert.NoError(t, err)
	defer dev.Close()

	assert.NoError(t, dev.FlagsAdd(luks.FlagNoReadWorkqueue, luks.FlagSubmitFromCryptCPUs, luks.FlagNoReadWorkqueue /* this is dup */))
	if testPersistentFlags {
		// test adding duplicated flag
		assert.NoError(t, dev.FlagsAdd(luks.FlagAllowDiscards))
	}

	// open the crypt device again, this time with our Golang API
	assert.NoError(t, dev.Unlock(0, []byte(password), name))
	defer luks.Lock(name)

	out, err := exec.Command("cryptsetup", "status", name).CombinedOutput()
	assert.NoError(t, err, "Unable to get status of volume %v", name)

	var expectedFlags string
	if testPersistentFlags {
		expectedFlags = "discards submit_from_crypt_cpus no_read_workqueue"
	} else {
		expectedFlags = "submit_from_crypt_cpus no_read_workqueue"
	}
	assert.Contains(t, string(out), "  flags:   "+expectedFlags+" \n", "expected LUKS flags '%v', got:\n%v", expectedFlags, string(out))

	// dm-crypt mount is an asynchronous process, we need to wait a bit until /dev/mapper/ file appears
	time.Sleep(200 * time.Millisecond)

	// try to mount it to ext4 filesystem
	tmpMountpoint2, err := ioutil.TempDir("", "luks.go.mount."+name)
	assert.NoError(t, err)
	defer os.RemoveAll(tmpMountpoint2)

	if err := syscall.Mount(mapperFile, tmpMountpoint2, "ext4", 0, ""); err != nil {
		assert.Error(t, os.NewSyscallError("mount", err))
	}
	defer syscall.Unmount(tmpMountpoint2, 0)

	data, err := ioutil.ReadFile(filepath.Join(tmpMountpoint2, "empty.txt"))
	assert.NoError(t, err)
	assert.Equal(t, "Hello, world!", string(data))

	if testing.Verbose() {
		stat, err := os.Stat(mapperFile)
		assert.NoError(t, err)
		sys, ok := stat.Sys().(*syscall.Stat_t)
		assert.True(t, ok, "Cannot determine the device major and minor numbers for %s", mapperFile)
		major := unix.Major(sys.Rdev)
		minor := unix.Minor(sys.Rdev)

		udevFile := fmt.Sprintf("/run/udev/data/b%d:%d", major, minor)

		fmt.Printf(">>> %s\n", udevFile)
		content, err := ioutil.ReadFile(udevFile)
		assert.NoError(t, err)
		fmt.Print(string(content))
	}

	out, err = exec.Command("/usr/bin/lsblk", "-rno", "UUID", mapperFile).CombinedOutput()
	assert.NoError(t, err)
	out = bytes.TrimRight(out, "\n")
	assert.Equal(t, expectedUUID, string(out))
}

func TestLUKS1(t *testing.T) {
	runLuksTest(t, "luks1", false, "--type", "luks1", "--iter-time", "5") // lower the unlock time to make tests faster
}

func TestLUKS2(t *testing.T) {
	runLuksTest(t, "luks2", true, "--type", "luks2", "--iter-time", "5")
}
<|endoftext|>


<commit_before>package scheduler

import (
	"os"
	"time"

	"github.com/concourse/atc"
	"github.com/concourse/atc/db"
	"github.com/concourse/atc/db/algorithm"
	"github.com/pivotal-golang/lager"
)

//go:generate counterfeiter . Locker

type Locker interface {
	AcquireWriteLock([]db.NamedLock) (db.Lock, error)
	AcquireWriteLockImmediately([]db.NamedLock) (db.Lock, error)

	AcquireReadLock([]db.NamedLock) (db.Lock, error)
}

//go:generate counterfeiter . BuildScheduler

type BuildScheduler interface {
	TryNextPendingBuild(lager.Logger, *algorithm.VersionsDB, atc.JobConfig, atc.ResourceConfigs) Waiter
	BuildLatestInputs(lager.Logger, *algorithm.VersionsDB, atc.JobConfig, atc.ResourceConfigs) error
}

type Runner struct {
	Logger lager.Logger

	Locker Locker
	DB     db.PipelineDB

	Scheduler BuildScheduler

	Noop bool

	Interval time.Duration
}

func (runner *Runner) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	close(ready)

	if runner.Interval == 0 {
		panic("unconfigured scheduler interval")
	}

	runner.Logger.Info("start", lager.Data{
		"inverval": runner.Interval.String(),
	})

	defer runner.Logger.Info("done")

dance:
	for {
		err := runner.tick(runner.Logger.Session("tick"))
		if err != nil {
			return err
		}

		select {
		case <-time.After(runner.Interval):
		case <-signals:
			break dance
		}
	}

	return nil
}

func (runner *Runner) tick(logger lager.Logger) error {
	start := time.Now()

	logger.Info("start")
	defer func() {
		logger.Info("done", lager.Data{"took": time.Since(start).String()})
	}()

	config, _, err := runner.DB.GetConfig()
	if err != nil {
		if err == db.ErrPipelineNotFound {
			return err
		}

		logger.Error("failed-to-get-config", err)

		return nil
	}

	if runner.Noop {
		return nil
	}

	lockName := []db.NamedLock{db.PipelineSchedulingLock(runner.DB.GetPipelineName())}
	schedulingLock, err := runner.Locker.AcquireWriteLockImmediately(lockName)
	if err == db.ErrLockNotAvailable {
		return nil
	}

	if err != nil {
		logger.Error("failed-to-acquire-scheduling-lock", err)
		return nil
	}

	defer schedulingLock.Release()

	versions, err := runner.DB.LoadVersionsDB()
	if err != nil {
		logger.Error("failed-to-load-versions-db", err)
		return err
	}

	for _, job := range config.Jobs {
		sLog := logger.Session("scheduling", lager.Data{
			"job": job.Name,
		})

		runner.schedule(sLog, versions, job, config.Resources)
	}

	return nil
}

func (runner *Runner) schedule(logger lager.Logger, versions *algorithm.VersionsDB, job atc.JobConfig, resources atc.ResourceConfigs) {
	runner.Scheduler.TryNextPendingBuild(logger, versions, job, resources).Wait()

	err := runner.Scheduler.BuildLatestInputs(logger, versions, job, resources)
	if err != nil {
		logger.Error("failed-to-build-from-latest-inputs", err)
	}
}
<commit_msg>restore logging improvements to scheduler<commit_after>package scheduler

import (
	"os"
	"time"

	"github.com/concourse/atc"
	"github.com/concourse/atc/db"
	"github.com/concourse/atc/db/algorithm"
	"github.com/pivotal-golang/lager"
)

//go:generate counterfeiter . Locker

type Locker interface {
	AcquireWriteLock([]db.NamedLock) (db.Lock, error)
	AcquireWriteLockImmediately([]db.NamedLock) (db.Lock, error)

	AcquireReadLock([]db.NamedLock) (db.Lock, error)
}

//go:generate counterfeiter . BuildScheduler

type BuildScheduler interface {
	TryNextPendingBuild(lager.Logger, *algorithm.VersionsDB, atc.JobConfig, atc.ResourceConfigs) Waiter
	BuildLatestInputs(lager.Logger, *algorithm.VersionsDB, atc.JobConfig, atc.ResourceConfigs) error
}

type Runner struct {
	Logger lager.Logger

	Locker Locker
	DB     db.PipelineDB

	Scheduler BuildScheduler

	Noop bool

	Interval time.Duration
}

func (runner *Runner) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	close(ready)

	if runner.Interval == 0 {
		panic("unconfigured scheduler interval")
	}

	runner.Logger.Info("start", lager.Data{
		"inverval": runner.Interval.String(),
	})

	defer runner.Logger.Info("done")

dance:
	for {
		err := runner.tick(runner.Logger.Session("tick"))
		if err != nil {
			return err
		}

		select {
		case <-time.After(runner.Interval):
		case <-signals:
			break dance
		}
	}

	return nil
}

func (runner *Runner) tick(logger lager.Logger) error {
	start := time.Now()

	config, _, err := runner.DB.GetConfig()
	if err != nil {
		if err == db.ErrPipelineNotFound {
			return err
		}

		logger.Error("failed-to-get-config", err)

		return nil
	}

	if runner.Noop {
		return nil
	}

	lockName := []db.NamedLock{db.PipelineSchedulingLock(runner.DB.GetPipelineName())}
	schedulingLock, err := runner.Locker.AcquireWriteLockImmediately(lockName)
	if err == db.ErrLockNotAvailable {
		return nil
	}

	if err != nil {
		logger.Error("failed-to-acquire-scheduling-lock", err)
		return nil
	}

	defer schedulingLock.Release()

	logger.Info("start")
	defer func() {
		logger.Info("done", lager.Data{"took": time.Since(start).String()})
	}()

	versions, err := runner.DB.LoadVersionsDB()
	if err != nil {
		logger.Error("failed-to-load-versions-db", err)
		return err
	}

	logger.Info("loaded-versions", lager.Data{"took": time.Since(start).String()})

	for _, job := range config.Jobs {
		sLog := logger.Session("scheduling", lager.Data{
			"job": job.Name,
		})

		runner.schedule(sLog, versions, job, config.Resources)
	}

	return nil
}

func (runner *Runner) schedule(logger lager.Logger, versions *algorithm.VersionsDB, job atc.JobConfig, resources atc.ResourceConfigs) {
	runner.Scheduler.TryNextPendingBuild(logger, versions, job, resources).Wait()

	err := runner.Scheduler.BuildLatestInputs(logger, versions, job, resources)
	if err != nil {
		logger.Error("failed-to-build-from-latest-inputs", err)
	}
}
<|endoftext|>


<commit_before>// Copyright ©2015 The gonum 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 testlapack

import (
	"fmt"
	"math/rand"
	"testing"

	"github.com/gonum/blas"
	"github.com/gonum/floats"
)

type Dormqrer interface {
	Dorm2rer
	Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int)
}

func DormqrTest(t *testing.T, impl Dormqrer) {
	rnd := rand.New(rand.NewSource(1))
	for _, side := range []blas.Side{blas.Left, blas.Right} {
		for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} {
			for _, test := range []struct {
				common, adim, cdim, lda, ldc int
			}{
				{6, 7, 8, 0, 0},
				{6, 8, 7, 0, 0},
				{7, 6, 8, 0, 0},
				{7, 8, 6, 0, 0},
				{8, 6, 7, 0, 0},
				{8, 7, 6, 0, 0},
				{100, 200, 300, 0, 0},
				{100, 300, 200, 0, 0},
				{200, 100, 300, 0, 0},
				{200, 300, 100, 0, 0},
				{300, 100, 200, 0, 0},
				{300, 200, 100, 0, 0},
				{100, 200, 300, 400, 500},
				{100, 300, 200, 400, 500},
				{200, 100, 300, 400, 500},
				{200, 300, 100, 400, 500},
				{300, 100, 200, 400, 500},
				{300, 200, 100, 400, 500},
				{100, 200, 300, 500, 400},
				{100, 300, 200, 500, 400},
				{200, 100, 300, 500, 400},
				{200, 300, 100, 500, 400},
				{300, 100, 200, 500, 400},
				{300, 200, 100, 500, 400},
			} {
				var ma, na, mc, nc int
				if side == blas.Left {
					ma = test.common
					na = test.adim
					mc = test.common
					nc = test.cdim
				} else {
					ma = test.common
					na = test.adim
					mc = test.cdim
					nc = test.common
				}
				// Generate a random matrix
				lda := test.lda
				if lda == 0 {
					lda = na
				}
				a := make([]float64, ma*lda)
				for i := range a {
					a[i] = rnd.Float64()
				}
				// Compute random C matrix
				ldc := test.ldc
				if ldc == 0 {
					ldc = nc
				}
				c := make([]float64, mc*ldc)
				for i := range c {
					c[i] = rnd.Float64()
				}

				// Compute QR
				k := min(ma, na)
				tau := make([]float64, k)
				work := make([]float64, 1)
				impl.Dgeqrf(ma, na, a, lda, tau, work, -1)
				work = make([]float64, int(work[0]))
				impl.Dgeqrf(ma, na, a, lda, tau, work, len(work))

				cCopy := make([]float64, len(c))
				copy(cCopy, c)
				ans := make([]float64, len(c))
				copy(ans, cCopy)

				if side == blas.Left {
					work = make([]float64, nc)
				} else {
					work = make([]float64, mc)
				}
				impl.Dorm2r(side, trans, mc, nc, k, a, lda, tau, ans, ldc, work)

				// Make sure Dorm2r and Dormqr match with small work
				for i := range work {
					work[i] = rnd.Float64()
				}
				copy(c, cCopy)
				impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work))
				if !floats.EqualApprox(c, ans, 1e-12) {
					t.Errorf("Dormqr and Dorm2r mismatch for small work")
				}

				// Try with the optimum amount of work
				copy(c, cCopy)
				impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, -1)
				work = make([]float64, int(work[0]))
				for i := range work {
					work[i] = rnd.Float64()
				}
				impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work))
				if !floats.EqualApprox(c, ans, 1e-12) {
					t.Errorf("Dormqr and Dorm2r mismatch for full work")
					fmt.Println("ccopy")
					for i := 0; i < mc; i++ {
						fmt.Println(cCopy[i*ldc : (i+1)*ldc])
					}
					fmt.Println("ans =")
					for i := 0; i < mc; i++ {
						fmt.Println(ans[i*ldc : (i+1)*ldc])
					}
					fmt.Println("c =")
					for i := 0; i < mc; i++ {
						fmt.Println(c[i*ldc : (i+1)*ldc])
					}
				}

				// Try with amount of work that is less than
				// optimal but still long enough to use the
				// blocked code.
				copy(c, cCopy)
				if side == blas.Left {
					work = make([]float64, 3*nc)
				} else {
					work = make([]float64, 3*mc)
				}
				impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work))
				if !floats.EqualApprox(c, ans, 1e-12) {
					t.Errorf("Dormqr and Dorm2r mismatch for medium work")
				}
			}
		}
	}
}
<commit_msg>testlapack: use nil for slice arguments in workspace query in DormqrTest<commit_after>// Copyright ©2015 The gonum 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 testlapack

import (
	"fmt"
	"math/rand"
	"testing"

	"github.com/gonum/blas"
	"github.com/gonum/floats"
)

type Dormqrer interface {
	Dorm2rer
	Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int)
}

func DormqrTest(t *testing.T, impl Dormqrer) {
	rnd := rand.New(rand.NewSource(1))
	for _, side := range []blas.Side{blas.Left, blas.Right} {
		for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} {
			for _, test := range []struct {
				common, adim, cdim, lda, ldc int
			}{
				{6, 7, 8, 0, 0},
				{6, 8, 7, 0, 0},
				{7, 6, 8, 0, 0},
				{7, 8, 6, 0, 0},
				{8, 6, 7, 0, 0},
				{8, 7, 6, 0, 0},
				{100, 200, 300, 0, 0},
				{100, 300, 200, 0, 0},
				{200, 100, 300, 0, 0},
				{200, 300, 100, 0, 0},
				{300, 100, 200, 0, 0},
				{300, 200, 100, 0, 0},
				{100, 200, 300, 400, 500},
				{100, 300, 200, 400, 500},
				{200, 100, 300, 400, 500},
				{200, 300, 100, 400, 500},
				{300, 100, 200, 400, 500},
				{300, 200, 100, 400, 500},
				{100, 200, 300, 500, 400},
				{100, 300, 200, 500, 400},
				{200, 100, 300, 500, 400},
				{200, 300, 100, 500, 400},
				{300, 100, 200, 500, 400},
				{300, 200, 100, 500, 400},
			} {
				var ma, na, mc, nc int
				if side == blas.Left {
					ma = test.common
					na = test.adim
					mc = test.common
					nc = test.cdim
				} else {
					ma = test.common
					na = test.adim
					mc = test.cdim
					nc = test.common
				}
				// Generate a random matrix
				lda := test.lda
				if lda == 0 {
					lda = na
				}
				a := make([]float64, ma*lda)
				for i := range a {
					a[i] = rnd.Float64()
				}
				// Compute random C matrix
				ldc := test.ldc
				if ldc == 0 {
					ldc = nc
				}
				c := make([]float64, mc*ldc)
				for i := range c {
					c[i] = rnd.Float64()
				}

				// Compute QR
				k := min(ma, na)
				tau := make([]float64, k)
				work := make([]float64, 1)
				impl.Dgeqrf(ma, na, a, lda, tau, work, -1)
				work = make([]float64, int(work[0]))
				impl.Dgeqrf(ma, na, a, lda, tau, work, len(work))

				cCopy := make([]float64, len(c))
				copy(cCopy, c)
				ans := make([]float64, len(c))
				copy(ans, cCopy)

				if side == blas.Left {
					work = make([]float64, nc)
				} else {
					work = make([]float64, mc)
				}
				impl.Dorm2r(side, trans, mc, nc, k, a, lda, tau, ans, ldc, work)

				// Make sure Dorm2r and Dormqr match with small work
				for i := range work {
					work[i] = rnd.Float64()
				}
				copy(c, cCopy)
				impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work))
				if !floats.EqualApprox(c, ans, 1e-12) {
					t.Errorf("Dormqr and Dorm2r mismatch for small work")
				}

				// Try with the optimum amount of work
				copy(c, cCopy)
				impl.Dormqr(side, trans, mc, nc, k, nil, lda, nil, nil, ldc, work, -1)
				work = make([]float64, int(work[0]))
				for i := range work {
					work[i] = rnd.Float64()
				}
				impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work))
				if !floats.EqualApprox(c, ans, 1e-12) {
					t.Errorf("Dormqr and Dorm2r mismatch for full work")
					fmt.Println("ccopy")
					for i := 0; i < mc; i++ {
						fmt.Println(cCopy[i*ldc : (i+1)*ldc])
					}
					fmt.Println("ans =")
					for i := 0; i < mc; i++ {
						fmt.Println(ans[i*ldc : (i+1)*ldc])
					}
					fmt.Println("c =")
					for i := 0; i < mc; i++ {
						fmt.Println(c[i*ldc : (i+1)*ldc])
					}
				}

				// Try with amount of work that is less than
				// optimal but still long enough to use the
				// blocked code.
				copy(c, cCopy)
				if side == blas.Left {
					work = make([]float64, 3*nc)
				} else {
					work = make([]float64, 3*mc)
				}
				impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work))
				if !floats.EqualApprox(c, ans, 1e-12) {
					t.Errorf("Dormqr and Dorm2r mismatch for medium work")
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/voxelbrain/pixelpixel/pixelutils"
	"github.com/voxelbrain/pixelpixel/pixelutils/twitter"
	"image"
	"image/color"
	"image/draw"
	_ "image/png"
	"log"
	"os"
	"strings"
)

type TweetSection struct {
	BackgroundImage string
	Hashtag         string
	Tweets          chan *twitter.Tweet
}

var (
	TweetSections = []TweetSection{
		{
			BackgroundImage: `imgs/windows.png`,
			Hashtag:         "#Windows",
			Tweets:          make(chan *twitter.Tweet),
		},
		{
			BackgroundImage: `imgs/osx.png`,
			Hashtag:         "#OSX",
			Tweets:          make(chan *twitter.Tweet),
		},
		{
			BackgroundImage: `imgs/ubuntu.png`,
			Hashtag:         "#Ubuntu",
			Tweets:          make(chan *twitter.Tweet),
		},
	}
	translucentBlack = color.RGBA{0, 0, 0, 200}
)

func main() {
	cred := loadCredentials()
	fakeC := make(chan draw.Image)
	c := pixelutils.PixelPusher()
	pixel := pixelutils.NewPixel()

	TweetDispatch(cred)

	for i, section := range TweetSections {
		subPixel := pixelutils.SubImage(pixel, image.Rect(0, i*85, 256, (i+1)*85))
		pixelutils.StretchCopy(subPixel, loadImage(section.BackgroundImage))
		pixelutils.Fill(subPixel, translucentBlack)
		go TweetDrawer(fakeC, subPixel, section.Tweets)
	}

	for _ = range fakeC {
		c <- pixel
	}
}

func TweetDispatch(cred *twitter.Credentials) {
	allHashtags := make([]string, 0, len(TweetSections))
	for _, section := range TweetSections {
		allHashtags = append(allHashtags, section.Hashtag)
	}

	tweets, err := twitter.Hashtags(cred, allHashtags...)
	if err != nil {
		log.Fatalf("Could not start Twitter stream: %s", err)
	}
	go func() {
		for tweet := range tweets {
			for _, section := range TweetSections {
				if strings.Contains(strings.ToLower(tweet.Text), strings.ToLower(section.Hashtag)) {
					section.Tweets <- tweet
				}
			}
		}
	}()
}

func TweetDrawer(c chan<- draw.Image, pixel draw.Image, tweets <-chan *twitter.Tweet) {
	counter := 0
	bg := image.NewNRGBA(pixel.Bounds())
	pixelutils.StretchCopy(bg, pixel)
	c <- pixel
	avatarArea := pixelutils.SubImage(pixel, image.Rectangle{
		Min: pixel.Bounds().Min,
		Max: pixel.Bounds().Min.Add(image.Point{85, 85}),
	})
	textArea := pixelutils.PixelSizeChanger(pixelutils.SubImage(pixel, image.Rectangle{
		Min: pixel.Bounds().Min.Add(image.Point{90, 0}),
		Max: pixel.Bounds().Max,
	}), 2, 2)
	for tweet := range tweets {
		counter++
		pixelutils.StretchCopy(pixel, bg)
		pixelutils.StretchCopy(avatarArea, tweet.Author.ProfilePicture)
		pixelutils.DrawText(pixelutils.PixelSizeChanger(avatarArea, 3, 3), pixelutils.Red, fmt.Sprintf("%03d", counter))
		pixelutils.DrawText(textArea, pixelutils.White, tweet.Text)
		c <- pixel
	}
}

func loadImage(path string) image.Image {
	f, err := os.Open(path)
	if err != nil {
		log.Fatalf("Could not open hard-coded source image: %s", err)
	}
	defer f.Close()
	img, _, err := image.Decode(f)
	if err != nil {
		log.Fatalf("Could not decode hard-coded source image: %s", err)
	}
	return img
}

func loadCredentials() *twitter.Credentials {
	f, err := os.Open("credentials.json")
	if err != nil {
		log.Fatalf("Could not open credentials file: %s", err)
	}
	defer f.Close()

	var cred *twitter.Credentials
	err = json.NewDecoder(f).Decode(&cred)
	if err != nil {
		log.Fatalf("Could not decode credentials file: %s", err)
	}
	return cred
}
<commit_msg>Adjust Twitter for new API<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/voxelbrain/pixelpixel/pixelutils"
	"github.com/voxelbrain/pixelpixel/pixelutils/twitter"
	"image"
	"image/color"
	"image/draw"
	_ "image/png"
	"log"
	"os"
	"strings"
)

type TweetSection struct {
	BackgroundImage string
	Hashtag         string
	Tweets          chan *twitter.Tweet
}

var (
	TweetSections = []TweetSection{
		{
			BackgroundImage: `imgs/windows.png`,
			Hashtag:         "#Windows",
			Tweets:          make(chan *twitter.Tweet),
		},
		{
			BackgroundImage: `imgs/osx.png`,
			Hashtag:         "#OSX",
			Tweets:          make(chan *twitter.Tweet),
		},
		{
			BackgroundImage: `imgs/ubuntu.png`,
			Hashtag:         "#Ubuntu",
			Tweets:          make(chan *twitter.Tweet),
		},
	}
	translucentBlack = color.RGBA{0, 0, 0, 200}
)

func main() {
	cred := loadCredentials()
	fakeC := make(chan draw.Image)
	wall, _ := pixelutils.PixelPusher()
	pixel := pixelutils.NewPixel()

	TweetDispatch(cred)

	for i, section := range TweetSections {
		subPixel := pixelutils.SubImage(pixel, image.Rect(0, i*85, 256, (i+1)*85))
		pixelutils.StretchCopy(subPixel, loadImage(section.BackgroundImage))
		pixelutils.Fill(subPixel, translucentBlack)
		go TweetDrawer(fakeC, subPixel, section.Tweets)
	}

	for _ = range fakeC {
		wall <- pixel
	}
}

func TweetDispatch(cred *twitter.Credentials) {
	allHashtags := make([]string, 0, len(TweetSections))
	for _, section := range TweetSections {
		allHashtags = append(allHashtags, section.Hashtag)
	}

	tweets, err := twitter.Hashtags(cred, allHashtags...)
	if err != nil {
		log.Fatalf("Could not start Twitter stream: %s", err)
	}
	go func() {
		for tweet := range tweets {
			for _, section := range TweetSections {
				if strings.Contains(strings.ToLower(tweet.Text), strings.ToLower(section.Hashtag)) {
					section.Tweets <- tweet
				}
			}
		}
	}()
}

func TweetDrawer(c chan<- draw.Image, pixel draw.Image, tweets <-chan *twitter.Tweet) {
	counter := 0
	bg := image.NewNRGBA(pixel.Bounds())
	pixelutils.StretchCopy(bg, pixel)
	c <- pixel
	avatarArea := pixelutils.SubImage(pixel, image.Rectangle{
		Min: pixel.Bounds().Min,
		Max: pixel.Bounds().Min.Add(image.Point{85, 85}),
	})
	textArea := pixelutils.PixelSizeChanger(pixelutils.SubImage(pixel, image.Rectangle{
		Min: pixel.Bounds().Min.Add(image.Point{90, 0}),
		Max: pixel.Bounds().Max,
	}), 2, 2)
	for tweet := range tweets {
		counter++
		pixelutils.StretchCopy(pixel, bg)
		pixelutils.StretchCopy(avatarArea, tweet.Author.ProfilePicture)
		pixelutils.DrawText(pixelutils.PixelSizeChanger(avatarArea, 3, 3), pixelutils.Red, fmt.Sprintf("%03d", counter))
		pixelutils.DrawText(textArea, pixelutils.White, tweet.Text)
		c <- pixel
	}
}

func loadImage(path string) image.Image {
	f, err := os.Open(path)
	if err != nil {
		log.Fatalf("Could not open hard-coded source image: %s", err)
	}
	defer f.Close()
	img, _, err := image.Decode(f)
	if err != nil {
		log.Fatalf("Could not decode hard-coded source image: %s", err)
	}
	return img
}

func loadCredentials() *twitter.Credentials {
	f, err := os.Open("credentials.json")
	if err != nil {
		log.Fatalf("Could not open credentials file: %s", err)
	}
	defer f.Close()

	var cred *twitter.Credentials
	err = json.NewDecoder(f).Decode(&cred)
	if err != nil {
		log.Fatalf("Could not decode credentials file: %s", err)
	}
	return cred
}
<|endoftext|>