<commit_before>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package backend

import (
	"fmt"
	"net/http"

	"github.com/webx-top/com"
	"github.com/webx-top/echo"
	"github.com/webx-top/echo/handler/pprof"
	"github.com/webx-top/echo/middleware"
	"github.com/webx-top/echo/middleware/language"
	"github.com/webx-top/echo/middleware/render"
	"github.com/webx-top/echo/middleware/render/driver"
	"github.com/webx-top/echo/middleware/session"
	"github.com/webx-top/echo/subdomains"

	"github.com/admpub/events"
	"github.com/admpub/events/emitter"
	"github.com/admpub/log"
	"github.com/admpub/nging/application/cmd/event"
	"github.com/admpub/nging/application/handler"
	"github.com/admpub/nging/application/library/config"
	ngingMW "github.com/admpub/nging/application/middleware"
)

const (
	DefaultTemplateDir   = `./template/backend`
	DefaultAssetsDir     = `./public/assets`
	DefaultAssetsURLPath = `/public/assets/backend`
)

var (
	TemplateDir      = DefaultTemplateDir //模板文件夹
	AssetsDir        = DefaultAssetsDir   //素材文件夹
	AssetsURLPath    = DefaultAssetsURLPath
	DefaultAvatarURL = AssetsURLPath + `/images/user_128.png`
	RendererDo       = func(driver.Driver) {}
	ParseStrings     = map[string]string{}
	ParseStringFuncs = map[string]func() string{}
	SkippedGzipPaths = map[string]bool{}
	GzipSkipper      = func(skippedPaths map[string]bool) func(c echo.Context) bool {
		return func(c echo.Context) bool {
			upath := c.Request().URL().Path()
			skipped, _ := skippedPaths[upath]
			return skipped
		}
	}
	DefaultLocalHostNames = []string{
		`127.0.0.1`, `localhost`,
	}
)

func MakeSubdomains(domain string, appends []string) string {
	domain, _ = com.SplitHost(domain)
	port := fmt.Sprintf("%d", config.DefaultCLIConfig.Port)
	newDomain := domain + `,` + domain + `:` + port
	for _, hostName := range appends {
		if hostName == domain {
			continue
		}
		newDomain += `,` + hostName + `:` + port
	}
	return newDomain
}

func init() {
	echo.Set(`BackendPrefix`, handler.BackendPrefix)
	echo.Set(`GlobalPrefix`, handler.GlobalPrefix)
	event.OnStart(0, func() {
		handler.GlobalPrefix = echo.String(`GlobalPrefix`)
		handler.BackendPrefix = echo.String(`BackendPrefix`)
		handler.FrontendPrefix = echo.String(`FrontendPrefix`)
		ngingMW.DefaultAvatarURL = DefaultAssetsURLPath
		e := handler.Echo()
		e.SetPrefix(handler.GlobalPrefix)
		handler.SetRootGroup(handler.BackendPrefix)
		subdomains.Default.Default = `backend`
		domainName := subdomains.Default.Default
		backendDomain := config.DefaultCLIConfig.BackendDomain
		if len(backendDomain) > 0 {
			domainName += `@` + MakeSubdomains(backendDomain, DefaultLocalHostNames)
		}
		subdomains.Default.Add(domainName, e)

		e.Use(middleware.Log(), middleware.Recover())
		skippedGzipPaths := map[string]bool{
			e.Prefix() + `/server/cmdSend/info`:      true,
			e.Prefix() + `/download/progress/info`:   true,
			e.Prefix() + `/debug/pprof/`:             true,
			e.Prefix() + `/debug/pprof/allocs`:       true,
			e.Prefix() + `/debug/pprof/block`:        true,
			e.Prefix() + `/debug/pprof/cmdline`:      true,
			e.Prefix() + `/debug/pprof/goroutine`:    true,
			e.Prefix() + `/debug/pprof/heap`:         true,
			e.Prefix() + `/debug/pprof/mutex`:        true,
			e.Prefix() + `/debug/pprof/profile`:      true,
			e.Prefix() + `/debug/pprof/threadcreate`: true,
			e.Prefix() + `/debug/pprof/trace`:        true,
		}
		for k, v := range skippedGzipPaths {
			SkippedGzipPaths[k] = v
		}
		e.Use(middleware.Gzip(&middleware.GzipConfig{
			Skipper: GzipSkipper(SkippedGzipPaths),
		}))
		e.Use(func(h echo.Handler) echo.HandlerFunc {
			return func(c echo.Context) error {
				c.Response().Header().Set(`Server`, event.SofewareName+`/`+config.Version.Number)
				return h.Handle(c)
			}
		})

		// 注册静态资源文件(网站素材文件)
		e.Use(event.StaticMW) //打包的静态资源
		// 上传文件资源(改到manager中用File函数实现)
		// e.Use(middleware.Static(&middleware.StaticOptions{
		// 	Root: helper.UploadDir,
		// 	Path: helper.UploadURLPath,
		// }))

		// 启用session
		e.Use(session.Middleware(config.SessionOptions))
		// 启用多语言支持
		config.DefaultConfig.Language.SetFSFunc(event.LangFSFunc)
		e.Use(language.New(&config.DefaultConfig.Language).Middleware())

		// 启用Validation
		e.Use(middleware.Validate(echo.NewValidation))

		// 事物支持
		e.Use(ngingMW.Tansaction())
		// 注册模板引擎
		renderOptions := &render.Config{
			TmplDir: TemplateDir,
			Engine:  `standard`,
			ParseStrings: map[string]string{
				`__ASSETS__`: AssetsURLPath,
				`__TMPL__`:   TemplateDir,
			},
			ParseStringFuncs: map[string]func() string{
				`__BACKEND__`:  func() string { return subdomains.Default.URL(handler.BackendPrefix, `backend`) },
				`__FRONTEND__`: func() string { return subdomains.Default.URL(handler.FrontendPrefix, `frontend`) },
			},
			DefaultHTTPErrorCode: http.StatusOK,
			Reload:               true,
			ErrorPages:           config.DefaultConfig.Sys.ErrorPages,
		}
		if ParseStrings != nil {
			for key, val := range ParseStrings {
				renderOptions.ParseStrings[key] = val
			}
		}
		if ParseStringFuncs != nil {
			for key, val := range ParseStringFuncs {
				renderOptions.ParseStringFuncs[key] = val
			}
		}
		if RendererDo != nil {
			renderOptions.AddRendererDo(RendererDo)
		}
		renderOptions.AddFuncSetter(ngingMW.ErrorPageFunc)
		renderOptions.ApplyTo(e, event.BackendTmplMgr)
		//RendererDo(renderOptions.Renderer())
		emitter.DefaultCondEmitter.On(`clearCache`, events.Callback(func(_ events.Event) error {
			log.Debug(`clear: Backend Template Object Cache`)
			renderOptions.Renderer().ClearCache()
			return nil
		}))
		e.Get(`/favicon.ico`, event.FaviconHandler)
		if event.Develop {
			pprof.Wrap(e)
		}
		Initialize()
	})
}
<commit_msg>improved<commit_after>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package backend

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/webx-top/com"
	"github.com/webx-top/echo"
	"github.com/webx-top/echo/handler/pprof"
	"github.com/webx-top/echo/middleware"
	"github.com/webx-top/echo/middleware/language"
	"github.com/webx-top/echo/middleware/render"
	"github.com/webx-top/echo/middleware/render/driver"
	"github.com/webx-top/echo/middleware/session"
	"github.com/webx-top/echo/subdomains"

	"github.com/admpub/events"
	"github.com/admpub/events/emitter"
	"github.com/admpub/log"
	"github.com/admpub/nging/application/cmd/event"
	"github.com/admpub/nging/application/handler"
	"github.com/admpub/nging/application/library/config"
	ngingMW "github.com/admpub/nging/application/middleware"
)

const (
	DefaultTemplateDir   = `./template/backend`
	DefaultAssetsDir     = `./public/assets`
	DefaultAssetsURLPath = `/public/assets/backend`
)

var (
	TemplateDir      = DefaultTemplateDir //模板文件夹
	AssetsDir        = DefaultAssetsDir   //素材文件夹
	AssetsURLPath    = DefaultAssetsURLPath
	DefaultAvatarURL = AssetsURLPath + `/images/user_128.png`
	RendererDo       = func(driver.Driver) {}
	ParseStrings     = map[string]string{}
	ParseStringFuncs = map[string]func() string{}
	SkippedGzipPaths = map[string]bool{}
	GzipSkipper      = func(skippedPaths map[string]bool) func(c echo.Context) bool {
		return func(c echo.Context) bool {
			upath := c.Request().URL().Path()
			skipped, _ := skippedPaths[upath]
			return skipped
		}
	}
	DefaultLocalHostNames = []string{
		`127.0.0.1`, `localhost`,
	}
)

func MakeSubdomains(domain string, appends []string) string {
	var prefix string
	if pos := strings.Index(domain, `://`); pos > 0 {
		pos += 3
		prefix = domain[:pos]
		if pos+1 <= len(domain) {
			domain = domain[pos+1:]
		} else {
			domain = ``
		}
	}
	domain, _ = com.SplitHost(domain)
	port := fmt.Sprintf("%d", config.DefaultCLIConfig.Port)
	newDomain := prefix + domain + `,` + domain + `:` + port
	for _, hostName := range appends {
		if hostName == domain {
			continue
		}
		newDomain += `,` + hostName + `:` + port
	}
	return newDomain
}

