<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"time"
)

// flags
var (
	root       = flag.String("root", "./", "Specify search root directory")
	suffix     = flag.String("filetype", "go txt", `Specify target file types into the " "`)
	suffixList []string
	keyword    = flag.String("keyword", "TODO:", "Specify gather target keyword")
	// TODO: Reconsider name for sortFlag
	sortFlag = flag.String("sort", "off", "Specify sorted flags [on:off]?")
	result   = flag.String("result", "on", "Specify result [on:off]?")
)

func init() {
	// TODO: 今はコメントアウト
	// runtime.GOMAXPROCS(runtime.NumCPU())

	var err error
	flag.Parse()
	*root, err = filepath.Abs(*root)
	if err != nil {
		log.Fatalf("init:%v", err)
	}
	suffixList = strings.Split(*suffix, " ")
	argsCheck()
}

// Checking after parsing flags
func argsCheck() {
	if len(flag.Args()) != 0 {
		fmt.Fprintf(os.Stderr, "cmd = %v\n\n", os.Args)
		fmt.Fprintf(os.Stderr, "-----| Unknown option |-----\n\n")
		for _, x := range flag.Args() {
			fmt.Fprintln(os.Stderr, x)
		}
		fmt.Fprintf(os.Stderr, "\n")
		fmt.Fprintln(os.Stderr, "-----| Usage |-----")
		flag.PrintDefaults()
		os.Exit(1)
	}
}

// Use wait group!!
// TODO: To simple
func dirsCrawl(root string) map[string][]os.FileInfo {
	// mux group
	dirsCache := make(map[string]bool)
	infoCache := make(map[string][]os.FileInfo)
	mux := new(sync.Mutex)

	wg := new(sync.WaitGroup)

	var crawl func(string)
	crawl = func(dirname string) {
		defer wg.Done()

		mux.Lock()
		if dirsCache[dirname] {
			mux.Unlock()
			return
		}
		dirsCache[dirname] = true

		f, err := os.Open(dirname)
		if err != nil {
			log.Printf("crawl:%v", err)
			mux.Unlock()
			return
		}
		// Case of f.Readdir error use this
		defer func() {
			// TODO: Fix from bad implementation
			// os.Invalid == (f == nil)
			// This comparison is maybe bad implementation...
			errclose := f.Close()
			if errclose != nil && errclose.Error() != os.ErrInvalid.Error() {
				log.Printf("crawl:%v", errclose)
			}
		}()

		info, err := f.Readdir(0)
		if err != nil {
			log.Printf("crawl info:%v", err)
			mux.Unlock()
			return
		}
		infoCache[dirname] = info

		// NOTE: Countermove for "too many open files"
		if err := f.Close(); err != nil {
			log.Printf("crawl:%v", err)
		}
		mux.Unlock()
		// "too many open files" の対応でlockしたけど...
		// ここまでlockするならスレッド分ける意義が薄そう...

		for _, x := range info {
			if x.IsDir() {
				wg.Add(1)
				go crawl(filepath.Join(dirname, x.Name()))
			}
		}
	}

	wg.Add(1)
	crawl(root)
	wg.Wait()
	return infoCache
}

// Use flag suffixList
func suffixSeacher(filename string, targetSuffix []string) bool {
	for _, x := range targetSuffix {
		if strings.HasSuffix(filename, "."+x) {
			return true
		}
	}
	return false
}

// specify filename and target, Gather target(TODOs), return todoList.
// シンプルでいい感じに見えるけど、goroutineで呼びまくると...(´・ω・`)っ"too many open files"
// REMIND: todoListをchannelに変えてstringを投げるようにすれば数を制限したgoroutineが使えそう
func gather(filename string, target string) (todoList []string) {
	f, err := os.Open(filename)
	if err != nil {
		log.Printf("gather:%v", err)
		return nil
	}
	defer func() {
		if err := f.Close(); err != nil {
			log.Printf("gather:%v", err)
		}
	}()

	sc := bufio.NewScanner(f)
	for i := uint(1); sc.Scan(); i++ {
		if err := sc.Err(); err != nil {
			log.Printf("gather:%v", err)
			return nil
		}
		if index := strings.Index(sc.Text(), target); index != -1 {
			todoList = append(todoList, fmt.Sprintf("L%v:%s", i, sc.Text()[index+len(target):]))
		}
	}
	return todoList
}

// Use flag keyword
// NOTE:
// gopher増やしまくるとcloseが間に合わなくてosのfile descriptor上限に突っかかる
// goroutine にリミットを付けてファイルオープンを制限して上限に引っかからない様にしてみる
// TODO: Review
// TODO: To simple
func unlimitedGopherWorks(infoMap map[string][]os.FileInfo, filetypes []string, keyword string) (todoMap map[string][]string) {

	todoMap = make(map[string][]string)
	// NOTE: Countermove "too many open files"!!
	gophersLimit := 512 // NOTE: This Limit is requir (Limit < file descriptor limits)
	var gophersLimiter int

	mux := new(sync.Mutex)
	wg := new(sync.WaitGroup)

	// call gather() and append in todoMap
	worker := func(filepath string) {
		defer wg.Done()
		defer func() {
			mux.Lock()
			gophersLimiter--
			mux.Unlock()
		}()

		todoList := gather(filepath, keyword)
		if todoList != nil {
			mux.Lock()
			todoMap[filepath] = todoList
			mux.Unlock()
		}
	}

	for dirname, infos := range infoMap {
		for _, info := range infos {
			if suffixSeacher(info.Name(), filetypes) {
				wg.Add(1)
				mux.Lock()
				gophersLimiter++
				mux.Unlock()

				go worker(filepath.Join(dirname, info.Name()))

				// NOTE:
				// Countermove "too many open files"
				// gophersLimiterの読み出しで値が不確定だけどこれは大体合ってれば問題ないはず
				// TODO: それでも気になるので、速度を落とさずいい方法があれば修正する
				if gophersLimiter > gophersLimit/2 {
					time.Sleep(time.Microsecond)
				}
				if gophersLimiter > gophersLimit {
					log.Printf("Open files %v over, Do limitation to Gophers!!", gophersLimit)
					log.Printf("Wait gophers...")
					wg.Wait()
					log.Printf("Done!")
					mux.Lock()
					gophersLimiter = 0
					mux.Unlock()
				}
			}
		}
	}
	wg.Wait()
	return todoMap
}
// GophersProc is get todoMap data
func GophersProc(root string) (todoMap map[string][]string) {
	infomap := dirsCrawl(root)
	todoMap = unlimitedGopherWorks(infomap, suffixList, *keyword)
	return
}

// OutputTODOList is output crawl results
// TODO: Refactor
func OutputTODOList(todoMap map[string][]string) {
	// TODO: To lighten
	if *sortFlag == "on" {
		// Optional
		var filenames []string
		for filename := range todoMap {
			filenames = append(filenames, filename)
		}
		sort.Strings(filenames)

		// TODO: Fix to Duplication
		for _, filename := range filenames {
			fmt.Println(filename)
			for _, todo := range todoMap[filename] {
				fmt.Println(todo)
			}
			fmt.Println()
		}
	} else {
		// Main ...duplication
		for filename, todoList := range todoMap {
			fmt.Println(filename)
			for _, s := range todoList {
				fmt.Println(s)
			}
			fmt.Println()
		}
	}

	if *result == "on" {
		fmt.Println("-----| RESULT |-----")
		fmt.Printf("%v files found have the keyword\n\n", len(todoMap))
		fmt.Println("ALL FLAGS")
		fmt.Printf("root=%q\n", *root)
		fmt.Printf("filetype=%q\n", *suffix)
		fmt.Printf("keywrod=%q\n", *keyword)
		fmt.Printf("sort=%q\n", *sortFlag)
		fmt.Printf("result=%q\n", *result)
	}
}

// TODO: エラーをログに出すのを関数単位じゃなくmainまでatを付けて持って帰りたい
// NOTE: fmt.Errorf()でatを入れて返すとエラーのタイプが変わる
func main() {
	todoMap := GophersProc(*root)
	OutputTODOList(todoMap)
}
<commit_msg>refactor to dirsCrawl Changes to be committed: modified:   todogotcha.go<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"time"
)

// flags
var (
	root       = flag.String("root", "./", "Specify search root directory")
	suffix     = flag.String("filetype", "go txt", `Specify target file types into the " "`)
	suffixList []string
	keyword    = flag.String("keyword", "TODO:", "Specify gather target keyword")
	// TODO: Reconsider name for sortFlag
	sortFlag = flag.String("sort", "off", "Specify sorted flags [on:off]?")
	result   = flag.String("result", "on", "Specify result [on:off]?")
)

func init() {
	// TODO: 今はコメントアウト
	// runtime.GOMAXPROCS(runtime.NumCPU())

	var err error
	flag.Parse()
	*root, err = filepath.Abs(*root)
	if err != nil {
		log.Fatalf("init:%v", err)
	}
	suffixList = strings.Split(*suffix, " ")
	argsCheck()
}

// Checking after parsing flags
func argsCheck() {
	if len(flag.Args()) != 0 {
		fmt.Fprintf(os.Stderr, "cmd = %v\n\n", os.Args)
		fmt.Fprintf(os.Stderr, "-----| Unknown option |-----\n\n")
		for _, x := range flag.Args() {
			fmt.Fprintln(os.Stderr, x)
		}
		fmt.Fprintf(os.Stderr, "\n")
		fmt.Fprintln(os.Stderr, "-----| Usage |-----")
		flag.PrintDefaults()
		os.Exit(1)
	}
}

// Use wait group dirsCrawl
// TODO: To simple
func dirsCrawl(root string) map[string][]os.FileInfo {
	// mux group
	dirsCache := make(map[string]bool)
	infoCache := make(map[string][]os.FileInfo)
	mux := new(sync.Mutex)

	wg := new(sync.WaitGroup)

	var crawl func(string)
	crawl = func(dirname string) {
		defer wg.Done()
		infos := new([]os.FileInfo)

		// NOTE: Countermove "too many open files"
		mux.Lock()
		ok := func() bool {
			if dirsCache[dirname] {
				return false
			}
			dirsCache[dirname] = true

			f, err := os.Open(dirname)
			if err != nil {
				log.Printf("crawl:%v", err)
				return false
			}
			defer func() {
				if errclose := f.Close(); errclose != nil {
					log.Printf("crawl:%v", errclose)
				}
			}()

			*infos, err = f.Readdir(0)
			if err != nil {
				log.Printf("crawl info:%v", err)
				return false
			}
			infoCache[dirname] = *infos
			return true
		}()
		mux.Unlock()
		if !ok { return }
		// NOTE: ここまでロックするならスレッドを分ける意味は薄いかも

		for _, x := range *infos {
			if x.IsDir() {
				wg.Add(1)
				go crawl(filepath.Join(dirname, x.Name()))
			}
		}
	}

	wg.Add(1)
	crawl(root)
	wg.Wait()
	return infoCache
}

// Use flag suffixList
func suffixSeacher(filename string, targetSuffix []string) bool {
	for _, x := range targetSuffix {
		if strings.HasSuffix(filename, "."+x) {
			return true
		}
	}
	return false
}

// specify filename and target, Gather target(TODOs), return todoList.
// シンプルでいい感じに見えるけど、goroutineで呼びまくると...(´・ω・`)っ"too many open files"
// REMIND: todoListをchannelに変えてstringを投げるようにすれば数を制限したgoroutineが使えそう
func gather(filename string, target string) (todoList []string) {
	f, err := os.Open(filename)
	if err != nil {
		log.Printf("gather:%v", err)
		return nil
	}
	defer func() {
		if err := f.Close(); err != nil {
			log.Printf("gather:%v", err)
		}
	}()

	sc := bufio.NewScanner(f)
	for i := uint(1); sc.Scan(); i++ {
		if err := sc.Err(); err != nil {
			log.Printf("gather:%v", err)
			return nil
		}
		if index := strings.Index(sc.Text(), target); index != -1 {
			todoList = append(todoList, fmt.Sprintf("L%v:%s", i, sc.Text()[index+len(target):]))
		}
	}
	return todoList
}

