<commit_before>//go:build windows
// +build windows

package xdg_test

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

	"github.com/adrg/xdg"
	"github.com/stretchr/testify/require"
)

func TestDefaultBaseDirs(t *testing.T) {
	home := xdg.Home
	systemDrive := `C:\`
	roamingAppData := filepath.Join(home, "AppData", "Roaming")
	localAppData := filepath.Join(home, "AppData", "Local")
	systemRoot := filepath.Join(systemDrive, "Windows")
	programData := filepath.Join(systemDrive, "ProgramData")

	envSamples := []*envSample{
		&envSample{
			name:     "XDG_DATA_HOME",
			expected: localAppData,
			actual:   &xdg.DataHome,
		},
		&envSample{
			name:     "XDG_DATA_DIRS",
			expected: []string{roamingAppData, programData},
			actual:   &xdg.DataDirs,
		},
		&envSample{
			name:     "XDG_CONFIG_HOME",
			expected: localAppData,
			actual:   &xdg.ConfigHome,
		},
		&envSample{
			name:     "XDG_CONFIG_DIRS",
			expected: []string{programData, roamingAppData},
			actual:   &xdg.ConfigDirs,
		},
		&envSample{
			name:     "XDG_STATE_HOME",
			expected: localAppData,
			actual:   &xdg.StateHome,
		},
		&envSample{
			name:     "XDG_CACHE_HOME",
			expected: filepath.Join(localAppData, "cache"),
			actual:   &xdg.CacheHome,
		},
		&envSample{
			name:     "XDG_RUNTIME_DIR",
			expected: localAppData,
			actual:   &xdg.RuntimeDir,
		},
		&envSample{
			name: "XDG_APPLICATION_DIRS",
			expected: []string{
				filepath.Join(roamingAppData, "Microsoft", "Windows", "Start Menu", "Programs"),
				filepath.Join(programData, "Microsoft", "Windows", "Start Menu", "Programs"),
			},
			actual: &xdg.ApplicationDirs,
		},
		&envSample{
			name: "XDG_FONT_DIRS",
			expected: []string{
				filepath.Join(systemRoot, "Fonts"),
				filepath.Join(localAppData, "Microsoft", "Windows", "Fonts"),
			},
			actual: &xdg.FontDirs,
		},
	}

	// Test default environment.
	testDirs(t, envSamples...)

	// Test system drive not set.
	envSystemDrive := os.Getenv("SystemDrive")
	require.NoError(t, os.Unsetenv("SystemDrive"))
	testDirs(t, envSamples...)
	require.NoError(t, os.Setenv("SystemDrive", envSystemDrive))
}

func TestCustomBaseDirs(t *testing.T) {
	home := xdg.Home
	roamingAppData := filepath.Join(home, "Custom", "Appdata", "Roaming")
	localAppData := filepath.Join(home, "Custom", "AppData", "Local")
	programData := filepath.Join(home, "Custom", "ProgramData")

	envRoamingAppData := os.Getenv("APPDATA")
	require.NoError(t, os.Setenv("APPDATA", roamingAppData))
	envLocalAppData := os.Getenv("LOCALAPPDATA")
	require.NoError(t, os.Setenv("LOCALAPPDATA", localAppData))
	envProgramData := os.Getenv("ProgramData")
	require.NoError(t, os.Setenv("ProgramData", programData))

	testDirs(t,
		&envSample{
			name:     "XDG_DATA_HOME",
			value:    filepath.Join(localAppData, "Data"),
			expected: filepath.Join(localAppData, "Data"),
			actual:   &xdg.DataHome,
		},
		&envSample{
			name:     "XDG_DATA_DIRS",
			value:    fmt.Sprintf("%s;%s", filepath.Join(localAppData, "Data"), filepath.Join(roamingAppData, "Data")),
			expected: []string{filepath.Join(localAppData, "Data"), filepath.Join(roamingAppData, "Data")},
			actual:   &xdg.DataDirs,
		},
		&envSample{
			name:     "XDG_CONFIG_HOME",
			value:    filepath.Join(localAppData, "Config"),
			expected: filepath.Join(localAppData, "Config"),
			actual:   &xdg.ConfigHome,
		},
		&envSample{
			name:     "XDG_CONFIG_DIRS",
			value:    fmt.Sprintf("%s;%s", filepath.Join(localAppData, "Config"), filepath.Join(roamingAppData, "Config")),
			expected: []string{filepath.Join(localAppData, "Config"), filepath.Join(roamingAppData, "Config")},
			actual:   &xdg.ConfigDirs,
		},
		&envSample{
			name:     "XDG_STATE_HOME",
			value:    filepath.Join(programData, "State"),
			expected: filepath.Join(programData, "State"),
			actual:   &xdg.StateHome,
		},
		&envSample{
			name:     "XDG_CACHE_HOME",
			value:    filepath.Join(programData, "Cache"),
			expected: filepath.Join(programData, "Cache"),
			actual:   &xdg.CacheHome,
		},
		&envSample{
			name:     "XDG_RUNTIME_DIR",
			value:    filepath.Join(programData, "Runtime"),
			expected: filepath.Join(programData, "Runtime"),
			actual:   &xdg.RuntimeDir,
		},
	)

	require.NoError(t, os.Setenv("APPDATA", envRoamingAppData))
	require.NoError(t, os.Setenv("LOCALAPPDATA", envLocalAppData))
	require.NoError(t, os.Setenv("ProgramData", envProgramData))
}

func TestDefaultUserDirs(t *testing.T) {
	home := xdg.Home
	roamingAppData := filepath.Join(home, "AppData", "Roaming")

	testDirs(t,
		&envSample{
			name:     "XDG_DESKTOP_DIR",
			expected: filepath.Join(home, "Desktop"),
			actual:   &xdg.UserDirs.Desktop,
		},
		&envSample{
			name:     "XDG_DOWNLOAD_DIR",
			expected: filepath.Join(home, "Downloads"),
			actual:   &xdg.UserDirs.Download,
		},
		&envSample{
			name:     "XDG_DOCUMENTS_DIR",
			expected: filepath.Join(home, "Documents"),
			actual:   &xdg.UserDirs.Documents,
		},
		&envSample{
			name:     "XDG_MUSIC_DIR",
			expected: filepath.Join(home, "Music"),
			actual:   &xdg.UserDirs.Music,
		},
		&envSample{
			name:     "XDG_PICTURES_DIR",
			expected: filepath.Join(home, "Pictures"),
			actual:   &xdg.UserDirs.Pictures,
		},
		&envSample{
			name:     "XDG_VIDEOS_DIR",
			expected: filepath.Join(home, "Videos"),
			actual:   &xdg.UserDirs.Videos,
		},
		&envSample{
			name:     "XDG_TEMPLATES_DIR",
			expected: filepath.Join(roamingAppData, "Microsoft", "Windows", "Templates"),
			actual:   &xdg.UserDirs.Templates,
		},
		&envSample{
			name:     "XDG_PUBLICSHARE_DIR",
			expected: filepath.Join(`C:\`, "Users", "Public"),
			actual:   &xdg.UserDirs.PublicShare,
		},
	)
}

func TestCustomUserDirs(t *testing.T) {
	home := xdg.Home

	testDirs(t,
		&envSample{
			name:     "XDG_DESKTOP_DIR",
			value:    filepath.Join(home, "Files/Desktop"),
			expected: filepath.Join(home, "Files/Desktop"),
			actual:   &xdg.UserDirs.Desktop,
		},
		&envSample{
			name:     "XDG_DOWNLOAD_DIR",
			value:    filepath.Join(home, "Files/Downloads"),
			expected: filepath.Join(home, "Files/Downloads"),
			actual:   &xdg.UserDirs.Download,
		},
		&envSample{
			name:     "XDG_DOCUMENTS_DIR",
			value:    filepath.Join(home, "Files/Documents"),
			expected: filepath.Join(home, "Files/Documents"),
			actual:   &xdg.UserDirs.Documents,
		},
		&envSample{
			name:     "XDG_MUSIC_DIR",
			value:    filepath.Join(home, "Files/Music"),
			expected: filepath.Join(home, "Files/Music"),
			actual:   &xdg.UserDirs.Music,
		},
		&envSample{
			name:     "XDG_PICTURES_DIR",
			value:    filepath.Join(home, "Files/Pictures"),
			expected: filepath.Join(home, "Files/Pictures"),
			actual:   &xdg.UserDirs.Pictures,
		},
		&envSample{
			name:     "XDG_VIDEOS_DIR",
			value:    filepath.Join(home, "Files/Videos"),
			expected: filepath.Join(home, "Files/Videos"),
			actual:   &xdg.UserDirs.Videos,
		},
		&envSample{
			name:     "XDG_TEMPLATES_DIR",
			value:    filepath.Join(home, "Files/Templates"),
			expected: filepath.Join(home, "Files/Templates"),
			actual:   &xdg.UserDirs.Templates,
		},
		&envSample{
			name:     "XDG_PUBLICSHARE_DIR",
			value:    filepath.Join(home, "Files/Public"),
			expected: filepath.Join(home, "Files/Public"),
			actual:   &xdg.UserDirs.PublicShare,
		},
	)
}
<commit_msg>Fix gofmt -s notice on Windows paths test file<commit_after>//go:build windows
// +build windows

package xdg_test

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

	"github.com/adrg/xdg"
	"github.com/stretchr/testify/require"
)

func TestDefaultBaseDirs(t *testing.T) {
	home := xdg.Home
	systemDrive := `C:\`
	roamingAppData := filepath.Join(home, "AppData", "Roaming")
	localAppData := filepath.Join(home, "AppData", "Local")
	systemRoot := filepath.Join(systemDrive, "Windows")
	programData := filepath.Join(systemDrive, "ProgramData")

	envSamples := []*envSample{
		{
			name:     "XDG_DATA_HOME",
			expected: localAppData,
			actual:   &xdg.DataHome,
		},
		{
			name:     "XDG_DATA_DIRS",
			expected: []string{roamingAppData, programData},
			actual:   &xdg.DataDirs,
		},
		{
			name:     "XDG_CONFIG_HOME",
			expected: localAppData,
			actual:   &xdg.ConfigHome,
		},
		{
			name:     "XDG_CONFIG_DIRS",
			expected: []string{programData, roamingAppData},
			actual:   &xdg.ConfigDirs,
		},
		{
			name:     "XDG_STATE_HOME",
			expected: localAppData,
			actual:   &xdg.StateHome,
		},
		{
			name:     "XDG_CACHE_HOME",
			expected: filepath.Join(localAppData, "cache"),
			actual:   &xdg.CacheHome,
		},
		{
			name:     "XDG_RUNTIME_DIR",
			expected: localAppData,
			actual:   &xdg.RuntimeDir,
		},
		{
			name: "XDG_APPLICATION_DIRS",
			expected: []string{
				filepath.Join(roamingAppData, "Microsoft", "Windows", "Start Menu", "Programs"),
				filepath.Join(programData, "Microsoft", "Windows", "Start Menu", "Programs"),
			},
			actual: &xdg.ApplicationDirs,
		},
		{
			name: "XDG_FONT_DIRS",
			expected: []string{
				filepath.Join(systemRoot, "Fonts"),
				filepath.Join(localAppData, "Microsoft", "Windows", "Fonts"),
			},
			actual: &xdg.FontDirs,
		},
	}

	// Test default environment.
	testDirs(t, envSamples...)

	// Test system drive not set.
	envSystemDrive := os.Getenv("SystemDrive")
	require.NoError(t, os.Unsetenv("SystemDrive"))
	testDirs(t, envSamples...)
	require.NoError(t, os.Setenv("SystemDrive", envSystemDrive))
}

func TestCustomBaseDirs(t *testing.T) {
	home := xdg.Home
	roamingAppData := filepath.Join(home, "Custom", "Appdata", "Roaming")
	localAppData := filepath.Join(home, "Custom", "AppData", "Local")
	programData := filepath.Join(home, "Custom", "ProgramData")

	envRoamingAppData := os.Getenv("APPDATA")
	require.NoError(t, os.Setenv("APPDATA", roamingAppData))
	envLocalAppData := os.Getenv("LOCALAPPDATA")
	require.NoError(t, os.Setenv("LOCALAPPDATA", localAppData))
	envProgramData := os.Getenv("ProgramData")
	require.NoError(t, os.Setenv("ProgramData", programData))

	testDirs(t,
		&envSample{
			name:     "XDG_DATA_HOME",
			value:    filepath.Join(localAppData, "Data"),
			expected: filepath.Join(localAppData, "Data"),
			actual:   &xdg.DataHome,
		},
		&envSample{
			name:     "XDG_DATA_DIRS",
			value:    fmt.Sprintf("%s;%s", filepath.Join(localAppData, "Data"), filepath.Join(roamingAppData, "Data")),
			expected: []string{filepath.Join(localAppData, "Data"), filepath.Join(roamingAppData, "Data")},
			actual:   &xdg.DataDirs,
		},
		&envSample{
			name:     "XDG_CONFIG_HOME",
			value:    filepath.Join(localAppData, "Config"),
			expected: filepath.Join(localAppData, "Config"),
			actual:   &xdg.ConfigHome,
		},
		&envSample{
			name:     "XDG_CONFIG_DIRS",
			value:    fmt.Sprintf("%s;%s", filepath.Join(localAppData, "Config"), filepath.Join(roamingAppData, "Config")),
			expected: []string{filepath.Join(localAppData, "Config"), filepath.Join(roamingAppData, "Config")},
			actual:   &xdg.ConfigDirs,
		},
		&envSample{
			name:     "XDG_STATE_HOME",
			value:    filepath.Join(programData, "State"),
			expected: filepath.Join(programData, "State"),
			actual:   &xdg.StateHome,
		},
		&envSample{
			name:     "XDG_CACHE_HOME",
			value:    filepath.Join(programData, "Cache"),
			expected: filepath.Join(programData, "Cache"),
			actual:   &xdg.CacheHome,
		},
		&envSample{
			name:     "XDG_RUNTIME_DIR",
			value:    filepath.Join(programData, "Runtime"),
			expected: filepath.Join(programData, "Runtime"),
			actual:   &xdg.RuntimeDir,
		},
	)

	require.NoError(t, os.Setenv("APPDATA", envRoamingAppData))
	require.NoError(t, os.Setenv("LOCALAPPDATA", envLocalAppData))
	require.NoError(t, os.Setenv("ProgramData", envProgramData))
}

func TestDefaultUserDirs(t *testing.T) {
	home := xdg.Home
	roamingAppData := filepath.Join(home, "AppData", "Roaming")

	testDirs(t,
		&envSample{
			name:     "XDG_DESKTOP_DIR",
			expected: filepath.Join(home, "Desktop"),
			actual:   &xdg.UserDirs.Desktop,
		},
		&envSample{
			name:     "XDG_DOWNLOAD_DIR",
			expected: filepath.Join(home, "Downloads"),
			actual:   &xdg.UserDirs.Download,
		},
		&envSample{
			name:     "XDG_DOCUMENTS_DIR",
			expected: filepath.Join(home, "Documents"),
			actual:   &xdg.UserDirs.Documents,
		},
		&envSample{
			name:     "XDG_MUSIC_DIR",
			expected: filepath.Join(home, "Music"),
			actual:   &xdg.UserDirs.Music,
		},
		&envSample{
			name:     "XDG_PICTURES_DIR",
			expected: filepath.Join(home, "Pictures"),
			actual:   &xdg.UserDirs.Pictures,
		},
		&envSample{
			name:     "XDG_VIDEOS_DIR",
			expected: filepath.Join(home, "Videos"),
			actual:   &xdg.UserDirs.Videos,
		},
		&envSample{
			name:     "XDG_TEMPLATES_DIR",
			expected: filepath.Join(roamingAppData, "Microsoft", "Windows", "Templates"),
			actual:   &xdg.UserDirs.Templates,
		},
		&envSample{
			name:     "XDG_PUBLICSHARE_DIR",
			expected: filepath.Join(`C:\`, "Users", "Public"),
			actual:   &xdg.UserDirs.PublicShare,
		},
	)
}

func TestCustomUserDirs(t *testing.T) {
	home := xdg.Home

	testDirs(t,
		&envSample{
			name:     "XDG_DESKTOP_DIR",
			value:    filepath.Join(home, "Files/Desktop"),
			expected: filepath.Join(home, "Files/Desktop"),
			actual:   &xdg.UserDirs.Desktop,
		},
		&envSample{
			name:     "XDG_DOWNLOAD_DIR",
			value:    filepath.Join(home, "Files/Downloads"),
			expected: filepath.Join(home, "Files/Downloads"),
			actual:   &xdg.UserDirs.Download,
		},
		&envSample{
			name:     "XDG_DOCUMENTS_DIR",
			value:    filepath.Join(home, "Files/Documents"),
			expected: filepath.Join(home, "Files/Documents"),
			actual:   &xdg.UserDirs.Documents,
		},
		&envSample{
			name:     "XDG_MUSIC_DIR",
			value:    filepath.Join(home, "Files/Music"),
			expected: filepath.Join(home, "Files/Music"),
			actual:   &xdg.UserDirs.Music,
		},
		&envSample{
			name:     "XDG_PICTURES_DIR",
			value:    filepath.Join(home, "Files/Pictures"),
			expected: filepath.Join(home, "Files/Pictures"),
			actual:   &xdg.UserDirs.Pictures,
		},
		&envSample{
			name:     "XDG_VIDEOS_DIR",
			value:    filepath.Join(home, "Files/Videos"),
			expected: filepath.Join(home, "Files/Videos"),
			actual:   &xdg.UserDirs.Videos,
		},
		&envSample{
			name:     "XDG_TEMPLATES_DIR",
			value:    filepath.Join(home, "Files/Templates"),
			expected: filepath.Join(home, "Files/Templates"),
			actual:   &xdg.UserDirs.Templates,
		},
		&envSample{
			name:     "XDG_PUBLICSHARE_DIR",
			value:    filepath.Join(home, "Files/Public"),
			expected: filepath.Join(home, "Files/Public"),
			actual:   &xdg.UserDirs.PublicShare,
		},
	)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"io"
	"net/http"
)

var errFetchFail = errors.New("Failed to fetch SHA")

func fetchVersionSha(source string) (string, error) {
	resp, err := http.Get(source)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return "", errFetchFail
	}
	var body [40]byte
	n, err := resp.Body.Read(body[0:])
	if err != nil && err != io.EOF {
		return "", err
	}
	if n < 1 {
		return "", errFetchFail
	}
	return string(body[:n]), nil
}

type checkResult struct {
	Check
	Err    error
	Result string
}

func (left checkResult) sameAs(right checkResult) bool {
	return left.Result == right.Result
}

type Check struct {
	Name   string
	Source string
	Verify string
}

func (c Check) check(results chan<- checkResult) {
	sha, err := fetchVersionSha(c.Source)
	results <- checkResult{c, err, sha}
}

func queueAllChecks(checks []Check, resultsChannel chan<- checkResult) {
	for _, c := range checks {
		go c.check(resultsChannel)
	}
}
<commit_msg>use strings.Compare to check version strings<commit_after>package main

import (
	"errors"
	"io"
	"net/http"
	"strings"
)

var errFetchFail = errors.New("Failed to fetch SHA")

func fetchVersionSha(source string) (string, error) {
	resp, err := http.Get(source)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return "", errFetchFail
	}
	var body [40]byte
	n, err := resp.Body.Read(body[0:])
	if err != nil && err != io.EOF {
		return "", err
	}
	if n < 1 {
		return "", errFetchFail
	}
	return string(body[:n]), nil
}

type checkResult struct {
	Check
	Err    error
	Result string
}

func (left checkResult) sameAs(right checkResult) bool {
	return strings.Compare(left.Result, right.Result) == 0
}

type Check struct {
	Name   string
	Source string
	Verify string
}

func (c Check) check(results chan<- checkResult) {
	sha, err := fetchVersionSha(c.Source)
	results <- checkResult{c, err, sha}
}

func queueAllChecks(checks []Check, resultsChannel chan<- checkResult) {
	for _, c := range checks {
		go c.check(resultsChannel)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"image/png"
	"testing"
	"errors"
)

var (
	testVersion = Version(1)
)

func TestVersionDeterminesSize(t *testing.T) {
	table := []struct {
		version int
		expected int
	}{
		{1, 21},
		{2, 25},
		{6, 41},
	}

	for _, test := range table {
		buffer := new(bytes.Buffer)
		GenerateQRCode(buffer, qrcode, Version(test.version))
		img, _ := png.Decode(buffer)
		if width := img.Bounds().Dx(); width != test.expected {
			t.Errorf("Version %2d, expected %3d but got %3d",
				test.version, test.expected, width)
			}
		}
	}

func TestGenerateQRCodeGeneratesPNG(t *testing.T) {
	buffer := new(bytes.Buffer)
	GenerateQRCode(buffer, qrcode, testVersion)

	if buffer.Len() == 0 {
		t.Errorf("Your QR code is empty as space... like the real Space space, " +
			"not the space between those spaces. There's nothing in there.")

		_, err := png.Decode(buffer)

		if err != nil {
			t.Errorf("Generated QRCode is not a PNG: %s", err)
		}
	}
}

type ErrorWriter struct{}

func (e *ErrorWriter) Write(b []byte) (int, error) {
	return 0, errors.New("Expected error")
}

func TestGenerateQRCodePropogatesErrors(t *testing.T) {
	w := new(ErrorWriter)
	err := GenerateQRCode(w, qrcode, testVersion)

	if err == nil || err.Error() != "Expected error" {
		t.Errorf("error not propogated correctly, got %v", err)
	}

}
<commit_msg>Formatting<commit_after>package main

import (
	"bytes"
	"errors"
	"image/png"
	"testing"
)

var (
	testVersion = Version(1)
)

func TestVersionDeterminesSize(t *testing.T) {
	table := []struct {
		version  int
		expected int
	}{
		{1, 21},
		{2, 25},
		{6, 41},
	}

	for _, test := range table {
		buffer := new(bytes.Buffer)
		GenerateQRCode(buffer, qrcode, Version(test.version))
		img, _ := png.Decode(buffer)
		if width := img.Bounds().Dx(); width != test.expected {
			t.Errorf("Version %2d, expected %3d but got %3d",
				test.version, test.expected, width)
		}
	}
}

func TestGenerateQRCodeGeneratesPNG(t *testing.T) {
	buffer := new(bytes.Buffer)
	GenerateQRCode(buffer, qrcode, testVersion)

	if buffer.Len() == 0 {
		t.Errorf("Your QR code is empty as space... like the real Space space, " +
			"not the space between those spaces. There's nothing in there.")

		_, err := png.Decode(buffer)

		if err != nil {
			t.Errorf("Generated QRCode is not a PNG: %s", err)
		}
	}
}

type ErrorWriter struct{}

func (e *ErrorWriter) Write(b []byte) (int, error) {
	return 0, errors.New("Expected error")
}

func TestGenerateQRCodePropogatesErrors(t *testing.T) {
	w := new(ErrorWriter)
	err := GenerateQRCode(w, qrcode, testVersion)

	if err == nil || err.Error() != "Expected error" {
		t.Errorf("error not propogated correctly, got %v", err)
	}

}
<|endoftext|>


<commit_before>// Copyright 2016 Peter Goetz
//
// 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 main_test

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"gopkg.in/alecthomas/kingpin.v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/petergtz/pegomock/pegomock"

	"testing"
)

var (
	joinPath = filepath.Join
)

func TestPegomock(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Pegomock CLI Suite")
}

var _ = Describe("Testing pegomock CLI", func() {

	var (
		packageDir, subPackageDir string
		app                       *kingpin.Application
		origWorkingDir            string
		done                      chan bool = make(chan bool)
	)

	BeforeEach(func() {
		packageDir = joinPath(os.Getenv("GOPATH"), "src", "pegomocktest")
		Expect(os.MkdirAll(packageDir, 0755)).To(Succeed())
		subPackageDir = joinPath(packageDir, "subpackage")
		Expect(os.MkdirAll(subPackageDir, 0755)).To(Succeed())

		var e error
		origWorkingDir, e = os.Getwd()
		Expect(e).NotTo(HaveOccurred())
		os.Chdir(packageDir)

		writeFile(joinPath(packageDir, "mydisplay.go"),
			"package pegomocktest; type MyDisplay interface {  Show() }")
		writeFile(joinPath(subPackageDir, "subdisplay.go"),
			"package subpackage; type SubDisplay interface {  ShowMe() }")

		app = kingpin.New("pegomock", "Generates mocks based on interfaces.")
		app.Terminate(func(int) { panic("Unexpected terminate") })
	})

	AfterEach(func() {
		Expect(os.RemoveAll(packageDir)).To(Succeed())
		os.Chdir(origWorkingDir)
	})

	Describe(`"generate" command`, func() {

		Context(`with args "MyDisplay"`, func() {

			It(`generates a file mock_mydisplay_test.go that contains "package pegomocktest_test"`, func() {
				// The rationale behind this is:
				// mocks should always be part of test packages, because we don't
				// want them to be part of the production code.
				// But to be useful, they must still reside in the package, where
				// they are actually used.

				main.Run(cmd("pegomock generate MyDisplay"), os.Stdout, app, done)

				Expect(joinPath(packageDir, "mock_mydisplay_test.go")).To(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})
		})

		Context(`with args "pegomocktest/subpackage SubDisplay"`, func() {
			It(`generates a file mock_subdisplay_test.go in "pegomocktest" that contains "package pegomocktest_test"`, func() {
				main.Run(cmd("pegomock generate pegomocktest/subpackage SubDisplay"), os.Stdout, app, done)

				Expect(joinPath(packageDir, "mock_subdisplay_test.go")).To(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})
		})

		Context("with args mydisplay.go", func() {
			It(`generates a file mock_mydisplay_test.go that contains "package pegomocktest_test"`, func() {
				main.Run(cmd("pegomock generate mydisplay.go"), os.Stdout, app, done)

				Expect(joinPath(packageDir, "mock_mydisplay_test.go")).To(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})
		})

		Context("with args -d mydisplay.go", func() {
			It(`prints out debug information on stdout`, func() {
				var buf bytes.Buffer
				main.Run(cmd("pegomock generate -d mydisplay.go"), &buf, app, done)
				Expect(buf.String()).To(ContainSubstring("- method Show"))
			})
		})

		Context("with too many args", func() {

			It(`reports an error and the usage`, func() {
				var buf bytes.Buffer
				Expect(func() {
					main.Run(cmd("pegomock generate with too many args"), &buf, app, done)
				}).To(Panic())

				Expect(buf.String()).To(ContainSubstring("Please provide exactly 1 interface or 1 package + 1 interface"))
				Expect(buf.String()).To(ContainSubstring("usage"))
			})
		})

	})

	Describe(`"watch" command`, func() {

		AfterEach(func(testDone Done) { done <- true; close(testDone) }, 3)

		Context("with no further action", func() {
			It(`Creates a template file interfaces_to_mock in the current directory`, func() {
				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				Eventually(func() string { return "interfaces_to_mock" }, "3s").Should(BeAnExistingFile())
			})
		})

		Context("after populating interfaces_to_mock with an actual interface", func() {
			It(`Eventually creates a file mock_mydisplay_test.go starting with "package pegomocktest_test"`, func() {
				writeFile(joinPath(packageDir, "interfaces_to_mock"), "MyDisplay")

				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})

			Context("and overriding the output filepath", func() {
				It(`Eventually creates a file foo.go starting with "package pegomocktest_test"`, func() {
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "-o foo.go MyDisplay")

					go main.Run(cmd("pegomock watch"), os.Stdout, app, done)

					Eventually(joinPath(packageDir, "foo.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
				})
			})

			Context("and overriding the package name", func() {
				It(`Eventually creates a file starting with "package the_overriden_test_package"`, func() {
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "--package the_overriden_test_package MyDisplay")

					go main.Run(cmd("pegomock watch"), os.Stdout, app, done)

					Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package the_overriden_test_package")))
				})
			})

			Context("in multiple packages and providing those packages to watch", func() {
				It(`Eventually creates correct files in respective directories`, func() {
					os.Chdir("..")
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "MyDisplay")
					writeFile(joinPath(subPackageDir, "interfaces_to_mock"), "SubDisplay")

					go main.Run(cmd("pegomock watch pegomocktest pegomocktest/subpackage"), os.Stdout, app, done)

					Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
					Eventually(joinPath(subPackageDir, "mock_subdisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package subpackage_test")))
				})
			})

			Context("in one package, but providing multiple packages to create mocks from", func() {
				It(`Eventually creates correct files in respective directories`, func() {
					os.Chdir("..")
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "MyDisplay\npegomocktest/subpackage SubDisplay")

					go main.Run(cmd("pegomock watch pegomocktest pegomocktest/subpackage"), os.Stdout, app, done)

					Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
					Eventually(joinPath(packageDir, "mock_subdisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
				})
			})

			Context("in multiple packages and watching --recursive", func() {
				It(`Eventually creates correct files in respective directories`, func() {
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "MyDisplay")
					writeFile(joinPath(subPackageDir, "interfaces_to_mock"), "SubDisplay")

					go main.Run(cmd("pegomock watch --recursive"), os.Stdout, app, done)

					Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
					Eventually(joinPath(subPackageDir, "mock_subdisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package subpackage_test")))
				})
			})

		})

		Context("after populating interfaces_to_mock with a Go file", func() {
			It(`Eventually creates a file mock_mydisplay_test.go starting with "package pegomocktest_test"`, func() {
				writeFile(joinPath(packageDir, "interfaces_to_mock"), "mydisplay.go")

				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)

				Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})
		})
	})

	Context("with some unknown command", func() {
		It(`reports an error and the usage`, func() {
			var buf bytes.Buffer
			kingpin.CommandLine.Terminate(nil)
			kingpin.CommandLine.Writer(&buf)

			main.Run(cmd("pegomock some unknown command"), &buf, app, done)
			Expect(buf.String()).To(ContainSubstring("error"))
		})
	})

})

func writeFile(filepath string, content string) {
	Expect(ioutil.WriteFile(filepath, []byte(content), 0644)).To(Succeed())
}

func cmd(line string) []string {
	return strings.Split(line, " ")
}
<commit_msg>Run mock-file-updater directly to speed up tests<commit_after>// Copyright 2016 Peter Goetz
//
// 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 main_test

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"gopkg.in/alecthomas/kingpin.v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/petergtz/pegomock/pegomock"
	"github.com/petergtz/pegomock/pegomock/watch"

	"testing"
)

var (
	joinPath = filepath.Join
)

func TestPegomock(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Pegomock CLI Suite")
}

var _ = Describe("Testing pegomock CLI", func() {

	var (
		packageDir, subPackageDir string
		app                       *kingpin.Application
		origWorkingDir            string
		done                      chan bool = make(chan bool)
	)

	BeforeEach(func() {
		packageDir = joinPath(os.Getenv("GOPATH"), "src", "pegomocktest")
		Expect(os.MkdirAll(packageDir, 0755)).To(Succeed())
		subPackageDir = joinPath(packageDir, "subpackage")
		Expect(os.MkdirAll(subPackageDir, 0755)).To(Succeed())

		var e error
		origWorkingDir, e = os.Getwd()
		Expect(e).NotTo(HaveOccurred())
		os.Chdir(packageDir)

		writeFile(joinPath(packageDir, "mydisplay.go"),
			"package pegomocktest; type MyDisplay interface {  Show() }")
		writeFile(joinPath(subPackageDir, "subdisplay.go"),
			"package subpackage; type SubDisplay interface {  ShowMe() }")

		app = kingpin.New("pegomock", "Generates mocks based on interfaces.")
		app.Terminate(func(int) { panic("Unexpected terminate") })
	})

	AfterEach(func() {
		Expect(os.RemoveAll(packageDir)).To(Succeed())
		os.Chdir(origWorkingDir)
	})

	Describe(`"generate" command`, func() {

		Context(`with args "MyDisplay"`, func() {

			It(`generates a file mock_mydisplay_test.go that contains "package pegomocktest_test"`, func() {
				// The rationale behind this is:
				// mocks should always be part of test packages, because we don't
				// want them to be part of the production code.
				// But to be useful, they must still reside in the package, where
				// they are actually used.

				main.Run(cmd("pegomock generate MyDisplay"), os.Stdout, app, done)

				Expect(joinPath(packageDir, "mock_mydisplay_test.go")).To(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})
		})

		Context(`with args "pegomocktest/subpackage SubDisplay"`, func() {
			It(`generates a file mock_subdisplay_test.go in "pegomocktest" that contains "package pegomocktest_test"`, func() {
				main.Run(cmd("pegomock generate pegomocktest/subpackage SubDisplay"), os.Stdout, app, done)

				Expect(joinPath(packageDir, "mock_subdisplay_test.go")).To(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})
		})

		Context("with args mydisplay.go", func() {
			It(`generates a file mock_mydisplay_test.go that contains "package pegomocktest_test"`, func() {
				main.Run(cmd("pegomock generate mydisplay.go"), os.Stdout, app, done)

				Expect(joinPath(packageDir, "mock_mydisplay_test.go")).To(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})
		})

		Context("with args -d mydisplay.go", func() {
			It(`prints out debug information on stdout`, func() {
				var buf bytes.Buffer
				main.Run(cmd("pegomock generate -d mydisplay.go"), &buf, app, done)
				Expect(buf.String()).To(ContainSubstring("- method Show"))
			})
		})

		Context("with too many args", func() {

			It(`reports an error and the usage`, func() {
				var buf bytes.Buffer
				Expect(func() {
					main.Run(cmd("pegomock generate with too many args"), &buf, app, done)
				}).To(Panic())

				Expect(buf.String()).To(ContainSubstring("Please provide exactly 1 interface or 1 package + 1 interface"))
				Expect(buf.String()).To(ContainSubstring("usage"))
			})
		})

	})

	Describe(`"watch" command`, func() {

		AfterEach(func(testDone Done) { done <- true; close(testDone) }, 3)

		Context("with no further action", func() {
			It(`Creates a template file interfaces_to_mock in the current directory`, func() {
				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				Eventually(func() string { return "interfaces_to_mock" }, "3s").Should(BeAnExistingFile())
			})
		})

		Context("after populating interfaces_to_mock with an actual interface", func() {
			It(`Eventually creates a file mock_mydisplay_test.go starting with "package pegomocktest_test"`, func() {
				writeFile(joinPath(packageDir, "interfaces_to_mock"), "MyDisplay")

				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})

			Context("and overriding the output filepath", func() {
				It(`Eventually creates a file foo.go starting with "package pegomocktest_test"`, func() {
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "-o foo.go MyDisplay")

					watch.NewMockFileUpdater([]string{packageDir}, false).Update()
					go func() { <-done }()

					Eventually(joinPath(packageDir, "foo.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
				})
			})

			Context("and overriding the package name", func() {
				It(`Eventually creates a file starting with "package the_overriden_test_package"`, func() {
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "--package the_overriden_test_package MyDisplay")

					watch.NewMockFileUpdater([]string{packageDir}, false).Update()
					go func() { <-done }()

					Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package the_overriden_test_package")))
				})
			})

			Context("in multiple packages and providing those packages to watch", func() {
				It(`Eventually creates correct files in respective directories`, func() {
					os.Chdir("..")
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "MyDisplay")
					writeFile(joinPath(subPackageDir, "interfaces_to_mock"), "SubDisplay")

					watch.NewMockFileUpdater([]string{"pegomocktest", "pegomocktest/subpackage"}, false).Update()
					go func() { <-done }()

					Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
					Eventually(joinPath(subPackageDir, "mock_subdisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package subpackage_test")))
				})
			})

			Context("in one package, but providing multiple packages to create mocks from", func() {
				It(`Eventually creates correct files in respective directories`, func() {
					os.Chdir("..")
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "MyDisplay\npegomocktest/subpackage SubDisplay")

					watch.NewMockFileUpdater([]string{"pegomocktest", "pegomocktest/subpackage"}, false).Update()
					go func() { <-done }()

					Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
					Eventually(joinPath(packageDir, "mock_subdisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
				})
			})

			Context("in multiple packages and watching --recursive", func() {
				It(`Eventually creates correct files in respective directories`, func() {
					writeFile(joinPath(packageDir, "interfaces_to_mock"), "MyDisplay")
					writeFile(joinPath(subPackageDir, "interfaces_to_mock"), "SubDisplay")

					watch.NewMockFileUpdater([]string{packageDir}, true).Update()
					go func() { <-done }()

					Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package pegomocktest_test")))
					Eventually(joinPath(subPackageDir, "mock_subdisplay_test.go"), "3s").Should(SatisfyAll(
						BeAnExistingFile(),
						BeAFileContainingSubString("package subpackage_test")))
				})
			})

		})

		Context("after populating interfaces_to_mock with a Go file", func() {
			It(`Eventually creates a file mock_mydisplay_test.go starting with "package pegomocktest_test"`, func() {
				writeFile(joinPath(packageDir, "interfaces_to_mock"), "mydisplay.go")

				watch.NewMockFileUpdater([]string{packageDir}, false).Update()
				go func() { <-done }()

				Eventually(joinPath(packageDir, "mock_mydisplay_test.go"), "3s").Should(SatisfyAll(
					BeAnExistingFile(),
					BeAFileContainingSubString("package pegomocktest_test")))
			})
		})
	})

	Context("with some unknown command", func() {
		It(`reports an error and the usage`, func() {
			var buf bytes.Buffer
			kingpin.CommandLine.Terminate(nil)
			kingpin.CommandLine.Writer(&buf)

			main.Run(cmd("pegomock some unknown command"), &buf, app, done)
			Expect(buf.String()).To(ContainSubstring("error"))
		})
	})

})

func writeFile(filepath string, content string) {
	Expect(ioutil.WriteFile(filepath, []byte(content), 0644)).To(Succeed())
}

func cmd(line string) []string {
	return strings.Split(line, " ")
}
<|endoftext|>


<commit_before>package compressor

import (
	"io"

	"github.com/pierrec/lz4"
)

type CompressorLZ4 struct{}

func NewLZ4() *CompressorLZ4 {
	comp := &CompressorLZ4{}

	return comp
}

func (comp *CompressorLZ4) GetWriter(writer io.Writer) (io.Writer, error) {
	return lz4.NewWriter(writer), nil
}

func (comp *CompressorLZ4) GetReader(reader io.Reader) (io.Reader, error) {
	return lz4.NewReader(reader), nil
}
<commit_msg>Added comments to compressor package.<commit_after>package compressor

import (
	"io"

	"github.com/pierrec/lz4"
)

// CompressorLZ4 is a wrapper around the LZ4 compression library, allowing
// run-time creation of readers and writers as interface values.
type CompressorLZ4 struct{}

// NewLZ4 creates a new wrapper around the LZ4 compression library.
func NewLZ4() *CompressorLZ4 {
	comp := &CompressorLZ4{}

	return comp
}

// GetWriter wraps a new LZ4 writer around the provided writer and returns it
// as an interface value. This allows us to have a common function signature
// with other compression libraries.
func (comp *CompressorLZ4) GetWriter(writer io.Writer) (io.Writer, error) {
	return lz4.NewWriter(writer), nil
}

// GetReader wraps a new LZ4 reader around the provided reader and returns it
// as an interface value. This allows us to have a common function signature
// with other compression libraries.
func (comp *CompressorLZ4) GetReader(reader io.Reader) (io.Reader, error) {
	return lz4.NewReader(reader), nil
}
<|endoftext|>


<commit_before>package middleware

import (
	"errors"
	"github.com/stretchr/testify/assert"
	"testing"

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

func TestCheckStopForumSpam(t *testing.T) {

	err := CheckStopForumSpam("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, errors.New("no ip provided"), "Error should match")
	}

	err = CheckStopForumSpam("127.0.0.1")
	assert.NoError(t, err, "An error was not expected")

	err = CheckStopForumSpam("188.143.232.34")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, ErrBlacklisted, "Error should match")
	}

}
<commit_msg>add middleware tests<commit_after>package middleware

import (
	"errors"
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestCheckStopForumSpam(t *testing.T) {

	err := CheckStopForumSpam("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, errors.New("no ip provided"), "Error should match")
	}

	err = CheckStopForumSpam("127.0.0.1")
	assert.NoError(t, err, "An error was not expected")

	err = CheckStopForumSpam("188.143.232.34")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, ErrBlacklisted, "Error should match")
	}

}
<|endoftext|>


<commit_before>// Copyright 2022 The Go 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 app

import (
	"context"
	"embed"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"sort"
	"time"

	"github.com/influxdata/influxdb-client-go/v2/api"
	"golang.org/x/build/internal/influx"
	"golang.org/x/build/third_party/bandchart"
)

// /dashboard/ displays a dashboard of benchmark results over time for
// performance monitoring.

//go:embed dashboard/*
var dashboardFS embed.FS

// dashboardRegisterOnMux registers the dashboard URLs on mux.
func (a *App) dashboardRegisterOnMux(mux *http.ServeMux) {
	mux.Handle("/dashboard/", http.FileServer(http.FS(dashboardFS)))
	mux.Handle("/dashboard/third_party/bandchart/", http.StripPrefix("/dashboard/third_party/bandchart/", http.FileServer(http.FS(bandchart.FS))))
	mux.HandleFunc("/dashboard/data.json", a.dashboardData)
}

// BenchmarkJSON contains the timeseries values for a single benchmark name +
// unit.
//
// We could try to shoehorn this into benchfmt.Result, but that isn't really
// the best fit for a graph.
type BenchmarkJSON struct {
	Name string
	Unit string

	// These will be sorted by CommitDate.
	Values []ValueJSON
}

type ValueJSON struct {
	CommitHash string
	CommitDate time.Time

	// These are pre-formatted as percent change.
	Low    float64
	Center float64
	High   float64
}

// fetch queries Influx to fill Values. Name and Unit must be set.
//
// WARNING: Name and Unit are not sanitized. DO NOT pass user input.
func (b *BenchmarkJSON) fetch(ctx context.Context, qc api.QueryAPI) error {
	if b.Name == "" {
		return fmt.Errorf("Name must be set")
	}
	if b.Unit == "" {
		return fmt.Errorf("Unit must be set")
	}

	// TODO(prattmic): Adjust UI to comfortably display more than 7d of
	// data.
	query := fmt.Sprintf(`
from(bucket: "perf")
  |> range(start: -7d)
  |> filter(fn: (r) => r["_measurement"] == "benchmark-result")
  |> filter(fn: (r) => r["name"] == "%s")
  |> filter(fn: (r) => r["unit"] == "%s")
  |> filter(fn: (r) => r["branch"] == "master")
  |> filter(fn: (r) => r["goos"] == "linux")
  |> filter(fn: (r) => r["goarch"] == "amd64")
  |> pivot(columnKey: ["_field"], rowKey: ["_time"], valueColumn: "_value")
  |> yield(name: "last")
`, b.Name, b.Unit)

	ir, err := qc.Query(ctx, query)
	if err != nil {
		return fmt.Errorf("error performing query: %W", err)
	}

	for ir.Next() {
		rec := ir.Record()

		low, ok := rec.ValueByKey("low").(float64)
		if !ok {
			return fmt.Errorf("record %s low value got type %T want float64", rec, rec.ValueByKey("low"))
		}

		center, ok := rec.ValueByKey("center").(float64)
		if !ok {
			return fmt.Errorf("record %s center value got type %T want float64", rec, rec.ValueByKey("center"))
		}

		high, ok := rec.ValueByKey("high").(float64)
		if !ok {
			return fmt.Errorf("record %s high value got type %T want float64", rec, rec.ValueByKey("high"))
		}

		commit, ok := rec.ValueByKey("experiment-commit").(string)
		if !ok {
			return fmt.Errorf("record %s experiment-commit value got type %T want float64", rec, rec.ValueByKey("experiment-commit"))
		}

		b.Values = append(b.Values, ValueJSON{
			CommitDate: rec.Time(),
			CommitHash: commit,
			Low:        low - 1,
			Center:     center - 1,
			High:       high - 1,
		})
	}

	sort.Slice(b.Values, func(i, j int) bool {
		return b.Values[i].CommitDate.Before(b.Values[j].CommitDate)
	})

	return nil
}

// search handles /dashboard/data.json.
//
// TODO(prattmic): Consider caching Influx results in-memory for a few mintures
// to reduce load on Influx.
func (a *App) dashboardData(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	start := time.Now()
	defer func() {
		log.Printf("Dashboard total query time: %s", time.Since(start))
	}()

	ifxc, err := a.influxClient(ctx)
	if err != nil {
		log.Printf("Error getting Influx client: %v", err)
		http.Error(w, "Error connecting to Influx", 500)
		return
	}
	defer ifxc.Close()

	qc := ifxc.QueryAPI(influx.Org)

	// Keep benchmarks with the same name grouped together, which is
	// assumed by the JS.
	//
	// WARNING: Name and Unit are not sanitized. DO NOT pass user input.
	benchmarks := []BenchmarkJSON{
		{
			Name: "Tile38WithinCircle100kmRequest",
			Unit: "sec/op",
		},
		{
			Name: "Tile38WithinCircle100kmRequest",
			Unit: "p90-latency-sec",
		},
		{
			Name: "Tile38WithinCircle100kmRequest",
			Unit: "average-RSS-bytes",
		},
		{
			Name: "Tile38WithinCircle100kmRequest",
			Unit: "peak-RSS-bytes",
		},
		{
			Name: "GoBuildKubelet",
			Unit: "sec/op",
		},
		{
			Name: "GoBuildKubeletLink",
			Unit: "sec/op",
		},
	}

	for i := range benchmarks {
		b := &benchmarks[i]
		// WARNING: Name and Unit are not sanitized. DO NOT pass user
		// input.
		if err := b.fetch(ctx, qc); err != nil {
			log.Printf("Error fetching benchmark %s/%s: %v", b.Name, b.Unit, err)
			http.Error(w, "Error fetching benchmark", 500)
			return
		}
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	e := json.NewEncoder(w)
	e.SetIndent("", "\t")
	e.Encode(benchmarks)
}
<commit_msg>perf: increase dashboard to 30d of history<commit_after>// Copyright 2022 The Go 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 app

import (
	"context"
	"embed"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"sort"
	"time"

	"github.com/influxdata/influxdb-client-go/v2/api"
	"golang.org/x/build/internal/influx"
	"golang.org/x/build/third_party/bandchart"
)

// /dashboard/ displays a dashboard of benchmark results over time for
// performance monitoring.

//go:embed dashboard/*
var dashboardFS embed.FS

// dashboardRegisterOnMux registers the dashboard URLs on mux.
func (a *App) dashboardRegisterOnMux(mux *http.ServeMux) {
	mux.Handle("/dashboard/", http.FileServer(http.FS(dashboardFS)))
	mux.Handle("/dashboard/third_party/bandchart/", http.StripPrefix("/dashboard/third_party/bandchart/", http.FileServer(http.FS(bandchart.FS))))
	mux.HandleFunc("/dashboard/data.json", a.dashboardData)
}

// BenchmarkJSON contains the timeseries values for a single benchmark name +
// unit.
//
// We could try to shoehorn this into benchfmt.Result, but that isn't really
// the best fit for a graph.
type BenchmarkJSON struct {
	Name string
	Unit string

	// These will be sorted by CommitDate.
	Values []ValueJSON
}

type ValueJSON struct {
	CommitHash string
	CommitDate time.Time

	// These are pre-formatted as percent change.
	Low    float64
	Center float64
	High   float64
}

// fetch queries Influx to fill Values. Name and Unit must be set.
//
// WARNING: Name and Unit are not sanitized. DO NOT pass user input.
func (b *BenchmarkJSON) fetch(ctx context.Context, qc api.QueryAPI) error {
	if b.Name == "" {
		return fmt.Errorf("Name must be set")
	}
	if b.Unit == "" {
		return fmt.Errorf("Unit must be set")
	}

	// TODO(prattmic): Adjust UI to comfortably display more than 7d of
	// data.
	query := fmt.Sprintf(`
from(bucket: "perf")
  |> range(start: -30d)
  |> filter(fn: (r) => r["_measurement"] == "benchmark-result")
  |> filter(fn: (r) => r["name"] == "%s")
  |> filter(fn: (r) => r["unit"] == "%s")
  |> filter(fn: (r) => r["branch"] == "master")
  |> filter(fn: (r) => r["goos"] == "linux")
  |> filter(fn: (r) => r["goarch"] == "amd64")
  |> pivot(columnKey: ["_field"], rowKey: ["_time"], valueColumn: "_value")
  |> yield(name: "last")
`, b.Name, b.Unit)

	ir, err := qc.Query(ctx, query)
	if err != nil {
		return fmt.Errorf("error performing query: %W", err)
	}

	for ir.Next() {
		rec := ir.Record()

		low, ok := rec.ValueByKey("low").(float64)
		if !ok {
			return fmt.Errorf("record %s low value got type %T want float64", rec, rec.ValueByKey("low"))
		}

		center, ok := rec.ValueByKey("center").(float64)
		if !ok {
			return fmt.Errorf("record %s center value got type %T want float64", rec, rec.ValueByKey("center"))
		}

		high, ok := rec.ValueByKey("high").(float64)
		if !ok {
			return fmt.Errorf("record %s high value got type %T want float64", rec, rec.ValueByKey("high"))
		}

		commit, ok := rec.ValueByKey("experiment-commit").(string)
		if !ok {
			return fmt.Errorf("record %s experiment-commit value got type %T want float64", rec, rec.ValueByKey("experiment-commit"))
		}

		b.Values = append(b.Values, ValueJSON{
			CommitDate: rec.Time(),
			CommitHash: commit,
			Low:        low - 1,
			Center:     center - 1,
			High:       high - 1,
		})
	}

	sort.Slice(b.Values, func(i, j int) bool {
		return b.Values[i].CommitDate.Before(b.Values[j].CommitDate)
	})

	return nil
}

// search handles /dashboard/data.json.
//
// TODO(prattmic): Consider caching Influx results in-memory for a few mintures
// to reduce load on Influx.
func (a *App) dashboardData(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	start := time.Now()
	defer func() {
		log.Printf("Dashboard total query time: %s", time.Since(start))
	}()

	ifxc, err := a.influxClient(ctx)
	if err != nil {
		log.Printf("Error getting Influx client: %v", err)
		http.Error(w, "Error connecting to Influx", 500)
		return
	}
	defer ifxc.Close()

	qc := ifxc.QueryAPI(influx.Org)

	// Keep benchmarks with the same name grouped together, which is
	// assumed by the JS.
	//
	// WARNING: Name and Unit are not sanitized. DO NOT pass user input.
	benchmarks := []BenchmarkJSON{
		{
			Name: "Tile38WithinCircle100kmRequest",
			Unit: "sec/op",
		},
		{
			Name: "Tile38WithinCircle100kmRequest",
			Unit: "p90-latency-sec",
		},
		{
			Name: "Tile38WithinCircle100kmRequest",
			Unit: "average-RSS-bytes",
		},
		{
			Name: "Tile38WithinCircle100kmRequest",
			Unit: "peak-RSS-bytes",
		},
		{
			Name: "GoBuildKubelet",
			Unit: "sec/op",
		},
		{
			Name: "GoBuildKubeletLink",
			Unit: "sec/op",
		},
	}

	for i := range benchmarks {
		b := &benchmarks[i]
		// WARNING: Name and Unit are not sanitized. DO NOT pass user
		// input.
		if err := b.fetch(ctx, qc); err != nil {
			log.Printf("Error fetching benchmark %s/%s: %v", b.Name, b.Unit, err)
			http.Error(w, "Error fetching benchmark", 500)
			return
		}
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	e := json.NewEncoder(w)
	e.SetIndent("", "\t")
	e.Encode(benchmarks)
}
<|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 f32

import (
	"math"
	"testing"
)

const (
	msgRes      = "%v: unexpected result Got: %v Expected: %v"
	msgVal      = "%v: unexpected value at %v Got: %v Expected: %v"
	msgGuard    = "%v: guard violated in %s vector %v %v"
	msgReadOnly = "%v: modified read-only %v argument"
	epsilon     = 1e-4
)

var (
	nan = float32(math.NaN())
	inf = float32(math.Inf(1))
)

// within tests for nan-aware equality within epsilon.
func within(x, y float32) bool {
	a, b := float64(x), float64(y)
	return same(x, y) || math.Abs(a-b) <= epsilon
}

func same(x, y float32) bool {
	a, b := float64(x), float64(y)
	return a == b || (math.IsNaN(a) && math.IsNaN(b))
}

func same64(a, b float64) bool {
	return a == b || (math.IsNaN(a) && math.IsNaN(b))
}

// sameStrided returns true if the strided vector x contains elements of the
// dense vector ref at indices i*inc, false otherwise.
func sameStrided(ref, x []float32, inc int) bool {
	if inc < 0 {
		inc = -inc
	}
	for i, v := range ref {
		if !same(x[i*inc], v) {
			return false
		}
	}
	return true
}

func guardVector(v []float32, g float32, gdLn int) (guarded []float32) {
	guarded = make([]float32, len(v)+gdLn*2)
	copy(guarded[gdLn:], v)
	for i := 0; i < gdLn; i++ {
		guarded[i] = g
		guarded[len(guarded)-1-i] = g
	}
	return guarded
}

func isValidGuard(v []float32, g float32, gdLn int) bool {
	for i := 0; i < gdLn; i++ {
		if !same(v[i], g) || !same(v[len(v)-1-i], g) {
			return false
		}
	}
	return true
}

func guardIncVector(vec []float32, gdVal float32, inc, gdLen int) (guarded []float32) {
	if inc < 0 {
		inc = -inc
	}
	inrLen := len(vec) * inc
	guarded = make([]float32, inrLen+gdLen*2)
	for i := range guarded {
		guarded[i] = gdVal
	}
	for i, v := range vec {
		guarded[gdLen+i*inc] = v
	}
	return guarded
}

func checkValidIncGuard(t *testing.T, v []float32, g float32, inc, gdLn int) {
	srcLn := len(v) - 2*gdLn
	for i := range v {
		switch {
		case same(v[i], g):
			// Correct value
		case i < gdLn:
			t.Error("Front guard violated at", i, v[:gdLn])
		case i > gdLn+srcLn:
			t.Error("Back guard violated at", i-gdLn-srcLn, v[gdLn+srcLn:])
		case (i-gdLn)%inc == 0 && (i-gdLn)/inc < len(v):
		default:
			t.Error("Internal guard violated at", i-gdLn, v[gdLn:gdLn+srcLn])
		}
	}
}

var ( // Offset sets for testing alignment handling in Unitary assembly functions.
	align2 = newIncSet(0, 1, 2, 3)
	align3 = newIncToSet(0, 1, 2, 3)
)

type incSet struct {
	x, y int
}

// genInc will generate all (x,y) combinations of the input increment set.
func newIncSet(inc ...int) []incSet {
	n := len(inc)
	is := make([]incSet, n*n)
	for x := range inc {
		for y := range inc {
			is[x*n+y] = incSet{inc[x], inc[y]}
		}
	}
	return is
}

type incToSet struct {
	dst, x, y int
}

// genIncTo will generate all (dst,x,y) combinations of the input increment set.
func newIncToSet(inc ...int) []incToSet {
	n := len(inc)
	is := make([]incToSet, n*n*n)
	for i, dst := range inc {
		for x := range inc {
			for y := range inc {
				is[i*n*n+x*n+y] = incToSet{dst, inc[x], inc[y]}
			}
		}
	}
	return is
}
<commit_msg>internal/asm/f32: make Ger test pass on arm64<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 f32

import (
	"math"
	"testing"
)

const (
	msgRes      = "%v: unexpected result Got: %v Expected: %v"
	msgVal      = "%v: unexpected value at %v Got: %v Expected: %v"
	msgGuard    = "%v: guard violated in %s vector %v %v"
	msgReadOnly = "%v: modified read-only %v argument"
	epsilon     = 5e-3
)

var (
	nan = float32(math.NaN())
	inf = float32(math.Inf(1))
)

// within tests for nan-aware equality within epsilon.
func within(x, y float32) bool {
	a, b := float64(x), float64(y)
	return same(x, y) || math.Abs(a-b) <= epsilon
}

func same(x, y float32) bool {
	a, b := float64(x), float64(y)
	return a == b || (math.IsNaN(a) && math.IsNaN(b))
}

func same64(a, b float64) bool {
	return a == b || (math.IsNaN(a) && math.IsNaN(b))
}

// sameStrided returns true if the strided vector x contains elements of the
// dense vector ref at indices i*inc, false otherwise.
func sameStrided(ref, x []float32, inc int) bool {
	if inc < 0 {
		inc = -inc
	}
	for i, v := range ref {
		if !same(x[i*inc], v) {
			return false
		}
	}
	return true
}

func guardVector(v []float32, g float32, gdLn int) (guarded []float32) {
	guarded = make([]float32, len(v)+gdLn*2)
	copy(guarded[gdLn:], v)
	for i := 0; i < gdLn; i++ {
		guarded[i] = g
		guarded[len(guarded)-1-i] = g
	}
	return guarded
}

func isValidGuard(v []float32, g float32, gdLn int) bool {
	for i := 0; i < gdLn; i++ {
		if !same(v[i], g) || !same(v[len(v)-1-i], g) {
			return false
		}
	}
	return true
}

func guardIncVector(vec []float32, gdVal float32, inc, gdLen int) (guarded []float32) {
	if inc < 0 {
		inc = -inc
	}
	inrLen := len(vec) * inc
	guarded = make([]float32, inrLen+gdLen*2)
	for i := range guarded {
		guarded[i] = gdVal
	}
	for i, v := range vec {
		guarded[gdLen+i*inc] = v
	}
	return guarded
}

func checkValidIncGuard(t *testing.T, v []float32, g float32, inc, gdLn int) {
	srcLn := len(v) - 2*gdLn
	for i := range v {
		switch {
		case same(v[i], g):
			// Correct value
		case i < gdLn:
			t.Error("Front guard violated at", i, v[:gdLn])
		case i > gdLn+srcLn:
			t.Error("Back guard violated at", i-gdLn-srcLn, v[gdLn+srcLn:])
		case (i-gdLn)%inc == 0 && (i-gdLn)/inc < len(v):
		default:
			t.Error("Internal guard violated at", i-gdLn, v[gdLn:gdLn+srcLn])
		}
	}
}

var ( // Offset sets for testing alignment handling in Unitary assembly functions.
	align2 = newIncSet(0, 1, 2, 3)
	align3 = newIncToSet(0, 1, 2, 3)
)

type incSet struct {
	x, y int
}

// genInc will generate all (x,y) combinations of the input increment set.
func newIncSet(inc ...int) []incSet {
	n := len(inc)
	is := make([]incSet, n*n)
	for x := range inc {
		for y := range inc {
			is[x*n+y] = incSet{inc[x], inc[y]}
		}
	}
	return is
}

type incToSet struct {
	dst, x, y int
}

// genIncTo will generate all (dst,x,y) combinations of the input increment set.
func newIncToSet(inc ...int) []incToSet {
	n := len(inc)
	is := make([]incToSet, n*n*n)
	for i, dst := range inc {
		for x := range inc {
			for y := range inc {
				is[i*n*n+x*n+y] = incToSet{dst, inc[x], inc[y]}
			}
		}
	}
	return is
}
<|endoftext|>


<commit_before>package goparser

import (
	"errors"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"go/types"
	"io/ioutil"

	"github.com/cweill/gotests/internal/models"
)

var ErrEmptyFile = errors.New("file is empty")

type Result struct {
	Header *models.Header
	Funcs  []*models.Function
}

type Parser struct {
	Importer types.Importer
}

func (p *Parser) Parse(srcPath string, files []models.Path) (*Result, error) {
	b, err := ioutil.ReadFile(srcPath)
	if err != nil {
		return nil, fmt.Errorf("ioutil.ReadFile: %v", err)
	}
	if len(b) == 0 {
		return nil, ErrEmptyFile
	}
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, srcPath, nil, 0)
	if err != nil {
		return nil, fmt.Errorf("target parser.ParseFile(): %v", err)
	}
	pkg := f.Name.String()
	var fs []*ast.File
	for _, file := range files {
		ff, err := parser.ParseFile(fset, string(file), nil, 0)
		if err != nil {
			return nil, fmt.Errorf("other file parser.ParseFile: %v", err)
		}
		if name := ff.Name.String(); name != pkg {
			continue
		}
		fs = append(fs, ff)
	}
	conf := &types.Config{
		Importer: p.Importer,
		// Adding a NO-OP error function ignores errors and performs best-effort
		// type checking. https://godoc.org/golang.org/x/tools/go/types#Config
		Error: func(error) {},
	}
	ti := &types.Info{
		Types: make(map[ast.Expr]types.TypeAndValue),
	}
	// Note: conf.Check can fail, but since Info is not required data, it's ok.
	conf.Check("", fset, fs, ti)
	ul := make(map[string]types.Type)
	el := make(map[*types.Struct]ast.Expr)
	for e, t := range ti.Types {
		// Collect the underlying types.
		ul[t.Type.String()] = t.Type.Underlying()
		// Collect structs to determine the fields of a receiver.
		if v, ok := t.Type.(*types.Struct); ok {
			el[v] = e
		}
	}
	r := &Result{
		Header: &models.Header{
			Package: pkg,
			Imports: parseImports(f.Imports),
			Code:    goCode(b, f),
		},
	}
	for _, d := range f.Decls {
		fDecl, ok := d.(*ast.FuncDecl)
		if !ok {
			continue
		}
		r.Funcs = append(r.Funcs, parseFunc(fDecl, ul, el))
	}
	return r, nil
}

// Returns the Go code below the imports block.
func goCode(b []byte, f *ast.File) []byte {
	furthestPos := f.Name.End()
	for _, node := range f.Imports {
		if pos := node.End(); pos > furthestPos {
			furthestPos = pos
		}
	}
	if furthestPos < token.Pos(len(b)) {
		furthestPos++
	}
	return b[furthestPos:]
}

func parseFunc(fDecl *ast.FuncDecl, ul map[string]types.Type, el map[*types.Struct]ast.Expr) *models.Function {
	f := &models.Function{
		Name:       fDecl.Name.String(),
		IsExported: fDecl.Name.IsExported(),
	}
	if fDecl.Recv != nil && fDecl.Recv.List != nil {
		f.Receiver = parseReceiver(fDecl.Recv.List[0], ul, el)
	}
	if fDecl.Type.Params != nil {
		i := 0
		for _, fi := range fDecl.Type.Params.List {
			for _, pf := range parseFields(fi, ul) {
				pf.Index = i
				f.Parameters = append(f.Parameters, pf)
				i++
			}
		}
	}
	if fDecl.Type.Results != nil {
		i := 0
		for _, fi := range fDecl.Type.Results.List {
			for _, pf := range parseFields(fi, ul) {
				if pf.Type.String() == "error" {
					f.ReturnsError = true
				} else {
					pf.Index = i
					f.Results = append(f.Results, pf)
					i++
				}
			}
		}
	}
	return f
}

func parseImports(imps []*ast.ImportSpec) []*models.Import {
	var is []*models.Import
	for _, imp := range imps {
		var n string
		if imp.Name != nil {
			n = imp.Name.String()
		}
		is = append(is, &models.Import{
			Name: n,
			Path: imp.Path.Value,
		})
	}
	return is
}

func parseReceiver(f *ast.Field, ul map[string]types.Type, el map[*types.Struct]ast.Expr) *models.Receiver {
	r := &models.Receiver{
		Field: parseFields(f, ul)[0],
	}
	t, ok := ul[r.Type.Value]
	if !ok {
		return r
	}
	s, ok := t.(*types.Struct)
	if !ok {
		return r
	}
	st := el[s].(*ast.StructType)
	if st.Fields == nil {
		return r
	}
	for _, f := range st.Fields.List {
		r.Fields = append(r.Fields, parseFields(f, ul)...)
	}
	for i, f := range r.Fields {
		f.Name = s.Field(i).Name()
	}
	return r

}

func parseFields(f *ast.Field, ul map[string]types.Type) []*models.Field {
	if f == nil {
		return nil
	}
	t := parseExpr(f.Type, ul)
	if len(f.Names) == 0 {
		return []*models.Field{{
			Type: t,
		}}
	}
	var fs []*models.Field
	for _, n := range f.Names {
		fs = append(fs, &models.Field{
			Name: n.Name,
			Type: t,
		})
	}
	return fs
}

func parseExpr(e ast.Expr, ul map[string]types.Type) *models.Expression {
	var u string
	switch v := e.(type) {
	case *ast.StarExpr:
		val := types.ExprString(v.X)
		if ul[val] != nil {
			u = ul[val].String()
		}
		return &models.Expression{
			Value:      val,
			IsStar:     true,
			Underlying: u,
		}
	case *ast.Ellipsis:
		exp := parseExpr(v.Elt, ul)
		if ul[exp.Value] != nil {
			u = ul[exp.Value].String()
		}
		return &models.Expression{
			Value:      exp.Value,
			IsStar:     exp.IsStar,
			IsVariadic: true,
			Underlying: u,
		}
	default:
		val := types.ExprString(e)
		if ul[val] != nil {
			u = ul[val].String()
		}
		return &models.Expression{
			Value:      val,
			Underlying: u,
			IsWriter:   val == "io.Writer",
		}
	}
}
<commit_msg>Remove unnecessary nil check.<commit_after>package goparser

import (
	"errors"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"go/types"
	"io/ioutil"

	"github.com/cweill/gotests/internal/models"
)

var ErrEmptyFile = errors.New("file is empty")

type Result struct {
	Header *models.Header
	Funcs  []*models.Function
}

type Parser struct {
	Importer types.Importer
}

func (p *Parser) Parse(srcPath string, files []models.Path) (*Result, error) {
	b, err := ioutil.ReadFile(srcPath)
	if err != nil {
		return nil, fmt.Errorf("ioutil.ReadFile: %v", err)
	}
	if len(b) == 0 {
		return nil, ErrEmptyFile
	}
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, srcPath, nil, 0)
	if err != nil {
		return nil, fmt.Errorf("target parser.ParseFile(): %v", err)
	}
	pkg := f.Name.String()
	var fs []*ast.File
	for _, file := range files {
		ff, err := parser.ParseFile(fset, string(file), nil, 0)
		if err != nil {
			return nil, fmt.Errorf("other file parser.ParseFile: %v", err)
		}
		if name := ff.Name.String(); name != pkg {
			continue
		}
		fs = append(fs, ff)
	}
	conf := &types.Config{
		Importer: p.Importer,
		// Adding a NO-OP error function ignores errors and performs best-effort
		// type checking. https://godoc.org/golang.org/x/tools/go/types#Config
		Error: func(error) {},
	}
	ti := &types.Info{
		Types: make(map[ast.Expr]types.TypeAndValue),
	}
	// Note: conf.Check can fail, but since Info is not required data, it's ok.
	conf.Check("", fset, fs, ti)
	ul := make(map[string]types.Type)
	el := make(map[*types.Struct]ast.Expr)
	for e, t := range ti.Types {
		// Collect the underlying types.
		ul[t.Type.String()] = t.Type.Underlying()
		// Collect structs to determine the fields of a receiver.
		if v, ok := t.Type.(*types.Struct); ok {
			el[v] = e
		}
	}
	r := &Result{
		Header: &models.Header{
			Package: pkg,
			Imports: parseImports(f.Imports),
			Code:    goCode(b, f),
		},
	}
	for _, d := range f.Decls {
		fDecl, ok := d.(*ast.FuncDecl)
		if !ok {
			continue
		}
		r.Funcs = append(r.Funcs, parseFunc(fDecl, ul, el))
	}
	return r, nil
}

// Returns the Go code below the imports block.
func goCode(b []byte, f *ast.File) []byte {
	furthestPos := f.Name.End()
	for _, node := range f.Imports {
		if pos := node.End(); pos > furthestPos {
			furthestPos = pos
		}
	}
	if furthestPos < token.Pos(len(b)) {
		furthestPos++
	}
	return b[furthestPos:]
}

func parseFunc(fDecl *ast.FuncDecl, ul map[string]types.Type, el map[*types.Struct]ast.Expr) *models.Function {
	f := &models.Function{
		Name:       fDecl.Name.String(),
		IsExported: fDecl.Name.IsExported(),
	}
	if fDecl.Recv != nil && fDecl.Recv.List != nil {
		f.Receiver = parseReceiver(fDecl.Recv.List[0], ul, el)
	}
	if fDecl.Type.Params != nil {
		i := 0
		for _, fi := range fDecl.Type.Params.List {
			for _, pf := range parseFields(fi, ul) {
				pf.Index = i
				f.Parameters = append(f.Parameters, pf)
				i++
			}
		}
	}
	if fDecl.Type.Results != nil {
		i := 0
		for _, fi := range fDecl.Type.Results.List {
			for _, pf := range parseFields(fi, ul) {
				if pf.Type.String() == "error" {
					f.ReturnsError = true
				} else {
					pf.Index = i
					f.Results = append(f.Results, pf)
					i++
				}
			}
		}
	}
	return f
}

func parseImports(imps []*ast.ImportSpec) []*models.Import {
	var is []*models.Import
	for _, imp := range imps {
		var n string
		if imp.Name != nil {
			n = imp.Name.String()
		}
		is = append(is, &models.Import{
			Name: n,
			Path: imp.Path.Value,
		})
	}
	return is
}

func parseReceiver(f *ast.Field, ul map[string]types.Type, el map[*types.Struct]ast.Expr) *models.Receiver {
	r := &models.Receiver{
		Field: parseFields(f, ul)[0],
	}
	t, ok := ul[r.Type.Value]
	if !ok {
		return r
	}
	s, ok := t.(*types.Struct)
	if !ok {
		return r
	}
	st := el[s].(*ast.StructType)
	if st.Fields == nil {
		return r
	}
	for _, f := range st.Fields.List {
		r.Fields = append(r.Fields, parseFields(f, ul)...)
	}
	for i, f := range r.Fields {
		f.Name = s.Field(i).Name()
	}
	return r

}

func parseFields(f *ast.Field, ul map[string]types.Type) []*models.Field {
	t := parseExpr(f.Type, ul)
	if len(f.Names) == 0 {
		return []*models.Field{{
			Type: t,
		}}
	}
	var fs []*models.Field
	for _, n := range f.Names {
		fs = append(fs, &models.Field{
			Name: n.Name,
			Type: t,
		})
	}
	return fs
}

func parseExpr(e ast.Expr, ul map[string]types.Type) *models.Expression {
	var u string
	switch v := e.(type) {
	case *ast.StarExpr:
		val := types.ExprString(v.X)
		if ul[val] != nil {
			u = ul[val].String()
		}
		return &models.Expression{
			Value:      val,
			IsStar:     true,
			Underlying: u,
		}
	case *ast.Ellipsis:
		exp := parseExpr(v.Elt, ul)
		if ul[exp.Value] != nil {
			u = ul[exp.Value].String()
		}
		return &models.Expression{
			Value:      exp.Value,
			IsStar:     exp.IsStar,
			IsVariadic: true,
			Underlying: u,
		}
	default:
		val := types.ExprString(e)
		if ul[val] != nil {
			u = ul[val].String()
		}
		return &models.Expression{
			Value:      val,
			Underlying: u,
			IsWriter:   val == "io.Writer",
		}
	}
}
<|endoftext|>


<commit_before>package registry

import (
	"context"
	"path/filepath"

	"github.com/hashicorp/hcl/v2"
	sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer"
	"github.com/hashicorp/packer/packer"
)

// JSONMetadataRegistry is a HCP handler made to process legacy JSON templates
type JSONMetadataRegistry struct {
	configuration *packer.Core
	bucket        *Bucket
}

func NewJSONMetadataRegistry(config *packer.Core) (*JSONMetadataRegistry, hcl.Diagnostics) {
	bucket, diags := createConfiguredBucket(
		filepath.Dir(config.Template.Path),
		withPackerEnvConfiguration,
	)

	if diags.HasErrors() {
		return nil, diags
	}

	for _, b := range config.Template.Builders {
		// Get all builds slated within config ignoring any only or exclude flags.
		bucket.RegisterBuildForComponent(packer.HCPName(b))
	}

	return &JSONMetadataRegistry{
		configuration: config,
		bucket:        bucket,
	}, nil
}

// PopulateIteration creates the metadata on HCP for a build
func (h *JSONMetadataRegistry) PopulateIteration(ctx context.Context) error {
	for _, b := range h.configuration.Template.Builders {
		// Get all builds slated within config ignoring any only or exclude flags.
		h.bucket.RegisterBuildForComponent(b.Name)
	}

	err := h.bucket.Validate()
	if err != nil {
		return err
	}
	err = h.bucket.Initialize(ctx)
	if err != nil {
		return err
	}

	err = h.bucket.populateIteration(ctx)
	if err != nil {
		return err
	}

	return nil
}

// StartBuild is invoked when one build for the configuration is starting to be processed
func (h *JSONMetadataRegistry) StartBuild(ctx context.Context, buildName string) error {
	return h.bucket.startBuild(ctx, buildName)
}

// CompleteBuild is invoked when one build for the configuration has finished
func (h *JSONMetadataRegistry) CompleteBuild(
	ctx context.Context,
	buildName string,
	artifacts []sdkpacker.Artifact,
	buildErr error,
) ([]sdkpacker.Artifact, error) {
	return h.bucket.completeBuild(ctx, buildName, artifacts, buildErr)
}
<commit_msg>hcp: remove duplicated build registration for JSON<commit_after>package registry

import (
	"context"
	"path/filepath"

	"github.com/hashicorp/hcl/v2"
	sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer"
	"github.com/hashicorp/packer/packer"
)

// JSONMetadataRegistry is a HCP handler made to process legacy JSON templates
type JSONMetadataRegistry struct {
	configuration *packer.Core
	bucket        *Bucket
}

func NewJSONMetadataRegistry(config *packer.Core) (*JSONMetadataRegistry, hcl.Diagnostics) {
	bucket, diags := createConfiguredBucket(
		filepath.Dir(config.Template.Path),
		withPackerEnvConfiguration,
	)

	if diags.HasErrors() {
		return nil, diags
	}

	for _, b := range config.Template.Builders {
		// Get all builds slated within config ignoring any only or exclude flags.
		bucket.RegisterBuildForComponent(packer.HCPName(b))
	}

	return &JSONMetadataRegistry{
		configuration: config,
		bucket:        bucket,
	}, nil
}

// PopulateIteration creates the metadata on HCP for a build
func (h *JSONMetadataRegistry) PopulateIteration(ctx context.Context) error {
	err := h.bucket.Validate()
	if err != nil {
		return err
	}
	err = h.bucket.Initialize(ctx)
	if err != nil {
		return err
	}

	err = h.bucket.populateIteration(ctx)
	if err != nil {
		return err
	}

	return nil
}

// StartBuild is invoked when one build for the configuration is starting to be processed
func (h *JSONMetadataRegistry) StartBuild(ctx context.Context, buildName string) error {
	return h.bucket.startBuild(ctx, buildName)
}

// CompleteBuild is invoked when one build for the configuration has finished
func (h *JSONMetadataRegistry) CompleteBuild(
	ctx context.Context,
	buildName string,
	artifacts []sdkpacker.Artifact,
	buildErr error,
) ([]sdkpacker.Artifact, error) {
	return h.bucket.completeBuild(ctx, buildName, artifacts, buildErr)
}
<|endoftext|>


<commit_before>package printer

import (
	"context"
	"testing"

	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/require"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"

	"github.com/vmware-tanzu/octant/internal/testutil"
	"github.com/vmware-tanzu/octant/pkg/view/component"
)

func TestNodeListHandler(t *testing.T) {
	controller := gomock.NewController(t)
	defer controller.Finish()

	tpo := newTestPrinterOptions(controller)
	printOptions := tpo.ToOptions()

	node := testutil.CreateNode("node-1")
	node.Status.NodeInfo.KubeletVersion = "1.15.1"
	node.CreationTimestamp = *testutil.CreateTimestamp()

	tpo.PathForObject(node, node.Name, "/node")

	list := &corev1.NodeList{
		Items: []corev1.Node{
			*node,
		},
	}

	ctx := context.Background()
	got, err := NodeListHandler(ctx, list, printOptions)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Nodes", "We couldn't find any nodes!", nodeListColumns, []component.TableRow{
		{
			"Age":     component.NewTimestamp(node.CreationTimestamp.Time),
			"Name":    component.NewLink("", "node-1", "/node"),
			"Labels":  component.NewLabels(make(map[string]string)),
			"Version": component.NewText("1.15.1"),
			"Status":  component.NewText("Unknown"),
			"Roles":   component.NewText("<none>"),
		},
	})

	component.AssertEqual(t, expected, got)
}

func Test_NodeConfiguration(t *testing.T) {
	node := testutil.CreateNode("node")
	node.Status.NodeInfo.Architecture = "amd64"
	node.Status.NodeInfo.BootID = "7eee89e0-b78a-4c30-a1bc-d43ad479b35a"
	node.Status.NodeInfo.ContainerRuntimeVersion = "containerd://1.2.6-0ubuntu1"
	node.Status.NodeInfo.KernelVersion = "4.15.0-58-generic"
	node.Status.NodeInfo.KubeProxyVersion = "v1.15.3"
	node.Status.NodeInfo.KubeletVersion = "v1.15.3"
	node.Status.NodeInfo.MachineID = "87050f150cca41c0ab58b7672b5dbc11"
	node.Status.NodeInfo.OperatingSystem = "linux"
	node.Status.NodeInfo.OSImage = "Ubuntu Disco Dingo (development branch)"
	node.Spec.PodCIDR = "10.244.0.0/24"
	node.Status.NodeInfo.SystemUUID = "5AF9704C-2606-11B2-A85C-C7F92F2B85CA"

	cases := []struct {
		name     string
		node     *corev1.Node
		isErr    bool
		expected *component.Summary
	}{
		{
			name: "general",
			node: node,
			expected: component.NewSummary("Status", []component.SummarySection{
				{
					Header:  "Architecture",
					Content: component.NewText("amd64"),
				},
				{
					Header:  "Boot ID",
					Content: component.NewText("7eee89e0-b78a-4c30-a1bc-d43ad479b35a"),
				},
				{
					Header:  "Container Runtime Version",
					Content: component.NewText("containerd://1.2.6-0ubuntu1"),
				},
				{
					Header:  "Kernel Version",
					Content: component.NewText("4.15.0-58-generic"),
				},
				{
					Header:  "KubeProxy Version",
					Content: component.NewText("v1.15.3"),
				},
				{
					Header:  "Kubelet Version",
					Content: component.NewText("v1.15.3"),
				},
				{
					Header:  "Machine ID",
					Content: component.NewText("87050f150cca41c0ab58b7672b5dbc11"),
				},
				{
					Header:  "Operating System",
					Content: component.NewText("linux"),
				},
				{
					Header:  "OS Image",
					Content: component.NewText("Ubuntu Disco Dingo (development branch)"),
				},
				{
					Header:  "Pod CIDR",
					Content: component.NewText("10.244.0.0/24"),
				},
				{
					Header:  "System UUID",
					Content: component.NewText("5AF9704C-2606-11B2-A85C-C7F92F2B85CA"),
				},
			}...),
		},
		{
			name:  "pod is nil",
			node:  nil,
			isErr: true,
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			controller := gomock.NewController(t)
			defer controller.Finish()

			tpo := newTestPrinterOptions(controller)
			printOptions := tpo.ToOptions()

			nc := NewNodeConfiguration(tc.node)

			summary, err := nc.Create(printOptions)
			if tc.isErr {
				require.Error(t, err)
				return
			}
			require.NoError(t, err)

			component.AssertEqual(t, tc.expected, summary)
		})
	}
}

func Test_createAddressesView(t *testing.T) {
	node := testutil.CreateNode("node-1")
	node.Status.Addresses = []corev1.NodeAddress{
		{
			Type:    corev1.NodeHostName,
			Address: "host.local",
		},
		{
			Type:    corev1.NodeInternalIP,
			Address: "192.168.1.1",
		},
	}

	got, err := createNodeAddressesView(node)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Addresses", "There are no addresses!", nodeAddressesColumns, []component.TableRow{
		{
			"Type":    component.NewText("Hostname"),
			"Address": component.NewText("host.local"),
		},
		{
			"Type":    component.NewText("InternalIP"),
			"Address": component.NewText("192.168.1.1"),
		},
	})

	component.AssertEqual(t, expected, got)
}

func Test_createNodeResourcesView(t *testing.T) {
	node := testutil.CreateNode("node-1")

	capacityQuantity, err := resource.ParseQuantity("1")
	require.NoError(t, err)
	allocatedQuantity, err := resource.ParseQuantity("2")
	require.NoError(t, err)

	resourceNames := []corev1.ResourceName{corev1.ResourceCPU, corev1.ResourceMemory, corev1.ResourcePods,
		corev1.ResourceEphemeralStorage}

	node.Status.Allocatable = map[corev1.ResourceName]resource.Quantity{}
	node.Status.Capacity = map[corev1.ResourceName]resource.Quantity{}

	for _, resourceName := range resourceNames {
		node.Status.Allocatable[resourceName] = allocatedQuantity
		node.Status.Capacity[resourceName] = capacityQuantity
	}

	got, err := createNodeResourcesView(node)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Resources", "There are no resources!", nodeResourcesColumns, []component.TableRow{
		{
			"Key":         component.NewText("CPU"),
			"Capacity":    component.NewText("1"),
			"Allocatable": component.NewText("2"),
		},
		{
			"Key":         component.NewText("Memory"),
			"Capacity":    component.NewText("1"),
			"Allocatable": component.NewText("2"),
		},
		{
			"Key":         component.NewText("Ephemeral Storage"),
			"Capacity":    component.NewText("1"),
			"Allocatable": component.NewText("2"),
		},
		{
			"Key":         component.NewText("Pods"),
			"Capacity":    component.NewText("1"),
			"Allocatable": component.NewText("2"),
		},
	})

	component.AssertEqual(t, expected, got)
}

func Test_createNodeConditionsView(t *testing.T) {

	node := testutil.CreateNode("node-1")
	node.Status.Conditions = []corev1.NodeCondition{
		{
			Type:               "type",
			Status:             "status",
			LastHeartbeatTime:  *testutil.CreateTimestamp(),
			LastTransitionTime: *testutil.CreateTimestamp(),
			Reason:             "reason",
			Message:            "message",
		},
	}

	got, err := createNodeConditionsView(node)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Conditions", "There are no node conditions!", nodeConditionsColumns, []component.TableRow{
		{
			"Type":            component.NewText("type"),
			"Reason":          component.NewText("reason"),
			"Status":          component.NewText("status"),
			"Message":         component.NewText("message"),
			"Last Heartbeat":  component.NewTimestamp(node.Status.Conditions[0].LastHeartbeatTime.Time),
			"Last Transition": component.NewTimestamp(node.Status.Conditions[0].LastTransitionTime.Time),
		},
	})

	component.AssertEqual(t, expected, got)
}

func Test_createNodeImagesView(t *testing.T) {

	node := testutil.CreateNode("node-1")
	node.Status.Images = []corev1.ContainerImage{
		{
			Names:     []string{"a"},
			SizeBytes: 10,
		},
		{
			Names:     []string{"b-1", "b-2"},
			SizeBytes: 10,
		},
	}

	got, err := createNodeImagesView(node)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Images", "There are no images!", nodeImagesColumns, []component.TableRow{
		{
			"Names": component.NewMarkdownText("a"),
			"Size":  component.NewText("10"),
		},
		{
			"Names": component.NewMarkdownText("b-1\nb-2"),
			"Size":  component.NewText("10"),
		},
	})

	component.AssertEqual(t, expected, got)
}
<commit_msg>fix test<commit_after>package printer

import (
	"context"
	"testing"

	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/require"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"

	"github.com/vmware-tanzu/octant/internal/testutil"
	"github.com/vmware-tanzu/octant/pkg/view/component"
)

func TestNodeListHandler(t *testing.T) {
	controller := gomock.NewController(t)
	defer controller.Finish()

	tpo := newTestPrinterOptions(controller)
	printOptions := tpo.ToOptions()

	node := testutil.CreateNode("node-1")
	node.Status.NodeInfo.KubeletVersion = "1.15.1"
	node.CreationTimestamp = *testutil.CreateTimestamp()

	tpo.PathForObject(node, node.Name, "/node")

	list := &corev1.NodeList{
		Items: []corev1.Node{
			*node,
		},
	}

	ctx := context.Background()
	got, err := NodeListHandler(ctx, list, printOptions)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Nodes", "We couldn't find any nodes!", nodeListColumns, []component.TableRow{
		{
			"Age":     component.NewTimestamp(node.CreationTimestamp.Time),
			"Name":    component.NewLink("", "node-1", "/node"),
			"Labels":  component.NewLabels(make(map[string]string)),
			"Version": component.NewText("1.15.1"),
			"Status":  component.NewText("Unknown"),
			"Roles":   component.NewText("<none>"),
		},
	})

	component.AssertEqual(t, expected, got)
}

func Test_NodeConfiguration(t *testing.T) {
	node := testutil.CreateNode("node")
	node.Status.NodeInfo.Architecture = "amd64"
	node.Status.NodeInfo.BootID = "7eee89e0-b78a-4c30-a1bc-d43ad479b35a"
	node.Status.NodeInfo.ContainerRuntimeVersion = "containerd://1.2.6-0ubuntu1"
	node.Status.NodeInfo.KernelVersion = "4.15.0-58-generic"
	node.Status.NodeInfo.KubeProxyVersion = "v1.15.3"
	node.Status.NodeInfo.KubeletVersion = "v1.15.3"
	node.Status.NodeInfo.MachineID = "87050f150cca41c0ab58b7672b5dbc11"
	node.Status.NodeInfo.OperatingSystem = "linux"
	node.Status.NodeInfo.OSImage = "Ubuntu Disco Dingo (development branch)"
	node.Spec.PodCIDR = "10.244.0.0/24"
	node.Status.NodeInfo.SystemUUID = "5AF9704C-2606-11B2-A85C-C7F92F2B85CA"

	cases := []struct {
		name     string
		node     *corev1.Node
		isErr    bool
		expected *component.Summary
	}{
		{
			name: "general",
			node: node,
			expected: component.NewSummary("Status", []component.SummarySection{
				{
					Header:  "Architecture",
					Content: component.NewText("amd64"),
				},
				{
					Header:  "Boot ID",
					Content: component.NewText("7eee89e0-b78a-4c30-a1bc-d43ad479b35a"),
				},
				{
					Header:  "Container Runtime Version",
					Content: component.NewText("containerd://1.2.6-0ubuntu1"),
				},
				{
					Header:  "Kernel Version",
					Content: component.NewText("4.15.0-58-generic"),
				},
				{
					Header:  "KubeProxy Version",
					Content: component.NewText("v1.15.3"),
				},
				{
					Header:  "Kubelet Version",
					Content: component.NewText("v1.15.3"),
				},
				{
					Header:  "Machine ID",
					Content: component.NewText("87050f150cca41c0ab58b7672b5dbc11"),
				},
				{
					Header:  "Operating System",
					Content: component.NewText("linux"),
				},
				{
					Header:  "OS Image",
					Content: component.NewText("Ubuntu Disco Dingo (development branch)"),
				},
				{
					Header:  "Pod CIDR",
					Content: component.NewText("10.244.0.0/24"),
				},
				{
					Header:  "System UUID",
					Content: component.NewText("5AF9704C-2606-11B2-A85C-C7F92F2B85CA"),
				},
			}...),
		},
		{
			name:  "pod is nil",
			node:  nil,
			isErr: true,
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			controller := gomock.NewController(t)
			defer controller.Finish()

			tpo := newTestPrinterOptions(controller)
			printOptions := tpo.ToOptions()

			nc := NewNodeConfiguration(tc.node)

			summary, err := nc.Create(printOptions)
			if tc.isErr {
				require.Error(t, err)
				return
			}
			require.NoError(t, err)

			component.AssertEqual(t, tc.expected, summary)
		})
	}
}

func Test_createAddressesView(t *testing.T) {
	node := testutil.CreateNode("node-1")
	node.Status.Addresses = []corev1.NodeAddress{
		{
			Type:    corev1.NodeHostName,
			Address: "host.local",
		},
		{
			Type:    corev1.NodeInternalIP,
			Address: "192.168.1.1",
		},
	}

	got, err := createNodeAddressesView(node)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Addresses", "There are no addresses!", nodeAddressesColumns, []component.TableRow{
		{
			"Type":    component.NewText("Hostname"),
			"Address": component.NewText("host.local"),
		},
		{
			"Type":    component.NewText("InternalIP"),
			"Address": component.NewText("192.168.1.1"),
		},
	})

	component.AssertEqual(t, expected, got)
}

func Test_createNodeResourcesView(t *testing.T) {
	node := testutil.CreateNode("node-1")

	capacityQuantity, err := resource.ParseQuantity("1")
	require.NoError(t, err)
	allocatedQuantity, err := resource.ParseQuantity("2")
	require.NoError(t, err)

	resourceNames := []corev1.ResourceName{corev1.ResourceCPU, corev1.ResourceMemory, corev1.ResourcePods,
		corev1.ResourceEphemeralStorage}

	node.Status.Allocatable = map[corev1.ResourceName]resource.Quantity{}
	node.Status.Capacity = map[corev1.ResourceName]resource.Quantity{}

	for _, resourceName := range resourceNames {
		node.Status.Allocatable[resourceName] = allocatedQuantity
		node.Status.Capacity[resourceName] = capacityQuantity
	}

	got, err := createNodeResourcesView(node)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Resources", "There are no resources!", nodeResourcesColumns, []component.TableRow{
		{
			"Key":         component.NewText("CPU"),
			"Capacity":    component.NewText("1"),
			"Allocatable": component.NewText("2"),
		},
		{
			"Key":         component.NewText("Memory"),
			"Capacity":    component.NewText("1"),
			"Allocatable": component.NewText("2"),
		},
		{
			"Key":         component.NewText("Ephemeral Storage"),
			"Capacity":    component.NewText("1"),
			"Allocatable": component.NewText("2"),
		},
		{
			"Key":         component.NewText("Pods"),
			"Capacity":    component.NewText("1"),
			"Allocatable": component.NewText("2"),
		},
	})

	component.AssertEqual(t, expected, got)
}

func Test_createNodeConditionsView(t *testing.T) {

	node := testutil.CreateNode("node-1")
	node.Status.Conditions = []corev1.NodeCondition{
		{
			Type:               "type",
			Status:             "status",
			LastHeartbeatTime:  *testutil.CreateTimestamp(),
			LastTransitionTime: *testutil.CreateTimestamp(),
			Reason:             "reason",
			Message:            "message",
		},
	}

	got, err := createNodeConditionsView(node)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Conditions", "There are no node conditions!", nodeConditionsColumns, []component.TableRow{
		{
			"Type":            component.NewText("type"),
			"Reason":          component.NewText("reason"),
			"Status":          component.NewText("status"),
			"Message":         component.NewText("message"),
			"Last Heartbeat":  component.NewTimestamp(node.Status.Conditions[0].LastHeartbeatTime.Time),
			"Last Transition": component.NewTimestamp(node.Status.Conditions[0].LastTransitionTime.Time),
		},
	})

	component.AssertEqual(t, expected, got)
}

func Test_createNodeImagesView(t *testing.T) {

	node := testutil.CreateNode("node-1")
	node.Status.Images = []corev1.ContainerImage{
		{
			Names:     []string{"a"},
			SizeBytes: 1000000,
		},
		{
			Names:     []string{"b-1", "b-2"},
			SizeBytes: 1000000,
		},
	}

	got, err := createNodeImagesView(node)
	require.NoError(t, err)

	expected := component.NewTableWithRows("Images", "There are no images!", nodeImagesColumns, []component.TableRow{
		{
			"Names": component.NewMarkdownText("a"),
			"Size (GB)":  component.NewText("0.001"),
		},
		{
			"Names": component.NewMarkdownText("b-1\nb-2"),
			"Size (GB)":  component.NewText("0.001"),
		},
	})

	component.AssertEqual(t, expected, got)
}
<|endoftext|>


<commit_before>package validate

import (
	"testing"

	"github.com/hashicorp/go-cty/cty"
)

func TestIsHTTPSURL(t *testing.T) {
	cases := []struct {
		Url    string
		Errors int
	}{
		{
			Url:    "",
			Errors: 1,
		},
		{
			Url:    "this is not a url",
			Errors: 1,
		},
		{
			Url:    "www.example.com",
			Errors: 1,
		},
		{
			Url:    "ftp://www.example.com",
			Errors: 1,
		},
		{
			Url:    "http://www.example.com",
			Errors: 1,
		},
		{
			Url:    "https://www.example.com",
			Errors: 0,
		},
	}

	for _, tc := range cases {
		t.Run(tc.Url, func(t *testing.T) {
			diags := IsHttpsUrl(tc.Url, cty.Path{})

			if len(diags) != tc.Errors {
				t.Fatalf("Expected URLIsHTTPS to have %d not %d errors for %q", tc.Errors, len(diags), tc.Url)
			}
		})
	}
}

func TestIsHTTPOrHTTPSURL(t *testing.T) {
	cases := []struct {
		Url    string
		Errors int
	}{
		{
			Url:    "",
			Errors: 1,
		},
		{
			Url:    "this is not a url",
			Errors: 1,
		},
		{
			Url:    "www.example.com",
			Errors: 1,
		},
		{
			Url:    "ftp://www.example.com",
			Errors: 1,
		},
		{
			Url:    "http://www.example.com",
			Errors: 0,
		},
		{
			Url:    "https://www.example.com",
			Errors: 0,
		},
	}

	for _, tc := range cases {
		t.Run(tc.Url, func(t *testing.T) {
			diags := IsHttpOrHttpsUrl(tc.Url, cty.Path{})

			if len(diags) != tc.Errors {
				t.Fatalf("Expected URLIsHTTPOrHTTPS to have %d not %d errors for %q", tc.Errors, len(diags), tc.Url)
			}
		})
	}
}

func TestIsAppURI(t *testing.T) {
	cases := []struct {
		Url    string
		Errors int
	}{
		{
			Url:    "",
			Errors: 1,
		},
		{
			Url:    "this is not a url",
			Errors: 1,
		},
		{
			Url:    "www.example.com",
			Errors: 1,
		},
		{
			Url:    "ftp://www.example.com",
			Errors: 1,
		},
		{
			Url:    "http://www.example.com",
			Errors: 0,
		},
		{
			Url:    "https://www.example.com",
			Errors: 0,
		},
		{
			Url:    "api://www.example.com",
			Errors: 0,
		},
		{
			Url:    "urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66",
			Errors: 0,
		},
		{
			Url:    "urn:nbn:de:bvb:19-146642",
			Errors: 0,
		},
		{
			Url:    "ms-appx://www.example.com",
			Errors: 0,
		},
	}

	for _, tc := range cases {
		t.Run(tc.Url, func(t *testing.T) {
			diags := IsAppUri(tc.Url, cty.Path{})

			if len(diags) != tc.Errors {
				t.Fatalf("Expected URLIsAppURI to have %d not %d errors for %q", tc.Errors, len(diags), tc.Url)
			}
		})
	}
}

func TestIsUriFunc(t *testing.T) {
	cases := []struct {
		TestName           string
		Url                string
		UrnAllowed         bool
		allowTrailingSlash bool
		forceTrailingSlash bool
		Errors             int
		Schemes            []string
	}{
		{
			TestName:           "no path with trailing slash not allowed should error",
			Url:                "http://www.example.com/",
			UrnAllowed:         true,
			allowTrailingSlash: false,
			forceTrailingSlash: false,
			Errors:             1,
			Schemes:            []string{"http"},
		},
		{
			TestName:           "no path with no trailing slash valid",
			Url:                "http://www.example.com",
			UrnAllowed:         true,
			allowTrailingSlash: false,
			forceTrailingSlash: false,
			Errors:             0,
			Schemes:            []string{"http"},
		},
		{
			TestName:           "path with no trailing slash is valid",
			Url:                "http://www.example.com/path",
			UrnAllowed:         true,
			allowTrailingSlash: false,
			forceTrailingSlash: false,
			Errors:             0,
			Schemes:            []string{"http"},
		},
		{
			TestName:           "uri empty should not be valid",
			Url:                "",
			UrnAllowed:         true,
			allowTrailingSlash: false,
			forceTrailingSlash: false,
			Errors:             1,
			Schemes:            []string{"http"},
		},
	}

	for _, tc := range cases {
		t.Run(tc.TestName, func(t *testing.T) {
			diags := IsUriFunc(tc.Schemes, tc.UrnAllowed, tc.allowTrailingSlash, tc.forceTrailingSlash)
			if len(diags(tc.Url, cty.Path{})) != tc.Errors {
				t.Fatalf("Expected IsUriFunc to have %d errors for %v", tc.Errors, tc.Url)
			}
		})
	}
}
<commit_msg>Minor casing<commit_after>package validate

import (
	"testing"

	"github.com/hashicorp/go-cty/cty"
)

func TestIsHTTPSURL(t *testing.T) {
	cases := []struct {
		Url    string
		Errors int
	}{
		{
			Url:    "",
			Errors: 1,
		},
		{
			Url:    "this is not a url",
			Errors: 1,
		},
		{
			Url:    "www.example.com",
			Errors: 1,
		},
		{
			Url:    "ftp://www.example.com",
			Errors: 1,
		},
		{
			Url:    "http://www.example.com",
			Errors: 1,
		},
		{
			Url:    "https://www.example.com",
			Errors: 0,
		},
	}

	for _, tc := range cases {
		t.Run(tc.Url, func(t *testing.T) {
			diags := IsHttpsUrl(tc.Url, cty.Path{})

			if len(diags) != tc.Errors {
				t.Fatalf("Expected URLIsHTTPS to have %d not %d errors for %q", tc.Errors, len(diags), tc.Url)
			}
		})
	}
}

func TestIsHTTPOrHTTPSURL(t *testing.T) {
	cases := []struct {
		Url    string
		Errors int
	}{
		{
			Url:    "",
			Errors: 1,
		},
		{
			Url:    "this is not a url",
			Errors: 1,
		},
		{
			Url:    "www.example.com",
			Errors: 1,
		},
		{
			Url:    "ftp://www.example.com",
			Errors: 1,
		},
		{
			Url:    "http://www.example.com",
			Errors: 0,
		},
		{
			Url:    "https://www.example.com",
			Errors: 0,
		},
	}

	for _, tc := range cases {
		t.Run(tc.Url, func(t *testing.T) {
			diags := IsHttpOrHttpsUrl(tc.Url, cty.Path{})

			if len(diags) != tc.Errors {
				t.Fatalf("Expected URLIsHTTPOrHTTPS to have %d not %d errors for %q", tc.Errors, len(diags), tc.Url)
			}
		})
	}
}

func TestIsAppURI(t *testing.T) {
	cases := []struct {
		Url    string
		Errors int
	}{
		{
			Url:    "",
			Errors: 1,
		},
		{
			Url:    "this is not a url",
			Errors: 1,
		},
		{
			Url:    "www.example.com",
			Errors: 1,
		},
		{
			Url:    "ftp://www.example.com",
			Errors: 1,
		},
		{
			Url:    "http://www.example.com",
			Errors: 0,
		},
		{
			Url:    "https://www.example.com",
			Errors: 0,
		},
		{
			Url:    "api://www.example.com",
			Errors: 0,
		},
		{
			Url:    "urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66",
			Errors: 0,
		},
		{
			Url:    "urn:nbn:de:bvb:19-146642",
			Errors: 0,
		},
		{
			Url:    "ms-appx://www.example.com",
			Errors: 0,
		},
	}

	for _, tc := range cases {
		t.Run(tc.Url, func(t *testing.T) {
			diags := IsAppUri(tc.Url, cty.Path{})

			if len(diags) != tc.Errors {
				t.Fatalf("Expected URLIsAppURI to have %d not %d errors for %q", tc.Errors, len(diags), tc.Url)
			}
		})
	}
}

func TestIsUriFunc(t *testing.T) {
	cases := []struct {
		TestName           string
		Url                string
		UrnAllowed         bool
		AllowTrailingSlash bool
		ForceTrailingSlash bool
		Errors             int
		Schemes            []string
	}{
		{
			TestName:           "no path with trailing slash not allowed should error",
			Url:                "http://www.example.com/",
			UrnAllowed:         true,
			AllowTrailingSlash: false,
			ForceTrailingSlash: false,
			Errors:             1,
			Schemes:            []string{"http"},
		},
		{
			TestName:           "no path with no trailing slash valid",
			Url:                "http://www.example.com",
			UrnAllowed:         true,
			AllowTrailingSlash: false,
			ForceTrailingSlash: false,
			Errors:             0,
			Schemes:            []string{"http"},
		},
		{
			TestName:           "path with no trailing slash is valid",
			Url:                "http://www.example.com/path",
			UrnAllowed:         true,
			AllowTrailingSlash: false,
			ForceTrailingSlash: false,
			Errors:             0,
			Schemes:            []string{"http"},
		},
		{
			TestName:           "uri empty should not be valid",
			Url:                "",
			UrnAllowed:         true,
			AllowTrailingSlash: false,
			ForceTrailingSlash: false,
			Errors:             1,
			Schemes:            []string{"http"},
		},
	}

	for _, tc := range cases {
		t.Run(tc.TestName, func(t *testing.T) {
			diags := IsUriFunc(tc.Schemes, tc.UrnAllowed, tc.AllowTrailingSlash, tc.ForceTrailingSlash)
			if len(diags(tc.Url, cty.Path{})) != tc.Errors {
				t.Fatalf("Expected IsUriFunc to have %d errors for %v", tc.Errors, tc.Url)
			}
		})
	}
}
<|endoftext|>


<commit_before><commit_msg>Add some tests<commit_after><|endoftext|>