func init() {
	echo.Set(`BackendPrefix`, handler.BackendPrefix)
	echo.Set(`GlobalPrefix`, handler.GlobalPrefix)
	event.OnStart(0, func() {
		handler.GlobalPrefix = echo.String(`GlobalPrefix`)
		handler.BackendPrefix = echo.String(`BackendPrefix`)
		handler.FrontendPrefix = echo.String(`FrontendPrefix`)
		ngingMW.DefaultAvatarURL = DefaultAssetsURLPath
		e := handler.Echo()
		e.SetPrefix(handler.GlobalPrefix)
		handler.SetRootGroup(handler.BackendPrefix)
		subdomains.Default.Default = `backend`
		domainName := subdomains.Default.Default
		backendDomain := config.DefaultCLIConfig.BackendDomain
		if len(backendDomain) > 0 {
			domainName += `@` + MakeSubdomains(backendDomain, DefaultLocalHostNames)
		}
		subdomains.Default.Add(domainName, e)

		e.Use(middleware.Log(), middleware.Recover())
		skippedGzipPaths := map[string]bool{
			e.Prefix() + `/server/cmdSend/info`:      true,
			e.Prefix() + `/download/progress/info`:   true,
			e.Prefix() + `/debug/pprof/`:             true,
			e.Prefix() + `/debug/pprof/allocs`:       true,
			e.Prefix() + `/debug/pprof/block`:        true,
			e.Prefix() + `/debug/pprof/cmdline`:      true,
			e.Prefix() + `/debug/pprof/goroutine`:    true,
			e.Prefix() + `/debug/pprof/heap`:         true,
			e.Prefix() + `/debug/pprof/mutex`:        true,
			e.Prefix() + `/debug/pprof/profile`:      true,
			e.Prefix() + `/debug/pprof/threadcreate`: true,
			e.Prefix() + `/debug/pprof/trace`:        true,
		}
		for k, v := range skippedGzipPaths {
			SkippedGzipPaths[k] = v
		}
		e.Use(middleware.Gzip(&middleware.GzipConfig{
			Skipper: GzipSkipper(SkippedGzipPaths),
		}))
		e.Use(func(h echo.Handler) echo.HandlerFunc {
			return func(c echo.Context) error {
				c.Response().Header().Set(`Server`, event.SofewareName+`/`+config.Version.Number)
				return h.Handle(c)
			}
		})

		// 注册静态资源文件(网站素材文件)
		e.Use(event.StaticMW) //打包的静态资源
		// 上传文件资源(改到manager中用File函数实现)
		// e.Use(middleware.Static(&middleware.StaticOptions{
		// 	Root: helper.UploadDir,
		// 	Path: helper.UploadURLPath,
		// }))

		// 启用session
		e.Use(session.Middleware(config.SessionOptions))
		// 启用多语言支持
		config.DefaultConfig.Language.SetFSFunc(event.LangFSFunc)
		e.Use(language.New(&config.DefaultConfig.Language).Middleware())

		// 启用Validation
		e.Use(middleware.Validate(echo.NewValidation))

		// 事物支持
		e.Use(ngingMW.Tansaction())
		// 注册模板引擎
		renderOptions := &render.Config{
			TmplDir: TemplateDir,
			Engine:  `standard`,
			ParseStrings: map[string]string{
				`__ASSETS__`: AssetsURLPath,
				`__TMPL__`:   TemplateDir,
			},
			ParseStringFuncs: map[string]func() string{
				`__BACKEND__`:  func() string { return subdomains.Default.URL(handler.BackendPrefix, `backend`) },
				`__FRONTEND__`: func() string { return subdomains.Default.URL(handler.FrontendPrefix, `frontend`) },
			},
			DefaultHTTPErrorCode: http.StatusOK,
			Reload:               true,
			ErrorPages:           config.DefaultConfig.Sys.ErrorPages,
		}
		if ParseStrings != nil {
			for key, val := range ParseStrings {
				renderOptions.ParseStrings[key] = val
			}
		}
		if ParseStringFuncs != nil {
			for key, val := range ParseStringFuncs {
				renderOptions.ParseStringFuncs[key] = val
			}
		}
		if RendererDo != nil {
			renderOptions.AddRendererDo(RendererDo)
		}
		renderOptions.AddFuncSetter(ngingMW.ErrorPageFunc)
		renderOptions.ApplyTo(e, event.BackendTmplMgr)
		//RendererDo(renderOptions.Renderer())
		emitter.DefaultCondEmitter.On(`clearCache`, events.Callback(func(_ events.Event) error {
			log.Debug(`clear: Backend Template Object Cache`)
			renderOptions.Renderer().ClearCache()
			return nil
		}))
		e.Get(`/favicon.ico`, event.FaviconHandler)
		if event.Develop {
			pprof.Wrap(e)
		}
		Initialize()
	})
}
<|endoftext|>


<commit_before>package writesplitter

import (
	"bufio"
	"bytes"
	"errors"
	"testing"
	"io"
)

type mockF struct {
	*bytes.Buffer
}

func (m *mockF) Close() error {
	m.Reset()
	return nil
}

func TestWriteNoSplit(t *testing.T) {
	createFile = func(name string) (io.WriteCloser, error) {
		return &mockF{&bytes.Buffer{}}, nil
	}
	ws := LineSplitter(5, "")

	mockD := bytes.NewBufferString(`Lorem ipsum dolor sit amet consectetur adipiscing elit
Cras in lacinia eros Aliquam aliquet sapien a
Ut mauris orci varius et cursus sed blandit
Mauris iaculis ac magna non tincidunt In rhoncus
Pellentesque quis erat quis ex aliquam porttitor Vestibulum
Pellentesque nec mollis nibh interdum eleifend nisl Donec
id commodo urna sed tempus mi Vestibulum facilisis
imperdiet dolor sed sollicitudin Proin in lectus sed`)

	expected := mockD.Len() - 7 // we do *not* expect the newlines
	total := 0

	scanner := bufio.NewScanner(mockD)
	for scanner.Scan() {

		n, _ := ws.Write(scanner.Bytes())
		total += n

		if err := scanner.Err(); err != nil {
			t.Error("scanner error", err)
		}
	}

	if expected != total {
		t.Error("len() mismatch: expected", expected, "actual", total)
	}

}

func TestWriteSplit(t *testing.T) {
	var b bytes.Buffer // pass in the buffer to allow for inspection

	createFile = func(name string) (io.WriteCloser, error) {
		return &mockF{&b}, nil
	}

	ws := ByteSplitter(255, "")

	mockD := bytes.NewBufferString(`Lorem ipsum dolor sit amet consectetur adipiscing elit
Cras in lacinia eros Aliquam aliquet sapien a
Ut mauris orci varius et cursus sed blandit
Mauris iaculis ac magna non tincidunt In rhoncus
Pellentesque quis erat quis ex aliquam porttitor Vestibulum
Pellentesque nec mollis nibh interdum eleifend nisl Donec
id commodo urna sed tempus mi Vestibulum facilisis
imperdiet dolor sed sollicitudin Proin in lectus sed`)

	expected := 102 // only the last three lines less two newlines (\n)
	total := 0

	scanner := bufio.NewScanner(mockD)
	for scanner.Scan() {

		n, _ := ws.Write(scanner.Bytes())
		total += n

		if err := scanner.Err(); err != nil {
			t.Error("scanner error", err)
		}
	}

	if expected != b.Len() {
		t.Error("len() mismatch: expected", expected, "actual", b.Len())
	}

}

func TestErrorOnCreate(t *testing.T) {
	createFile = func(name string) (io.WriteCloser, error) {
		return nil, errors.New("This is an error")
	}
	ws := LineSplitter(5, "")

	mockD := bytes.NewBufferString(`Lorem ipsum dolor sit amet consectetur adipiscing elit
Cras in lacinia eros Aliquam aliquet sapien a
Ut mauris orci varius et cursus sed blandit
Mauris iaculis ac magna non tincidunt In rhoncus
Pellentesque quis erat quis ex aliquam porttitor Vestibulum
Pellentesque nec mollis nibh interdum eleifend nisl Donec
id commodo urna sed tempus mi Vestibulum facilisis
imperdiet dolor sed sollicitudin Proin in lectus sed`)

	expected := mockD.Len() - 7 // we do *not* expect the newlines
	total := 0

	var n int
	var err error

	scanner := bufio.NewScanner(mockD)
	for scanner.Scan() {

		n, err = ws.Write(scanner.Bytes())
		if err == nil {
			t.Fail()
		}
		total += n

		if err = scanner.Err(); err != nil {
			t.Error("scanner error", err)
		}
	}

	if expected == total {
		t.Error("len() mismatch: expected", expected, "actual", total)
	}

}
<commit_msg>test was flawed<commit_after><|endoftext|>


<commit_before>// Copyright 2019 The Go Cloud Development Kit Authors
//
// 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
//
//     https://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 azurekeyvault

import (
	"context"
	"errors"
	"log"
	"net/url"
	"os"
	"strings"
	"testing"

	"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/azure"
	"gocloud.dev/internal/testing/setup"
	"gocloud.dev/secrets"
	"gocloud.dev/secrets/driver"
	"gocloud.dev/secrets/drivertest"
)

// Prerequisites for --record mode
//
// 1. Sign-in to your Azure Subscription at http://portal.azure.com.
//
// 2. Create a KeyVault, see https://docs.microsoft.com/en-us/azure/key-vault/quick-create-portal.
//
// 3. Choose an authentication model. This test uses Service Principal, see https://docs.microsoft.com/en-us/rest/api/azure/index#register-your-client-application-with-azure-ad.
// For documentation on acceptable auth models, see https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis.
//
// 4. Set your environment variables depending on the auth model selection. Modify helper initEnv() as needed.
// For Service Principal, please set the following, see https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization.
// - AZURE_TENANT_ID (The ID for the Active Directory tenant that the service principal belongs to.)
// - AZURE_CLIENT_ID (The name or ID of the service principal.)
// - AZURE_CLIENT_SECRET (The secret associated with the service principal.)
// - AZURE_ENVIRONMENT
// - AZURE_AD_RESOURCE to https://vault.azure.net
//
// 5. Create/Import a Key. This can be done in the Azure Portal or by code.
//
// 6. Update constants below to match your Azure KeyVault settings.

const (
	keyVaultName = "go-cdk"
	keyID1       = "test1"
	keyID2       = "test2"
	// Important: an empty key version will default to 'Current Version' in Azure Key Vault.
	// See link below for more information on versioning
	// https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates
	keyVersion = ""
	algorithm  = string(keyvault.RSAOAEP256)
)

type harness struct {
	client *keyvault.BaseClient
	close  func()
}

func (h *harness) MakeDriver(ctx context.Context) (driver.Keeper, driver.Keeper, error) {
	keeper1 := keeper{
		client:       h.client,
		keyVaultName: keyVaultName,
		keyName:      keyID1,
		keyVersion:   keyVersion,
		options:      &KeeperOptions{Algorithm: algorithm},
	}

	keeper2 := keeper{
		client:       h.client,
		keyVaultName: keyVaultName,
		keyName:      keyID2,
		keyVersion:   keyVersion,
		options:      &KeeperOptions{Algorithm: algorithm},
	}

	return &keeper1, &keeper2, nil
}

func (h *harness) Close() {
	h.close()
}

func newHarness(ctx context.Context, t *testing.T) (drivertest.Harness, error) {
	// Use initEnv to setup your environment variables.
	if *setup.Record {
		initEnv()
	}

	done, sender := setup.NewAzureKeyVaultTestClient(ctx, t)
	client, err := Dial()
	if err != nil {
		return nil, err
	}
	client.Sender = sender

	// Use a null authorizer for replay mode.
	if !*setup.Record {
		na := &autorest.NullAuthorizer{}
		client.Authorizer = na
	}

	return &harness{
		client: client,
		close:  done,
	}, nil
}

func initEnv() {
	env, err := azure.EnvironmentFromName("AZUREPUBLICCLOUD")
	if err != nil {
		log.Fatalln(err)
	}

	// For Client Credentials authorization, set AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET
	// For Client Certificate and Azure Managed Service Identity, see doc below for help
	// https://github.com/Azure/azure-sdk-for-go

	if os.Getenv("AZURE_TENANT_ID") == "" ||
		os.Getenv("AZURE_CLIENT_ID") == "" ||
		os.Getenv("AZURE_CLIENT_SECRET") == "" {
		log.Fatal("Missing environment for recording tests, set AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET")
	}

	os.Setenv("AZURE_ENVIRONMENT", env.Name)

	vaultEndpoint := strings.TrimSuffix(env.KeyVaultEndpoint, "/")
	os.Setenv("AZURE_AD_RESOURCE", vaultEndpoint)
}

func TestConformance(t *testing.T) {
	drivertest.RunConformanceTests(t, newHarness, []drivertest.AsTest{verifyAs{}})
}

type verifyAs struct{}

func (v verifyAs) Name() string {
	return "verify As function"
}

func (v verifyAs) ErrorCheck(k *secrets.Keeper, err error) error {
	var e autorest.DetailedError
	if !k.ErrorAs(err, &e) {
		return errors.New("Keeper.ErrorAs failed")
	}
	return nil
}

// Key Vault-specific tests.