// Use flag keyword
// NOTE:
// gopher増やしまくるとcloseが間に合わなくてosのfile descriptor上限に突っかかる
// goroutine にリミットを付けてファイルオープンを制限して上限に引っかからない様にしてみる
// TODO: Review
// TODO: To simple
func unlimitedGopherWorks(infoMap map[string][]os.FileInfo, filetypes []string, keyword string) (todoMap map[string][]string) {

	todoMap = make(map[string][]string)
	// NOTE: Countermove "too many open files"!!
	gophersLimit := 512 // NOTE: This Limit is requir (Limit < file descriptor limits)
	var gophersLimiter int

	mux := new(sync.Mutex)
	wg := new(sync.WaitGroup)

	// call gather() and append in todoMap
	worker := func(filepath string) {
		defer wg.Done()
		defer func() {
			mux.Lock()
			gophersLimiter--
			mux.Unlock()
		}()

		todoList := gather(filepath, keyword)
		if todoList != nil {
			mux.Lock()
			todoMap[filepath] = todoList
			mux.Unlock()
		}
	}

	for dirname, infos := range infoMap {
		for _, info := range infos {
			if suffixSeacher(info.Name(), filetypes) {
				wg.Add(1)
				mux.Lock()
				gophersLimiter++
				mux.Unlock()

				go worker(filepath.Join(dirname, info.Name()))

				// NOTE:
				// Countermove "too many open files"
				// gophersLimiterの読み出しで値が不確定だけどこれは大体合ってれば問題ないはず
				// TODO: それでも気になるので、速度を落とさずいい方法があれば修正する
				if gophersLimiter > gophersLimit/2 {
					time.Sleep(time.Microsecond)
				}
				if gophersLimiter > gophersLimit {
					log.Printf("Open files %v over, Do limitation to Gophers!!", gophersLimit)
					log.Printf("Wait gophers...")
					wg.Wait()
					log.Printf("Done!")
					mux.Lock()
					gophersLimiter = 0
					mux.Unlock()
				}
			}
		}
	}
	wg.Wait()
	return todoMap
}
// GophersProc is get todoMap data
func GophersProc(root string) (todoMap map[string][]string) {
	infomap := dirsCrawl(root)
	todoMap = unlimitedGopherWorks(infomap, suffixList, *keyword)
	return
}

// OutputTODOList is output crawl results
// TODO: Refactor
func OutputTODOList(todoMap map[string][]string) {
	// TODO: To lighten
	if *sortFlag == "on" {
		// Optional
		var filenames []string
		for filename := range todoMap {
			filenames = append(filenames, filename)
		}
		sort.Strings(filenames)

		// TODO: Fix to Duplication
		for _, filename := range filenames {
			fmt.Println(filename)
			for _, todo := range todoMap[filename] {
				fmt.Println(todo)
			}
			fmt.Println()
		}
	} else {
		// Main ...duplication
		for filename, todoList := range todoMap {
			fmt.Println(filename)
			for _, s := range todoList {
				fmt.Println(s)
			}
			fmt.Println()
		}
	}

	if *result == "on" {
		fmt.Println("-----| RESULT |-----")
		fmt.Printf("%v files found have the keyword\n\n", len(todoMap))
		fmt.Println("ALL FLAGS")
		fmt.Printf("root=%q\n", *root)
		fmt.Printf("filetype=%q\n", *suffix)
		fmt.Printf("keywrod=%q\n", *keyword)
		fmt.Printf("sort=%q\n", *sortFlag)
		fmt.Printf("result=%q\n", *result)
	}
}

// TODO: エラーをログに出すのを関数単位じゃなくmainまでatを付けて持って帰りたい
// NOTE: fmt.Errorf()でatを入れて返すとエラーのタイプが変わる
func main() {
	todoMap := GophersProc(*root)
	OutputTODOList(todoMap)
}
<|endoftext|>


<commit_before>package modelhelper

import (
	"koding/db/models"
	"koding/db/mongodb"
)

func GetAccountById(id string) (*models.Account, error) {
	account := new(models.Account)
	err := mongodb.One("jAccounts", id, account)
	if err != nil {
		return nil, err
	}

	return account, nil
}
<commit_msg>Moderation:  CheckAccountExistence is added to accounts helper<commit_after>package modelhelper

import (
	"koding/db/models"
	"koding/db/mongodb"
)

func GetAccountById(id string) (*models.Account, error) {
	account := new(models.Account)
	return account, mongodb.One("jAccounts", id, account)
}

func CheckAccountExistence(id string) (bool, error) {
	var exists bool
	query := checkExistence(id, &exists)
	return exists, mongodb.Run("jAccounts", query)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"

	"go.skia.org/infra/go/paramtools"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/testutils"
	"go.skia.org/infra/go/testutils/unittest"
	"go.skia.org/infra/golden/go/diff/mocks"
	"go.skia.org/infra/golden/go/types"
)

func TestProcessPubSubMessage_OldJSON_NoCalculation_Ack(t *testing.T) {
	unittest.SmallTest(t)

	p := processor{}

	messageBytes := []byte(`{"grouping":{"name":"any-test","other grouping":"something","source_type":"any-corpus"},"additional_digests":["abcd","ef123"]}`)
	shouldAck := p.processMessage(context.Background(), messageBytes)
	assert.True(t, shouldAck)
}

func TestProcessPubSubMessage_ValidJSON_CalculateSucceeds_Ack(t *testing.T) {
	unittest.SmallTest(t)

	mc := mocks.Calculator{}

	expectedGrouping := paramtools.Params{
		types.CorpusField:     "any-corpus",
		types.PrimaryKeyField: "any-test",
		"other grouping":      "something",
	}
	expectedLeftDigests := []types.Digest{"abcd", "ef123"}
	expectedRightDigests := []types.Digest{"4567"}

	mc.On("CalculateDiffs", testutils.AnyContext, expectedGrouping, expectedLeftDigests, expectedRightDigests).Return(nil)

	p := processor{calculator: &mc}

	messageBytes := []byte(`{"version":2,"grouping":{"name":"any-test","other grouping":"something","source_type":"any-corpus"},"additional_left":["abcd","ef123"],"additional_right":["4567"]}`)
	shouldAck := p.processMessage(context.Background(), messageBytes)
	assert.True(t, shouldAck)
	mc.AssertExpectations(t)
}

func TestProcessPubSubMessage_ValidJSON_CalculateFails_Nack(t *testing.T) {
	unittest.SmallTest(t)

	mc := mocks.Calculator{}

	expectedGrouping := paramtools.Params{
		types.CorpusField:     "any-corpus",
		types.PrimaryKeyField: "any-test",
	}
	var noExpectedDigests []types.Digest

	mc.On("CalculateDiffs", testutils.AnyContext, expectedGrouping, noExpectedDigests, noExpectedDigests).Return(skerr.Fmt("boom"))

	p := processor{calculator: &mc}

	messageBytes := []byte(`{"version":2,"grouping":{"name":"any-test","source_type":"any-corpus"}}`)
	shouldAck := p.processMessage(context.Background(), messageBytes)
	assert.False(t, shouldAck)
	mc.AssertExpectations(t)
}

func TestProcessPubSubMessage_InvalidJSON_Ack(t *testing.T) {
	unittest.SmallTest(t)

	p := processor{}
	messageBytes := []byte(`invalid json`)
	shouldAck := p.processMessage(context.Background(), messageBytes)
	assert.True(t, shouldAck)
}
<commit_msg>[gold] Fix diffcalculator tests with new version<commit_after>package main

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"

	"go.skia.org/infra/go/paramtools"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/testutils"
	"go.skia.org/infra/go/testutils/unittest"
	"go.skia.org/infra/golden/go/diff/mocks"
	"go.skia.org/infra/golden/go/types"
)

func TestProcessPubSubMessage_OldJSON_NoCalculation_Ack(t *testing.T) {
	unittest.SmallTest(t)

	p := processor{}

	messageBytes := []byte(`{"grouping":{"name":"any-test","other grouping":"something","source_type":"any-corpus"},"additional_digests":["abcd","ef123"]}`)
	shouldAck := p.processMessage(context.Background(), messageBytes)
	assert.True(t, shouldAck)
}

func TestProcessPubSubMessage_ValidJSON_CalculateSucceeds_Ack(t *testing.T) {
	unittest.SmallTest(t)

	mc := mocks.Calculator{}

	expectedGrouping := paramtools.Params{
		types.CorpusField:     "any-corpus",
		types.PrimaryKeyField: "any-test",
		"other grouping":      "something",
	}
	expectedLeftDigests := []types.Digest{"abcd", "ef123"}
	expectedRightDigests := []types.Digest{"4567"}

	mc.On("CalculateDiffs", testutils.AnyContext, expectedGrouping, expectedLeftDigests, expectedRightDigests).Return(nil)

	p := processor{calculator: &mc}

	messageBytes := []byte(`{"version":3,"grouping":{"name":"any-test","other grouping":"something","source_type":"any-corpus"},"additional_left":["abcd","ef123"],"additional_right":["4567"]}`)
	shouldAck := p.processMessage(context.Background(), messageBytes)
	assert.True(t, shouldAck)
	mc.AssertExpectations(t)
}

func TestProcessPubSubMessage_ValidJSON_CalculateFails_Nack(t *testing.T) {
	unittest.SmallTest(t)

	mc := mocks.Calculator{}

	expectedGrouping := paramtools.Params{
		types.CorpusField:     "any-corpus",
		types.PrimaryKeyField: "any-test",
	}
	var noExpectedDigests []types.Digest

	mc.On("CalculateDiffs", testutils.AnyContext, expectedGrouping, noExpectedDigests, noExpectedDigests).Return(skerr.Fmt("boom"))

	p := processor{calculator: &mc}

	messageBytes := []byte(`{"version":3,"grouping":{"name":"any-test","source_type":"any-corpus"}}`)
	shouldAck := p.processMessage(context.Background(), messageBytes)
	assert.False(t, shouldAck)
	mc.AssertExpectations(t)
}

func TestProcessPubSubMessage_InvalidJSON_Ack(t *testing.T) {
	unittest.SmallTest(t)

	p := processor{}
	messageBytes := []byte(`invalid json`)
	shouldAck := p.processMessage(context.Background(), messageBytes)
	assert.True(t, shouldAck)
}
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	"log"
	"net/url"
	"regexp"
	"strings"

	"github.com/hashicorp/errwrap"
	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/servicenetworking/v1"
)