func TestNoConnectionError(t *testing.T) {
	client := keyvault.NewWithoutDefaults()
	k, err := NewKeeper(&client, keyVaultName, keyID1, keyVersion, &KeeperOptions{Algorithm: algorithm})
	if err != nil {
		t.Fatal(err)
	}
	if _, err := k.Encrypt(context.Background(), []byte("secrets")); err == nil {
		t.Error("Encrypt: got nil, want no connection error")
	}
}

func TestAlgorithmNotProvided(t *testing.T) {
	client := keyvault.NewWithoutDefaults()
	if _, err := NewKeeper(&client, keyVaultName, keyID1, keyVersion, nil); err == nil {
		t.Error("NewKeeper with no algorithm: got nil, want no algorithm error")
	}
}

func TestKeyInfoFromURL(t *testing.T) {
	tests := []struct {
		URL         string
		WantErr     bool
		WantVault   string
		WantKey     string
		WantVersion string
	}{
		{"azurekeyvault://vault1/key1/version1", false, "vault1", "key1", "version1"},
		{"azurekeyvault://vault2/key2/version2", false, "vault2", "key2", "version2"},
		{"azurekeyvault://vault3/key3", false, "vault3", "key3", ""},
		{"azurekeyvault://vault/key/version/extra", true, "", "", ""},
		{"azurekeyvault://vault", true, "", "", ""},
	}
	for _, test := range tests {
		u, err := url.Parse(test.URL)
		if err != nil {
			t.Fatal(err)
		}
		gotVault, gotKey, gotVersion, gotErr := keyInfoFromURL(u)
		if (gotErr != nil) != test.WantErr {
			t.Errorf("%s: got error %v, want error %v", test.URL, gotErr, test.WantErr)
		}
		if gotErr != nil {
			continue
		}
		if gotVault != test.WantVault {
			t.Errorf("%s: got vault %q want %q", test.URL, gotVault, test.WantVault)
		}
		if gotKey != test.WantKey {
			t.Errorf("%s: got key %q want %q", test.URL, gotKey, test.WantKey)
		}
		if gotVersion != test.WantVersion {
			t.Errorf("%s: got version %q want %q", test.URL, gotVersion, test.WantVersion)
		}
	}
}

func TestOpenKeeper(t *testing.T) {
	tests := []struct {
		URL     string
		WantErr bool
	}{
		// Missing algorithm query param.
		{"azurekeyvault://mykeyvault/mykey/myversion", true},
		// Invalid query parameter.
		{"azurekeyvault://mykeyvault/mykey/myversion?algorithm=RSA-OAEP-256&param=value", true},
		// Empty host.
		{"azurekeyvault:///mykey/myversion?algorithm=RSA-OAEP-256", true},
		// Path has 1 elements (no version) -> OK.
		{"azurekeyvault://mykeyvault/mykey?algorithm=RSA-OAEP-256", false},
		// Path has > 2 elements.
		{"azurekeyvault://mykeyvault/mykey/myversion/extra?algorithm=RSA-OAEP-256", true},
		// Path has empty first element.
		{"azurekeyvault://mykeyvault//myversion?algorithm=RSA-OAEP-256", true},
		// OK.
		{"azurekeyvault://mykeyvault/mykey/myversion?algorithm=RSA-OAEP-256", false},
	}

	ctx := context.Background()
	for _, test := range tests {
		_, err := secrets.OpenKeeper(ctx, test.URL)
		if (err != nil) != test.WantErr {
			t.Errorf("%s: got error %v, want error %v", test.URL, err, test.WantErr)
		}
	}
}
<commit_msg>secrets/azurekeyvault: improve docs for how to run -record tests (#1564)<commit_after>// Copyright 2019 The Go Cloud Development Kit Authors
//
// 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
//
//     https://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 azurekeyvault

import (
	"context"
	"errors"
	"log"
	"net/url"
	"os"
	"strings"
	"testing"

	"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/azure"
	"gocloud.dev/internal/testing/setup"
	"gocloud.dev/secrets"
	"gocloud.dev/secrets/driver"
	"gocloud.dev/secrets/drivertest"
)

// Prerequisites for --record mode
//
// 1. Sign-in to your Azure Subscription at http://portal.azure.com.
//
// 2. Create a KeyVault, see https://docs.microsoft.com/en-us/azure/key-vault/quick-create-portal.
//
// 3. Choose an authentication model. This test uses Service Principal, see https://docs.microsoft.com/en-us/rest/api/azure/index#register-your-client-application-with-azure-ad.
// For documentation on acceptable auth models, see https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis.
//
// 4. Set your environment variables depending on the auth model selection. Modify helper initEnv() as needed.
// For Service Principal, please set the following, see https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization.
//
// - AZURE_TENANT_ID: Go to "Azure Active Directory", then "Properties". The
//     "Directory ID" property is your AZURE_TENANT_ID.
// - AZURE_CLIENT_ID: Go to "Azure Active Directory", then "App Registrations",
//     then "View all applications". The "Application ID" column shows your
//     AZURE_CLIENT_ID.
// - AZURE_CLIENT_SECRET: Click on the application from the previous step,
//     then "Settings" and then "Keys". Create a key and use it as your
//     AZURE_CLIENT_SECRET. Make sure to save the value as it's hidden after
//     the initial creation.
// - AZURE_ENVIRONMENT: (optional).
// - AZURE_AD_RESOURCE: (optional).
//
// 5. Create/Import a Key. This can be done in the Azure Portal under "Key vaults".
//
// 6. Update constants below to match your Azure KeyVault settings.

const (
	keyVaultName = "go-cdk"
	keyID1       = "test1"
	keyID2       = "test2"
	// Important: an empty key version will default to 'Current Version' in Azure Key Vault.
	// See link below for more information on versioning
	// https://docs.microsoft.com/en-us/azure/key-vault/about-keys-secrets-and-certificates
	keyVersion = ""
	algorithm  = string(keyvault.RSAOAEP256)
)

type harness struct {
	client *keyvault.BaseClient
	close  func()
}

func (h *harness) MakeDriver(ctx context.Context) (driver.Keeper, driver.Keeper, error) {
	keeper1 := keeper{
		client:       h.client,
		keyVaultName: keyVaultName,
		keyName:      keyID1,
		keyVersion:   keyVersion,
		options:      &KeeperOptions{Algorithm: algorithm},
	}

	keeper2 := keeper{
		client:       h.client,
		keyVaultName: keyVaultName,
		keyName:      keyID2,
		keyVersion:   keyVersion,
		options:      &KeeperOptions{Algorithm: algorithm},
	}

	return &keeper1, &keeper2, nil
}

func (h *harness) Close() {
	h.close()
}

func newHarness(ctx context.Context, t *testing.T) (drivertest.Harness, error) {
	// Use initEnv to setup your environment variables.
	if *setup.Record {
		initEnv()
	}

	done, sender := setup.NewAzureKeyVaultTestClient(ctx, t)
	client, err := Dial()
	if err != nil {
		return nil, err
	}
	client.Sender = sender

	// Use a null authorizer for replay mode.
	if !*setup.Record {
		na := &autorest.NullAuthorizer{}
		client.Authorizer = na
	}

	return &harness{
		client: client,
		close:  done,
	}, nil
}

func initEnv() {
	env, err := azure.EnvironmentFromName("AZUREPUBLICCLOUD")
	if err != nil {
		log.Fatalln(err)
	}

	// For Client Credentials authorization, set AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET
	// For Client Certificate and Azure Managed Service Identity, see doc below for help
	// https://github.com/Azure/azure-sdk-for-go

	if os.Getenv("AZURE_TENANT_ID") == "" ||
		os.Getenv("AZURE_CLIENT_ID") == "" ||
		os.Getenv("AZURE_CLIENT_SECRET") == "" {
		log.Fatal("Missing environment for recording tests, set AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET")
	}

	os.Setenv("AZURE_ENVIRONMENT", env.Name)

	vaultEndpoint := strings.TrimSuffix(env.KeyVaultEndpoint, "/")
	os.Setenv("AZURE_AD_RESOURCE", vaultEndpoint)
}

func TestConformance(t *testing.T) {
	drivertest.RunConformanceTests(t, newHarness, []drivertest.AsTest{verifyAs{}})
}

type verifyAs struct{}

func (v verifyAs) Name() string {
	return "verify As function"
}

func (v verifyAs) ErrorCheck(k *secrets.Keeper, err error) error {
	var e autorest.DetailedError
	if !k.ErrorAs(err, &e) {
		return errors.New("Keeper.ErrorAs failed")
	}
	return nil
}

// Key Vault-specific tests.

func TestNoConnectionError(t *testing.T) {
	client := keyvault.NewWithoutDefaults()
	k, err := NewKeeper(&client, keyVaultName, keyID1, keyVersion, &KeeperOptions{Algorithm: algorithm})
	if err != nil {
		t.Fatal(err)
	}
	if _, err := k.Encrypt(context.Background(), []byte("secrets")); err == nil {
		t.Error("Encrypt: got nil, want no connection error")
	}
}

func TestAlgorithmNotProvided(t *testing.T) {
	client := keyvault.NewWithoutDefaults()
	if _, err := NewKeeper(&client, keyVaultName, keyID1, keyVersion, nil); err == nil {
		t.Error("NewKeeper with no algorithm: got nil, want no algorithm error")
	}
}

func TestKeyInfoFromURL(t *testing.T) {
	tests := []struct {
		URL         string
		WantErr     bool
		WantVault   string
		WantKey     string
		WantVersion string
	}{
		{"azurekeyvault://vault1/key1/version1", false, "vault1", "key1", "version1"},
		{"azurekeyvault://vault2/key2/version2", false, "vault2", "key2", "version2"},
		{"azurekeyvault://vault3/key3", false, "vault3", "key3", ""},
		{"azurekeyvault://vault/key/version/extra", true, "", "", ""},
		{"azurekeyvault://vault", true, "", "", ""},
	}
	for _, test := range tests {
		u, err := url.Parse(test.URL)
		if err != nil {
			t.Fatal(err)
		}
		gotVault, gotKey, gotVersion, gotErr := keyInfoFromURL(u)
		if (gotErr != nil) != test.WantErr {
			t.Errorf("%s: got error %v, want error %v", test.URL, gotErr, test.WantErr)
		}
		if gotErr != nil {
			continue
		}
		if gotVault != test.WantVault {
			t.Errorf("%s: got vault %q want %q", test.URL, gotVault, test.WantVault)
		}
		if gotKey != test.WantKey {
			t.Errorf("%s: got key %q want %q", test.URL, gotKey, test.WantKey)
		}
		if gotVersion != test.WantVersion {
			t.Errorf("%s: got version %q want %q", test.URL, gotVersion, test.WantVersion)
		}
	}
}

func TestOpenKeeper(t *testing.T) {
	tests := []struct {
		URL     string
		WantErr bool
	}{
		// Missing algorithm query param.
		{"azurekeyvault://mykeyvault/mykey/myversion", true},
		// Invalid query parameter.
		{"azurekeyvault://mykeyvault/mykey/myversion?algorithm=RSA-OAEP-256&param=value", true},
		// Empty host.
		{"azurekeyvault:///mykey/myversion?algorithm=RSA-OAEP-256", true},
		// Path has 1 elements (no version) -> OK.
		{"azurekeyvault://mykeyvault/mykey?algorithm=RSA-OAEP-256", false},
		// Path has > 2 elements.
		{"azurekeyvault://mykeyvault/mykey/myversion/extra?algorithm=RSA-OAEP-256", true},
		// Path has empty first element.
		{"azurekeyvault://mykeyvault//myversion?algorithm=RSA-OAEP-256", true},
		// OK.
		{"azurekeyvault://mykeyvault/mykey/myversion?algorithm=RSA-OAEP-256", false},
	}

	ctx := context.Background()
	for _, test := range tests {
		_, err := secrets.OpenKeeper(ctx, test.URL)
		if (err != nil) != test.WantErr {
			t.Errorf("%s: got error %v, want error %v", test.URL, err, test.WantErr)
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Added memory object types.<commit_after><|endoftext|>


<commit_before>// Windows font locator implementation

package seqdiagram

import (
    "os"
    "path/filepath"
)

// The font directory
// TODO: Must not hard code to C:\Windows\Font

var winFontDirectory string = "C:\\Windows\\Fonts"

// Desirable fonts
var ttfFonts = []string {
    "calibri.ttf",
    "verdana.ttf",
    "arial.ttf",
}

// Returns the first font found given the directory containing the true
// type fonts.
func locateWinTTFFont(ttfDir string) string {
    fonts := make([]string, 0)

    for _, fontName := range ttfFonts {
        path := filepath.Join(ttfDir, fontName)
        if stat, _ := os.Stat(path) ; (stat != nil) {
            fonts = append(fonts, path)
        }
    }
    return fonts
}

// Locates an appropriate font on Window
func LocateFont() []string {
    return locateWinTTFFont(winFontDirectory)
}
<commit_msg>Fixed type error<commit_after>// Windows font locator implementation

package seqdiagram

import (
    "os"
    "path/filepath"
)

// The font directory
// TODO: Must not hard code to C:\Windows\Font

var winFontDirectory string = "C:\\Windows\\Fonts"

// Desirable fonts
var ttfFonts = []string {
    "calibri.ttf",
    "verdana.ttf",
    "arial.ttf",
}

// Returns the first font found given the directory containing the true
// type fonts.
func locateWinTTFFont(ttfDir string) []string {
    fonts := make([]string, 0)

    for _, fontName := range ttfFonts {
        path := filepath.Join(ttfDir, fontName)
        if stat, _ := os.Stat(path) ; (stat != nil) {
            fonts = append(fonts, path)
        }
    }
    return fonts
}

// Locates an appropriate font on Window
func LocateFont() []string {
    return locateWinTTFFont(winFontDirectory)
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/nikhan/go-fetch"
	"github.com/nytlabs/st-core/core"
	"github.com/thejerf/suture"
)

type Position struct {
	X float64 `json:"x"`
	Y float64 `json:"y"`
}

type ProtoBlock struct {
	Label    string   `json:"label"`
	Parent   int      `json:"group"`
	Type     string   `json:"type"`
	Position Position `json:"position"`
}

type BlockLedger struct {
	Label       string              `json:"label"`
	Type        string              `json:"type"`
	Id          int                 `json:"id"`
	Block       *core.Block         `json:"-"`
	Parent      *Group              `json:"-"`
	Token       suture.ServiceToken `json:"-"`
	Composition int                 `json:"composition,omitempty"`
	Inputs      []BlockLedgerInput  `json:"inputs"`
	Outputs     []core.Output       `json:"outputs"`
	Position    Position            `json:"position"`
}

func (bl *BlockLedger) GetID() int {
	return bl.Id
}

func (bl *BlockLedger) GetParent() *Group {
	return bl.Parent
}

func (bl *BlockLedger) SetParent(group *Group) {
	bl.Parent = group
}

type BlockLedgerInput struct {
	Name  string            `json:"name,omitempty"`
	Type  string            `json:"type"`
	Value interface{}       `json:"value"`
	C     chan core.Message `json:"-"`
}

func (s *Server) ListBlocks() []BlockLedger {
	blocks := []BlockLedger{}
	for _, b := range s.blocks {
		blocks = append(blocks, *b)
	}
	return blocks
}

func (s *Server) BlockIndexHandler(w http.ResponseWriter, r *http.Request) {
	s.Lock()
	defer s.Unlock()

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(s.ListBlocks()); err != nil {
		panic(err)
	}
}

func (s *Server) BlockHandler(w http.ResponseWriter, r *http.Request) {
}
func (s *Server) BlockModifyPositionHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	var p Position
	err = json.Unmarshal(body, &p)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read JSON"})
		return
	}

	s.Lock()
	defer s.Unlock()

	b, ok := s.blocks[id]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not find block"})
		return
	}

	b.Position = p

	update := struct {
		Position
		Id int
	}{
		p,
		id,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: BLOCK, Data: update})
	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) CreateBlock(p ProtoBlock) (*BlockLedger, error) {
	blockSpec, ok := s.library[p.Type]
	if !ok {
		return nil, errors.New("spec not found")
	}

	block := core.NewBlock(blockSpec)

	m := &BlockLedger{
		Label:    p.Label,
		Position: p.Position,
		Type:     p.Type,
		Block:    block,
		Id:       s.GetNextID(),
	}

	is := m.Block.GetInputs()

	// may want to move this into actual block someday
	inputs := make([]BlockLedgerInput, len(is), len(is))
	for i, v := range is {
		if q, ok := v.Value.(*fetch.Query); ok {
			inputs[i] = BlockLedgerInput{
				Name:  v.Name,
				Type:  "fetch",
				Value: q.String(),
				C:     v.C,
			}
		} else {
			inputs[i] = BlockLedgerInput{
				Name:  v.Name,
				Type:  "const",
				Value: v.Value,
				C:     v.C,
			}
		}
	}

	if _, ok := s.groups[p.Parent]; !ok {
		return nil, errors.New("invalid group, could not create block")
	}

	m.Token = s.supervisor.Add(block)
	m.Inputs = inputs
	m.Outputs = block.GetOutputs()
	s.blocks[m.Id] = m

	s.websocketBroadcast(Update{Action: CREATE, Type: BLOCK, Data: m})

	err := s.AddChildToGroup(p.Parent, m)
	if err != nil {
		return nil, err

	}

	return m, nil
}

// CreateBlockHandler responds to a POST request to instantiate a new block and add it to the Server.
func (s *Server) BlockCreateHandler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	var m ProtoBlock
	err = json.Unmarshal(body, &m)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	s.Lock()
	defer s.Unlock()

	b, err := s.CreateBlock(m)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusOK)
	writeJSON(w, b)
}

func (s *Server) BlockModifyRouteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	routes, ok := vars["index"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no route index supplied"})
		return
	}

	route, err := strconv.Atoi(routes)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	var v BlockLedgerInput
	err = json.Unmarshal(body, &v)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not unmarshal value"})
		return
	}

	s.Lock()
	defer s.Unlock()

	err = s.ModifyBlockRoute(id, route, v)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) ModifyBlockRoute(id int, route int, v BlockLedgerInput) error {
	b, ok := s.blocks[id]
	if !ok {
		return errors.New("could not find block")
	}

	// again maybe this type should be native to block under core.
	var m interface{}
	switch v.Type {
	case "fetch":
		queryString, ok := v.Value.(string)
		if !ok {
			return errors.New("fetch is not string")
		}

		fo, err := fetch.Parse(queryString)
		if err != nil {
			return err
		}

		m = fo
	case "const":
		m = v.Value
	default:
		return errors.New("no value or query specified")
	}

	err := b.Block.SetInput(core.RouteIndex(route), m)
	if err != nil {
		return err
	}

	s.blocks[id].Inputs[route].Type = v.Type
	s.blocks[id].Inputs[route].Value = m

	update := struct {
		BlockLedgerInput
		Id    int `json:"id"`
		input int `json:"input"`
	}{
		v, id, route,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: BLOCK, Data: update})
	return nil
}

func (s *Server) BlockModifyNameHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	s.Lock()
	defer s.Unlock()

	_, ok = s.blocks[id]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"block not found"})
		return
	}

	var label string
	err = json.Unmarshal(body, &label)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not unmarshal value"})
		return
	}

	s.blocks[id].Label = label

	update := struct {
		Id    int    `json:"id"`
		Label string `json:"label"`
	}{
		id, label,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: BLOCK, Data: update})
	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) DeleteBlock(id int) error {
	b, ok := s.blocks[id]
	if !ok {
		return errors.New("block not found")
	}

	deleteSet := make(map[int]struct{})

	// build a set of connections that we may need to delete
	// we need to panic here because if any error is thrown we are in huge trouble
	// any panic indicates that our server connection ledger is no longer true
	for _, c := range s.connections {
		if c.Target.Id == id || c.Source.Id == id {
			deleteSet[c.Id] = struct{}{}
		}
	}

	// delete the connections that involve this block
	for k, _ := range deleteSet {
		s.DeleteConnection(k)
	}

	// remove from group
	s.DetachChild(b)

	// stop and delete the block
	s.supervisor.Remove(b.Token)
	s.websocketBroadcast(Update{Action: DELETE, Type: BLOCK, Data: s.blocks[id]})
	delete(s.blocks, id)
	return nil
}

func (s *Server) BlockDeleteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	s.Lock()
	defer s.Unlock()

	err = s.DeleteBlock(id)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusNoContent)

}
<commit_msg>adding GET /block/{id}<commit_after>package server

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/nikhan/go-fetch"
	"github.com/nytlabs/st-core/core"
	"github.com/thejerf/suture"
)

type Position struct {
	X float64 `json:"x"`
	Y float64 `json:"y"`
}

type ProtoBlock struct {
	Label    string   `json:"label"`
	Parent   int      `json:"group"`
	Type     string   `json:"type"`
	Position Position `json:"position"`
}

type BlockLedger struct {
	Label       string              `json:"label"`
	Type        string              `json:"type"`
	Id          int                 `json:"id"`
	Block       *core.Block         `json:"-"`
	Parent      *Group              `json:"-"`
	Token       suture.ServiceToken `json:"-"`
	Composition int                 `json:"composition,omitempty"`
	Inputs      []BlockLedgerInput  `json:"inputs"`
	Outputs     []core.Output       `json:"outputs"`
	Position    Position            `json:"position"`
}

func (bl *BlockLedger) GetID() int {
	return bl.Id
}

func (bl *BlockLedger) GetParent() *Group {
	return bl.Parent
}

func (bl *BlockLedger) SetParent(group *Group) {
	bl.Parent = group
}

type BlockLedgerInput struct {
	Name  string            `json:"name,omitempty"`
	Type  string            `json:"type"`
	Value interface{}       `json:"value"`
	C     chan core.Message `json:"-"`
}

func (s *Server) ListBlocks() []BlockLedger {
	blocks := []BlockLedger{}
	for _, b := range s.blocks {
		blocks = append(blocks, *b)
	}
	return blocks
}

func (s *Server) BlockIndexHandler(w http.ResponseWriter, r *http.Request) {
	s.Lock()
	defer s.Unlock()

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(s.ListBlocks()); err != nil {
		panic(err)
	}
}

func (s *Server) BlockHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	s.Lock()
	defer s.Unlock()

	b, ok := s.blocks[id]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not find block"})
		return
	}

	w.WriteHeader(http.StatusOK)
	writeJSON(w, b)
	return
}