func resourceServiceNetworkingConnection() *schema.Resource {
	return &schema.Resource{
		Create: resourceServiceNetworkingConnectionCreate,
		Read:   resourceServiceNetworkingConnectionRead,
		Update: resourceServiceNetworkingConnectionUpdate,
		Delete: resourceServiceNetworkingConnectionDelete,
		Importer: &schema.ResourceImporter{
			State: resourceServiceNetworkingConnectionImportState,
		},

		Schema: map[string]*schema.Schema{
			"network": {
				Type:             schema.TypeString,
				Required:         true,
				ForceNew:         true,
				DiffSuppressFunc: compareSelfLinkOrResourceName,
			},
			// NOTE(craigatgoogle): This field is weird, it's required to make the Insert/List calls as a parameter
			// named "parent", however it's also defined in the response as an output field called "peering", which
			// uses "-" as a delimiter instead of ".". To alleviate user confusion I've opted to model the gcloud
			// CLI's approach, calling the field "service" and accepting the same format as the CLI with the "."
			// delimiter.
			// See: https://cloud.google.com/vpc/docs/configure-private-services-access#creating-connection
			"service": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"reserved_peering_ranges": {
				Type:     schema.TypeList,
				Required: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"peering": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceServiceNetworkingConnectionCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	network := d.Get("network").(string)
	serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
	if err != nil {
		return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
	}

	connection := &servicenetworking.Connection{
		Network:               serviceNetworkingNetworkName,
		ReservedPeeringRanges: convertStringArr(d.Get("reserved_peering_ranges").([]interface{})),
	}

	parentService := formatParentService(d.Get("service").(string))
	op, err := config.clientServiceNetworking.Services.Connections.Create(parentService, connection).Do()
	if err != nil {
		return err
	}

	if err := serviceNetworkingOperationWait(config, op, "Create Service Networking Connection"); err != nil {
		return err
	}

	connectionId := &connectionId{
		Network: network,
		Service: d.Get("service").(string),
	}

	d.SetId(connectionId.Id())
	return resourceServiceNetworkingConnectionRead(d, meta)
}

func resourceServiceNetworkingConnectionRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	connectionId, err := parseConnectionId(d.Id())
	if err != nil {
		return errwrap.Wrapf("Unable to parse Service Networking Connection id, err: {{err}}", err)
	}

	serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, connectionId.Network)
	if err != nil {
		return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
	}

	parentService := formatParentService(connectionId.Service)
	response, err := config.clientServiceNetworking.Services.Connections.List(parentService).
		Network(serviceNetworkingNetworkName).Do()
	if err != nil {
		return err
	}

	var connection *servicenetworking.Connection
	for _, c := range response.Connections {
		if c.Network == serviceNetworkingNetworkName {
			connection = c
			break
		}
	}

	if connection == nil {
		d.SetId("")
		log.Printf("[WARNING] Failed to find Service Networking Connection, network: %s service: %s", connectionId.Network, connectionId.Service)
		return nil
	}

	d.Set("network", connectionId.Network)
	d.Set("service", connectionId.Service)
	d.Set("peering", connection.Peering)
	d.Set("reserved_peering_ranges", connection.ReservedPeeringRanges)
	return nil
}

func resourceServiceNetworkingConnectionUpdate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	connectionId, err := parseConnectionId(d.Id())
	if err != nil {
		return errwrap.Wrapf("Unable to parse Service Networking Connection id, err: {{err}}", err)
	}

	parentService := formatParentService(connectionId.Service)

	if d.HasChange("reserved_peering_ranges") {
		network := d.Get("network").(string)
		serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
		if err != nil {
			return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
		}

		connection := &servicenetworking.Connection{
			Network:               serviceNetworkingNetworkName,
			ReservedPeeringRanges: convertStringArr(d.Get("reserved_peering_ranges").([]interface{})),
		}

		// The API docs don't specify that you can do connections/-, but that's what gcloud does,
		// and it's easier than grabbing the connection name.
		op, err := config.clientServiceNetworking.Services.Connections.Patch(parentService+"/connections/-", connection).UpdateMask("reservedPeeringRanges").Force(true).Do()
		if err != nil {
			return err
		}
		if err := serviceNetworkingOperationWait(config, op, "Update Service Networking Connection"); err != nil {
			return err
		}
	}
	return resourceServiceNetworkingConnectionRead(d, meta)
}

func resourceServiceNetworkingConnectionDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	network := d.Get("network").(string)
	serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
	if err != nil {
		return err
	}

	obj := make(map[string]interface{})
	peering := d.Get("peering").(string)
	obj["name"] = peering
	url := fmt.Sprintf("%s%s/removePeering", config.ComputeBasePath, serviceNetworkingNetworkName)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutUpdate))
	if err != nil {
		return handleNotFoundError(err, d, fmt.Sprintf("ServiceNetworkingConnection %q", d.Id()))
	}

	op := &compute.Operation{}
	err = Convert(res, op)
	if err != nil {
		return err
	}

	err = computeOperationWaitTime(
		config.clientCompute, op, project, "Updating Network",
		int(d.Timeout(schema.TimeoutUpdate).Minutes()))
	if err != nil {
		return err
	}

	d.SetId("")
	log.Printf("[INFO] Service network connection removed.")

	return nil
}

func resourceServiceNetworkingConnectionImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	connectionId, err := parseConnectionId(d.Id())
	if err != nil {
		return nil, err
	}

	d.Set("network", connectionId.Network)
	d.Set("service", connectionId.Service)
	return []*schema.ResourceData{d}, nil
}

// NOTE(craigatgoogle): The Connection resource in this API doesn't have an Id field, so inorder
// to support the Read method, we create an Id using the tuple(Network, Service).
type connectionId struct {
	Network string
	Service string
}

func (id *connectionId) Id() string {
	return fmt.Sprintf("%s:%s", url.QueryEscape(id.Network), url.QueryEscape(id.Service))
}

func parseConnectionId(id string) (*connectionId, error) {
	res := strings.Split(id, ":")

	if len(res) != 2 {
		return nil, fmt.Errorf("Failed to parse service networking connection id, value: %s", id)
	}

	network, err := url.QueryUnescape(res[0])
	if err != nil {
		return nil, errwrap.Wrapf("Failed to parse service networking connection id, invalid network, err: {{err}}", err)
	} else if len(network) == 0 {
		return nil, fmt.Errorf("Failed to parse service networking connection id, empty network")
	}

	service, err := url.QueryUnescape(res[1])
	if err != nil {
		return nil, errwrap.Wrapf("Failed to parse service networking connection id, invalid service, err: {{err}}", err)
	} else if len(service) == 0 {
		return nil, fmt.Errorf("Failed to parse service networking connection id, empty service")
	}

	return &connectionId{
		Network: network,
		Service: service,
	}, nil
}

// NOTE(craigatgoogle): An out of band aspect of this API is that it uses a unique formatting of network
// different from the standard self_link URI. It requires a call to the resource manager to get the project
// number for the current project.
func retrieveServiceNetworkingNetworkName(d *schema.ResourceData, config *Config, network string) (string, error) {
	networkFieldValue, err := ParseNetworkFieldValue(network, d, config)
	if err != nil {
		return "", errwrap.Wrapf("Failed to retrieve network field value, err: {{err}}", err)
	}

	pid := networkFieldValue.Project
	if pid == "" {
		return "", fmt.Errorf("Could not determine project")
	}

	project, err := config.clientResourceManager.Projects.Get(pid).Do()
	if err != nil {
		return "", fmt.Errorf("Failed to retrieve project, pid: %s, err: %s", pid, err)
	}

	networkName := networkFieldValue.Name
	if networkName == "" {
		return "", fmt.Errorf("Failed to parse network")
	}

	// return the network name formatting unique to this API
	return fmt.Sprintf("projects/%v/global/networks/%v", project.ProjectNumber, networkName), nil

}

const parentServicePattern = "^services/.+$"

// NOTE(craigatgoogle): An out of band aspect of this API is that it requires the service name to be
// formatted as "services/<serviceName>"
func formatParentService(service string) string {
	r := regexp.MustCompile(parentServicePattern)
	if !r.MatchString(service) {
		return fmt.Sprintf("services/%s", service)
	} else {
		return service
	}
}
<commit_msg>remove need for provider-level project from service networking connection resource (#4445)<commit_after>package google

import (
	"fmt"
	"log"
	"net/url"
	"regexp"
	"strings"

	"github.com/hashicorp/errwrap"
	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/servicenetworking/v1"
)

func resourceServiceNetworkingConnection() *schema.Resource {
	return &schema.Resource{
		Create: resourceServiceNetworkingConnectionCreate,
		Read:   resourceServiceNetworkingConnectionRead,
		Update: resourceServiceNetworkingConnectionUpdate,
		Delete: resourceServiceNetworkingConnectionDelete,
		Importer: &schema.ResourceImporter{
			State: resourceServiceNetworkingConnectionImportState,
		},

		Schema: map[string]*schema.Schema{
			"network": {
				Type:             schema.TypeString,
				Required:         true,
				ForceNew:         true,
				DiffSuppressFunc: compareSelfLinkOrResourceName,
			},
			// NOTE(craigatgoogle): This field is weird, it's required to make the Insert/List calls as a parameter
			// named "parent", however it's also defined in the response as an output field called "peering", which
			// uses "-" as a delimiter instead of ".". To alleviate user confusion I've opted to model the gcloud
			// CLI's approach, calling the field "service" and accepting the same format as the CLI with the "."
			// delimiter.
			// See: https://cloud.google.com/vpc/docs/configure-private-services-access#creating-connection
			"service": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"reserved_peering_ranges": {
				Type:     schema.TypeList,
				Required: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"peering": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceServiceNetworkingConnectionCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	network := d.Get("network").(string)
	serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
	if err != nil {
		return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
	}

	connection := &servicenetworking.Connection{
		Network:               serviceNetworkingNetworkName,
		ReservedPeeringRanges: convertStringArr(d.Get("reserved_peering_ranges").([]interface{})),
	}

	parentService := formatParentService(d.Get("service").(string))
	op, err := config.clientServiceNetworking.Services.Connections.Create(parentService, connection).Do()
	if err != nil {
		return err
	}

	if err := serviceNetworkingOperationWait(config, op, "Create Service Networking Connection"); err != nil {
		return err
	}

	connectionId := &connectionId{
		Network: network,
		Service: d.Get("service").(string),
	}

	d.SetId(connectionId.Id())
	return resourceServiceNetworkingConnectionRead(d, meta)
}

func resourceServiceNetworkingConnectionRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	connectionId, err := parseConnectionId(d.Id())
	if err != nil {
		return errwrap.Wrapf("Unable to parse Service Networking Connection id, err: {{err}}", err)
	}

	serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, connectionId.Network)
	if err != nil {
		return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
	}

	parentService := formatParentService(connectionId.Service)
	response, err := config.clientServiceNetworking.Services.Connections.List(parentService).
		Network(serviceNetworkingNetworkName).Do()
	if err != nil {
		return err
	}

	var connection *servicenetworking.Connection
	for _, c := range response.Connections {
		if c.Network == serviceNetworkingNetworkName {
			connection = c
			break
		}
	}

	if connection == nil {
		d.SetId("")
		log.Printf("[WARNING] Failed to find Service Networking Connection, network: %s service: %s", connectionId.Network, connectionId.Service)
		return nil
	}

	d.Set("network", connectionId.Network)
	d.Set("service", connectionId.Service)
	d.Set("peering", connection.Peering)
	d.Set("reserved_peering_ranges", connection.ReservedPeeringRanges)
	return nil
}

func resourceServiceNetworkingConnectionUpdate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	connectionId, err := parseConnectionId(d.Id())
	if err != nil {
		return errwrap.Wrapf("Unable to parse Service Networking Connection id, err: {{err}}", err)
	}

	parentService := formatParentService(connectionId.Service)

	if d.HasChange("reserved_peering_ranges") {
		network := d.Get("network").(string)
		serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
		if err != nil {
			return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
		}

		connection := &servicenetworking.Connection{
			Network:               serviceNetworkingNetworkName,
			ReservedPeeringRanges: convertStringArr(d.Get("reserved_peering_ranges").([]interface{})),
		}

		// The API docs don't specify that you can do connections/-, but that's what gcloud does,
		// and it's easier than grabbing the connection name.
		op, err := config.clientServiceNetworking.Services.Connections.Patch(parentService+"/connections/-", connection).UpdateMask("reservedPeeringRanges").Force(true).Do()
		if err != nil {
			return err
		}
		if err := serviceNetworkingOperationWait(config, op, "Update Service Networking Connection"); err != nil {
			return err
		}
	}
	return resourceServiceNetworkingConnectionRead(d, meta)
}

func resourceServiceNetworkingConnectionDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	network := d.Get("network").(string)
	serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
	if err != nil {
		return err
	}

	obj := make(map[string]interface{})
	peering := d.Get("peering").(string)
	obj["name"] = peering
	url := fmt.Sprintf("%s%s/removePeering", config.ComputeBasePath, serviceNetworkingNetworkName)

	networkFieldValue, err := ParseNetworkFieldValue(network, d, config)
	if err != nil {
		return errwrap.Wrapf("Failed to retrieve network field value, err: {{err}}", err)
	}

	project := networkFieldValue.Project
	res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutUpdate))
	if err != nil {
		return handleNotFoundError(err, d, fmt.Sprintf("ServiceNetworkingConnection %q", d.Id()))
	}

	op := &compute.Operation{}
	err = Convert(res, op)
	if err != nil {
		return err
	}

	err = computeOperationWaitTime(
		config.clientCompute, op, project, "Updating Network",
		int(d.Timeout(schema.TimeoutUpdate).Minutes()))
	if err != nil {
		return err
	}

	d.SetId("")
	log.Printf("[INFO] Service network connection removed.")

	return nil
}

func resourceServiceNetworkingConnectionImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
	connectionId, err := parseConnectionId(d.Id())
	if err != nil {
		return nil, err
	}

	d.Set("network", connectionId.Network)
	d.Set("service", connectionId.Service)
	return []*schema.ResourceData{d}, nil
}

// NOTE(craigatgoogle): The Connection resource in this API doesn't have an Id field, so inorder
// to support the Read method, we create an Id using the tuple(Network, Service).
type connectionId struct {
	Network string
	Service string
}

func (id *connectionId) Id() string {
	return fmt.Sprintf("%s:%s", url.QueryEscape(id.Network), url.QueryEscape(id.Service))
}

func parseConnectionId(id string) (*connectionId, error) {
	res := strings.Split(id, ":")

	if len(res) != 2 {
		return nil, fmt.Errorf("Failed to parse service networking connection id, value: %s", id)
	}

	network, err := url.QueryUnescape(res[0])
	if err != nil {
		return nil, errwrap.Wrapf("Failed to parse service networking connection id, invalid network, err: {{err}}", err)
	} else if len(network) == 0 {
		return nil, fmt.Errorf("Failed to parse service networking connection id, empty network")
	}

	service, err := url.QueryUnescape(res[1])
	if err != nil {
		return nil, errwrap.Wrapf("Failed to parse service networking connection id, invalid service, err: {{err}}", err)
	} else if len(service) == 0 {
		return nil, fmt.Errorf("Failed to parse service networking connection id, empty service")
	}

	return &connectionId{
		Network: network,
		Service: service,
	}, nil
}

// NOTE(craigatgoogle): An out of band aspect of this API is that it uses a unique formatting of network
// different from the standard self_link URI. It requires a call to the resource manager to get the project
// number for the current project.
func retrieveServiceNetworkingNetworkName(d *schema.ResourceData, config *Config, network string) (string, error) {
	networkFieldValue, err := ParseNetworkFieldValue(network, d, config)
	if err != nil {
		return "", errwrap.Wrapf("Failed to retrieve network field value, err: {{err}}", err)
	}

	pid := networkFieldValue.Project
	if pid == "" {
		return "", fmt.Errorf("Could not determine project")
	}

	project, err := config.clientResourceManager.Projects.Get(pid).Do()
	if err != nil {
		return "", fmt.Errorf("Failed to retrieve project, pid: %s, err: %s", pid, err)
	}

	networkName := networkFieldValue.Name
	if networkName == "" {
		return "", fmt.Errorf("Failed to parse network")
	}

	// return the network name formatting unique to this API
	return fmt.Sprintf("projects/%v/global/networks/%v", project.ProjectNumber, networkName), nil

}

const parentServicePattern = "^services/.+$"

// NOTE(craigatgoogle): An out of band aspect of this API is that it requires the service name to be
// formatted as "services/<serviceName>"
func formatParentService(service string) string {
	r := regexp.MustCompile(parentServicePattern)
	if !r.MatchString(service) {
		return fmt.Sprintf("services/%s", service)
	} else {
		return service
	}
}
<|endoftext|>


<commit_before>package python

import (
	"path/filepath"

	"github.com/kr/fs"
	"sourcegraph.com/sourcegraph/srcgraph/config"
	"sourcegraph.com/sourcegraph/srcgraph/scan"
	"sourcegraph.com/sourcegraph/srcgraph/task2"
	"sourcegraph.com/sourcegraph/srcgraph/unit"
)

func init() {
	scan.Register("python", &pythonScanner{})
	unit.Register("python", &pythonPackage{})
}

type pythonPackage struct {
	name string
}

func (p *pythonPackage) Name() string {
	return p.name
}

func (p *pythonPackage) RootDir() string {
	return "."
}

func (p *pythonPackage) Paths() []string {
	return nil
}

type pythonScanner struct{}

func (p *pythonScanner) Scan(dir string, c *config.Repository, x *task2.Context) ([]unit.SourceUnit, error) {
	isPython := false
	walker := fs.Walk(dir)
	for walker.Step() {
		if !walker.Stat().IsDir() && filepath.Ext(walker.Path()) == ".py" {
			isPython = true
			break
		}
	}

	if isPython {
		return []unit.SourceUnit{&pythonPackage{filepath.Base(dir)}}, nil
	} else {
		return nil, nil
	}
}
<commit_msg>change python scanner<commit_after>package python

import (
	"path/filepath"

	"github.com/kr/fs"
	"sourcegraph.com/sourcegraph/srcgraph/config"
	"sourcegraph.com/sourcegraph/srcgraph/scan"
	"sourcegraph.com/sourcegraph/srcgraph/task2"
	"sourcegraph.com/sourcegraph/srcgraph/unit"
)

func init() {
	scan.Register("python", &fauxScanner{})
	unit.Register("python", &fauxPackage{})
}

type fauxPackage struct{}

func (p *fauxPackage) Name() string {
	return "python"
}

func (p *fauxPackage) RootDir() string {
	return "."
}

func (p *fauxPackage) Paths() []string {
	return nil
}

type fauxScanner struct{}