func (s *Server) BlockModifyPositionHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	var p Position
	err = json.Unmarshal(body, &p)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read JSON"})
		return
	}

	s.Lock()
	defer s.Unlock()

	b, ok := s.blocks[id]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not find block"})
		return
	}

	b.Position = p

	update := struct {
		Position
		Id int
	}{
		p,
		id,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: BLOCK, Data: update})
	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) CreateBlock(p ProtoBlock) (*BlockLedger, error) {
	blockSpec, ok := s.library[p.Type]
	if !ok {
		return nil, errors.New("spec not found")
	}

	block := core.NewBlock(blockSpec)

	m := &BlockLedger{
		Label:    p.Label,
		Position: p.Position,
		Type:     p.Type,
		Block:    block,
		Id:       s.GetNextID(),
	}

	is := m.Block.GetInputs()

	// may want to move this into actual block someday
	inputs := make([]BlockLedgerInput, len(is), len(is))
	for i, v := range is {
		if q, ok := v.Value.(*fetch.Query); ok {
			inputs[i] = BlockLedgerInput{
				Name:  v.Name,
				Type:  "fetch",
				Value: q.String(),
				C:     v.C,
			}
		} else {
			inputs[i] = BlockLedgerInput{
				Name:  v.Name,
				Type:  "const",
				Value: v.Value,
				C:     v.C,
			}
		}
	}

	if _, ok := s.groups[p.Parent]; !ok {
		return nil, errors.New("invalid group, could not create block")
	}

	m.Token = s.supervisor.Add(block)
	m.Inputs = inputs
	m.Outputs = block.GetOutputs()
	s.blocks[m.Id] = m

	s.websocketBroadcast(Update{Action: CREATE, Type: BLOCK, Data: m})

	err := s.AddChildToGroup(p.Parent, m)
	if err != nil {
		return nil, err

	}

	return m, nil
}

// CreateBlockHandler responds to a POST request to instantiate a new block and add it to the Server.
func (s *Server) BlockCreateHandler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	var m ProtoBlock
	err = json.Unmarshal(body, &m)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	s.Lock()
	defer s.Unlock()

	b, err := s.CreateBlock(m)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusOK)
	writeJSON(w, b)
}

func (s *Server) BlockModifyRouteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	routes, ok := vars["index"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no route index supplied"})
		return
	}

	route, err := strconv.Atoi(routes)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	var v BlockLedgerInput
	err = json.Unmarshal(body, &v)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not unmarshal value"})
		return
	}

	s.Lock()
	defer s.Unlock()

	err = s.ModifyBlockRoute(id, route, v)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) ModifyBlockRoute(id int, route int, v BlockLedgerInput) error {
	b, ok := s.blocks[id]
	if !ok {
		return errors.New("could not find block")
	}

	// again maybe this type should be native to block under core.
	var m interface{}
	switch v.Type {
	case "fetch":
		queryString, ok := v.Value.(string)
		if !ok {
			return errors.New("fetch is not string")
		}

		fo, err := fetch.Parse(queryString)
		if err != nil {
			return err
		}

		m = fo
	case "const":
		m = v.Value
	default:
		return errors.New("no value or query specified")
	}

	err := b.Block.SetInput(core.RouteIndex(route), m)
	if err != nil {
		return err
	}

	s.blocks[id].Inputs[route].Type = v.Type
	s.blocks[id].Inputs[route].Value = m

	update := struct {
		BlockLedgerInput
		Id    int `json:"id"`
		input int `json:"input"`
	}{
		v, id, route,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: BLOCK, Data: update})
	return nil
}

func (s *Server) BlockModifyNameHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not read request body"})
		return
	}

	s.Lock()
	defer s.Unlock()

	_, ok = s.blocks[id]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"block not found"})
		return
	}

	var label string
	err = json.Unmarshal(body, &label)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"could not unmarshal value"})
		return
	}

	s.blocks[id].Label = label

	update := struct {
		Id    int    `json:"id"`
		Label string `json:"label"`
	}{
		id, label,
	}

	s.websocketBroadcast(Update{Action: UPDATE, Type: BLOCK, Data: update})
	w.WriteHeader(http.StatusNoContent)
}

func (s *Server) DeleteBlock(id int) error {
	b, ok := s.blocks[id]
	if !ok {
		return errors.New("block not found")
	}

	deleteSet := make(map[int]struct{})

	// build a set of connections that we may need to delete
	// we need to panic here because if any error is thrown we are in huge trouble
	// any panic indicates that our server connection ledger is no longer true
	for _, c := range s.connections {
		if c.Target.Id == id || c.Source.Id == id {
			deleteSet[c.Id] = struct{}{}
		}
	}

	// delete the connections that involve this block
	for k, _ := range deleteSet {
		s.DeleteConnection(k)
	}

	// remove from group
	s.DetachChild(b)

	// stop and delete the block
	s.supervisor.Remove(b.Token)
	s.websocketBroadcast(Update{Action: DELETE, Type: BLOCK, Data: s.blocks[id]})
	delete(s.blocks, id)
	return nil
}

func (s *Server) BlockDeleteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	ids, ok := vars["id"]
	if !ok {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{"no ID supplied"})
		return
	}

	id, err := strconv.Atoi(ids)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	s.Lock()
	defer s.Unlock()

	err = s.DeleteBlock(id)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		writeJSON(w, Error{err.Error()})
		return
	}

	w.WriteHeader(http.StatusNoContent)

}
<|endoftext|>


<commit_before>package fromspring

import (
	"testing"
)

var parseLineTests = []struct {
	v                   string
	oasName             string
	oasType             string
	oasFormat           string
	oasDefault          interface{}
	explicitCustomTypes []string
}{
	{"private Boolean myPropBoolean;", "myPropBoolean", "boolean", "", nil, []string{}},
	{"private DateTime myPropDateTime;", "myPropDateTime", "string", "date-time", nil, []string{}},
	{"private Integer myPropInteger = 1;", "myPropInteger", "integer", "", 1, []string{}},
	{"private Long myPropLong = 1;", "myPropLong", "integer", "int64", 1, []string{}},
	{"private String myPropString;", "myPropString", "string", "", nil, []string{}},
	{"private String myPropString = \"\";", "myPropString", "string", "", "", []string{}},
	{"private String myPropString = \"AVAILABLE\";", "myPropString", "string", "", "AVAILABLE", []string{}},
	{"private List<Integer> myPropStrings = new ArrayList<>();", "myPropStrings", "array", "", nil, []string{}},
	{"private List<String> myPropStrings = new ArrayList<>();", "myPropStrings", "array", "", nil, []string{}},
	{"private List<Integer> myPropStrings;", "myPropStrings", "array", "", nil, []string{}},
	{"private List<String> myPropStrings;", "myPropStrings", "array", "", nil, []string{}},
}

func TestParseLine(t *testing.T) {
	for _, tt := range parseLineTests {
		name, schemaRef, err := ParseSpringLineToSchemaRef(tt.v, tt.explicitCustomTypes)
		if err != nil {
			t.Errorf("fromspring.ParseSpringLineToSchema() [%v]", err)
		}
		schema := schemaRef.Value
		if tt.oasName != name || tt.oasType != schema.Type || tt.oasFormat != schema.Format {
			t.Errorf(`fromspring.ParseSpringLineToSchema("%s") MISMATCH W[%v]G[%v] [%v][%v] [%v][%v]`, tt.v, tt.oasName, name, tt.oasType, schema.Type, tt.oasFormat, schema.Format)
		}
		//fmtutil.PrintJSON(schema)
	}
}

/*
const CampaignLeadSearchCriteriaSimple = `private List<Integer> leadIds = new ArrayList<>();
	private List<Integer> listIds = new ArrayList<>();
	private List<String> externIds = new ArrayList<>();
	private List<String> physicalStates;
	private List<String> agentDispositions;
	private List<String> leadPhoneNumbers = new ArrayList<>();
	private boolean orphanedLeadsOnly;
	private String callerId;
	private String leadPhoneNum;
	private List<Integer> campaignIds = new ArrayList<>();
	private String firstName;
	private String lastName;
	private String address1;
	private String address2;
	private String city;
	private String zip;
	private String emailAddress;
	private String auxData1;
	private String auxData2;
	private String auxData3;
	private String auxData4;
	private String auxData5;
	private Integer pendingAgentId;
	private Integer agentId;`
*/
<commit_msg>update for Java date<commit_after>package fromspring

import (
	"testing"
)

var parseLineTests = []struct {
	v                   string
	oasName             string
	oasType             string
	oasFormat           string
	oasDefault          interface{}
	explicitCustomTypes []string
}{
	{"private Boolean myPropBoolean;", "myPropBoolean", "boolean", "", nil, []string{}},
	{"private DateTime myPropDateTime;", "myPropDateTime", "string", "", nil, []string{}},
	{"private Integer myPropInteger = 1;", "myPropInteger", "integer", "", 1, []string{}},
	{"private Long myPropLong = 1;", "myPropLong", "integer", "int64", 1, []string{}},
	{"private String myPropString;", "myPropString", "string", "", nil, []string{}},
	{"private String myPropString = \"\";", "myPropString", "string", "", "", []string{}},
	{"private String myPropString = \"AVAILABLE\";", "myPropString", "string", "", "AVAILABLE", []string{}},
	{"private List<Integer> myPropStrings = new ArrayList<>();", "myPropStrings", "array", "", nil, []string{}},
	{"private List<String> myPropStrings = new ArrayList<>();", "myPropStrings", "array", "", nil, []string{}},
	{"private List<Integer> myPropStrings;", "myPropStrings", "array", "", nil, []string{}},
	{"private List<String> myPropStrings;", "myPropStrings", "array", "", nil, []string{}},
}

func TestParseLine(t *testing.T) {
	for _, tt := range parseLineTests {
		name, schemaRef, err := ParseSpringLineToSchemaRef(tt.v, tt.explicitCustomTypes)
		if err != nil {
			t.Errorf("fromspring.ParseSpringLineToSchema() [%v]", err)
		}
		schema := schemaRef.Value
		if tt.oasName != name || tt.oasType != schema.Type || tt.oasFormat != schema.Format {
			t.Errorf(`fromspring.ParseSpringLineToSchema("%s") MISMATCH W[%v]G[%v] [%v][%v] [%v][%v]`, tt.v, tt.oasName, name, tt.oasType, schema.Type, tt.oasFormat, schema.Format)
		}
		//fmtutil.PrintJSON(schema)
	}
}

/*
const CampaignLeadSearchCriteriaSimple = `private List<Integer> leadIds = new ArrayList<>();
	private List<Integer> listIds = new ArrayList<>();
	private List<String> externIds = new ArrayList<>();
	private List<String> physicalStates;
	private List<String> agentDispositions;
	private List<String> leadPhoneNumbers = new ArrayList<>();
	private boolean orphanedLeadsOnly;
	private String callerId;
	private String leadPhoneNum;
	private List<Integer> campaignIds = new ArrayList<>();
	private String firstName;
	private String lastName;
	private String address1;
	private String address2;
	private String city;
	private String zip;
	private String emailAddress;
	private String auxData1;
	private String auxData2;
	private String auxData3;
	private String auxData4;
	private String auxData5;
	private Integer pendingAgentId;
	private Integer agentId;`
*/
<|endoftext|>


<commit_before>package wallet

import (
	"bytes"
	"path/filepath"
	"testing"

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/bolt"
)

// resetChangeID clears the wallet's ConsensusChangeID. When Unlock is called,
// the wallet will rescan from the genesis block.
func resetChangeID(w *Wallet) {
	err := w.db.Update(func(tx *bolt.Tx) error {
		return dbPutConsensusChangeID(tx, modules.ConsensusChangeBeginning)
	})
	if err != nil {
		panic(err)
	}
}