func (p *fauxScanner) Scan(dir string, c *config.Repository, x *task2.Context) ([]unit.SourceUnit, error) {
	isPython := false
	walker := fs.Walk(dir)
	for walker.Step() {
		if !walker.Stat().IsDir() && filepath.Ext(walker.Path()) == ".py" {
			isPython = true
			break
		}
	}

	if isPython {
		return []unit.SourceUnit{&fauxPackage{}}, nil
	} else {
		return nil, nil
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, 2016 Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package taint

import (
	"reflect"
	"testing"
)

func TestInjectBool(t *testing.T) {
	s := true
	var d bool
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectString(t *testing.T) {
	s := "test"
	var d string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectInt(t *testing.T) {
	s := 42
	var d int
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectInt64Interface(t *testing.T) {
	var s interface{} = int64(42)
	var d int64
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectFloat64(t *testing.T) {
	s := 42.0
	var d float64
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectSliceOfStrings(t *testing.T) {
	s := []interface{}{
		"test1",
		"test2",
	}
	expected := []string{
		"test1",
		"test2",
	}
	var d []string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectArrayOfStrings(t *testing.T) {
	s := [2]string{
		"test1",
		"test2",
	}
	expected := [2]string{
		"test1",
		"test2",
	}
	var d [2]string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectArrayOfInterfacesToArrayOfStrings(t *testing.T) {
	s := [2]interface{}{
		"test1",
		"test2",
	}
	expected := [2]string{
		"test1",
		"test2",
	}
	var d [2]string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectStringToSliceOfStrings(t *testing.T) {
	s := "test1"
	expected := []string{
		"test1",
	}
	var d []string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectIntToSliceOfInts(t *testing.T) {
	s := 100
	expected := []int{
		100,
	}
	var d []int
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectIntToSliceOfInterfaces(t *testing.T) {
	s := 101
	expected := []interface{}{
		101,
	}
	var d []interface{}
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectSliceOfNestedInterfaces(t *testing.T) {
	s := []interface{}{
		"test1",
		"test2",
		42,
		42.0,
		[]string{
			"sub1",
			"sub2",
		},
		[]bool{
			true,
			false,
		},
	}
	expected := s
	var d []interface{}
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectMapOfStrings(t *testing.T) {
	s := map[interface{}]interface{}{
		"test1": "value1",
		"test2": "value1",
	}
	expected := map[string]string{
		"test1": "value1",
		"test2": "value1",
	}

	var d map[string]string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectMapOfFloat64s(t *testing.T) {
	s := map[interface{}]float64{
		"test1": 1.1,
		"test2": 2.5,
	}
	expected := map[string]float64{
		"test1": 1.1,
		"test2": 2.5,
	}

	var d map[string]float64
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

type Struct1 struct {
	Test1 string `taint:"test-1"`
	Test2 string `taint:",required"`
	Test3 string `taint:"test-3"`
	Test4 int
	Test5 string `taint:",test-something,test-soemthing-else"`
	Test6 string `taint:"-"`
	Test7 []struct{}
}

type Struct2 struct {
	Test1 string `taint:"test-1"`
	Test2 string `taint:",required"`
	Test4 int
	Test7 []struct{}
}

func TestInjectMapOfStruct1s(t *testing.T) {
	s := map[interface{}]Struct1{
		"test1": Struct1{
			Test1: "value1",
			Test2: "value2",
			Test3: "value3",
			Test4: 41,
			Test5: "value5",
		},
		"test2": Struct1{
			Test1: "value 1",
			Test2: "value 2",
			Test3: "value 3",
			Test4: 42,
			Test5: "value 5",
		},
	}
	expected := map[string]map[string]interface{}{
		"test1": map[string]interface{}{
			"test-1": "value1",
			"Test2":  "value2",
			"test-3": "value3",
			"Test4":  41,
			"Test5":  "value5",
			"Test7":  []struct{}(nil),
		},
		"test2": map[string]interface{}{
			"test-1": "value 1",
			"Test2":  "value 2",
			"test-3": "value 3",
			"Test4":  42,
			"Test5":  "value 5",
			"Test7":  []struct{}(nil),
		},
	}

	var d map[string]map[string]interface{}
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectStruct1(t *testing.T) {
	s := map[interface{}]interface{}{
		"test-1": "value1",
		"Test2":  "value1",
		"Test4":  4,
	}
	expected := Struct1{
		Test1: "value1",
		Test2: "value1",
		Test4: 4,
	}

	var d Struct1
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectStruct1ToStruct2(t *testing.T) {
	s := Struct1{
		Test1: "value1",
		Test2: "value1",
		Test4: 4,
		Test7: []struct{}{
			struct{}{},
			struct{}{},
		},
	}
	expected := Struct2{
		Test1: "value1",
		Test2: "value1",
		Test4: 4,
		Test7: []struct{}{
			struct{}{},
			struct{}{},
		},
	}

	var d Struct2
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInvalidTypeError(t *testing.T) {
	s := "test"
	var d int
	err := Inject(s, &d)
	if _, ok := err.(*InvalidTypeError); !ok {
		t.Errorf("Expected InvalidTypeError, but got %#v", err)
	}
}

func TestInvalidInjectError(t *testing.T) {
	s := ""
	var d string
	err := Inject(s, d)
	if _, ok := err.(*InvalidInjectError); !ok {
		t.Errorf("Expected InvalidInjectError, but got %#v", err)
	}
}

type Struct3 struct {
	Test2 string `taint:",required"`
}

func TestInvalidRequiredFieldErrorFromMap(t *testing.T) {
	s := map[string]string{}
	var d Struct3
	err := Inject(s, &d)
	terr, ok := err.(*FieldRequiredError)
	if !ok {
		t.Errorf("Expected FieldRequiredError, but got %#v", err)
	}
	if terr.FieldName != "Test2" {
		t.Errorf("Expected FieldRequiredError FieldName Test2, but got %#v", terr.FieldName)
	}
}

func TestInvalidRequiredFieldErrorFromStruct(t *testing.T) {
	s := struct{}{}
	var d Struct3
	err := Inject(s, &d)
	terr, ok := err.(*FieldRequiredError)
	if !ok {
		t.Errorf("Expected FieldRequiredError, but got %#v", err)
	}
	if terr.FieldName != "Test2" {
		t.Errorf("Expected FieldRequiredError FieldName Test2, but got %#v", terr.FieldName)
	}
}
<commit_msg>Simplify formatting in tests<commit_after>// Copyright (c) 2015, 2016 Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package taint

import (
	"reflect"
	"testing"
)

func TestInjectBool(t *testing.T) {
	s := true
	var d bool
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectString(t *testing.T) {
	s := "test"
	var d string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectInt(t *testing.T) {
	s := 42
	var d int
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectInt64Interface(t *testing.T) {
	var s interface{} = int64(42)
	var d int64
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectFloat64(t *testing.T) {
	s := 42.0
	var d float64
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if d != s {
		t.Errorf("%T destination %#v is not set to %#v", d, d, s)
	}
}

func TestInjectSliceOfStrings(t *testing.T) {
	s := []interface{}{
		"test1",
		"test2",
	}
	expected := []string{
		"test1",
		"test2",
	}
	var d []string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectArrayOfStrings(t *testing.T) {
	s := [2]string{
		"test1",
		"test2",
	}
	expected := [2]string{
		"test1",
		"test2",
	}
	var d [2]string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectArrayOfInterfacesToArrayOfStrings(t *testing.T) {
	s := [2]interface{}{
		"test1",
		"test2",
	}
	expected := [2]string{
		"test1",
		"test2",
	}
	var d [2]string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectStringToSliceOfStrings(t *testing.T) {
	s := "test1"
	expected := []string{
		"test1",
	}
	var d []string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectIntToSliceOfInts(t *testing.T) {
	s := 100
	expected := []int{
		100,
	}
	var d []int
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectIntToSliceOfInterfaces(t *testing.T) {
	s := 101
	expected := []interface{}{
		101,
	}
	var d []interface{}
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectSliceOfNestedInterfaces(t *testing.T) {
	s := []interface{}{
		"test1",
		"test2",
		42,
		42.0,
		[]string{
			"sub1",
			"sub2",
		},
		[]bool{
			true,
			false,
		},
	}
	expected := s
	var d []interface{}
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectMapOfStrings(t *testing.T) {
	s := map[interface{}]interface{}{
		"test1": "value1",
		"test2": "value1",
	}
	expected := map[string]string{
		"test1": "value1",
		"test2": "value1",
	}

	var d map[string]string
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectMapOfFloat64s(t *testing.T) {
	s := map[interface{}]float64{
		"test1": 1.1,
		"test2": 2.5,
	}
	expected := map[string]float64{
		"test1": 1.1,
		"test2": 2.5,
	}

	var d map[string]float64
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

type Struct1 struct {
	Test1 string `taint:"test-1"`
	Test2 string `taint:",required"`
	Test3 string `taint:"test-3"`
	Test4 int
	Test5 string `taint:",test-something,test-soemthing-else"`
	Test6 string `taint:"-"`
	Test7 []struct{}
}

type Struct2 struct {
	Test1 string `taint:"test-1"`
	Test2 string `taint:",required"`
	Test4 int
	Test7 []struct{}
}

func TestInjectMapOfStruct1s(t *testing.T) {
	s := map[interface{}]Struct1{
		"test1": {
			Test1: "value1",
			Test2: "value2",
			Test3: "value3",
			Test4: 41,
			Test5: "value5",
		},
		"test2": {
			Test1: "value 1",
			Test2: "value 2",
			Test3: "value 3",
			Test4: 42,
			Test5: "value 5",
		},
	}
	expected := map[string]map[string]interface{}{
		"test1": {
			"test-1": "value1",
			"Test2":  "value2",
			"test-3": "value3",
			"Test4":  41,
			"Test5":  "value5",
			"Test7":  []struct{}(nil),
		},
		"test2": {
			"test-1": "value 1",
			"Test2":  "value 2",
			"test-3": "value 3",
			"Test4":  42,
			"Test5":  "value 5",
			"Test7":  []struct{}(nil),
		},
	}

	var d map[string]map[string]interface{}
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectStruct1(t *testing.T) {
	s := map[interface{}]interface{}{
		"test-1": "value1",
		"Test2":  "value1",
		"Test4":  4,
	}
	expected := Struct1{
		Test1: "value1",
		Test2: "value1",
		Test4: 4,
	}

	var d Struct1
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInjectStruct1ToStruct2(t *testing.T) {
	s := Struct1{
		Test1: "value1",
		Test2: "value1",
		Test4: 4,
		Test7: []struct{}{
			{},
			{},
		},
	}
	expected := Struct2{
		Test1: "value1",
		Test2: "value1",
		Test4: 4,
		Test7: []struct{}{
			{},
			{},
		},
	}

	var d Struct2
	if err := Inject(s, &d); err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(d, expected) {
		t.Errorf("%T destination %#v is not set to %#v", d, d, expected)
	}
}

func TestInvalidTypeError(t *testing.T) {
	s := "test"
	var d int
	err := Inject(s, &d)
	if _, ok := err.(*InvalidTypeError); !ok {
		t.Errorf("Expected InvalidTypeError, but got %#v", err)
	}
}

func TestInvalidInjectError(t *testing.T) {
	s := ""
	var d string
	err := Inject(s, d)
	if _, ok := err.(*InvalidInjectError); !ok {
		t.Errorf("Expected InvalidInjectError, but got %#v", err)
	}
}

type Struct3 struct {
	Test2 string `taint:",required"`
}

func TestInvalidRequiredFieldErrorFromMap(t *testing.T) {
	s := map[string]string{}
	var d Struct3
	err := Inject(s, &d)
	terr, ok := err.(*FieldRequiredError)
	if !ok {
		t.Errorf("Expected FieldRequiredError, but got %#v", err)
	}
	if terr.FieldName != "Test2" {
		t.Errorf("Expected FieldRequiredError FieldName Test2, but got %#v", terr.FieldName)
	}
}

func TestInvalidRequiredFieldErrorFromStruct(t *testing.T) {
	s := struct{}{}
	var d Struct3
	err := Inject(s, &d)
	terr, ok := err.(*FieldRequiredError)
	if !ok {
		t.Errorf("Expected FieldRequiredError, but got %#v", err)
	}
	if terr.FieldName != "Test2" {
		t.Errorf("Expected FieldRequiredError FieldName Test2, but got %#v", terr.FieldName)
	}
}
<|endoftext|>


<commit_before>package input

import (
	"fmt"
	"os"
	"regexp"
	"time"

	"github.com/elastic/beats/libbeat/common"
	"github.com/elastic/beats/libbeat/logp"
)

// FileEvent is sent to the output and must contain all relevant information
type FileEvent struct {
	common.EventMetadata
	ReadTime     time.Time
	Source       string
	InputType    string
	DocumentType string
	Offset       int64
	Bytes        int
	Text         *string
	Fileinfo     os.FileInfo
	JSONFields   common.MapStr
	JSONConfig   *JSONConfig
	FileState    FileState
	DnsRecord    DnsRecord
}

type JSONConfig struct {
	MessageKey    string `config:"message_key"`
	KeysUnderRoot bool   `config:"keys_under_root"`
	OverwriteKeys bool   `config:"overwrite_keys"`
	AddErrorKey   bool   `config:"add_error_key"`
}

type MultilineConfig struct {
	Negate   bool           `config:"negate"`
	Match    string         `config:"match"       validate:"required"`
	MaxLines *int           `config:"max_lines"`
	Pattern  *regexp.Regexp `config:"pattern"`
	Timeout  *time.Duration `config:"timeout"     validate:"positive"`
}

func (c *MultilineConfig) Validate() error {
	if c.Match != "after" && c.Match != "before" {
		return fmt.Errorf("unknown matcher type: %s", c.Match)
	}
	return nil
}

// mergeJSONFields writes the JSON fields in the event map,
// respecting the KeysUnderRoot and OverwriteKeys configuration options.
// If MessageKey is defined, the Text value from the event always
// takes precedence.
func mergeJSONFields(f *FileEvent, event common.MapStr) {

	// The message key might have been modified by multiline
	if len(f.JSONConfig.MessageKey) > 0 && f.Text != nil {
		f.JSONFields[f.JSONConfig.MessageKey] = *f.Text
	}

	if f.JSONConfig.KeysUnderRoot {
		for k, v := range f.JSONFields {
			if f.JSONConfig.OverwriteKeys {
				if k == "@timestamp" {
					vstr, ok := v.(string)
					if !ok {
						logp.Err("JSON: Won't overwrite @timestamp because value is not string")
						event[jsonErrorKey] = "@timestamp not overwritten (not string)"
						continue
					}
					// @timestamp must be of time common.Time
					ts, err := common.ParseTime(vstr)
					if err != nil {
						logp.Err("JSON: Won't overwrite @timestamp because of parsing error: %v", err)
						event[jsonErrorKey] = fmt.Sprintf("@timestamp not overwritten (parse error on %s)", vstr)
						continue
					}
					event[k] = ts
				} else if k == "type" {
					vstr, ok := v.(string)
					if !ok {
						logp.Err("JSON: Won't overwrite type because value is not string")
						event[jsonErrorKey] = "type not overwritten (not string)"
						continue
					}
					if len(vstr) == 0 || vstr[0] == '_' {
						logp.Err("JSON: Won't overwrite type because value is empty or starts with an underscore")
						event[jsonErrorKey] = fmt.Sprintf("type not overwritten (invalid value [%s])", vstr)
						continue
					}
					event[k] = vstr
				} else {
					event[k] = v
				}
			} else if _, exists := event[k]; !exists {
				event[k] = v
			}
		}
	} else {
		event["json"] = f.JSONFields
	}
}

func (f *FileEvent) ToMapStr() common.MapStr {
	hostname, _ := os.Hostname()

	event := common.MapStr{
		"timestamp": common.Time(f.ReadTime),
		"domain":    f.DnsRecord.Domain,
		"rdata":     f.DnsRecord.Rdata,
		"rtype":     f.DnsRecord.Rtype,
		"client": common.MapStr{
			"hostname": hostname,
			"ip":       Ip,
		},
	}

	if f.DnsRecord.Ttl != -1 {
		event["ttl"] = f.DnsRecord.Ttl
	}

	return event
}

func (f *FileEvent) ExtractDnsRecord(regex *regexp.Regexp) bool {
	if f.Text == nil {
		return false
	}
	match := regex.FindStringSubmatch(*f.Text)
	subexpNames := regex.SubexpNames()

	if len(match) < len(subexpNames) {
		logp.Err("Not able to match all subExpNames")
		return false
	}

	result := make(map[string]string)
	for i, name := range subexpNames {
		result[name] = match[i]
	}

	// check for valid domain and rdata
	if _, ok := result["domain"]; ok {
		f.DnsRecord.Domain = result["domain"]
	}

	if _, ok := result["rdata"]; ok {
		f.DnsRecord.Domain = result["rdata"]
	}
	f.DnsRecord.Rdata = result["rdata"]

	return true
}
<commit_msg>fix dns extraction<commit_after>package input

import (
	"fmt"
	"os"
	"regexp"
	"time"

	"github.com/elastic/beats/libbeat/common"
	"github.com/elastic/beats/libbeat/logp"
)

// FileEvent is sent to the output and must contain all relevant information
type FileEvent struct {
	common.EventMetadata
	ReadTime     time.Time
	Source       string
	InputType    string
	DocumentType string
	Offset       int64
	Bytes        int
	Text         *string
	Fileinfo     os.FileInfo
	JSONFields   common.MapStr
	JSONConfig   *JSONConfig
	FileState    FileState
	DnsRecord    DnsRecord
}

type JSONConfig struct {
	MessageKey    string `config:"message_key"`
	KeysUnderRoot bool   `config:"keys_under_root"`
	OverwriteKeys bool   `config:"overwrite_keys"`
	AddErrorKey   bool   `config:"add_error_key"`
}

type MultilineConfig struct {
	Negate   bool           `config:"negate"`
	Match    string         `config:"match"       validate:"required"`
	MaxLines *int           `config:"max_lines"`
	Pattern  *regexp.Regexp `config:"pattern"`
	Timeout  *time.Duration `config:"timeout"     validate:"positive"`
}

func (c *MultilineConfig) Validate() error {
	if c.Match != "after" && c.Match != "before" {
		return fmt.Errorf("unknown matcher type: %s", c.Match)
	}
	return nil
}

// mergeJSONFields writes the JSON fields in the event map,
// respecting the KeysUnderRoot and OverwriteKeys configuration options.
// If MessageKey is defined, the Text value from the event always
// takes precedence.
func mergeJSONFields(f *FileEvent, event common.MapStr) {

	// The message key might have been modified by multiline
	if len(f.JSONConfig.MessageKey) > 0 && f.Text != nil {
		f.JSONFields[f.JSONConfig.MessageKey] = *f.Text
	}

	if f.JSONConfig.KeysUnderRoot {
		for k, v := range f.JSONFields {
			if f.JSONConfig.OverwriteKeys {
				if k == "@timestamp" {
					vstr, ok := v.(string)
					if !ok {
						logp.Err("JSON: Won't overwrite @timestamp because value is not string")
						event[jsonErrorKey] = "@timestamp not overwritten (not string)"
						continue
					}
					// @timestamp must be of time common.Time
					ts, err := common.ParseTime(vstr)
					if err != nil {
						logp.Err("JSON: Won't overwrite @timestamp because of parsing error: %v", err)
						event[jsonErrorKey] = fmt.Sprintf("@timestamp not overwritten (parse error on %s)", vstr)
						continue
					}
					event[k] = ts
				} else if k == "type" {
					vstr, ok := v.(string)
					if !ok {
						logp.Err("JSON: Won't overwrite type because value is not string")
						event[jsonErrorKey] = "type not overwritten (not string)"
						continue
					}
					if len(vstr) == 0 || vstr[0] == '_' {
						logp.Err("JSON: Won't overwrite type because value is empty or starts with an underscore")
						event[jsonErrorKey] = fmt.Sprintf("type not overwritten (invalid value [%s])", vstr)
						continue
					}
					event[k] = vstr
				} else {
					event[k] = v
				}
			} else if _, exists := event[k]; !exists {
				event[k] = v
			}
		}
	} else {
		event["json"] = f.JSONFields
	}
}

func (f *FileEvent) ToMapStr() common.MapStr {
	hostname, _ := os.Hostname()

	event := common.MapStr{
		"timestamp": common.Time(f.ReadTime),
		"domain":    f.DnsRecord.Domain,
		"rdata":     f.DnsRecord.Rdata,
		"rtype":     f.DnsRecord.Rtype,
		"client": common.MapStr{
			"hostname": hostname,
			"ip":       Ip,
		},
	}

	if f.DnsRecord.Ttl != -1 {
		event["ttl"] = f.DnsRecord.Ttl
	}

	return event
}

func (f *FileEvent) ExtractDnsRecord(regex *regexp.Regexp) bool {
	if f.Text == nil {
		return false
	}
	match := regex.FindStringSubmatch(*f.Text)
	subexpNames := regex.SubexpNames()

	if len(match) < len(subexpNames) {
		logp.Err("Not able to match all subExpNames")
		return false
	}

	result := make(map[string]string)
	for i, name := range subexpNames {
		result[name] = match[i]
	}

	// check for valid domain and rdata
	if _, ok := result["domain"]; ok {
		f.DnsRecord.Domain = result["domain"]
	}

	if _, ok := result["rdata"]; ok {
		f.DnsRecord.Rdata = result["rdata"]
	}

	return true
}
<|endoftext|>


<commit_before>package user

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/fubarhouse/golang-drush/command"
	"strings"
)

// DrupalUser represents fields from Drupals user table, as well as roles.
type DrupalUser struct {
	Alias string
	UID   int
	Name  string
	Email string
	State int
	Roles []string
}

// NewDrupalUser generates a new DrupalUser object.
func NewDrupalUser() DrupalUser {
	return DrupalUser{}
}

// SetRoles will allocate a valid and accurate value to the Roles field in a given DrupalUser object.
func (DrupalUser *DrupalUser) SetRoles() {
	var RolesCommand = fmt.Sprintf("user-information '%v' --fields=roles | cut -d: -f2", DrupalUser.Name)
	cmd := command.NewDrushCommand()
	cmd.Set(DrupalUser.Alias, RolesCommand, false)
	cmdRolesOut, cmdRolesErr := cmd.CombinedOutput()
	if cmdRolesErr != nil {
		log.Errorln("Could not execute Drush user-information:", cmdRolesErr.Error())
	}
	Roles := []string{}
	for _, Role := range strings.Split(string(cmdRolesOut), "\n") {
		Role = strings.TrimSpace(Role)
		if Role != "" {
			Roles = append(Roles, Role)
		}
	}
	DrupalUser.Roles = Roles
}

// Delete will delete a user from a Drupal site, but only if it exists.
func (DrupalUser *DrupalUser) Delete() {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	if UserGroup.FindUser(DrupalUser.Name) {
		var Command = fmt.Sprintf("user-cancel --yes '%v'", DrupalUser.Name)
		cmd := command.NewDrushCommand()
		cmd.Set(DrupalUser.Alias, Command, false)
		_, cmdErr := cmd.CombinedOutput()
		if cmdErr != nil {
			log.Warnf("Could not remove user %v on site %v: %v", DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
		} else {
			log.Infof("Removed user %v on site %v.", DrupalUser.Name, DrupalUser.Alias)
		}
	}
}

// Create will create a user from a Drupal site, but only if does not exist.
func (DrupalUser *DrupalUser) Create(Password string) {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	if !UserGroup.FindUser(DrupalUser.Name) {
		var Command = fmt.Sprintf("user-create '%v' --mail='%v' --password='%v'", DrupalUser.Name, DrupalUser.Email, Password)
		cmd := command.NewDrushCommand()
		cmd.Set(DrupalUser.Alias, Command, false)
		cmdOut, cmdErr := cmd.CombinedOutput()
		if cmdErr != nil {
			log.Warnf("Could not create user %v on site %v: %v: %v", DrupalUser.Name, DrupalUser.Alias, cmdErr.Error(), string(cmdOut))
		} else {
			log.Infof("Created user %v on site %v.", DrupalUser.Name, DrupalUser.Alias)
		}
	}
}

// StateChange will change the status of the user to the value specified in *DrupalUser.State
// There is a built-in verification process here, so a separate verification method is not required.
func (DrupalUser *DrupalUser) StateChange() {
	// Get the absolutely correct User object.
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	User := UserGroup.GetUser(DrupalUser.Name)

	if User.State != DrupalUser.State {
		State := "user-block"
		if User.State == 0 {
			State = "user-unblock"
		}
		cmd := command.NewDrushCommand()
		var Command = fmt.Sprintf("%v '%v'", State, DrupalUser.Name)
		cmd.Set(DrupalUser.Alias, Command, false)
		_, cmdErr := cmd.CombinedOutput()
		if cmdErr != nil {
			log.Warnf("Could not perform action %v for user %v on site %v: %v", State, DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
		} else {
			log.Infof("Performed action %v for user %v on site %v", State, DrupalUser.Name, DrupalUser.Alias)
		}
	}
}

// SetPassword will set the password of a user.
// Action will be performed, as there is no password validation available.
func (DrupalUser *DrupalUser) SetPassword(Password string) {
	var Command = fmt.Sprintf("user-password \"%v\" --password=\"%v\"", DrupalUser.Name, Password)
	cmd := command.NewDrushCommand()
	cmd.Set(DrupalUser.Alias, Command, false)
	_, cmdErr := cmd.CombinedOutput()
	if cmdErr != nil {
		log.Warnf("Could not complete password change for user %v on site %v: %v", DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
	} else {
		log.Infof("Password for user %v on site %v has been changed.", DrupalUser.Name, DrupalUser.Alias)
	}
}

// EmailChange will change the email of the target if the email address
// does not match the email address in the DrupalUser object.
func (DrupalUser *DrupalUser) EmailChange() {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	User := UserGroup.GetUser(DrupalUser.Name)
	if User.Email != DrupalUser.Email && UserGroup.FindUser(DrupalUser.Name) {
		var Command = "sqlq \"UPDATE users SET init='" + User.Email + "', mail='" + DrupalUser.Email + "' WHERE name='" + DrupalUser.Name + "';\""
		cmd := command.NewDrushCommand()
		cmd.Set(DrupalUser.Alias, Command, false)
		_, cmdErr := cmd.CombinedOutput()
		if cmdErr != nil {
			log.Warnf("Could not change email for user %v on site %v from %v to %v: %v", DrupalUser.Name, DrupalUser.Alias, User.Email, DrupalUser.Email, cmdErr.Error())
		} else {
			log.Infof("Changed email for user %v on site %v from %v to %v, clear caches if results are unexpected.", DrupalUser.Name, DrupalUser.Alias, User.Email, DrupalUser.Email)
		}
	}
}

// HasRole will determine if the user has a given String in the list of roles, which will return as a Boolean.
func (DrupalUser *DrupalUser) HasRole(Role string) bool {
	for _, value := range DrupalUser.Roles {
		if value == Role {
			return true
		}
	}
	return false
}

// RolesAdd will add all associated roles to the target user,
// when not present in the DrupalUser object.
func (DrupalUser *DrupalUser) RolesAdd() {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	User := UserGroup.GetUser(DrupalUser.Name)
	User.SetRoles()
	for _, Role := range DrupalUser.Roles {
		if Role != "authenticated user" {
			if !User.HasRole(Role) {
				var Command = fmt.Sprintf("user-add-role --name='%v' '%v'", DrupalUser.Name, Role)
				cmd := command.NewDrushCommand()
				cmd.Set(DrupalUser.Alias, Command, false)
				_, cmdErr := cmd.CombinedOutput()
				if cmdErr != nil {
					log.Warnf("Could not add role %v to use %v on site %v: %v", Role, DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
				} else {
					log.Infof("Added user %v to role %v on site %v.", DrupalUser.Name, Role, DrupalUser.Alias)
				}
			}
		}
	}
}

// RolesRemove will remove all associated roles to the target user,
// when present in the DrupalUser object.
func (DrupalUser *DrupalUser) RolesRemove() {
	// if not "authenticated user" {
	// if user has role, and the role needs to be removed, remove the role. {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	User := UserGroup.GetUser(DrupalUser.Name)
	User.SetRoles()
	for _, Role := range DrupalUser.Roles {
		if Role != "authenticated user" {
			if User.HasRole(Role) {
				var Command = fmt.Sprintf("user-remove-role --name='%v' '%v'", DrupalUser.Name, Role)
				cmd := command.NewDrushCommand()
				cmd.Set(DrupalUser.Alias, Command, false)
				_, cmdErr := cmd.CombinedOutput()
				if cmdErr != nil {
					log.Warnf("Could not remove role %v on user %v on site %v: %v", Role, DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
				} else {
					log.Infof("Removed user %v from role %v on site %v.", DrupalUser.Name, Role, DrupalUser.Alias)
				}
			}
		}
	}
}
<commit_msg>Add reporting on user availability when flow control for user creation fails.<commit_after>package user

import (
	"fmt"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/fubarhouse/golang-drush/command"
)

// DrupalUser represents fields from Drupals user table, as well as roles.
type DrupalUser struct {
	Alias string
	UID   int
	Name  string
	Email string
	State int
	Roles []string
}

// NewDrupalUser generates a new DrupalUser object.
func NewDrupalUser() DrupalUser {
	return DrupalUser{}
}

// SetRoles will allocate a valid and accurate value to the Roles field in a given DrupalUser object.
func (DrupalUser *DrupalUser) SetRoles() {
	var RolesCommand = fmt.Sprintf("user-information '%v' --fields=roles | cut -d: -f2", DrupalUser.Name)
	cmd := command.NewDrushCommand()
	cmd.Set(DrupalUser.Alias, RolesCommand, false)
	cmdRolesOut, cmdRolesErr := cmd.CombinedOutput()
	if cmdRolesErr != nil {
		log.Errorln("Could not execute Drush user-information:", cmdRolesErr.Error())
	}
	Roles := []string{}
	for _, Role := range strings.Split(string(cmdRolesOut), "\n") {
		Role = strings.TrimSpace(Role)
		if Role != "" {
			Roles = append(Roles, Role)
		}
	}
	DrupalUser.Roles = Roles
}

// Delete will delete a user from a Drupal site, but only if it exists.
func (DrupalUser *DrupalUser) Delete() {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	if UserGroup.FindUser(DrupalUser.Name) {
		var Command = fmt.Sprintf("user-cancel --yes '%v'", DrupalUser.Name)
		cmd := command.NewDrushCommand()
		cmd.Set(DrupalUser.Alias, Command, false)
		_, cmdErr := cmd.CombinedOutput()
		if cmdErr != nil {
			log.Warnf("Could not remove user %v on site %v: %v", DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
		} else {
			log.Infof("Removed user %v on site %v.", DrupalUser.Name, DrupalUser.Alias)
		}
	}
}

// Create will create a user from a Drupal site, but only if does not exist.
func (DrupalUser *DrupalUser) Create(Password string) {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	if !UserGroup.FindUser(DrupalUser.Name) {
		var Command = fmt.Sprintf("user-create '%v' --mail='%v' --password='%v'", DrupalUser.Name, DrupalUser.Email, Password)
		cmd := command.NewDrushCommand()
		cmd.Set(DrupalUser.Alias, Command, false)
		cmdOut, cmdErr := cmd.CombinedOutput()
		if cmdErr != nil {
			log.Warnf("Could not create user '%v' on site '%v': %v: %v", DrupalUser.Name, DrupalUser.Alias, cmdErr.Error(), string(cmdOut))
		} else {
			log.Infof("Created user '%v' on site '%v'.", DrupalUser.Name, DrupalUser.Alias)
		}
	} else {
		log.Warnln("Could not create user, user already exists.")
	}
}

// StateChange will change the status of the user to the value specified in *DrupalUser.State
// There is a built-in verification process here, so a separate verification method is not required.
func (DrupalUser *DrupalUser) StateChange() {
	// Get the absolutely correct User object.
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	User := UserGroup.GetUser(DrupalUser.Name)

	if User.State != DrupalUser.State {
		State := "user-block"
		if User.State == 0 {
			State = "user-unblock"
		}
		cmd := command.NewDrushCommand()
		var Command = fmt.Sprintf("%v '%v'", State, DrupalUser.Name)
		cmd.Set(DrupalUser.Alias, Command, false)
		_, cmdErr := cmd.CombinedOutput()
		if cmdErr != nil {
			log.Warnf("Could not perform action %v for user %v on site %v: %v", State, DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
		} else {
			log.Infof("Performed action %v for user %v on site %v", State, DrupalUser.Name, DrupalUser.Alias)
		}
	}
}

// SetPassword will set the password of a user.
// Action will be performed, as there is no password validation available.
func (DrupalUser *DrupalUser) SetPassword(Password string) {
	var Command = fmt.Sprintf("user-password \"%v\" --password=\"%v\"", DrupalUser.Name, Password)
	cmd := command.NewDrushCommand()
	cmd.Set(DrupalUser.Alias, Command, false)
	_, cmdErr := cmd.CombinedOutput()
	if cmdErr != nil {
		log.Warnf("Could not complete password change for user %v on site %v: %v", DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
	} else {
		log.Infof("Password for user %v on site %v has been changed.", DrupalUser.Name, DrupalUser.Alias)
	}
}

// EmailChange will change the email of the target if the email address
// does not match the email address in the DrupalUser object.
func (DrupalUser *DrupalUser) EmailChange() {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	User := UserGroup.GetUser(DrupalUser.Name)
	if User.Email != DrupalUser.Email && UserGroup.FindUser(DrupalUser.Name) {
		var Command = "sqlq \"UPDATE users SET init='" + User.Email + "', mail='" + DrupalUser.Email + "' WHERE name='" + DrupalUser.Name + "';\""
		cmd := command.NewDrushCommand()
		cmd.Set(DrupalUser.Alias, Command, false)
		_, cmdErr := cmd.CombinedOutput()
		if cmdErr != nil {
			log.Warnf("Could not change email for user %v on site %v from %v to %v: %v", DrupalUser.Name, DrupalUser.Alias, User.Email, DrupalUser.Email, cmdErr.Error())
		} else {
			log.Infof("Changed email for user %v on site %v from %v to %v, clear caches if results are unexpected.", DrupalUser.Name, DrupalUser.Alias, User.Email, DrupalUser.Email)
		}
	}
}

// HasRole will determine if the user has a given String in the list of roles, which will return as a Boolean.
func (DrupalUser *DrupalUser) HasRole(Role string) bool {
	for _, value := range DrupalUser.Roles {
		if value == Role {
			return true
		}
	}
	return false
}

// RolesAdd will add all associated roles to the target user,
// when not present in the DrupalUser object.
func (DrupalUser *DrupalUser) RolesAdd() {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	User := UserGroup.GetUser(DrupalUser.Name)
	User.SetRoles()
	for _, Role := range DrupalUser.Roles {
		if Role != "authenticated user" {
			if !User.HasRole(Role) {
				var Command = fmt.Sprintf("user-add-role --name='%v' '%v'", DrupalUser.Name, Role)
				cmd := command.NewDrushCommand()
				cmd.Set(DrupalUser.Alias, Command, false)
				_, cmdErr := cmd.CombinedOutput()
				if cmdErr != nil {
					log.Warnf("Could not add role %v to use %v on site %v: %v", Role, DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
				} else {
					log.Infof("Added user %v to role %v on site %v.", DrupalUser.Name, Role, DrupalUser.Alias)
				}
			}
		}
	}
}

// RolesRemove will remove all associated roles to the target user,
// when present in the DrupalUser object.
func (DrupalUser *DrupalUser) RolesRemove() {
	// if not "authenticated user" {
	// if user has role, and the role needs to be removed, remove the role. {
	UserGroup := NewDrupalUserGroup()
	UserGroup.Populate(DrupalUser.Alias)
	User := UserGroup.GetUser(DrupalUser.Name)
	User.SetRoles()
	for _, Role := range DrupalUser.Roles {
		if Role != "authenticated user" {
			if User.HasRole(Role) {
				var Command = fmt.Sprintf("user-remove-role --name='%v' '%v'", DrupalUser.Name, Role)
				cmd := command.NewDrushCommand()
				cmd.Set(DrupalUser.Alias, Command, false)
				_, cmdErr := cmd.CombinedOutput()
				if cmdErr != nil {
					log.Warnf("Could not remove role %v on user %v on site %v: %v", Role, DrupalUser.Name, DrupalUser.Alias, cmdErr.Error())
				} else {
					log.Infof("Removed user %v from role %v on site %v.", DrupalUser.Name, Role, DrupalUser.Alias)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package connection

import (
	"net/rpc"
	"time"

	"kego.io/kerr"
)

type Conn struct {
	client *rpc.Client
}

func New(client *rpc.Client) *Conn {
	return &Conn{
		client: client,
	}
}

func (c *Conn) Go(serviceMethod string, args interface{}, reply interface{}, done chan *rpc.Call, fail chan error) *rpc.Call {
	rpcCall := c.client.Go(serviceMethod, args, reply, make(chan *rpc.Call, 1))

	call := &rpc.Call{
		ServiceMethod: serviceMethod,
		Args:          args,
		Reply:         reply,
		Error:         rpcCall.Error,
		Done:          done,
	}

	go func() {
		select {
		case <-rpcCall.Done:
			done <- call
		case <-time.After(time.Millisecond * 200):
			fail <- kerr.New("CWOTFNPITL", "Timeout")
		}
	}()

	return call

}

func (c *Conn) Close() {
	c.Close()
}
<commit_msg>Disabled tests for connection<commit_after>package connection

// ke: {"package": {"notest": true}}

import (
	"net/rpc"
	"time"

	"kego.io/kerr"
)

type Conn struct {
	client *rpc.Client
}

func New(client *rpc.Client) *Conn {
	return &Conn{
		client: client,
	}
}

func (c *Conn) Go(serviceMethod string, args interface{}, reply interface{}, done chan *rpc.Call, fail chan error) *rpc.Call {
	rpcCall := c.client.Go(serviceMethod, args, reply, make(chan *rpc.Call, 1))

	call := &rpc.Call{
		ServiceMethod: serviceMethod,
		Args:          args,
		Reply:         reply,
		Error:         rpcCall.Error,
		Done:          done,
	}

	go func() {
		select {
		case <-rpcCall.Done:
			done <- call
		case <-time.After(time.Millisecond * 200):
			fail <- kerr.New("CWOTFNPITL", "Timeout")
		}
	}()

	return call

}

func (c *Conn) Close() {
	c.Close()
}
<|endoftext|>


<commit_before>package web

import (
	"akamai/atlas/forms/entity"
	"akamai/atlas/forms/persist"
	"html/template"
	"net/http"
	"net/http/httptest"
	"os"
	"path"
	"strings"
	"testing"
)

var normalPersist *persist.PersistJSON
var normalApp *App

func init() {
	testPath := os.Getenv("ATLAS_TEST_PATH")

	if testPath == "" {
		testPath = "../"
	}

	httpAddr := "localhost:3001"
	dataPath := path.Join(testPath, "test/data/")
	htmlPath := path.Join(testPath, "html/")
	chartsPath := path.Join(testPath, "test/charts/")
	staticPath := path.Join(testPath, "static/")
	formsRoot := "forms/"
	chartsRoot := ""
	staticRoot := "static/"

	normalPersist = persist.NewPersistJSON(dataPath)

	normalApp = &App{
		HttpAddr:     httpAddr,
		QuestionRepo: entity.QuestionRepo(normalPersist),
		ProfileRepo:  entity.ProfileRepo(normalPersist),
		ReviewRepo:   entity.ReviewRepo(normalPersist),
		HtmlPath:     htmlPath,
		StaticPath:   staticPath,
		StaticRoot:   staticRoot,
		ChartsPath:   chartsPath,
		ChartsRoot:   chartsRoot,
		FormsRoot:    formsRoot,
	}

	normalApp.templates = template.Must(
		template.ParseGlob(
			path.Join(htmlPath, "*.html")))
}

func TestReviewSetGet(t *testing.T) {
	t.Parallel()
	t.Log("TestReviewSetGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/forms/reviews/", nil)
	normalApp.ServeHTTP(w, r)
	t.Logf("TestReviewSetGet(): status code %d", w.Code)
	if w.Code != 200 {
		t.Fatalf("TestReviewSetGet() failed: %s", w)
	}
}

func TestQuestionSetGet(t *testing.T) {
	t.Parallel()
	t.Log("TestQuestionSetGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/forms/questions/", nil)
	normalApp.ServeHTTP(w, r)
	t.Logf("TestQuestionGet(): status code %d", w.Code)
	if w.Code != 200 {
		t.Fatalf("TestReviewSetGet() failed: %s", w)
	}
}

func TestProfileSetGet(t *testing.T) {
	t.Parallel()
	t.Log("TestProfileSetGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/forms/profiles/", nil)
	normalApp.ServeHTTP(w, r)
	t.Logf("TestProfileGet(): status code %d", w.Code)
	if w.Code != 200 {
		t.Fatalf("TestReviewSetGet() failed: %s", w)
	}
}

func TestChartsGet(t *testing.T) {
	t.Parallel()
	t.Log("TestChartsGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/", nil)
	normalApp.ServeHTTP(w, r)
	if w.Code != 200 {
		t.Fatalf("TestChartsGet() failed: response code %d != 200", w.Code)
	}
	body := w.Body.String()
	if !strings.Contains(body, "Demo Atlas") {
		t.Fatalf("TestChartsGet() failed: body does not mention 'Demo Atlas':\n %s", w.Body)
	}
}
<commit_msg>Add a unit test for HandleSiteJsonGet().<commit_after>package web

import (
	"akamai/atlas/forms/entity"
	"akamai/atlas/forms/persist"
	"html/template"
	"net/http"
	"net/http/httptest"
	"os"
	"path"
	"strings"
	"testing"
)

var normalPersist *persist.PersistJSON
var normalApp *App

func init() {
	testPath := os.Getenv("ATLAS_TEST_PATH")

	if testPath == "" {
		testPath = "../"
	}

	httpAddr := "localhost:3001"
	dataPath := path.Join(testPath, "test/data/")
	htmlPath := path.Join(testPath, "html/")
	chartsPath := path.Join(testPath, "test/charts/")
	staticPath := path.Join(testPath, "static/")
	formsRoot := "forms/"
	chartsRoot := ""
	staticRoot := "static/"

	normalPersist = persist.NewPersistJSON(dataPath)

	normalApp = &App{
		HttpAddr:     httpAddr,
		QuestionRepo: entity.QuestionRepo(normalPersist),
		ProfileRepo:  entity.ProfileRepo(normalPersist),
		ReviewRepo:   entity.ReviewRepo(normalPersist),
		HtmlPath:     htmlPath,
		StaticPath:   staticPath,
		StaticRoot:   staticRoot,
		ChartsPath:   chartsPath,
		ChartsRoot:   chartsRoot,
		FormsRoot:    formsRoot,
	}

	normalApp.templates = template.Must(
		template.ParseGlob(
			path.Join(htmlPath, "*.html")))
}

func TestReviewSetGet(t *testing.T) {
	t.Parallel()
	t.Log("TestReviewSetGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/forms/reviews/", nil)
	normalApp.ServeHTTP(w, r)
	t.Logf("TestReviewSetGet(): status code %d", w.Code)
	if w.Code != 200 {
		t.Fatalf("TestReviewSetGet() failed: %s", w)
	}
}

func TestQuestionSetGet(t *testing.T) {
	t.Parallel()
	t.Log("TestQuestionSetGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/forms/questions/", nil)
	normalApp.ServeHTTP(w, r)
	t.Logf("TestQuestionGet(): status code %d", w.Code)
	if w.Code != 200 {
		t.Fatalf("TestReviewSetGet() failed: %s", w)
	}
}

func TestProfileSetGet(t *testing.T) {
	t.Parallel()
	t.Log("TestProfileSetGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/forms/profiles/", nil)
	normalApp.ServeHTTP(w, r)
	t.Logf("TestProfileGet(): status code %d", w.Code)
	if w.Code != 200 {
		t.Fatalf("TestReviewSetGet() failed: %s", w)
	}
}

func TestChartsGet(t *testing.T) {
	t.Parallel()
	t.Log("TestChartsGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/", nil)
	normalApp.ServeHTTP(w, r)
	if w.Code != 200 {
		t.Fatalf("TestChartsGet() failed: response code %d != 200", w.Code)
	}
	body := w.Body.String()
	if !strings.Contains(body, "Demo Atlas") {
		t.Fatalf("TestChartsGet() failed: body does not mention 'Demo Atlas':\n %s", w.Body)
	}
}

func TestSiteJsonGet(t *testing.T) {
	t.Parallel()
	t.Log("TestSiteJsonGet(): starting.")
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "http://localhost:3001/site.json", nil)
	normalApp.ServeHTTP(w, r)
	if w.Code != 200 {
		t.Fatalf("TestSiteJsonGet() failed: response code %d != 200", w.Code)
	}
	body := w.Body.String()
	if !strings.Contains(body, "Demo Atlas") {
		t.Fatalf("TestSiteJsonGet() failed: body does not mention 'Demo Atlas':\n %s", w.Body)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"webircgateway/identd"
)

var (
	// Version - The current version of webircgateway
	Version    = "0.1.1"
	identdServ identd.Server
)

func main() {
	printVersion := flag.Bool("version", false, "Print the version")
	configFile := flag.String("config", "config.conf", "Config file location")
	runConfigTest := flag.Bool("test", false, "Just test the config file")
	flag.Parse()

	if *printVersion {
		fmt.Println(Version)
		os.Exit(0)
	}

	Config.configFile, _ = filepath.Abs(*configFile)
	log.Printf("Using config file %s", Config.configFile)

	err := loadConfig()
	if err != nil {
		log.Printf("Config file error: %s", err.Error())
		os.Exit(1)
	}

	if *runConfigTest {
		log.Println("Config file is OK")
		os.Exit(0)
	}

	watchForSignals()
	maybeStartStaticFileServer()
	initListenerEngines()
	startServers()
	maybeStartIdentd()

	justWait := make(chan bool)
	<-justWait
}

func initListenerEngines() {
	engineConfigured := false
	for _, serverEngine := range Config.serverEngines {
		switch serverEngine {
		case "kiwiirc":
			kiwiircHTTPHandler()
			engineConfigured = true
		case "websocket":
			websocketHTTPHandler()
			engineConfigured = true
		case "sockjs":
			sockjsHTTPHandler()
			engineConfigured = true
		default:
			log.Printf("Invalid server engine: '%s'", serverEngine)
		}
	}

	if !engineConfigured {
		log.Fatal("No server engines configured")
	}
}

func maybeStartIdentd() {
	identdServ = identd.NewIdentdServer()

	if Config.identd {
		err := identdServ.Run()
		if err != nil {
			log.Printf("Error starting identd server: %s", err.Error())
		} else {
			log.Printf("Identd server started")
		}
	}
}

func maybeStartStaticFileServer() {
	if Config.webroot != "" {
		webroot := ConfigResolvePath(Config.webroot)
		log.Printf("Serving files from %s", webroot)
		http.Handle("/", http.FileServer(http.Dir(webroot)))
	}
}

func startServers() {
	for _, server := range Config.servers {
		go startServer(server)
	}
}

func startServer(conf ConfigServer) {
	addr := fmt.Sprintf("%s:%d", conf.LocalAddr, conf.Port)

	if conf.TLS {
		if conf.CertFile == "" || conf.KeyFile == "" {
			log.Println("'cert' and 'key' options must be set for TLS servers")
			return
		}

		tlsCert := ConfigResolvePath(conf.CertFile)
		tlsKey := ConfigResolvePath(conf.KeyFile)

		log.Printf("Listening with TLS on %s", addr)
		err := http.ListenAndServeTLS(addr, tlsCert, tlsKey, nil)
		if err != nil {
			log.Printf("Failed to listen with TLS: %s", err.Error())
		}
	} else {
		log.Printf("Listening on %s", addr)
		err := http.ListenAndServe(addr, nil)
		log.Println(err)
	}
}

func watchForSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP)
	go func() {
		for {
			<-c
			fmt.Println("Recieved SIGHUP, reloading config file")
			loadConfig()
		}
	}()
}
<commit_msg>Server info available via /webirc/<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"webircgateway/identd"
)

var (
	// Version - The current version of webircgateway
	Version    = "0.1.1"
	identdServ identd.Server
)

func main() {
	printVersion := flag.Bool("version", false, "Print the version")
	configFile := flag.String("config", "config.conf", "Config file location")
	runConfigTest := flag.Bool("test", false, "Just test the config file")
	flag.Parse()

	if *printVersion {
		fmt.Println(Version)
		os.Exit(0)
	}

	Config.configFile, _ = filepath.Abs(*configFile)
	log.Printf("Using config file %s", Config.configFile)

	err := loadConfig()
	if err != nil {
		log.Printf("Config file error: %s", err.Error())
		os.Exit(1)
	}

	if *runConfigTest {
		log.Println("Config file is OK")
		os.Exit(0)
	}

	watchForSignals()
	maybeStartStaticFileServer()
	initListenerEngines()
	startServers()
	maybeStartIdentd()

	justWait := make(chan bool)
	<-justWait
}

func initListenerEngines() {
	engineConfigured := false
	for _, serverEngine := range Config.serverEngines {
		switch serverEngine {
		case "kiwiirc":
			kiwiircHTTPHandler()
			engineConfigured = true
		case "websocket":
			websocketHTTPHandler()
			engineConfigured = true
		case "sockjs":
			sockjsHTTPHandler()
			engineConfigured = true
		default:
			log.Printf("Invalid server engine: '%s'", serverEngine)
		}
	}

	if !engineConfigured {
		log.Fatal("No server engines configured")
	}
}

func maybeStartIdentd() {
	identdServ = identd.NewIdentdServer()

	if Config.identd {
		err := identdServ.Run()
		if err != nil {
			log.Printf("Error starting identd server: %s", err.Error())
		} else {
			log.Printf("Identd server started")
		}
	}
}

func maybeStartStaticFileServer() {
	if Config.webroot != "" {
		webroot := ConfigResolvePath(Config.webroot)
		log.Printf("Serving files from %s", webroot)
		http.Handle("/", http.FileServer(http.Dir(webroot)))
	}
}

func startServers() {
	// Add some general server info about this webircgateway instance
	http.HandleFunc("/webirc/", func(w http.ResponseWriter, r *http.Request) {
		out, _ := json.Marshal(map[string]interface{}{
			"name":    "webircgateway",
			"version": Version,
		})

		w.Write(out)
	})

	for _, server := range Config.servers {
		go startServer(server)
	}
}

func startServer(conf ConfigServer) {
	addr := fmt.Sprintf("%s:%d", conf.LocalAddr, conf.Port)

	if conf.TLS {
		if conf.CertFile == "" || conf.KeyFile == "" {
			log.Println("'cert' and 'key' options must be set for TLS servers")
			return
		}

		tlsCert := ConfigResolvePath(conf.CertFile)
		tlsKey := ConfigResolvePath(conf.KeyFile)

		log.Printf("Listening with TLS on %s", addr)
		err := http.ListenAndServeTLS(addr, tlsCert, tlsKey, nil)
		if err != nil {
			log.Printf("Failed to listen with TLS: %s", err.Error())
		}
	} else {
		log.Printf("Listening on %s", addr)
		err := http.ListenAndServe(addr, nil)
		log.Println(err)
	}
}

func watchForSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP)
	go func() {
		for {
			<-c
			fmt.Println("Recieved SIGHUP, reloading config file")
			loadConfig()
		}
	}()
}
<|endoftext|>