// TestPrimarySeed checks that the correct seed is returned when calling
// PrimarySeed.
func TestPrimarySeed(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	// Start with a blank wallet tester.
	wt, err := createBlankWalletTester("TestPrimarySeed")
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()

	// Create a seed and unlock the wallet.
	seed, err := wt.wallet.Encrypt(crypto.TwofishKey{})
	if err != nil {
		t.Fatal(err)
	}
	err = wt.wallet.Unlock(crypto.TwofishKey(crypto.HashObject(seed)))
	if err != nil {
		t.Fatal(err)
	}

	// Try getting an address, see that the seed advances correctly.
	primarySeed, progress, err := wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(primarySeed[:], seed[:]) {
		t.Error("PrimarySeed is returning a value inconsitent with the seed returned by Encrypt")
	}
	if progress != 0 {
		t.Error("primary seed is returning the wrong progress")
	}
	_, err = wt.wallet.NextAddress()
	if err != nil {
		t.Fatal(err)
	}
	_, progress, err = wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	if progress != 1 {
		t.Error("primary seed is returning the wrong progress")
	}

	// Lock then unlock the wallet and check the responses.
	err = wt.wallet.Lock()
	if err != nil {
		t.Fatal(err)
	}
	_, _, err = wt.wallet.PrimarySeed()
	if err != modules.ErrLockedWallet {
		t.Error("unexpected err:", err)
	}
	err = wt.wallet.Unlock(crypto.TwofishKey(crypto.HashObject(seed)))
	if err != nil {
		t.Fatal(err)
	}
	primarySeed, progress, err = wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(primarySeed[:], seed[:]) {
		t.Error("PrimarySeed is returning a value inconsitent with the seed returned by Encrypt")
	}
	if progress != 1 {
		t.Error("progress reporting an unexpected value")
	}
}

// TestLoadSeed checks that a seed can be successfully recovered from a wallet,
// and then remain available on subsequent loads of the wallet.
func TestLoadSeed(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	wt, err := createWalletTester("TestLoadSeed")
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()
	seed, _, err := wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	allSeeds, err := wt.wallet.AllSeeds()
	if err != nil {
		t.Fatal(err)
	}
	if len(allSeeds) != 1 {
		t.Fatal("AllSeeds should be returning the primary seed.")
	} else if allSeeds[0] != seed {
		t.Fatal("AllSeeds returned the wrong seed")
	}
	wt.wallet.Close()

	dir := filepath.Join(build.TempDir(modules.WalletDir, "TestLoadSeed - 0"), modules.WalletDir)
	w, err := New(wt.cs, wt.tpool, dir)
	if err != nil {
		t.Fatal(err)
	}
	newSeed, err := w.Encrypt(crypto.TwofishKey{})
	if err != nil {
		t.Fatal(err)
	}
	err = w.Unlock(crypto.TwofishKey(crypto.HashObject(newSeed)))
	if err != nil {
		t.Fatal(err)
	}
	// Balance of wallet should be 0.
	siacoinBal, _, _ := w.ConfirmedBalance()
	if !siacoinBal.Equals64(0) {
		t.Error("fresh wallet should not have a balance")
	}
	err = w.LoadSeed(crypto.TwofishKey(crypto.HashObject(newSeed)), seed)
	if err != nil {
		t.Fatal(err)
	}
	allSeeds, err = w.AllSeeds()
	if err != nil {
		t.Fatal(err)
	}
	if len(allSeeds) != 2 {
		t.Error("AllSeeds should be returning the primary seed with the recovery seed.")
	}
	if allSeeds[0] != newSeed {
		t.Error("AllSeeds returned the wrong seed")
	}
	if !bytes.Equal(allSeeds[1][:], seed[:]) {
		t.Error("AllSeeds returned the wrong seed")
	}
	w.Close()

	// Rather than worry about a rescan, which isn't implemented and has
	// synchronization difficulties, just load a new wallet from the same
	// settings file - the same effect is achieved without the difficulties.
	//
	// TODO: when proper seed loading is implemented, just check the balance
	// of w directly.
	w2, err := New(wt.cs, wt.tpool, dir)
	if err != nil {
		t.Fatal(err)
	}
	// reset the ccID so that the wallet does a full rescan
	resetChangeID(w2)
	err = w2.Unlock(crypto.TwofishKey(crypto.HashObject(newSeed)))
	if err != nil {
		t.Fatal(err)
	}
	siacoinBal2, _, _ := w2.ConfirmedBalance()
	if siacoinBal2.Cmp64(0) <= 0 {
		t.Error("wallet failed to load a seed with money in it")
	}
	allSeeds, err = w2.AllSeeds()
	if err != nil {
		t.Fatal(err)
	}
	if len(allSeeds) != 2 {
		t.Error("AllSeeds should be returning the primary seed with the recovery seed.")
	}
	if !bytes.Equal(allSeeds[0][:], newSeed[:]) {
		t.Error("AllSeeds returned the wrong seed")
	}
	if !bytes.Equal(allSeeds[1][:], seed[:]) {
		t.Error("AllSeeds returned the wrong seed")
	}
	w2.Close()
}

// TestSweepSeed tests that sweeping a seed results in a transfer of its
// outputs to the wallet.
func TestSweepSeed(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	// create a wallet with some money
	wt, err := createWalletTester("TestSweepSeed0")
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()
	seed, _, err := wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	// send money to ourselves, so that we sweep a real output (instead of
	// just a miner payout)
	uc, err := wt.wallet.NextAddress()
	if err != nil {
		t.Fatal(err)
	}
	_, err = wt.wallet.SendSiacoins(types.SiacoinPrecision, uc.UnlockHash())
	if err != nil {
		t.Fatal(err)
	}
	wt.miner.AddBlock()

	// create a blank wallet
	dir := filepath.Join(build.TempDir(modules.WalletDir, "TestSweepSeed1"), modules.WalletDir)
	w, err := New(wt.cs, wt.tpool, dir)
	if err != nil {
		t.Fatal(err)
	}
	newSeed, err := w.Encrypt(crypto.TwofishKey{})
	if err != nil {
		t.Fatal(err)
	}
	err = w.Unlock(crypto.TwofishKey(crypto.HashObject(newSeed)))
	if err != nil {
		t.Fatal(err)
	}
	// starting balance should be 0.
	siacoinBal, _, _ := w.ConfirmedBalance()
	if !siacoinBal.IsZero() {
		t.Error("fresh wallet should not have a balance")
	}

	// sweep the seed of the first wallet into the second
	swept, err := w.SweepSeed(seed)
	if err != nil {
		t.Fatal(err)
	}

	// new wallet should have exactly 'swept' coins
	_, incoming := w.UnconfirmedBalance()
	if incoming.Cmp(swept) != 0 {
		t.Fatalf("wallet should have correct balance after sweeping seed: wanted %v, got %v", swept, incoming)
	}
}

// TestGenerateKeys tests that the generateKeys function correctly generates a
// key for every index specified.
func TestGenerateKeys(t *testing.T) {
	for i, k := range generateKeys(modules.Seed{}, 1000, 4000) {
		if len(k.UnlockConditions.PublicKeys) == 0 {
			t.Errorf("index %v was skipped", i)
		}
	}
}
<commit_msg>fix TestPrimarySeed<commit_after>package wallet

import (
	"bytes"
	"path/filepath"
	"testing"

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/bolt"
)

// resetChangeID clears the wallet's ConsensusChangeID. When Unlock is called,
// the wallet will rescan from the genesis block.
func resetChangeID(w *Wallet) {
	err := w.db.Update(func(tx *bolt.Tx) error {
		return dbPutConsensusChangeID(tx, modules.ConsensusChangeBeginning)
	})
	if err != nil {
		panic(err)
	}
}

// TestPrimarySeed checks that the correct seed is returned when calling
// PrimarySeed.
func TestPrimarySeed(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	// Start with a blank wallet tester.
	wt, err := createBlankWalletTester("TestPrimarySeed")
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()

	// Create a seed and unlock the wallet.
	seed, err := wt.wallet.Encrypt(crypto.TwofishKey{})
	if err != nil {
		t.Fatal(err)
	}
	err = wt.wallet.Unlock(crypto.TwofishKey(crypto.HashObject(seed)))
	if err != nil {
		t.Fatal(err)
	}

	// Try getting an address, see that the seed advances correctly.
	primarySeed, remaining, err := wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(primarySeed[:], seed[:]) {
		t.Error("PrimarySeed is returning a value inconsitent with the seed returned by Encrypt")
	}
	if remaining != maxScanKeys {
		t.Error("primary seed is returning the wrong number of remaining addresses")
	}
	_, err = wt.wallet.NextAddress()
	if err != nil {
		t.Fatal(err)
	}
	_, remaining, err = wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	if remaining != maxScanKeys-1 {
		t.Error("primary seed is returning the wrong number of remaining addresses")
	}

	// Lock then unlock the wallet and check the responses.
	err = wt.wallet.Lock()
	if err != nil {
		t.Fatal(err)
	}
	_, _, err = wt.wallet.PrimarySeed()
	if err != modules.ErrLockedWallet {
		t.Error("unexpected err:", err)
	}
	err = wt.wallet.Unlock(crypto.TwofishKey(crypto.HashObject(seed)))
	if err != nil {
		t.Fatal(err)
	}
	primarySeed, remaining, err = wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(primarySeed[:], seed[:]) {
		t.Error("PrimarySeed is returning a value inconsitent with the seed returned by Encrypt")
	}
	if remaining != maxScanKeys-1 {
		t.Error("primary seed is returning the wrong number of remaining addresses")
	}
}

// TestLoadSeed checks that a seed can be successfully recovered from a wallet,
// and then remain available on subsequent loads of the wallet.
func TestLoadSeed(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	wt, err := createWalletTester("TestLoadSeed")
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()
	seed, _, err := wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	allSeeds, err := wt.wallet.AllSeeds()
	if err != nil {
		t.Fatal(err)
	}
	if len(allSeeds) != 1 {
		t.Fatal("AllSeeds should be returning the primary seed.")
	} else if allSeeds[0] != seed {
		t.Fatal("AllSeeds returned the wrong seed")
	}
	wt.wallet.Close()

	dir := filepath.Join(build.TempDir(modules.WalletDir, "TestLoadSeed - 0"), modules.WalletDir)
	w, err := New(wt.cs, wt.tpool, dir)
	if err != nil {
		t.Fatal(err)
	}
	newSeed, err := w.Encrypt(crypto.TwofishKey{})
	if err != nil {
		t.Fatal(err)
	}
	err = w.Unlock(crypto.TwofishKey(crypto.HashObject(newSeed)))
	if err != nil {
		t.Fatal(err)
	}
	// Balance of wallet should be 0.
	siacoinBal, _, _ := w.ConfirmedBalance()
	if !siacoinBal.Equals64(0) {
		t.Error("fresh wallet should not have a balance")
	}
	err = w.LoadSeed(crypto.TwofishKey(crypto.HashObject(newSeed)), seed)
	if err != nil {
		t.Fatal(err)
	}
	allSeeds, err = w.AllSeeds()
	if err != nil {
		t.Fatal(err)
	}
	if len(allSeeds) != 2 {
		t.Error("AllSeeds should be returning the primary seed with the recovery seed.")
	}
	if allSeeds[0] != newSeed {
		t.Error("AllSeeds returned the wrong seed")
	}
	if !bytes.Equal(allSeeds[1][:], seed[:]) {
		t.Error("AllSeeds returned the wrong seed")
	}
	w.Close()

	// Rather than worry about a rescan, which isn't implemented and has
	// synchronization difficulties, just load a new wallet from the same
	// settings file - the same effect is achieved without the difficulties.
	//
	// TODO: when proper seed loading is implemented, just check the balance
	// of w directly.
	w2, err := New(wt.cs, wt.tpool, dir)
	if err != nil {
		t.Fatal(err)
	}
	// reset the ccID so that the wallet does a full rescan
	resetChangeID(w2)
	err = w2.Unlock(crypto.TwofishKey(crypto.HashObject(newSeed)))
	if err != nil {
		t.Fatal(err)
	}
	siacoinBal2, _, _ := w2.ConfirmedBalance()
	if siacoinBal2.Cmp64(0) <= 0 {
		t.Error("wallet failed to load a seed with money in it")
	}
	allSeeds, err = w2.AllSeeds()
	if err != nil {
		t.Fatal(err)
	}
	if len(allSeeds) != 2 {
		t.Error("AllSeeds should be returning the primary seed with the recovery seed.")
	}
	if !bytes.Equal(allSeeds[0][:], newSeed[:]) {
		t.Error("AllSeeds returned the wrong seed")
	}
	if !bytes.Equal(allSeeds[1][:], seed[:]) {
		t.Error("AllSeeds returned the wrong seed")
	}
	w2.Close()
}

// TestSweepSeed tests that sweeping a seed results in a transfer of its
// outputs to the wallet.
func TestSweepSeed(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	// create a wallet with some money
	wt, err := createWalletTester("TestSweepSeed0")
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()
	seed, _, err := wt.wallet.PrimarySeed()
	if err != nil {
		t.Fatal(err)
	}
	// send money to ourselves, so that we sweep a real output (instead of
	// just a miner payout)
	uc, err := wt.wallet.NextAddress()
	if err != nil {
		t.Fatal(err)
	}
	_, err = wt.wallet.SendSiacoins(types.SiacoinPrecision, uc.UnlockHash())
	if err != nil {
		t.Fatal(err)
	}
	wt.miner.AddBlock()

	// create a blank wallet
	dir := filepath.Join(build.TempDir(modules.WalletDir, "TestSweepSeed1"), modules.WalletDir)
	w, err := New(wt.cs, wt.tpool, dir)
	if err != nil {
		t.Fatal(err)
	}
	newSeed, err := w.Encrypt(crypto.TwofishKey{})
	if err != nil {
		t.Fatal(err)
	}
	err = w.Unlock(crypto.TwofishKey(crypto.HashObject(newSeed)))
	if err != nil {
		t.Fatal(err)
	}
	// starting balance should be 0.
	siacoinBal, _, _ := w.ConfirmedBalance()
	if !siacoinBal.IsZero() {
		t.Error("fresh wallet should not have a balance")
	}

	// sweep the seed of the first wallet into the second
	swept, err := w.SweepSeed(seed)
	if err != nil {
		t.Fatal(err)
	}

	// new wallet should have exactly 'swept' coins
	_, incoming := w.UnconfirmedBalance()
	if incoming.Cmp(swept) != 0 {
		t.Fatalf("wallet should have correct balance after sweeping seed: wanted %v, got %v", swept, incoming)
	}
}

// TestGenerateKeys tests that the generateKeys function correctly generates a
// key for every index specified.
func TestGenerateKeys(t *testing.T) {
	for i, k := range generateKeys(modules.Seed{}, 1000, 4000) {
		if len(k.UnlockConditions.PublicKeys) == 0 {
			t.Errorf("index %v was skipped", i)
		}
	}
}
<|endoftext|>


<commit_before>package kuzzle_test

import (
	"encoding/json"
	"github.com/kuzzleio/sdk-go/internal"
	"github.com/kuzzleio/sdk-go/kuzzle"
	"github.com/kuzzleio/sdk-go/types"
	"github.com/stretchr/testify/assert"
	"log"
	"testing"
)

func TestListCollectionsIndexNull(t *testing.T) {
	k, _ := kuzzle.NewKuzzle(&internal.MockedConnection{}, nil)
	_, err := k.ListCollections("", nil)
	assert.NotNil(t, err)
}

func TestListCollectionsQueryError(t *testing.T) {
	c := &internal.MockedConnection{
		MockSend: func(query []byte, options types.QueryOptions) types.KuzzleResponse {
			request := types.KuzzleRequest{}
			json.Unmarshal(query, &request)
			assert.Equal(t, "collection", request.Controller)
			assert.Equal(t, "index", request.Index)
			assert.Equal(t, "list", request.Action)
			return types.KuzzleResponse{Error: types.MessageError{Message: "error"}}
		},
	}
	k, _ := kuzzle.NewKuzzle(c, nil)
	_, err := k.ListCollections("index", nil)
	assert.NotNil(t, err)
}

func TestListCollections(t *testing.T) {
	c := &internal.MockedConnection{
		MockSend: func(query []byte, options types.QueryOptions) types.KuzzleResponse {
			request := types.KuzzleRequest{}
			json.Unmarshal(query, &request)
			assert.Equal(t, "collection", request.Controller)
			assert.Equal(t, "list", request.Action)

			type collections struct {
				Collections []types.CollectionsList `json:"collections"`
			}

			list := make([]types.CollectionsList, 0)
			list = append(list, types.CollectionsList{Name: "collection1", Type: "stored"})
			list = append(list, types.CollectionsList{Name: "collection2", Type: "stored"})

			c := collections{
				Collections: list,
			}

			h, err := json.Marshal(c)
			if err != nil {
				log.Fatal(err)
			}

			return types.KuzzleResponse{Result: h}
		},
	}
	k, _ := kuzzle.NewKuzzle(c, nil)

	res, _ := k.ListCollections("index", nil)

	assert.Equal(t, "collection1", res[0].Name)
	assert.Equal(t, "collection2", res[1].Name)
	assert.Equal(t, "stored", res[0].Type)
	assert.Equal(t, "stored", res[1].Type)
}

func TestListCollectionsWiithOptions(t *testing.T) {
	c := &internal.MockedConnection{
		MockSend: func(query []byte, options types.QueryOptions) types.KuzzleResponse {
			request := types.KuzzleRequest{}
			json.Unmarshal(query, &request)
			assert.Equal(t, "collection", request.Controller)
			assert.Equal(t, "list", request.Action)

			type collections struct {
				Collections []types.CollectionsList `json:"collections"`
			}

			list := make([]types.CollectionsList, 0)
			list = append(list, types.CollectionsList{Name: "collection1", Type: "stored"})
			list = append(list, types.CollectionsList{Name: "collection2", Type: "stored"})

			c := collections{
				Collections: list,
			}

			h, err := json.Marshal(c)
			if err != nil {
				log.Fatal(err)
			}

			return types.KuzzleResponse{Result: h}
		},
	}
	k, _ := kuzzle.NewKuzzle(c, nil)

	qo := types.NewQueryOptions()
	qo.SetType("stored")

	res, _ := k.ListCollections("index", qo)

	assert.Equal(t, "collection1", res[0].Name)
	assert.Equal(t, "collection2", res[1].Name)
	assert.Equal(t, "stored", res[0].Type)
	assert.Equal(t, "stored", res[1].Type)
}
<commit_msg>Fix typo<commit_after>package kuzzle_test

import (
	"encoding/json"
	"github.com/kuzzleio/sdk-go/internal"
	"github.com/kuzzleio/sdk-go/kuzzle"
	"github.com/kuzzleio/sdk-go/types"
	"github.com/stretchr/testify/assert"
	"log"
	"testing"
)

func TestListCollectionsIndexNull(t *testing.T) {
	k, _ := kuzzle.NewKuzzle(&internal.MockedConnection{}, nil)
	_, err := k.ListCollections("", nil)
	assert.NotNil(t, err)
}

func TestListCollectionsQueryError(t *testing.T) {
	c := &internal.MockedConnection{
		MockSend: func(query []byte, options types.QueryOptions) types.KuzzleResponse {
			request := types.KuzzleRequest{}
			json.Unmarshal(query, &request)
			assert.Equal(t, "collection", request.Controller)
			assert.Equal(t, "index", request.Index)
			assert.Equal(t, "list", request.Action)
			return types.KuzzleResponse{Error: types.MessageError{Message: "error"}}
		},
	}
	k, _ := kuzzle.NewKuzzle(c, nil)
	_, err := k.ListCollections("index", nil)
	assert.NotNil(t, err)
}

func TestListCollections(t *testing.T) {
	c := &internal.MockedConnection{
		MockSend: func(query []byte, options types.QueryOptions) types.KuzzleResponse {
			request := types.KuzzleRequest{}
			json.Unmarshal(query, &request)
			assert.Equal(t, "collection", request.Controller)
			assert.Equal(t, "list", request.Action)

			type collections struct {
				Collections []types.CollectionsList `json:"collections"`
			}

			list := make([]types.CollectionsList, 0)
			list = append(list, types.CollectionsList{Name: "collection1", Type: "stored"})
			list = append(list, types.CollectionsList{Name: "collection2", Type: "stored"})

			c := collections{
				Collections: list,
			}

			h, err := json.Marshal(c)
			if err != nil {
				log.Fatal(err)
			}

			return types.KuzzleResponse{Result: h}
		},
	}
	k, _ := kuzzle.NewKuzzle(c, nil)

	res, _ := k.ListCollections("index", nil)

	assert.Equal(t, "collection1", res[0].Name)
	assert.Equal(t, "collection2", res[1].Name)
	assert.Equal(t, "stored", res[0].Type)
	assert.Equal(t, "stored", res[1].Type)
}

func TestListCollectionsWithOptions(t *testing.T) {
	c := &internal.MockedConnection{
		MockSend: func(query []byte, options types.QueryOptions) types.KuzzleResponse {
			request := types.KuzzleRequest{}
			json.Unmarshal(query, &request)
			assert.Equal(t, "collection", request.Controller)
			assert.Equal(t, "list", request.Action)

			type collections struct {
				Collections []types.CollectionsList `json:"collections"`
			}

			list := make([]types.CollectionsList, 0)
			list = append(list, types.CollectionsList{Name: "collection1", Type: "stored"})
			list = append(list, types.CollectionsList{Name: "collection2", Type: "stored"})

			c := collections{
				Collections: list,
			}

			h, err := json.Marshal(c)
			if err != nil {
				log.Fatal(err)
			}

			return types.KuzzleResponse{Result: h}
		},
	}
	k, _ := kuzzle.NewKuzzle(c, nil)

	qo := types.NewQueryOptions()
	qo.SetType("stored")

	res, _ := k.ListCollections("index", qo)

	assert.Equal(t, "collection1", res[0].Name)
	assert.Equal(t, "collection2", res[1].Name)
	assert.Equal(t, "stored", res[0].Type)
	assert.Equal(t, "stored", res[1].Type)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path"
)

func main() {
	fmt.Println(path.Base(os.Args[0]))
}
<commit_msg>monorepo/cmd/indexd: fix command<commit_after>package main

import (
	"fmt"

	"github.com/dvrkps/dojo/monorepo/internal/website"
)

func main() {
	ws, err := website.All()
	if err != nil {
		fmt.Println(err)
	}

	for _, w := range ws {
		r, err := w.Index(w)
		if err != nil {
			fmt.Printf("index: %v\n", err)
			continue
		}
		fmt.Printf("%v: %v\n", w.Key, r)
	}
}
<|endoftext|>


<commit_before>package mcstore

import (
	"time"

	"net/http/httptest"

	"github.com/emicklei/go-restful"
	"github.com/materials-commons/config"
	"github.com/materials-commons/mcstore/pkg/app"
	"github.com/materials-commons/mcstore/pkg/app/flow"
	"github.com/materials-commons/mcstore/pkg/db/dai"
	"github.com/materials-commons/mcstore/testdb"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("ServerApi", func() {
	var (
		api           *ServerAPI
		server        *httptest.Server
		container     *restful.Container
		rr            *httptest.ResponseRecorder
		uploads       dai.Uploads
		uploadRequest CreateUploadRequest
	)

	BeforeEach(func() {
		container = NewServicesContainerForTest()
		server = httptest.NewServer(container)
		rr = httptest.NewRecorder()
		config.Set("mcurl", server.URL)
		config.Set("apikey", "test")
		uploads = dai.NewRUploads(testdb.RSession())
		api = NewServerAPI()
		uploadRequest = CreateUploadRequest{
			ProjectID:     "test",
			DirectoryID:   "test",
			DirectoryPath: "test/test",
			FileName:      "testreq.txt",
			FileSize:      4,
			ChunkSize:     2,
			FileMTime:     time.Now().Format(time.RFC1123),
			Checksum:      "abc123",
		}
	})

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

	Describe("CreateUploadRequest", func() {
		var resp *CreateUploadResponse
		var err error

		AfterEach(func() {
			if resp != nil {
				uploads.Delete(resp.RequestID)
			}
		})

		It("Should create an upload request", func() {
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			Expect(resp.RequestID).NotTo(Equal(""))
			Expect(resp.StartingBlock).To(BeNumerically("==", 1))
		})

		It("Should return the same id for a duplicate upload request", func() {
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			Expect(resp.RequestID).NotTo(Equal(""))
			Expect(resp.StartingBlock).To(BeNumerically("==", 1))

			resp2, err := api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			Expect(resp2.RequestID).To(Equal(resp.RequestID))
			Expect(resp.StartingBlock).To(BeNumerically("==", 1))
		})
	})

	Describe("SendFlowData", func() {
		var flowReq flow.Request
		var resp *CreateUploadResponse
		var err error

		BeforeEach(func() {
			flowReq = flow.Request{
				FlowChunkNumber:  1,
				FlowTotalChunks:  2,
				FlowChunkSize:    2,
				FlowTotalSize:    4,
				FlowFileName:     "testreq.txt",
				FlowRelativePath: "test/testreq.txt",
				ProjectID:        "test",
				DirectoryID:      "test",
			}
		})

		AfterEach(func() {
			if resp != nil {
				uploads.Delete(resp.RequestID)
			}
		})

		It("Should fail on an invalid request id", func() {
			flowReq.FlowIdentifier = "i-dont-exist"
			cresp, err := api.SendFlowData(&flowReq)
			Expect(err).To(Equal(app.ErrInvalid))
			Expect(cresp).To(BeNil())
		})

		It("Should Send the data an increment and increment starting block", func() {
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			flowReq.FlowIdentifier = resp.RequestID
			cresp, err := api.SendFlowData(&flowReq)
			Expect(err).To(BeNil())
			Expect(cresp.Done).To(BeFalse())

			resp2, err := api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			Expect(resp2.RequestID).To(Equal(resp.RequestID))
			Expect(resp2.StartingBlock).To(BeNumerically("==", 2))
		})
	})

	Describe("ListUploadRequests", func() {
		var resp *CreateUploadResponse

		AfterEach(func() {
			if resp != nil {
				uploads.Delete(resp.RequestID)
			}
		})

		It("Should return an empty list when there are no upload requests", func() {
			uploads, err := api.ListUploadRequests("test")
			Expect(err).To(BeNil())
			Expect(uploads).To(HaveLen(0))
		})

		It("Should return a list with one request when a single upload request has been created", func() {
			var err error
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			uploads, err := api.ListUploadRequests("test")
			Expect(err).To(BeNil())
			Expect(uploads).To(HaveLen(1))
		})
	})

	Describe("DeleteUploadRequest", func() {
		var resp *CreateUploadResponse

		AfterEach(func() {
			if resp != nil {
				uploads.Delete(resp.RequestID)
			}
		})

		It("Should return an error if upload request doesn't exist", func() {
			err := api.DeleteUploadRequest("does-not-exist")
			Expect(err).NotTo(BeNil())
		})

		It("Should return an error if user doesn't have permission", func() {
			var err error
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())

			// Change to a user who doesn't have permission
			config.Set("apikey", "test2")

			err = api.DeleteUploadRequest(resp.RequestID)
			Expect(err).NotTo(BeNil())
		})

		It("Should succeed if request exists and user has permission", func() {
			var err error
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			err = api.DeleteUploadRequest(resp.RequestID)
			Expect(err).To(BeNil())
		})
	})
})
<commit_msg>Add tests for GetDirectory api call.<commit_after>package mcstore

import (
	"time"

	"net/http/httptest"

	"fmt"

	"github.com/emicklei/go-restful"
	"github.com/materials-commons/config"
	"github.com/materials-commons/mcstore/pkg/app"
	"github.com/materials-commons/mcstore/pkg/app/flow"
	"github.com/materials-commons/mcstore/pkg/db/dai"
	"github.com/materials-commons/mcstore/testdb"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = fmt.Println

var _ = Describe("ServerApi", func() {
	var (
		api           *ServerAPI
		server        *httptest.Server
		container     *restful.Container
		rr            *httptest.ResponseRecorder
		uploads       dai.Uploads
		uploadRequest CreateUploadRequest
	)

	BeforeEach(func() {
		container = NewServicesContainerForTest()
		server = httptest.NewServer(container)
		rr = httptest.NewRecorder()
		config.Set("mcurl", server.URL)
		config.Set("apikey", "test")
		uploads = dai.NewRUploads(testdb.RSession())
		api = NewServerAPI()
		uploadRequest = CreateUploadRequest{
			ProjectID:     "test",
			DirectoryID:   "test",
			DirectoryPath: "test/test",
			FileName:      "testreq.txt",
			FileSize:      4,
			ChunkSize:     2,
			FileMTime:     time.Now().Format(time.RFC1123),
			Checksum:      "abc123",
		}
	})

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

	Describe("CreateUploadRequest", func() {
		var resp *CreateUploadResponse
		var err error

		AfterEach(func() {
			if resp != nil {
				uploads.Delete(resp.RequestID)
			}
		})

		It("Should create an upload request", func() {
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			Expect(resp.RequestID).NotTo(Equal(""))
			Expect(resp.StartingBlock).To(BeNumerically("==", 1))
		})

		It("Should return the same id for a duplicate upload request", func() {
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			Expect(resp.RequestID).NotTo(Equal(""))
			Expect(resp.StartingBlock).To(BeNumerically("==", 1))

			resp2, err := api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			Expect(resp2.RequestID).To(Equal(resp.RequestID))
			Expect(resp.StartingBlock).To(BeNumerically("==", 1))
		})
	})

	Describe("SendFlowData", func() {
		var flowReq flow.Request
		var resp *CreateUploadResponse
		var err error

		BeforeEach(func() {
			flowReq = flow.Request{
				FlowChunkNumber:  1,
				FlowTotalChunks:  2,
				FlowChunkSize:    2,
				FlowTotalSize:    4,
				FlowFileName:     "testreq.txt",
				FlowRelativePath: "test/testreq.txt",
				ProjectID:        "test",
				DirectoryID:      "test",
			}
		})

		AfterEach(func() {
			if resp != nil {
				uploads.Delete(resp.RequestID)
			}
		})

		It("Should fail on an invalid request id", func() {
			flowReq.FlowIdentifier = "i-dont-exist"
			cresp, err := api.SendFlowData(&flowReq)
			Expect(err).To(Equal(app.ErrInvalid))
			Expect(cresp).To(BeNil())
		})

		It("Should Send the data an increment and increment starting block", func() {
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			flowReq.FlowIdentifier = resp.RequestID
			cresp, err := api.SendFlowData(&flowReq)
			Expect(err).To(BeNil())
			Expect(cresp.Done).To(BeFalse())

			resp2, err := api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			Expect(resp2.RequestID).To(Equal(resp.RequestID))
			Expect(resp2.StartingBlock).To(BeNumerically("==", 2))
		})
	})

	Describe("ListUploadRequests", func() {
		var resp *CreateUploadResponse

		AfterEach(func() {
			if resp != nil {
				uploads.Delete(resp.RequestID)
			}
		})

		It("Should return an empty list when there are no upload requests", func() {
			uploads, err := api.ListUploadRequests("test")
			Expect(err).To(BeNil())
			Expect(uploads).To(HaveLen(0))
		})

		It("Should return a list with one request when a single upload request has been created", func() {
			var err error
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			uploads, err := api.ListUploadRequests("test")
			Expect(err).To(BeNil())
			Expect(uploads).To(HaveLen(1))
		})
	})

	Describe("DeleteUploadRequest", func() {
		var resp *CreateUploadResponse

		AfterEach(func() {
			if resp != nil {
				uploads.Delete(resp.RequestID)
			}
		})

		It("Should return an error if upload request doesn't exist", func() {
			err := api.DeleteUploadRequest("does-not-exist")
			Expect(err).NotTo(BeNil())
		})

		It("Should return an error if user doesn't have permission", func() {
			var err error
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())

			// Change to a user who doesn't have permission
			config.Set("apikey", "test2")

			err = api.DeleteUploadRequest(resp.RequestID)
			Expect(err).NotTo(BeNil())
		})

		It("Should succeed if request exists and user has permission", func() {
			var err error
			resp, err = api.CreateUploadRequest(uploadRequest)
			Expect(err).To(BeNil())
			err = api.DeleteUploadRequest(resp.RequestID)
			Expect(err).To(BeNil())
		})
	})

	Describe("GetDirectory", func() {
		var (
			dirs       dai.Dirs = dai.NewRDirs(testdb.RSession())
			dirID      string
			dirRequest DirectoryRequest
		)

		BeforeEach(func() {
			dirID = ""
			dirRequest = DirectoryRequest{
				ProjectName: "test",
				ProjectID:   "test",
				Path:        "/tmp/test/abc",
			}
		})

		AfterEach(func() {
			if dirID != "" {
				dirs.Delete(dirID)
			}
		})

		It("Should fail if directory doesn't include the project name", func() {
			var err error
			dirRequest.Path = "/tmp/test2/abc"
			dirID, err := api.GetDirectory(dirRequest)
			Expect(err).To(Equal(app.ErrInvalid))
			Expect(dirID).To(Equal(""))
		})

		It("Should retrieve an existing directory", func() {
			dirRequest.Path = "/tmp/test"
			dirid, err := api.GetDirectory(dirRequest)
			Expect(err).To(BeNil())
			Expect(dirid).To(Equal("test"))
		})

		It("Should create a new directory when it doesn't exist", func() {
			var err error
			dirID, err = api.GetDirectory(dirRequest)
			Expect(err).To(BeNil())
			Expect(dirID).To(ContainSubstring("-"))
		})
	})
})
<|endoftext|>