<commit_before>package router

import (
	"fmt"
	"io/ioutil"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	routev1 "github.com/openshift/api/route/v1"
	routeclientset "github.com/openshift/client-go/route/clientset/versioned"
	"github.com/openshift/origin/test/extended/router/h2spec"
	exutil "github.com/openshift/origin/test/extended/util"
	"github.com/openshift/origin/test/extended/util/url"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	e2e "k8s.io/kubernetes/test/e2e/framework"
)

const h2specDialTimeoutInSeconds = 15

type h2specFailingTest struct {
	TestCase   *h2spec.JUnitTestCase
	TestNumber int
}

type h2specRouteTypeTest struct {
	routeType     routev1.TLSTerminationType
	hostname      string
	knownFailures map[string]bool
}

var _ = g.Describe("[sig-network-edge][Conformance][Area:Networking][Feature:Router]", func() {
	defer g.GinkgoRecover()

	var (
		configPath = exutil.FixturePath("testdata", "router", "router-h2spec.yaml")
		oc         = exutil.NewCLI("router-h2spec")
	)

	// this hook must be registered before the framework namespace teardown
	// hook
	g.AfterEach(func() {
		if g.CurrentGinkgoTestDescription().Failed {
			client := routeclientset.NewForConfigOrDie(oc.AdminConfig()).RouteV1().Routes(oc.KubeFramework().Namespace.Name)
			if routes, _ := client.List(metav1.ListOptions{}); routes != nil {
				outputIngress(routes.Items...)
			}
			exutil.DumpPodLogsStartingWith("h2spec", oc)
		}
	})

	g.By(fmt.Sprintf("creating routes from a config file %q", configPath))

	g.Describe("The HAProxy router", func() {
		g.It("should pass the h2spec conformance tests", func() {
			routerImage, err := exutil.FindRouterImage(oc)
			o.Expect(err).NotTo(o.HaveOccurred())

			err = oc.Run("new-app").Args("-f", configPath, "-p", "HAPROXY_IMAGE="+routerImage).Execute()
			o.Expect(err).NotTo(o.HaveOccurred())

			e2e.ExpectNoError(oc.KubeFramework().WaitForPodRunning("h2spec-haproxy"))

			routeTypeTests := []h2specRouteTypeTest{{
				routeType: routev1.TLSTerminationEdge,
				knownFailures: map[string]bool{
					"http2/4.2.3": true,
				},
			}, {
				routeType: routev1.TLSTerminationPassthrough,
				knownFailures: map[string]bool{
					"http2/4.2.3": true,
				},
			}, {
				routeType: routev1.TLSTerminationReencrypt,
				knownFailures: map[string]bool{
					"http2/4.2.3": true,
				},
			}}

			g.By("verifying accessing the host returns a 200 status code")
			for i := 0; i < len(routeTypeTests); i++ {
				urlTester := url.NewTester(oc.AdminKubeClient(), oc.KubeFramework().Namespace.Name).WithErrorPassthrough(true)
				defer urlTester.Close()
				hostname := getHostnameForRoute(oc, fmt.Sprintf("h2spec-haproxy-%s", routeTypeTests[i].routeType))
				urlTester.Within(30*time.Second, url.Expect("GET", "https://"+hostname).Through(hostname).SkipTLSVerification().HasStatusCode(200))
				routeTypeTests[i].hostname = hostname // now valid for the remaining tests
			}

			// ROUTER_H2SPEC_SAMPLE when set runs the
			// conformance tests for N iterations to
			// identify flaking tests.
			//
			// This should be enabled in development every
			// time we consume any new version of haproxy
			// be that a major, minor or a micro update to
			// continuously validate the set of test case
			// IDs that fail.
			if iterations := lookupEnv("ROUTER_H2SPEC_SAMPLE", ""); iterations != "" {
				n, err := strconv.Atoi(iterations)
				o.Expect(err).NotTo(o.HaveOccurred())
				runConformanceTestsAndLogAggregateFailures(oc, routeTypeTests, n)
				return
			}

			for _, t := range routeTypeTests {
				g.By(fmt.Sprintf("[%s] Running h2spec conformance tests against %q", t.routeType, t.hostname))

				testSuites := runConformanceTests(oc, t)
				o.Expect(testSuites).ShouldNot(o.BeEmpty())

				failures := failingTests(testSuites)
				failureCount := len(failures)

				g.By("Analyzing results")
				for _, f := range failures {
					if _, exists := t.knownFailures[f.ID()]; exists {
						failureCount -= 1
						e2e.Logf("[%s] TestCase ID: %q is a known failure; ignoring", t.routeType, f.ID())
					} else {
						e2e.Logf("[%s] TestCase ID: %q (%q) ****FAILED****", t.routeType, f.ID(), f.TestCase.ClassName)
					}
				}
				o.Expect(failureCount).Should(o.BeZero(), "expected zero failures")
			}
		})
	})
})

func failingTests(testSuites []*h2spec.JUnitTestSuite) []h2specFailingTest {
	var failures []h2specFailingTest

	for _, ts := range testSuites {
		for i := 0; i < ts.Tests; i++ {
			if ts.TestCases[i].Error != nil {
				failures = append(failures, h2specFailingTest{
					TestNumber: i + 1,
					TestCase:   ts.TestCases[i],
				})
			}
		}
	}

	return failures
}

func runConformanceTests(oc *exutil.CLI, t h2specRouteTypeTest) []*h2spec.JUnitTestSuite {
	podName := "h2spec"
	e2e.ExpectNoError(oc.KubeFramework().WaitForPodRunning(podName))

	var results []*h2spec.JUnitTestSuite

	o.Expect(wait.PollImmediate(time.Second, 5*time.Minute, func() (bool, error) {
		g.By("Running the h2spec CLI test")

		ns := oc.KubeFramework().Namespace.Name
		outputFile, err := ioutil.TempFile("", "runConformanceTests")
		if err != nil {
			e2e.Logf("[%s] error: failed to generate tmp file: %v; retrying...", t.routeType, err)
			return false, nil
		}
		defer os.Remove(outputFile.Name())

		output, _ := e2e.RunHostCmd(ns, podName, h2specCommand(h2specDialTimeoutInSeconds, t.hostname, outputFile.Name()))
		// h2spec will exit with non-zero if _any_ test in the
		// suite fails, or if there is a dial timeout, so we
		// ignore the error. We can exit from this loop if we
		// can fetch the results, if we can decode the results
		// and we have > 0 test suites from the decoded
		// results.

		g.By(fmt.Sprintf("[%s] Copying results from %s:%q", t.routeType, podName, outputFile.Name()))
		data, err := e2e.RunHostCmd(ns, podName, fmt.Sprintf("cat %q", outputFile.Name()))
		if err != nil {
			e2e.Logf("[%s] error: failed to copy results: %v; retrying...", t.routeType, err)
			return false, nil
		}
		if data == "" {
			e2e.Logf("[%s] error: zero length results file; retrying...", t.routeType)
			return false, nil
		}

		g.By(fmt.Sprintf("[%s] Decoding results", t.routeType))
		testSuites, err := h2spec.DecodeJUnitReport(strings.NewReader(data))
		if err != nil {
			e2e.Logf("[%s] error: decoding results: %v; retrying...", t.routeType, err)
			return false, nil
		}
		if len(testSuites) == 0 {
			e2e.Logf("[%s] error: no test results found; retrying...", t.routeType)
			return false, nil
		}

		// Log what we consider a successful run
		e2e.Logf("[%s] h2spec results\n%s", t.routeType, output)
		results = testSuites
		return true, nil
	})).NotTo(o.HaveOccurred())

	return results
}

func runConformanceTestsAndLogAggregateFailures(oc *exutil.CLI, tests []h2specRouteTypeTest, iterations int) {
	sortKeys := func(m map[string]int) []string {
		var index []string
		for k := range m {
			index = append(index, k)
		}
		sort.Strings(index)
		return index
	}

	printFailures := func(t h2specRouteTypeTest, prefix string, m map[string]int) {
		for _, id := range sortKeys(m) {
			e2e.Logf("[%s] %sTestCase ID: %q, cumulative failures: %v", t.routeType, prefix, id, m[id])
		}
	}

	failuresByTestCaseID := map[string]int{}

	for _, t := range tests {
		for i := 1; i <= iterations; i++ {
			failures := failingTests(runConformanceTests(oc, t))
			e2e.Logf("[%s] Iteration %v/%v: had %v failures", t.routeType, i, iterations, len(failures))

			// Aggregate any new failures
			for _, f := range failures {
				failuresByTestCaseID[f.ID()]++
			}

			// Dump the current state at every iteration should
			// you wish to interrupt/abort the running test.
			printFailures(t, "\t", failuresByTestCaseID)
		}
	}

	for _, t := range tests {
		e2e.Logf("[%s] Sampling completed: %v test cases failed", t.routeType, len(failuresByTestCaseID))
		printFailures(t, "\t", failuresByTestCaseID)
	}
}

func getHostnameForRoute(oc *exutil.CLI, routeName string) string {
	var hostname string
	ns := oc.KubeFramework().Namespace.Name
	err := wait.Poll(time.Second, changeTimeoutSeconds*time.Second, func() (bool, error) {
		route, err := oc.RouteClient().RouteV1().Routes(ns).Get(routeName, metav1.GetOptions{})
		if err != nil {
			e2e.Logf("Error getting hostname for route %q: %v", routeName, err)
			return false, err
		}
		if len(route.Status.Ingress) == 0 || len(route.Status.Ingress[0].Host) == 0 {
			return false, nil
		}
		hostname = route.Status.Ingress[0].Host
		return true, nil
	})
	o.Expect(err).NotTo(o.HaveOccurred())
	return hostname
}

func h2specCommand(timeout int, hostname, results string) string {
	return fmt.Sprintf("h2spec --timeout=%v --tls --insecure --strict --host=%q --junit-report=%q", timeout, hostname, results)
}

func (f h2specFailingTest) ID() string {
	return fmt.Sprintf("%s.%d", f.TestCase.Package, f.TestNumber)
}

func lookupEnv(key, defaultVal string) string {
	if val, ok := os.LookupEnv(key); ok {
		return val
	}
	return defaultVal
}
<commit_msg>test: h2spec should not print outside of a It/Describe<commit_after>package router

import (
	"fmt"
	"io/ioutil"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"

	routev1 "github.com/openshift/api/route/v1"
	routeclientset "github.com/openshift/client-go/route/clientset/versioned"
	"github.com/openshift/origin/test/extended/router/h2spec"
	exutil "github.com/openshift/origin/test/extended/util"
	"github.com/openshift/origin/test/extended/util/url"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	e2e "k8s.io/kubernetes/test/e2e/framework"
)

const h2specDialTimeoutInSeconds = 15

type h2specFailingTest struct {
	TestCase   *h2spec.JUnitTestCase
	TestNumber int
}

type h2specRouteTypeTest struct {
	routeType     routev1.TLSTerminationType
	hostname      string
	knownFailures map[string]bool
}

var _ = g.Describe("[sig-network-edge][Conformance][Area:Networking][Feature:Router]", func() {
	defer g.GinkgoRecover()

	var (
		configPath = exutil.FixturePath("testdata", "router", "router-h2spec.yaml")
		oc         = exutil.NewCLI("router-h2spec")
	)

	// this hook must be registered before the framework namespace teardown
	// hook
	g.AfterEach(func() {
		if g.CurrentGinkgoTestDescription().Failed {
			client := routeclientset.NewForConfigOrDie(oc.AdminConfig()).RouteV1().Routes(oc.KubeFramework().Namespace.Name)
			if routes, _ := client.List(metav1.ListOptions{}); routes != nil {
				outputIngress(routes.Items...)
			}
			exutil.DumpPodLogsStartingWith("h2spec", oc)
		}
	})

	g.Describe("The HAProxy router", func() {
		g.It("should pass the h2spec conformance tests", func() {
			g.By(fmt.Sprintf("creating routes from a config file %q", configPath))
			routerImage, err := exutil.FindRouterImage(oc)
			o.Expect(err).NotTo(o.HaveOccurred())

			err = oc.Run("new-app").Args("-f", configPath, "-p", "HAPROXY_IMAGE="+routerImage).Execute()
			o.Expect(err).NotTo(o.HaveOccurred())

			e2e.ExpectNoError(oc.KubeFramework().WaitForPodRunning("h2spec-haproxy"))

			routeTypeTests := []h2specRouteTypeTest{{
				routeType: routev1.TLSTerminationEdge,
				knownFailures: map[string]bool{
					"http2/4.2.3": true,
				},
			}, {
				routeType: routev1.TLSTerminationPassthrough,
				knownFailures: map[string]bool{
					"http2/4.2.3": true,
				},
			}, {
				routeType: routev1.TLSTerminationReencrypt,
				knownFailures: map[string]bool{
					"http2/4.2.3": true,
				},
			}}

			g.By("verifying accessing the host returns a 200 status code")
			for i := 0; i < len(routeTypeTests); i++ {
				urlTester := url.NewTester(oc.AdminKubeClient(), oc.KubeFramework().Namespace.Name).WithErrorPassthrough(true)
				defer urlTester.Close()
				hostname := getHostnameForRoute(oc, fmt.Sprintf("h2spec-haproxy-%s", routeTypeTests[i].routeType))
				urlTester.Within(30*time.Second, url.Expect("GET", "https://"+hostname).Through(hostname).SkipTLSVerification().HasStatusCode(200))
				routeTypeTests[i].hostname = hostname // now valid for the remaining tests
			}

			// ROUTER_H2SPEC_SAMPLE when set runs the
			// conformance tests for N iterations to
			// identify flaking tests.
			//
			// This should be enabled in development every
			// time we consume any new version of haproxy
			// be that a major, minor or a micro update to
			// continuously validate the set of test case
			// IDs that fail.
			if iterations := lookupEnv("ROUTER_H2SPEC_SAMPLE", ""); iterations != "" {
				n, err := strconv.Atoi(iterations)
				o.Expect(err).NotTo(o.HaveOccurred())
				runConformanceTestsAndLogAggregateFailures(oc, routeTypeTests, n)
				return
			}

			for _, t := range routeTypeTests {
				g.By(fmt.Sprintf("[%s] Running h2spec conformance tests against %q", t.routeType, t.hostname))

				testSuites := runConformanceTests(oc, t)
				o.Expect(testSuites).ShouldNot(o.BeEmpty())

				failures := failingTests(testSuites)
				failureCount := len(failures)

				g.By("Analyzing results")
				for _, f := range failures {
					if _, exists := t.knownFailures[f.ID()]; exists {
						failureCount -= 1
						e2e.Logf("[%s] TestCase ID: %q is a known failure; ignoring", t.routeType, f.ID())
					} else {
						e2e.Logf("[%s] TestCase ID: %q (%q) ****FAILED****", t.routeType, f.ID(), f.TestCase.ClassName)
					}
				}
				o.Expect(failureCount).Should(o.BeZero(), "expected zero failures")
			}
		})
	})
})

func failingTests(testSuites []*h2spec.JUnitTestSuite) []h2specFailingTest {
	var failures []h2specFailingTest

	for _, ts := range testSuites {
		for i := 0; i < ts.Tests; i++ {
			if ts.TestCases[i].Error != nil {
				failures = append(failures, h2specFailingTest{
					TestNumber: i + 1,
					TestCase:   ts.TestCases[i],
				})
			}
		}
	}

	return failures
}

func runConformanceTests(oc *exutil.CLI, t h2specRouteTypeTest) []*h2spec.JUnitTestSuite {
	podName := "h2spec"
	e2e.ExpectNoError(oc.KubeFramework().WaitForPodRunning(podName))

	var results []*h2spec.JUnitTestSuite

	o.Expect(wait.PollImmediate(time.Second, 5*time.Minute, func() (bool, error) {
		g.By("Running the h2spec CLI test")

		ns := oc.KubeFramework().Namespace.Name
		outputFile, err := ioutil.TempFile("", "runConformanceTests")
		if err != nil {
			e2e.Logf("[%s] error: failed to generate tmp file: %v; retrying...", t.routeType, err)
			return false, nil
		}
		defer os.Remove(outputFile.Name())

		output, _ := e2e.RunHostCmd(ns, podName, h2specCommand(h2specDialTimeoutInSeconds, t.hostname, outputFile.Name()))
		// h2spec will exit with non-zero if _any_ test in the
		// suite fails, or if there is a dial timeout, so we
		// ignore the error. We can exit from this loop if we
		// can fetch the results, if we can decode the results
		// and we have > 0 test suites from the decoded
		// results.

		g.By(fmt.Sprintf("[%s] Copying results from %s:%q", t.routeType, podName, outputFile.Name()))
		data, err := e2e.RunHostCmd(ns, podName, fmt.Sprintf("cat %q", outputFile.Name()))
		if err != nil {
			e2e.Logf("[%s] error: failed to copy results: %v; retrying...", t.routeType, err)
			return false, nil
		}
		if data == "" {
			e2e.Logf("[%s] error: zero length results file; retrying...", t.routeType)
			return false, nil
		}

		g.By(fmt.Sprintf("[%s] Decoding results", t.routeType))
		testSuites, err := h2spec.DecodeJUnitReport(strings.NewReader(data))
		if err != nil {
			e2e.Logf("[%s] error: decoding results: %v; retrying...", t.routeType, err)
			return false, nil
		}
		if len(testSuites) == 0 {
			e2e.Logf("[%s] error: no test results found; retrying...", t.routeType)
			return false, nil
		}

		// Log what we consider a successful run
		e2e.Logf("[%s] h2spec results\n%s", t.routeType, output)
		results = testSuites
		return true, nil
	})).NotTo(o.HaveOccurred())

	return results
}

func runConformanceTestsAndLogAggregateFailures(oc *exutil.CLI, tests []h2specRouteTypeTest, iterations int) {
	sortKeys := func(m map[string]int) []string {
		var index []string
		for k := range m {
			index = append(index, k)
		}
		sort.Strings(index)
		return index
	}

	printFailures := func(t h2specRouteTypeTest, prefix string, m map[string]int) {
		for _, id := range sortKeys(m) {
			e2e.Logf("[%s] %sTestCase ID: %q, cumulative failures: %v", t.routeType, prefix, id, m[id])
		}
	}

	failuresByTestCaseID := map[string]int{}

	for _, t := range tests {
		for i := 1; i <= iterations; i++ {
			failures := failingTests(runConformanceTests(oc, t))
			e2e.Logf("[%s] Iteration %v/%v: had %v failures", t.routeType, i, iterations, len(failures))

			// Aggregate any new failures
			for _, f := range failures {
				failuresByTestCaseID[f.ID()]++
			}

			// Dump the current state at every iteration should
			// you wish to interrupt/abort the running test.
			printFailures(t, "\t", failuresByTestCaseID)
		}
	}

	for _, t := range tests {
		e2e.Logf("[%s] Sampling completed: %v test cases failed", t.routeType, len(failuresByTestCaseID))
		printFailures(t, "\t", failuresByTestCaseID)
	}
}

func getHostnameForRoute(oc *exutil.CLI, routeName string) string {
	var hostname string
	ns := oc.KubeFramework().Namespace.Name
	err := wait.Poll(time.Second, changeTimeoutSeconds*time.Second, func() (bool, error) {
		route, err := oc.RouteClient().RouteV1().Routes(ns).Get(routeName, metav1.GetOptions{})
		if err != nil {
			e2e.Logf("Error getting hostname for route %q: %v", routeName, err)
			return false, err
		}
		if len(route.Status.Ingress) == 0 || len(route.Status.Ingress[0].Host) == 0 {
			return false, nil
		}
		hostname = route.Status.Ingress[0].Host
		return true, nil
	})
	o.Expect(err).NotTo(o.HaveOccurred())
	return hostname
}

func h2specCommand(timeout int, hostname, results string) string {
	return fmt.Sprintf("h2spec --timeout=%v --tls --insecure --strict --host=%q --junit-report=%q", timeout, hostname, results)
}

func (f h2specFailingTest) ID() string {
	return fmt.Sprintf("%s.%d", f.TestCase.Package, f.TestNumber)
}

func lookupEnv(key, defaultVal string) string {
	if val, ok := os.LookupEnv(key); ok {
		return val
	}
	return defaultVal
}
<|endoftext|>


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

package http

import (
	"encoding/json"
	"fmt"
	"reflect"
	"testing"
	"time"
)

var writeSetCookiesTests = []struct {
	Cookie *Cookie
	Raw    string
}{
	{
		&Cookie{Name: "cookie-1", Value: "v$1"},
		"cookie-1=v$1",
	},
	{
		&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
		"cookie-2=two; Max-Age=3600",
	},
	{
		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
		"cookie-3=three; Domain=.example.com",
	},
	{
		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
		"cookie-4=four; Path=/restricted/",
	},
}

func TestWriteSetCookies(t *testing.T) {
	for i, tt := range writeSetCookiesTests {
		if g, e := tt.Cookie.String(), tt.Raw; g != e {
			t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, e, g)
			continue
		}
	}
}

type headerOnlyResponseWriter Header

func (ho headerOnlyResponseWriter) Header() Header {
	return Header(ho)
}

func (ho headerOnlyResponseWriter) Write([]byte) (int, error) {
	panic("NOIMPL")
}

func (ho headerOnlyResponseWriter) WriteHeader(int) {
	panic("NOIMPL")
}

func TestSetCookie(t *testing.T) {
	m := make(Header)
	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-1", Value: "one", Path: "/restricted/"})
	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600})
	if l := len(m["Set-Cookie"]); l != 2 {
		t.Fatalf("expected %d cookies, got %d", 2, l)
	}
	if g, e := m["Set-Cookie"][0], "cookie-1=one; Path=/restricted/"; g != e {
		t.Errorf("cookie #1: want %q, got %q", e, g)
	}
	if g, e := m["Set-Cookie"][1], "cookie-2=two; Max-Age=3600"; g != e {
		t.Errorf("cookie #2: want %q, got %q", e, g)
	}
}

var addCookieTests = []struct {
	Cookies []*Cookie
	Raw     string
}{
	{
		[]*Cookie{},
		"",
	},
	{
		[]*Cookie{{Name: "cookie-1", Value: "v$1"}},
		"cookie-1=v$1",
	},
	{
		[]*Cookie{
			{Name: "cookie-1", Value: "v$1"},
			{Name: "cookie-2", Value: "v$2"},
			{Name: "cookie-3", Value: "v$3"},
		},
		"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
	},
}

func TestAddCookie(t *testing.T) {
	for i, tt := range addCookieTests {
		req, _ := NewRequest("GET", "http://example.com/", nil)
		for _, c := range tt.Cookies {
			req.AddCookie(c)
		}
		if g := req.Header.Get("Cookie"); g != tt.Raw {
			t.Errorf("Test %d:\nwant: %s\n got: %s\n", i, tt.Raw, g)
			continue
		}
	}
}

var readSetCookiesTests = []struct {
	Header  Header
	Cookies []*Cookie
}{
	{
		Header{"Set-Cookie": {"Cookie-1=v$1"}},
		[]*Cookie{{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
	},
	{
		Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
		[]*Cookie{{
			Name:       "NID",
			Value:      "99=YsDT5i3E-CXax-",
			Path:       "/",
			Domain:     ".google.ch",
			HttpOnly:   true,
			Expires:    time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
			RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
			Raw:        "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
		}},
	},
}

func toJSON(v interface{}) string {
	b, err := json.Marshal(v)
	if err != nil {
		return fmt.Sprintf("%#v", v)
	}
	return string(b)
}

func TestReadSetCookies(t *testing.T) {
	for i, tt := range readSetCookiesTests {
		for n := 0; n < 2; n++ { // to verify readSetCookies doesn't mutate its input
			c := readSetCookies(tt.Header)
			if !reflect.DeepEqual(c, tt.Cookies) {
				t.Errorf("#%d readSetCookies: have\n%s\nwant\n%s\n", i, toJSON(c), toJSON(tt.Cookies))
				continue
			}
		}
	}
}

var readCookiesTests = []struct {
	Header  Header
	Filter  string
	Cookies []*Cookie
}{
	{
		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
		"",
		[]*Cookie{
			{Name: "Cookie-1", Value: "v$1"},
			{Name: "c2", Value: "v2"},
		},
	},
	{
		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
		"c2",
		[]*Cookie{
			{Name: "c2", Value: "v2"},
		},
	},
	{
		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
		"",
		[]*Cookie{
			{Name: "Cookie-1", Value: "v$1"},
			{Name: "c2", Value: "v2"},
		},
	},
	{
		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
		"c2",
		[]*Cookie{
			{Name: "c2", Value: "v2"},
		},
	},
}

func TestReadCookies(t *testing.T) {
	for i, tt := range readCookiesTests {
		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input
			c := readCookies(tt.Header, tt.Filter)
			if !reflect.DeepEqual(c, tt.Cookies) {
				t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
				continue
			}
		}
	}
}
<commit_msg>net/http: some more cookie tests<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http

import (
	"encoding/json"
	"fmt"
	"reflect"
	"testing"
	"time"
)

var writeSetCookiesTests = []struct {
	Cookie *Cookie
	Raw    string
}{
	{
		&Cookie{Name: "cookie-1", Value: "v$1"},
		"cookie-1=v$1",
	},
	{
		&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
		"cookie-2=two; Max-Age=3600",
	},
	{
		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
		"cookie-3=three; Domain=.example.com",
	},
	{
		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
		"cookie-4=four; Path=/restricted/",
	},
}

func TestWriteSetCookies(t *testing.T) {
	for i, tt := range writeSetCookiesTests {
		if g, e := tt.Cookie.String(), tt.Raw; g != e {
			t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, e, g)
			continue
		}
	}
}

type headerOnlyResponseWriter Header

func (ho headerOnlyResponseWriter) Header() Header {
	return Header(ho)
}

func (ho headerOnlyResponseWriter) Write([]byte) (int, error) {
	panic("NOIMPL")
}

func (ho headerOnlyResponseWriter) WriteHeader(int) {
	panic("NOIMPL")
}

func TestSetCookie(t *testing.T) {
	m := make(Header)
	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-1", Value: "one", Path: "/restricted/"})
	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600})
	if l := len(m["Set-Cookie"]); l != 2 {
		t.Fatalf("expected %d cookies, got %d", 2, l)
	}
	if g, e := m["Set-Cookie"][0], "cookie-1=one; Path=/restricted/"; g != e {
		t.Errorf("cookie #1: want %q, got %q", e, g)
	}
	if g, e := m["Set-Cookie"][1], "cookie-2=two; Max-Age=3600"; g != e {
		t.Errorf("cookie #2: want %q, got %q", e, g)
	}
}

var addCookieTests = []struct {
	Cookies []*Cookie
	Raw     string
}{
	{
		[]*Cookie{},
		"",
	},
	{
		[]*Cookie{{Name: "cookie-1", Value: "v$1"}},
		"cookie-1=v$1",
	},
	{
		[]*Cookie{
			{Name: "cookie-1", Value: "v$1"},
			{Name: "cookie-2", Value: "v$2"},
			{Name: "cookie-3", Value: "v$3"},
		},
		"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
	},
}

func TestAddCookie(t *testing.T) {
	for i, tt := range addCookieTests {
		req, _ := NewRequest("GET", "http://example.com/", nil)
		for _, c := range tt.Cookies {
			req.AddCookie(c)
		}
		if g := req.Header.Get("Cookie"); g != tt.Raw {
			t.Errorf("Test %d:\nwant: %s\n got: %s\n", i, tt.Raw, g)
			continue
		}
	}
}

var readSetCookiesTests = []struct {
	Header  Header
	Cookies []*Cookie
}{
	{
		Header{"Set-Cookie": {"Cookie-1=v$1"}},
		[]*Cookie{{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
	},
	{
		Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
		[]*Cookie{{
			Name:       "NID",
			Value:      "99=YsDT5i3E-CXax-",
			Path:       "/",
			Domain:     ".google.ch",
			HttpOnly:   true,
			Expires:    time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
			RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
			Raw:        "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
		}},
	},
	{
		Header{"Set-Cookie": {".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}},
		[]*Cookie{{
			Name:       ".ASPXAUTH",
			Value:      "7E3AA",
			Path:       "/",
			Expires:    time.Date(2012, 3, 7, 14, 25, 6, 0, time.UTC),
			RawExpires: "Wed, 07-Mar-2012 14:25:06 GMT",
			HttpOnly:   true,
			Raw:        ".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly",
		}},
	},
	{
		Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly"}},
		[]*Cookie{{
			Name:     "ASP.NET_SessionId",
			Value:    "foo",
			Path:     "/",
			HttpOnly: true,
			Raw:      "ASP.NET_SessionId=foo; path=/; HttpOnly",
		}},
	},

	// TODO(bradfitz): users have reported seeing this in the
	// wild, but do browsers handle it? RFC 6265 just says "don't
	// do that" (section 3) and then never mentions header folding
	// again.
	// Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly, .ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}},
}

func toJSON(v interface{}) string {
	b, err := json.Marshal(v)
	if err != nil {
		return fmt.Sprintf("%#v", v)
	}
	return string(b)
}

func TestReadSetCookies(t *testing.T) {
	for i, tt := range readSetCookiesTests {
		for n := 0; n < 2; n++ { // to verify readSetCookies doesn't mutate its input
			c := readSetCookies(tt.Header)
			if !reflect.DeepEqual(c, tt.Cookies) {
				t.Errorf("#%d readSetCookies: have\n%s\nwant\n%s\n", i, toJSON(c), toJSON(tt.Cookies))
				continue
			}
		}
	}
}

var readCookiesTests = []struct {
	Header  Header
	Filter  string
	Cookies []*Cookie
}{
	{
		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
		"",
		[]*Cookie{
			{Name: "Cookie-1", Value: "v$1"},
			{Name: "c2", Value: "v2"},
		},
	},
	{
		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
		"c2",
		[]*Cookie{
			{Name: "c2", Value: "v2"},
		},
	},
	{
		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
		"",
		[]*Cookie{
			{Name: "Cookie-1", Value: "v$1"},
			{Name: "c2", Value: "v2"},
		},
	},
	{
		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
		"c2",
		[]*Cookie{
			{Name: "c2", Value: "v2"},
		},
	},
}

func TestReadCookies(t *testing.T) {
	for i, tt := range readCookiesTests {
		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input
			c := readCookies(tt.Header, tt.Filter)
			if !reflect.DeepEqual(c, tt.Cookies) {
				t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
				continue
			}
		}
	}
}
<|endoftext|>


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

package http_test

import (
	"net/http"
	"runtime"
	"sort"
	"strings"
	"testing"
	"time"
)

func interestingGoroutines() (gs []string) {
	buf := make([]byte, 2<<20)
	buf = buf[:runtime.Stack(buf, true)]
	for _, g := range strings.Split(string(buf), "\n\n") {
		sl := strings.SplitN(g, "\n", 2)
		if len(sl) != 2 {
			continue
		}
		stack := strings.TrimSpace(sl[1])
		if stack == "" ||
			strings.Contains(stack, "created by net.newPollServer") ||
			strings.Contains(stack, "created by testing.RunTests") ||
			strings.Contains(stack, "closeWriteAndWait") ||
			strings.Contains(stack, "testing.Main(") {
			continue
		}
		gs = append(gs, stack)
	}
	sort.Strings(gs)
	return
}

// Verify the other tests didn't leave any goroutines running.
// This is in a file named z_last_test.go so it sorts at the end.
func TestGoroutinesRunning(t *testing.T) {
	gs := interestingGoroutines()

	n := 0
	stackCount := make(map[string]int)
	for _, g := range gs {
		stackCount[g]++
		n++
	}

	t.Logf("num goroutines = %d", n)
	if n > 0 {
		t.Error("Too many goroutines.")
		for stack, count := range stackCount {
			t.Logf("%d instances of:\n%s", count, stack)
		}
	}
}

func afterTest(t *testing.T) {
	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
	if testing.Short() {
		return
	}
	buf := make([]byte, 1<<20)
	var stacks string
	var bad string
	badSubstring := map[string]string{
		").readLoop(":                                  "a Transport",
		").writeLoop(":                                 "a Transport",
		"created by net/http/httptest.(*Server).Start": "an httptest.Server",
		"timeoutHandler":                               "a TimeoutHandler",
		"net.(*netFD).connect(":                        "a timing out dial",
	}
	for i := 0; i < 4; i++ {
		bad = ""
		stacks = string(buf[:runtime.Stack(buf, true)])
		for substr, what := range badSubstring {
			if strings.Contains(stacks, substr) {
				bad = what
			}
		}
		if bad == "" {
			return
		}
		// Bad stuff found, but goroutines might just still be
		// shutting down, so give it some time.
		time.Sleep(250 * time.Millisecond)
	}
	gs := interestingGoroutines()
	t.Errorf("Test appears to have leaked %s:\n%s", bad, strings.Join(gs, "\n\n"))
}
<commit_msg>net/http: fix test breakage on Windows<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http_test

import (
	"net/http"
	"runtime"
	"sort"
	"strings"
	"testing"
	"time"
)

func interestingGoroutines() (gs []string) {
	buf := make([]byte, 2<<20)
	buf = buf[:runtime.Stack(buf, true)]
	for _, g := range strings.Split(string(buf), "\n\n") {
		sl := strings.SplitN(g, "\n", 2)
		if len(sl) != 2 {
			continue
		}
		stack := strings.TrimSpace(sl[1])
		if stack == "" ||
			strings.Contains(stack, "created by net.newPollServer") ||
			strings.Contains(stack, "created by net.startServer") ||
			strings.Contains(stack, "created by testing.RunTests") ||
			strings.Contains(stack, "closeWriteAndWait") ||
			strings.Contains(stack, "testing.Main(") {
			continue
		}
		gs = append(gs, stack)
	}
	sort.Strings(gs)
	return
}

// Verify the other tests didn't leave any goroutines running.
// This is in a file named z_last_test.go so it sorts at the end.
func TestGoroutinesRunning(t *testing.T) {
	gs := interestingGoroutines()

	n := 0
	stackCount := make(map[string]int)
	for _, g := range gs {
		stackCount[g]++
		n++
	}

	t.Logf("num goroutines = %d", n)
	if n > 0 {
		t.Error("Too many goroutines.")
		for stack, count := range stackCount {
			t.Logf("%d instances of:\n%s", count, stack)
		}
	}
}

func afterTest(t *testing.T) {
	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
	if testing.Short() {
		return
	}
	buf := make([]byte, 1<<20)
	var stacks string
	var bad string
	badSubstring := map[string]string{
		").readLoop(":                                  "a Transport",
		").writeLoop(":                                 "a Transport",
		"created by net/http/httptest.(*Server).Start": "an httptest.Server",
		"timeoutHandler":                               "a TimeoutHandler",
		"net.(*netFD).connect(":                        "a timing out dial",
	}
	for i := 0; i < 4; i++ {
		bad = ""
		stacks = string(buf[:runtime.Stack(buf, true)])
		for substr, what := range badSubstring {
			if strings.Contains(stacks, substr) {
				bad = what
			}
		}
		if bad == "" {
			return
		}
		// Bad stuff found, but goroutines might just still be
		// shutting down, so give it some time.
		time.Sleep(250 * time.Millisecond)
	}
	gs := interestingGoroutines()
	t.Errorf("Test appears to have leaked %s:\n%s", bad, strings.Join(gs, "\n\n"))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdPushAura = &Command{
	Usage: "pushAura",
	Short: "force pushAura -resourcepath=<filepath>",
	Long: `
	force pushAura -resourcepath <fullFilePath>

	force pushAura -f=<fullFilePath>

	`,
}

func init() {
	cmdPushAura.Run = runPushAura
	cmdPushAura.Flag.Var(&resourcepath, "f", "fully qualified file name for entity")
	//	cmdPushAura.Flag.StringVar(&resourcepath, "f", "", "fully qualified file name for entity")
	cmdPushAura.Flag.StringVar(&metadataType, "t", "", "Type of entity or bundle to create")
	cmdPushAura.Flag.StringVar(&metadataType, "type", "", "Type of entity or bundle to create")
}

var (
//resourcepath = cmdPushAura.Flag.String("filepath", "", "fully qualified file name for entity")
//	isBundle   = cmdPushAura.Flag.Bool("isBundle", false, "Creating a bundle or not")
//createType = cmdPushAura.Flag.String("auraType", "", "Type of entity or bundle to create")
)

func runPushAura(cmd *Command, args []string) {
	absPath, _ := filepath.Abs(resourcepath[0])

	if _, err := os.Stat(absPath); os.IsNotExist(err) {
		fmt.Println(err.Error())
		ErrorAndExit("File does not exist\n" + absPath)
	}

	// Verify that the file is in an aura bundles folder
	if !InAuraBundlesFolder(absPath) {
		ErrorAndExit("File is not in an aura bundle folder (aura)")
	}

	// See if this is a directory
	info, _ := os.Stat(absPath)
	if info.IsDir() {
		// If this is a path, then it is expected be a direct child of "metatdata/aura".
		// If so, then we are going to push all the definitions in the bundle one at a time.
		filepath.Walk(absPath, func(path string, inf os.FileInfo, err error) error {
			info, err = os.Stat(filepath.Join(absPath, inf.Name()))
			if err != nil {
				fmt.Println(err.Error())
			} else {
				if info.IsDir() || inf.Name() == ".manifest" {
					fmt.Println("\nSkip")
				} else {
					pushAuraComponent(filepath.Join(absPath, inf.Name()))
				}
			}
			return nil
		})
	} else {
		pushAuraComponent(absPath)
	}
	return
}

func pushAuraComponent(fname string) {
	force, _ := ActiveForce()
	// Check for manifest file
	if _, err := os.Stat(filepath.Join(filepath.Dir(fname), ".manifest")); os.IsNotExist(err) {
		// No manifest, but is in aurabundle folder, assume creating a new bundle with this file
		// as the first artifact.
		createNewAuraBundleAndDefinition(*force, fname)
	} else {
		// Got the manifest, let's update the artifact
		fmt.Println("Updating")
		updateAuraDefinition(*force, fname)
		return
	}
}

func isValidAuraExtension(fname string) bool {
	var ext = strings.Trim(strings.ToLower(filepath.Ext(fname)), " ")
	if ext == ".app" || ext == ".cmp" || ext == ".evt" {
		return true
	} else {
		ErrorAndExit("You need to create an application (.app) or component (.cmp) or and event (.evt) as the first item in your bundle.")
	}
	return false
}

func createNewAuraBundleAndDefinition(force Force, fname string) {
	// 	Creating a new bundle. We need
	// 		the name of the bundle (parent folder of file)
	//		the type of artifact (based on naming convention)
	// 		the contents of the file
	if isValidAuraExtension(fname) {
		// Need the parent folder name to name the bundle
		var bundleName = filepath.Base(filepath.Dir(fname))
		// Create the manifext
		var manifest BundleManifest
		manifest.Name = bundleName

		_, _ = getFormatByresourcepath(fname)
		targetDirectory = SetTargetDirectory(fname)

		// Create a bundle defintion
		bundle, err, emessages := force.CreateAuraBundle(bundleName)
		if err != nil {
			if emessages[0].ErrorCode == "DUPLICATE_VALUE" {
				// Should look up the bundle and get it's id then update it.
				FetchManifest(bundleName)
				updateAuraDefinition(force, fname)
				return
			}
			ErrorAndExit(err.Error())
		} else {
			manifest.Id = bundle.Id
			component, err, emessages := createBundleEntity(manifest, force, fname)
			if err != nil {
				ErrorAndExit(err.Error(), emessages[0].ErrorCode)
			}
			createManifest(manifest, component, fname)
		}
	}
}

func SetTargetDirectory(fname string) string {
	// Need to get the parent of metadata
	return strings.Split(fname, "/metadata/aura")[0]
}

func createBundleEntity(manifest BundleManifest, force Force, fname string) (component ForceCreateRecordResult, err error, emessages []ForceError) {
	// create the bundle entity
	format, deftype := getFormatByresourcepath(fname)
	mbody, _ := readFile(fname)
	component, err, emessages = force.CreateAuraComponent(map[string]string{"AuraDefinitionBundleId": manifest.Id, "DefType": deftype, "Format": format, "Source": mbody})
	return
}

func createManifest(manifest BundleManifest, component ForceCreateRecordResult, fname string) {
	cfile := ComponentFile{}
	cfile.FileName = fname
	cfile.ComponentId = component.Id

	manifest.Files = append(manifest.Files, cfile)
	bmBody, _ := json.Marshal(manifest)

	ioutil.WriteFile(filepath.Join(filepath.Dir(fname), ".manifest"), bmBody, 0644)
	return
}

func updateManifest(manifest BundleManifest, component ForceCreateRecordResult, fname string) {
	cfile := ComponentFile{}
	cfile.FileName = fname
	cfile.ComponentId = component.Id

	manifest.Files = append(manifest.Files, cfile)
	bmBody, _ := json.Marshal(manifest)

	ioutil.WriteFile(filepath.Join(filepath.Dir(fname), ".manifest"), bmBody, 0644)
	return
}

func GetManifest(fname string) (manifest BundleManifest, err error) {
	manifestname := filepath.Join(filepath.Dir(fname), ".manifest")

	if _, err = os.Stat(manifestname); os.IsNotExist(err) {
		return
	}

	mbody, _ := readFile(filepath.Join(filepath.Dir(fname), ".manifest"))
	json.Unmarshal([]byte(mbody), &manifest)
	return
}

func updateAuraDefinition(force Force, fname string) {

	//Get the manifest
	manifest, err := GetManifest(fname)

	for i := range manifest.Files {
		component := manifest.Files[i]
		if filepath.Base(component.FileName) == filepath.Base(fname) {
			//Here is where we make the call to send the update
			mbody, _ := readFile(fname)
			err := force.UpdateAuraComponent(map[string]string{"source": mbody}, component.ComponentId)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			fmt.Printf("Aura definition updated: %s\n", filepath.Base(fname))
			return
		}
	}
	component, err, emessages := createBundleEntity(manifest, force, fname)
	if err != nil {
		ErrorAndExit(err.Error(), emessages[0].ErrorCode)
	}
	updateManifest(manifest, component, fname)
	fmt.Println("New component in the bundle")
}

func getFormatByresourcepath(resourcepath string) (format string, defType string) {
	var fname = strings.ToLower(resourcepath)
	if strings.Contains(fname, "application.app") {
		format = "XML"
		defType = "APPLICATION"
	} else if strings.Contains(fname, "component.cmp") {
		format = "XML"
		defType = "COMPONENT"
	} else if strings.Contains(fname, "event.evt") {
		format = "XML"
		defType = "EVENT"
	} else if strings.Contains(fname, "controller.js") {
		format = "JS"
		defType = "CONTROLLER"
	} else if strings.Contains(fname, "model.js") {
		format = "JS"
		defType = "MODEL"
	} else if strings.Contains(fname, "helper.js") {
		format = "JS"
		defType = "HELPER"
	} else if strings.Contains(fname, "renderer.js") {
		format = "JS"
		defType = "RENDERER"
	} else if strings.Contains(fname, "style.css") {
		format = "CSS"
		defType = "STYLE"
	} else {
		if filepath.Ext(fname) == ".app" {
			format = "XML"
			defType = "APPLICATION"
		} else if filepath.Ext(fname) == ".cmp" {
			format = "XML"
			defType = "COMPONENT"
		} else if filepath.Ext(fname) == ".evt" {
			format = "XML"
			defType = "EVENT"
		} else if filepath.Ext(fname) == ".css" {
			format = "CSS"
			defType = "STYLE"
		} else if filepath.Ext(fname) == ".auradoc" {
			format = "XML"
			defType = "DOCUMENTATION"
		} else {
			ErrorAndExit("Could not determine aura definition type.", fname)
		}
	}
	return
}

func getDefinitionFormat(deftype string) (result string) {
	switch strings.ToUpper(deftype) {
	case "APPLICATION", "COMPONENT", "EVENT", "DOCUMENTATION":
		result = "XML"
	case "CONTROLLER", "MODEL", "HELPER", "RENDERER":
		result = "JS"
	case "STYLE":
		result = "CSS"
	}
	return
}

func InAuraBundlesFolder(fname string) bool {
	info, _ := os.Stat(fname)
	if info.IsDir() {
		return strings.HasSuffix(filepath.Dir(fname), "metadata/aura")
	} else {
		return strings.HasSuffix(filepath.Dir(filepath.Dir(fname)), "metadata/aura")
	}
}

func readFile(resourcepath string) (body string, err error) {
	data, err := ioutil.ReadFile(resourcepath)
	if err != nil {
		return
	}
	body = string(data)
	return
}
<commit_msg>Use filepath.FromSlash to path string.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdPushAura = &Command{
	Usage: "pushAura",
	Short: "force pushAura -resourcepath=<filepath>",
	Long: `
	force pushAura -resourcepath <fullFilePath>

	force pushAura -f=<fullFilePath>

	`,
}

func init() {
	cmdPushAura.Run = runPushAura
	cmdPushAura.Flag.Var(&resourcepath, "f", "fully qualified file name for entity")
	//	cmdPushAura.Flag.StringVar(&resourcepath, "f", "", "fully qualified file name for entity")
	cmdPushAura.Flag.StringVar(&metadataType, "t", "", "Type of entity or bundle to create")
	cmdPushAura.Flag.StringVar(&metadataType, "type", "", "Type of entity or bundle to create")
}

var (
//resourcepath = cmdPushAura.Flag.String("filepath", "", "fully qualified file name for entity")
//	isBundle   = cmdPushAura.Flag.Bool("isBundle", false, "Creating a bundle or not")
//createType = cmdPushAura.Flag.String("auraType", "", "Type of entity or bundle to create")
)

func runPushAura(cmd *Command, args []string) {
	absPath, _ := filepath.Abs(resourcepath[0])

	if _, err := os.Stat(absPath); os.IsNotExist(err) {
		fmt.Println(err.Error())
		ErrorAndExit("File does not exist\n" + absPath)
	}

	// Verify that the file is in an aura bundles folder
	if !InAuraBundlesFolder(absPath) {
		ErrorAndExit("File is not in an aura bundle folder (aura)")
	}

	// See if this is a directory
	info, _ := os.Stat(absPath)
	if info.IsDir() {
		// If this is a path, then it is expected be a direct child of "metatdata/aura".
		// If so, then we are going to push all the definitions in the bundle one at a time.
		filepath.Walk(absPath, func(path string, inf os.FileInfo, err error) error {
			info, err = os.Stat(filepath.Join(absPath, inf.Name()))
			if err != nil {
				fmt.Println(err.Error())
			} else {
				if info.IsDir() || inf.Name() == ".manifest" {
					fmt.Println("\nSkip")
				} else {
					pushAuraComponent(filepath.Join(absPath, inf.Name()))
				}
			}
			return nil
		})
	} else {
		pushAuraComponent(absPath)
	}
	return
}

func pushAuraComponent(fname string) {
	force, _ := ActiveForce()
	// Check for manifest file
	if _, err := os.Stat(filepath.Join(filepath.Dir(fname), ".manifest")); os.IsNotExist(err) {
		// No manifest, but is in aurabundle folder, assume creating a new bundle with this file
		// as the first artifact.
		createNewAuraBundleAndDefinition(*force, fname)
	} else {
		// Got the manifest, let's update the artifact
		fmt.Println("Updating")
		updateAuraDefinition(*force, fname)
		return
	}
}

func isValidAuraExtension(fname string) bool {
	var ext = strings.Trim(strings.ToLower(filepath.Ext(fname)), " ")
	if ext == ".app" || ext == ".cmp" || ext == ".evt" {
		return true
	} else {
		ErrorAndExit("You need to create an application (.app) or component (.cmp) or and event (.evt) as the first item in your bundle.")
	}
	return false
}

func createNewAuraBundleAndDefinition(force Force, fname string) {
	// 	Creating a new bundle. We need
	// 		the name of the bundle (parent folder of file)
	//		the type of artifact (based on naming convention)
	// 		the contents of the file
	if isValidAuraExtension(fname) {
		// Need the parent folder name to name the bundle
		var bundleName = filepath.Base(filepath.Dir(fname))
		// Create the manifext
		var manifest BundleManifest
		manifest.Name = bundleName

		_, _ = getFormatByresourcepath(fname)
		targetDirectory = SetTargetDirectory(fname)

		// Create a bundle defintion
		bundle, err, emessages := force.CreateAuraBundle(bundleName)
		if err != nil {
			if emessages[0].ErrorCode == "DUPLICATE_VALUE" {
				// Should look up the bundle and get it's id then update it.
				FetchManifest(bundleName)
				updateAuraDefinition(force, fname)
				return
			}
			ErrorAndExit(err.Error())
		} else {
			manifest.Id = bundle.Id
			component, err, emessages := createBundleEntity(manifest, force, fname)
			if err != nil {
				ErrorAndExit(err.Error(), emessages[0].ErrorCode)
			}
			createManifest(manifest, component, fname)
		}
	}
}

func SetTargetDirectory(fname string) string {
	// Need to get the parent of metadata
	return strings.Split(fname, "/metadata/aura")[0]
}

func createBundleEntity(manifest BundleManifest, force Force, fname string) (component ForceCreateRecordResult, err error, emessages []ForceError) {
	// create the bundle entity
	format, deftype := getFormatByresourcepath(fname)
	mbody, _ := readFile(fname)
	component, err, emessages = force.CreateAuraComponent(map[string]string{"AuraDefinitionBundleId": manifest.Id, "DefType": deftype, "Format": format, "Source": mbody})
	return
}

func createManifest(manifest BundleManifest, component ForceCreateRecordResult, fname string) {
	cfile := ComponentFile{}
	cfile.FileName = fname
	cfile.ComponentId = component.Id

	manifest.Files = append(manifest.Files, cfile)
	bmBody, _ := json.Marshal(manifest)

	ioutil.WriteFile(filepath.Join(filepath.Dir(fname), ".manifest"), bmBody, 0644)
	return
}

func updateManifest(manifest BundleManifest, component ForceCreateRecordResult, fname string) {
	cfile := ComponentFile{}
	cfile.FileName = fname
	cfile.ComponentId = component.Id

	manifest.Files = append(manifest.Files, cfile)
	bmBody, _ := json.Marshal(manifest)

	ioutil.WriteFile(filepath.Join(filepath.Dir(fname), ".manifest"), bmBody, 0644)
	return
}

func GetManifest(fname string) (manifest BundleManifest, err error) {
	manifestname := filepath.Join(filepath.Dir(fname), ".manifest")

	if _, err = os.Stat(manifestname); os.IsNotExist(err) {
		return
	}

	mbody, _ := readFile(filepath.Join(filepath.Dir(fname), ".manifest"))
	json.Unmarshal([]byte(mbody), &manifest)
	return
}

func updateAuraDefinition(force Force, fname string) {

	//Get the manifest
	manifest, err := GetManifest(fname)

	for i := range manifest.Files {
		component := manifest.Files[i]
		if filepath.Base(component.FileName) == filepath.Base(fname) {
			//Here is where we make the call to send the update
			mbody, _ := readFile(fname)
			err := force.UpdateAuraComponent(map[string]string{"source": mbody}, component.ComponentId)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			fmt.Printf("Aura definition updated: %s\n", filepath.Base(fname))
			return
		}
	}
	component, err, emessages := createBundleEntity(manifest, force, fname)
	if err != nil {
		ErrorAndExit(err.Error(), emessages[0].ErrorCode)
	}
	updateManifest(manifest, component, fname)
	fmt.Println("New component in the bundle")
}

func getFormatByresourcepath(resourcepath string) (format string, defType string) {
	var fname = strings.ToLower(resourcepath)
	if strings.Contains(fname, "application.app") {
		format = "XML"
		defType = "APPLICATION"
	} else if strings.Contains(fname, "component.cmp") {
		format = "XML"
		defType = "COMPONENT"
	} else if strings.Contains(fname, "event.evt") {
		format = "XML"
		defType = "EVENT"
	} else if strings.Contains(fname, "controller.js") {
		format = "JS"
		defType = "CONTROLLER"
	} else if strings.Contains(fname, "model.js") {
		format = "JS"
		defType = "MODEL"
	} else if strings.Contains(fname, "helper.js") {
		format = "JS"
		defType = "HELPER"
	} else if strings.Contains(fname, "renderer.js") {
		format = "JS"
		defType = "RENDERER"
	} else if strings.Contains(fname, "style.css") {
		format = "CSS"
		defType = "STYLE"
	} else {
		if filepath.Ext(fname) == ".app" {
			format = "XML"
			defType = "APPLICATION"
		} else if filepath.Ext(fname) == ".cmp" {
			format = "XML"
			defType = "COMPONENT"
		} else if filepath.Ext(fname) == ".evt" {
			format = "XML"
			defType = "EVENT"
		} else if filepath.Ext(fname) == ".css" {
			format = "CSS"
			defType = "STYLE"
		} else if filepath.Ext(fname) == ".auradoc" {
			format = "XML"
			defType = "DOCUMENTATION"
		} else {
			ErrorAndExit("Could not determine aura definition type.", fname)
		}
	}
	return
}

func getDefinitionFormat(deftype string) (result string) {
	switch strings.ToUpper(deftype) {
	case "APPLICATION", "COMPONENT", "EVENT", "DOCUMENTATION":
		result = "XML"
	case "CONTROLLER", "MODEL", "HELPER", "RENDERER":
		result = "JS"
	case "STYLE":
		result = "CSS"
	}
	return
}

func InAuraBundlesFolder(fname string) bool {
	info, _ := os.Stat(fname)
	if info.IsDir() {
		return strings.HasSuffix(filepath.Dir(fname), filepath.FromSlash("metadata/aura"))
	} else {
		return strings.HasSuffix(filepath.Dir(filepath.Dir(fname)), filepath.FromSlash("metadata/aura"))
	}
}

func readFile(resourcepath string) (body string, err error) {
	data, err := ioutil.ReadFile(resourcepath)
	if err != nil {
		return
	}
	body = string(data)
	return
}
<|endoftext|>


<commit_before>package mstats

import (
	"fmt"
	"runtime"
	"sync/atomic"
	"time"
)

// Var is an atomic variable satisfying expvar.Var
type Var struct {
	atomic.Value
}

func (a *Var) String() string {
	v := a.Load()
	if v == nil {
		return "0"
	}
	return fmt.Sprintf("%d", v.(uint64))
}

// PauseNS is the total number of nanoseconds the GC has paused the application
var PauseNS Var

// NumGC is the number of collections
var NumGC Var

// Alloc is the number of bytes allocated and not yet freed by the application
var Alloc Var

// Start polls runtime.ReadMemStats with interval d and updates the package level variables
func Start(d time.Duration) {
	for range time.Tick(d) {
		var m runtime.MemStats
		runtime.ReadMemStats(&m)
		PauseNS.Store(m.PauseTotalNs)
		Alloc.Store(m.Alloc)
		NumGC.Store(uint64(m.NumGC))
	}
}
<commit_msg>fmt -> strconv<commit_after>package mstats

import (
	"runtime"
	"strconv"
	"sync/atomic"
	"time"
)

// Var is an atomic variable satisfying expvar.Var
type Var struct {
	atomic.Value
}

func (a *Var) String() string {
	v := a.Load()
	if v == nil {
		return "0"
	}
	return strconv.FormatUint(v.(uint64), 10)
}

// PauseNS is the total number of nanoseconds the GC has paused the application
var PauseNS Var

// NumGC is the number of collections
var NumGC Var

// Alloc is the number of bytes allocated and not yet freed by the application
var Alloc Var

// Start polls runtime.ReadMemStats with interval d and updates the package level variables
func Start(d time.Duration) {
	for range time.Tick(d) {
		var m runtime.MemStats
		runtime.ReadMemStats(&m)
		PauseNS.Store(m.PauseTotalNs)
		Alloc.Store(m.Alloc)
		NumGC.Store(uint64(m.NumGC))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"time"
)

func Who(char string, lvl int) {
	date := time.Now()
	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// check if character exists in DB
	stmt, err := db.Prepare("SELECT account_name, char_name FROM chars WHERE LOWER(char_name) = LOWER(?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var acc string
	var name string
	err = stmt.QueryRow(char).Scan(&acc, &name)
	if err != nil {
		// if char doesn't exist, 'who char'
		fmt.Printf("who %s\n", char)
		return
	} else {
		// if char does exist, tell the DB the time they were spotted and
		// update their level
		// todo: also check class change for necro->lich
		// todo: also check for account name change
		tx, err := db.Begin()
		if err != nil {
			log.Fatal(err)
		}
		stmt, err := tx.Prepare("UPDATE chars SET char_level = ?, last_seen = ? WHERE account_name = ? AND char_name = ?")
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		_, err = stmt.Exec(lvl, date, acc, name)
		if err != nil {
			log.Fatal(err)
		}
		tx.Commit()
	}
}

func WhoChar(char string, lvl int, class string, race string, acct string) {
        date := time.Now()
        db, err := sql.Open("sqlite3", "toril.db")
        if err != nil {
                log.Fatal(err)
        }
        defer db.Close()

        // check if character exists in DB
        stmt, err := db.Prepare("SELECT account_name, char_name FROM chars WHERE LOWER(char_name) = LOWER(?)")
        if err != nil {
                log.Fatal(err)
        }
        defer stmt.Close()
        var acc string
        var name string
        err = stmt.QueryRow(char).Scan(&acc, &name)
        if err != nil {
		// if no char, check if account exists in DB, create char
	}
}
<commit_msg>Finished rebuilding parseWho.py as who.go<commit_after>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"time"
)

func Who(char string, lvl int) {
	date := time.Now()
	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// check if character exists in DB
	stmt, err := db.Prepare("SELECT account_name, char_name FROM chars WHERE LOWER(char_name) = LOWER(?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var acc string
	var name string
	err = stmt.QueryRow(char).Scan(&acc, &name)
	if err != nil {
		// if char doesn't exist, 'who char'
		fmt.Printf("who %s\n", char)
		return
	} else {
		// if char does exist, tell the DB the time they were spotted and
		// update their level
		// todo: also check class change for necro->lich
		// todo: also check for account name change
		tx, err := db.Begin()
		if err != nil {
			log.Fatal(err)
		}
		stmt, err := tx.Prepare("UPDATE chars SET char_level = ?, last_seen = ? WHERE account_name = ? AND char_name = ?")
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		_, err = stmt.Exec(lvl, date, acc, name)
		if err != nil {
			log.Fatal(err)
		}
		tx.Commit()
	}
}

func WhoChar(char string, lvl int, class string, race string, acct string) {
	date := time.Now()
	db, err := sql.Open("sqlite3", "toril.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// check if character exists in DB
	stmt, err := db.Prepare("SELECT account_name, char_name FROM chars WHERE LOWER(char_name) = LOWER(?)")
	if err != nil {
		log.Fatal(err)
	}
	defer stmt.Close()
	var acc string
	var name string
	err = stmt.QueryRow(char).Scan(&acc, &name)
	if err != nil {
		// if no char, check if account exists in DB, create char
		stmt, err = db.Prepare("SELECT account_name FROM accounts WHERE LOWER(account_name) = LOWER(?)")
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		err = stmt.QueryRow(char).Scan(&acc)
		if err != nil { // if no acct, create acccount
			tx, err := db.Begin()
			if err != nil {
				log.Fatal(err)
			}

			stmt, err := tx.Prepare("INSERT INTO accounts (account_name) VALUES(?)")
			if err != nil {
				log.Fatal(err)
			}
			defer stmt.Close()

			_, err = stmt.Exec(acct)
			if err != nil {
				log.Fatal(err)
			}
			tx.Commit()
		}
		// create character
		tx, err := db.Begin()
		if err != nil {
			log.Fatal(err)
		}

		stmt, err := tx.Prepare("INSERT INTO chars VALUES(%s, %s, %s, %s, %s, %s, 't')")
		if err != nil {
			log.Fatal(err)
		}
		defer stmt.Close()

		_, err = stmt.Exec(acct, char, class, race, lvl, date)
		if err != nil {
			log.Fatal(err)
		}
		tx.Commit()
	}
}
<|endoftext|>


<commit_before>package neptulon

import (
	"crypto/tls"
	"crypto/x509"
	"sync"
	"testing"
	"time"

	"github.com/neptulon/ca"
	"github.com/neptulon/client"
	"github.com/neptulon/randstr"
)

// todo: if we are going to expose raw Listener, this should be in integration tests, otherwise Listener should be private
func TestListener(t *testing.T) {
	msg1 := "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
	msg2 := "In sit amet lectus felis, at pellentesque turpis."
	msg3 := "Nunc urna enim, cursus varius aliquet ac, imperdiet eget tellus."
	msg4 := randstr.Get(45000)   // 0.45 MB
	msg5 := randstr.Get(5000000) // 5.0 MB

	host := "127.0.0.1:3010"
	certChain, err := ca.GenCertChain("FooBar", "127.0.0.1", "127.0.0.1", time.Hour, 512)
	if err != nil {
		t.Fatal(err)
	}

	l, err := ListenTLS(certChain.ServerCert, certChain.ServerKey, certChain.IntCACert, host, false)
	if err != nil {
		t.Fatal(err)
	}

	var listenerWG sync.WaitGroup
	listenerWG.Add(1)
	go func() {
		defer listenerWG.Done()
		l.Accept(func(conn *client.Conn) {},
			func(conn *client.Conn, msg []byte) {
				m := string(msg)
				if m == "close" {
					conn.Close()
					return
				}

				connstate, _ := conn.ConnectionState()
				certs := connstate.PeerCertificates
				if len(certs) > 0 {
					t.Logf("Client connected with client certificate subject: %v\n", certs[0].Subject)
				}

				if m != msg1 && m != msg2 && m != msg3 && m != msg4 && m != msg5 {
					t.Fatal("Sent and incoming messages did not match! Sent message was message:", m)
				}
			}, func(conn *client.Conn) {})
	}()

	roots := x509.NewCertPool()
	ok := roots.AppendCertsFromPEM(certChain.IntCACert)
	if !ok {
		panic("failed to parse root certificate")
	}

	tlsConf := &tls.Config{RootCAs: roots}
	conn, err := tls.Dial("tcp", host, tlsConf)
	if err != nil {
		t.Fatal(err)
	}

	newconn, _ := client.NewTLSConn(conn, 0, 0, 0, false)

	send(t, newconn, msg1)
	send(t, newconn, msg1)
	send(t, newconn, msg2)
	send(t, newconn, msg3)
	send(t, newconn, msg4)
	send(t, newconn, msg1)
	send(t, newconn, msg5)
	send(t, newconn, msg1)
	send(t, newconn, "close")

	l.reqWG.Wait()

	l.connWG.Wait()
	newconn.Close()

	l.Close()
	listenerWG.Wait()

	// t.Logf("\nconn:\n%+v\n\n", conn)
	// t.Logf("\nconn.ConnectionState():\n%+v\n\n", conn.ConnectionState())
	// t.Logf("\ntls.Config:\n%+v\n\n", tlsConf)
}

// func TestClientDisconnect(t *testing.T) {
// 	// todo: we need to verify that events occur in the order that we want them (either via event hooks or log analysis)
// 	// this seems like a listener test than a integration test from a client perspective
// 	s := getServer(t)
// 	c := getClientConnWithClientCert(t)
// 	if err := c.Close(); err != nil {
// 		t.Fatal("Failed to close the client connection:", err)
// 	}
// 	if err := s.Stop(); err != nil {
// 		t.Fatal("Failed to stop the server:", err)
// 	}
// 	wg.Wait()
// }

func send(t *testing.T, conn *client.Conn, msg string) {
	data := []byte(msg)
	n := len(data)

	if err := conn.Write(data); err != nil {
		t.Fatal(err)
	}

	if n < 100 {
		t.Logf("Sent message to listener from client: %v (%v bytes)", msg, n)
	} else {
		t.Logf("Sent message to listener from client: ... (%v bytes)", n)
	}
}

// closeGraceful waits for all request then connection handler goroutines to return then closes the listener. This method is meant for testing.
func closeGraceful(l *Listener) error {
	// todo: more proper way is to do TCPConn.CloseRead()/reqWG.Wait()/TCPConn.CloseWrite()/listener.Close()
	// but that requires using net.TCPListener/TCPConn and then upgrading to TLS (which is also good when supporting UnixSocket)
	l.reqWG.Wait()
	l.connWG.Wait()
	return l.listener.Close()
}
<commit_msg>move old listener tests to conn_test<commit_after>package neptulon

import "testing"

func TestListenTLS(t *testing.T) {

}
<|endoftext|>


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

package adb

import (
	"bufio"
	"bytes"
	"context"
	"fmt"
	"net"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/google/gapid/core/app"
	"github.com/google/gapid/core/fault"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/core/os/android"
	"github.com/google/gapid/core/os/device"
	"github.com/google/gapid/core/os/shell"
	"github.com/google/gapid/gapis/perfetto"

	common_pb "protos/perfetto/common"
)

const (
	// ErrDeviceNotRooted is returned by Device.Root when the device is running a
	// production build as is not 'rooted'.
	ErrDeviceNotRooted = fault.Const("Device is not a userdebug build")
	ErrRootFailed      = fault.Const("Device failed to switch to root")

	maxRootAttempts                         = 5
	gpuRenderStagesDataSourceDescriptorName = "gpu.renderstages"

	perfettoPort = NamedFileSystemSocket("/dev/socket/traced_consumer")

	driverOverride = "gapid.driver_package_override"
	driverProperty = "ro.gfx.driver.1"
)

func isRootSuccessful(line string) bool {
	for _, expected := range []string{
		"adbd is already running as root",
		"* daemon started successfully *",
	} {
		if line == expected {
			return true
		}
	}
	return false
}

// Root restarts adb as root. If the device is running a production build then
// Root will return ErrDeviceNotRooted.
func (b *binding) Root(ctx context.Context) error {
	buf := bytes.Buffer{}
	buf.WriteString("adb root gave output:")
retry:
	for attempt := 0; attempt < maxRootAttempts; attempt++ {
		output, err := b.Command("root").Call(ctx)
		if err != nil {
			return err
		}
		if len(output) == 0 {
			return nil // Assume no output is success
		}
		output = strings.Replace(output, "\r\n", "\n", -1) // Not expected, but let's be safe.
		buf.WriteString(fmt.Sprintf("\n#%d: %v", attempt, output))
		lines := strings.Split(output, "\n")
		for i := len(lines) - 1; i >= 0; i-- {
			line := lines[i]
			if isRootSuccessful(line) {
				return nil // Success
			}
			switch line {
			case "adbd cannot run as root in production builds":
				return ErrDeviceNotRooted
			case "restarting adbd as root":
				time.Sleep(time.Millisecond * 100)
				continue retry
			default:
				// Some output we weren't expecting.
			}
		}
	}
	return log.Err(ctx, ErrRootFailed, buf.String())
}

// IsDebuggableBuild returns true if the device runs a debuggable Android build.
func (b *binding) IsDebuggableBuild(ctx context.Context) (bool, error) {
	output, err := b.Command("shell", "getprop", "ro.debuggable").Call(ctx)
	if err != nil {
		return false, err
	}
	return output == "1", nil
}

// InstallAPK installs the specified APK to the device. If reinstall is true
// and the package is already installed on the device then it will be replaced.
func (b *binding) InstallAPK(ctx context.Context, path string, reinstall bool, grantPermissions bool) error {
	args := []string{}
	if reinstall {
		args = append(args, "-r")
	}
	if grantPermissions && b.Instance().GetConfiguration().GetOS().GetAPIVersion() >= 23 {
		// Starting with API 23, permissions are not granted by default
		// during installation. Before API 23, the flag did not exist.
		args = append(args, "-g")
	}
	args = append(args, path)
	return b.Command("install", args...).Run(ctx)
}

// SELinuxEnforcing returns true if the device is currently in a
// SELinux enforcing mode, or false if the device is currently in a SELinux
// permissive mode.
func (b *binding) SELinuxEnforcing(ctx context.Context) (bool, error) {
	res, err := b.Shell("getenforce").Call(ctx)
	return strings.Contains(strings.ToLower(res), "enforcing"), err
}

// SetSELinuxEnforcing changes the SELinux-enforcing mode.
func (b *binding) SetSELinuxEnforcing(ctx context.Context, enforce bool) error {
	if enforce {
		return b.Shell("setenforce", "1").Run(ctx)
	}
	return b.Shell("setenforce", "0").Run(ctx)
}

// StartActivity launches the specified activity action.
func (b *binding) StartActivity(ctx context.Context, a android.ActivityAction, extras ...android.ActionExtra) error {
	args := append([]string{
		"start",
		"-S", // Force-stop the target app before starting the activity
		"-W", // Wait until the launch finishes
		"-a", a.Name,
		"-n", a.Component(),
	}, extrasFlags(extras)...)
	return b.Shell("am", args...).Run(ctx)
}

// StartActivityForDebug launches the specified activity in debug mode.
func (b *binding) StartActivityForDebug(ctx context.Context, a android.ActivityAction, extras ...android.ActionExtra) error {
	args := append([]string{
		"start",
		"-S", // Force-stop the target app before starting the activity
		"-W", // Wait until the launch finishes
		"-D", // Debug mode
		"-a", a.Name,
		"-n", a.Component(),
	}, extrasFlags(extras)...)
	return b.Shell("am", args...).Run(ctx)
}

// StartService launches the specified service action.
func (b *binding) StartService(ctx context.Context, a android.ServiceAction, extras ...android.ActionExtra) error {
	cmd := "start-foreground-service"
	if b.Instance().GetConfiguration().GetOS().GetAPIVersion() < 26 {
		// "am start-foreground-service" was added in API 26.
		cmd = "startservice"
	}
	args := append([]string{
		cmd,
		"-a", a.Name,
		"-n", a.Component(),
	}, extrasFlags(extras)...)
	return b.Shell("am", args...).Run(ctx)
}

// ForceStop stops everything associated with the given package.
func (b *binding) ForceStop(ctx context.Context, pkg string) error {
	return b.Shell("am", "force-stop", pkg).Run(ctx)
}

// SystemProperty returns the system property in string
func (b *binding) SystemProperty(ctx context.Context, name string) (string, error) {
	res, err := b.Shell("getprop", name).Call(ctx)
	if err != nil {
		return "", log.Errf(ctx, err, "getprop returned error: \n%s", err.Error())
	}
	return res, nil
}

// SetSystemProperty sets the system property with the given string value
func (b *binding) SetSystemProperty(ctx context.Context, name, value string) error {
	if len(value) == 0 {
		value = `""`
	}
	res, err := b.Shell("setprop", name, value).Call(ctx)
	if res != "" {
		return log.Errf(ctx, nil, "setprop returned error: \n%s", res)
	}
	if err != nil {
		return err
	}
	return nil
}

// SystemSetting returns the system setting with the given namespaced key.
func (b *binding) SystemSetting(ctx context.Context, namespace, key string) (string, error) {
	res, err := b.Shell("settings", "get", namespace, key).Call(ctx)
	if err != nil {
		return "", log.Errf(ctx, err, "settings get returned error: \n%s", err.Error())
	}
	return res, nil
}

// SetSystemSetting sets the system setting with with the given namespaced key
// to value.
func (b *binding) SetSystemSetting(ctx context.Context, namespace, key, value string) error {
	res, err := b.Shell("settings", "put", namespace, key, value).Call(ctx)
	if err != nil {
		return log.Errf(ctx, nil, "settings put returned error: \n%s", res)
	}
	return nil
}

// DeleteSystemSetting removes the system setting with with the given namespaced key.
func (b *binding) DeleteSystemSetting(ctx context.Context, namespace, key string) error {
	res, err := b.Shell("settings", "delete", namespace, key).Call(ctx)
	if err != nil {
		return log.Errf(ctx, nil, "settings delete returned error: \n%s", res)
	}
	return nil
}

// TempFile creates a temporary file on the given Device. It returns the
// path to the file, and a function that can be called to clean it up.
func (b *binding) TempFile(ctx context.Context) (string, func(ctx context.Context), error) {
	res, err := b.Shell("mktemp").Call(ctx)
	if err != nil {
		return "", nil, err
	}
	return res, func(ctx context.Context) {
		b.Shell("rm", "-f", res).Call(ctx)
	}, nil
}

// FileContents returns the contents of a given file on the Device.
func (b *binding) FileContents(ctx context.Context, path string) (string, error) {
	return b.Shell("cat", path).Call(ctx)
}

// RemoveFile removes the given file from the device
func (b *binding) RemoveFile(ctx context.Context, path string) error {
	_, err := b.Shell("rm", "-f", path).Call(ctx)
	return err
}

// GetEnv returns the default environment for the Device.
func (b *binding) GetEnv(ctx context.Context) (*shell.Env, error) {
	env, err := b.Shell("env").Call(ctx)
	if err != nil {
		return nil, err
	}
	scanner := bufio.NewScanner(strings.NewReader(env))
	e := &shell.Env{}
	for scanner.Scan() {
		e.Add(scanner.Text())
	}
	return e, nil
}

func (b *binding) SupportsPerfetto(ctx context.Context) bool {
	os := b.Instance().GetConfiguration().GetOS()
	return os.GetAPIVersion() >= 28
}

func (b *binding) ConnectPerfetto(ctx context.Context) (*perfetto.Client, error) {
	if !b.SupportsPerfetto(ctx) {
		return nil, fmt.Errorf("Perfetto is not supported on this device")
	}

	localPort, err := LocalFreeTCPPort()
	if err != nil {
		return nil, err
	}

	if err := b.Forward(ctx, localPort, perfettoPort); err != nil {
		return nil, err
	}
	cleanup := app.Cleanup(func(ctx context.Context) {
		b.RemoveForward(ctx, localPort)
	})

	conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%v", localPort))
	if err != nil {
		cleanup.Invoke(ctx)
		return nil, err
	}
	return perfetto.NewClient(ctx, conn, cleanup)
}

func (b *binding) QueryPerfettoServiceState(ctx context.Context) (*device.PerfettoCapability, error) {
	result := b.To.Configuration.PerfettoCapability
	if result == nil {
		result = &device.PerfettoCapability{
			GpuProfiling: &device.GPUProfiling{},
		}
	}
	gpu := result.GpuProfiling
	if gpu == nil {
		gpu = &device.GPUProfiling{}
		result.GpuProfiling = gpu
	}

	if b.Instance().GetConfiguration().GetOS().GetName() == "R" {
		// TODO(b/146384733): Change this to API version when it releases
		gpu.HasFrameLifecycle = true
	}

	c, err := b.ConnectPerfetto(ctx)
	if err != nil {
		return result, err
	}
	defer c.Close(ctx)

	err = c.Query(ctx, func(s *common_pb.TracingServiceState) error {
		for _, ds := range s.GetDataSources() {
			desc := ds.GetDsDescriptor()
			if desc.GetName() == gpuRenderStagesDataSourceDescriptorName {
				gpu.HasRenderStage = true
				continue
			}
			counters := desc.GetGpuCounterDescriptor().GetSpecs()
			if len(counters) != 0 {
				if gpu.GpuCounterDescriptor == nil {
					gpu.GpuCounterDescriptor = &device.GpuCounterDescriptor{}
				}
				// We mirror the Perfetto GpuCounterDescriptor proto into GAPID, hence
				// they are binary format compatible.
				data, err := proto.Marshal(desc.GetGpuCounterDescriptor())
				if err != nil {
					continue
				}
				proto.UnmarshalMerge(data, gpu.GpuCounterDescriptor)
			}
		}
		return nil
	})
	return result, err
}

func extrasFlags(extras []android.ActionExtra) []string {
	flags := []string{}
	for _, e := range extras {
		flags = append(flags, e.Flags()...)
	}
	return flags
}

// DriverPackage queries and returns the package of the preview graphics driver.
func (b *binding) GraphicsDriver(ctx context.Context) (Driver, error) {
	// Check if there is an override setup.
	driver, err := b.SystemSetting(ctx, "global", driverOverride)
	if err != nil {
		driver = ""
	}

	if driver == "" || driver == "null" {
		driver, err = b.SystemProperty(ctx, driverProperty)
		if err != nil {
			return Driver{}, err
		}
		if driver == "" {
			// There is no prerelease driver.
			return Driver{}, nil
		}
	}

	// Check the package path of the driver.
	path, err := b.Shell("pm", "path", driver).Call(ctx)
	if err != nil {
		return Driver{}, err
	}
	if !strings.HasPrefix(path, "package:") {
		return Driver{}, nil
	}
	path = path[8:]
	if path == "" {
		return Driver{}, nil
	}

	return Driver{
		Package: driver,
		Path:    path,
	}, nil
}
<commit_msg>Go back to using the perfetto CLI to query capabilities.<commit_after>// Copyright (C) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package adb

import (
	"bufio"
	"bytes"
	"context"
	"encoding/base64"
	"fmt"
	"net"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/google/gapid/core/app"
	"github.com/google/gapid/core/fault"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/core/os/android"
	"github.com/google/gapid/core/os/device"
	"github.com/google/gapid/core/os/shell"
	"github.com/google/gapid/gapis/perfetto"

	common_pb "protos/perfetto/common"
)

const (
	// ErrDeviceNotRooted is returned by Device.Root when the device is running a
	// production build as is not 'rooted'.
	ErrDeviceNotRooted = fault.Const("Device is not a userdebug build")
	ErrRootFailed      = fault.Const("Device failed to switch to root")

	maxRootAttempts                         = 5
	gpuRenderStagesDataSourceDescriptorName = "gpu.renderstages"

	perfettoPort = NamedFileSystemSocket("/dev/socket/traced_consumer")

	driverOverride = "gapid.driver_package_override"
	driverProperty = "ro.gfx.driver.1"
)

func isRootSuccessful(line string) bool {
	for _, expected := range []string{
		"adbd is already running as root",
		"* daemon started successfully *",
	} {
		if line == expected {
			return true
		}
	}
	return false
}

// Root restarts adb as root. If the device is running a production build then
// Root will return ErrDeviceNotRooted.
func (b *binding) Root(ctx context.Context) error {
	buf := bytes.Buffer{}
	buf.WriteString("adb root gave output:")
retry:
	for attempt := 0; attempt < maxRootAttempts; attempt++ {
		output, err := b.Command("root").Call(ctx)
		if err != nil {
			return err
		}
		if len(output) == 0 {
			return nil // Assume no output is success
		}
		output = strings.Replace(output, "\r\n", "\n", -1) // Not expected, but let's be safe.
		buf.WriteString(fmt.Sprintf("\n#%d: %v", attempt, output))
		lines := strings.Split(output, "\n")
		for i := len(lines) - 1; i >= 0; i-- {
			line := lines[i]
			if isRootSuccessful(line) {
				return nil // Success
			}
			switch line {
			case "adbd cannot run as root in production builds":
				return ErrDeviceNotRooted
			case "restarting adbd as root":
				time.Sleep(time.Millisecond * 100)
				continue retry
			default:
				// Some output we weren't expecting.
			}
		}
	}
	return log.Err(ctx, ErrRootFailed, buf.String())
}

// IsDebuggableBuild returns true if the device runs a debuggable Android build.
func (b *binding) IsDebuggableBuild(ctx context.Context) (bool, error) {
	output, err := b.Command("shell", "getprop", "ro.debuggable").Call(ctx)
	if err != nil {
		return false, err
	}
	return output == "1", nil
}

// InstallAPK installs the specified APK to the device. If reinstall is true
// and the package is already installed on the device then it will be replaced.
func (b *binding) InstallAPK(ctx context.Context, path string, reinstall bool, grantPermissions bool) error {
	args := []string{}
	if reinstall {
		args = append(args, "-r")
	}
	if grantPermissions && b.Instance().GetConfiguration().GetOS().GetAPIVersion() >= 23 {
		// Starting with API 23, permissions are not granted by default
		// during installation. Before API 23, the flag did not exist.
		args = append(args, "-g")
	}
	args = append(args, path)
	return b.Command("install", args...).Run(ctx)
}

// SELinuxEnforcing returns true if the device is currently in a
// SELinux enforcing mode, or false if the device is currently in a SELinux
// permissive mode.
func (b *binding) SELinuxEnforcing(ctx context.Context) (bool, error) {
	res, err := b.Shell("getenforce").Call(ctx)
	return strings.Contains(strings.ToLower(res), "enforcing"), err
}

// SetSELinuxEnforcing changes the SELinux-enforcing mode.
func (b *binding) SetSELinuxEnforcing(ctx context.Context, enforce bool) error {
	if enforce {
		return b.Shell("setenforce", "1").Run(ctx)
	}
	return b.Shell("setenforce", "0").Run(ctx)
}

// StartActivity launches the specified activity action.
func (b *binding) StartActivity(ctx context.Context, a android.ActivityAction, extras ...android.ActionExtra) error {
	args := append([]string{
		"start",
		"-S", // Force-stop the target app before starting the activity
		"-W", // Wait until the launch finishes
		"-a", a.Name,
		"-n", a.Component(),
	}, extrasFlags(extras)...)
	return b.Shell("am", args...).Run(ctx)
}

// StartActivityForDebug launches the specified activity in debug mode.
func (b *binding) StartActivityForDebug(ctx context.Context, a android.ActivityAction, extras ...android.ActionExtra) error {
	args := append([]string{
		"start",
		"-S", // Force-stop the target app before starting the activity
		"-W", // Wait until the launch finishes
		"-D", // Debug mode
		"-a", a.Name,
		"-n", a.Component(),
	}, extrasFlags(extras)...)
	return b.Shell("am", args...).Run(ctx)
}

// StartService launches the specified service action.
func (b *binding) StartService(ctx context.Context, a android.ServiceAction, extras ...android.ActionExtra) error {
	cmd := "start-foreground-service"
	if b.Instance().GetConfiguration().GetOS().GetAPIVersion() < 26 {
		// "am start-foreground-service" was added in API 26.
		cmd = "startservice"
	}
	args := append([]string{
		cmd,
		"-a", a.Name,
		"-n", a.Component(),
	}, extrasFlags(extras)...)
	return b.Shell("am", args...).Run(ctx)
}

// ForceStop stops everything associated with the given package.
func (b *binding) ForceStop(ctx context.Context, pkg string) error {
	return b.Shell("am", "force-stop", pkg).Run(ctx)
}

// SystemProperty returns the system property in string
func (b *binding) SystemProperty(ctx context.Context, name string) (string, error) {
	res, err := b.Shell("getprop", name).Call(ctx)
	if err != nil {
		return "", log.Errf(ctx, err, "getprop returned error: \n%s", err.Error())
	}
	return res, nil
}

// SetSystemProperty sets the system property with the given string value
func (b *binding) SetSystemProperty(ctx context.Context, name, value string) error {
	if len(value) == 0 {
		value = `""`
	}
	res, err := b.Shell("setprop", name, value).Call(ctx)
	if res != "" {
		return log.Errf(ctx, nil, "setprop returned error: \n%s", res)
	}
	if err != nil {
		return err
	}
	return nil
}

// SystemSetting returns the system setting with the given namespaced key.
func (b *binding) SystemSetting(ctx context.Context, namespace, key string) (string, error) {
	res, err := b.Shell("settings", "get", namespace, key).Call(ctx)
	if err != nil {
		return "", log.Errf(ctx, err, "settings get returned error: \n%s", err.Error())
	}
	return res, nil
}

// SetSystemSetting sets the system setting with with the given namespaced key
// to value.
func (b *binding) SetSystemSetting(ctx context.Context, namespace, key, value string) error {
	res, err := b.Shell("settings", "put", namespace, key, value).Call(ctx)
	if err != nil {
		return log.Errf(ctx, nil, "settings put returned error: \n%s", res)
	}
	return nil
}

// DeleteSystemSetting removes the system setting with with the given namespaced key.
func (b *binding) DeleteSystemSetting(ctx context.Context, namespace, key string) error {
	res, err := b.Shell("settings", "delete", namespace, key).Call(ctx)
	if err != nil {
		return log.Errf(ctx, nil, "settings delete returned error: \n%s", res)
	}
	return nil
}

// TempFile creates a temporary file on the given Device. It returns the
// path to the file, and a function that can be called to clean it up.
func (b *binding) TempFile(ctx context.Context) (string, func(ctx context.Context), error) {
	res, err := b.Shell("mktemp").Call(ctx)
	if err != nil {
		return "", nil, err
	}
	return res, func(ctx context.Context) {
		b.Shell("rm", "-f", res).Call(ctx)
	}, nil
}

// FileContents returns the contents of a given file on the Device.
func (b *binding) FileContents(ctx context.Context, path string) (string, error) {
	return b.Shell("cat", path).Call(ctx)
}

// RemoveFile removes the given file from the device
func (b *binding) RemoveFile(ctx context.Context, path string) error {
	_, err := b.Shell("rm", "-f", path).Call(ctx)
	return err
}

// GetEnv returns the default environment for the Device.
func (b *binding) GetEnv(ctx context.Context) (*shell.Env, error) {
	env, err := b.Shell("env").Call(ctx)
	if err != nil {
		return nil, err
	}
	scanner := bufio.NewScanner(strings.NewReader(env))
	e := &shell.Env{}
	for scanner.Scan() {
		e.Add(scanner.Text())
	}
	return e, nil
}

func (b *binding) SupportsPerfetto(ctx context.Context) bool {
	os := b.Instance().GetConfiguration().GetOS()
	return os.GetAPIVersion() >= 28
}

func (b *binding) ConnectPerfetto(ctx context.Context) (*perfetto.Client, error) {
	if !b.SupportsPerfetto(ctx) {
		return nil, fmt.Errorf("Perfetto is not supported on this device")
	}

	localPort, err := LocalFreeTCPPort()
	if err != nil {
		return nil, err
	}

	if err := b.Forward(ctx, localPort, perfettoPort); err != nil {
		return nil, err
	}
	cleanup := app.Cleanup(func(ctx context.Context) {
		b.RemoveForward(ctx, localPort)
	})

	conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%v", localPort))
	if err != nil {
		cleanup.Invoke(ctx)
		return nil, err
	}
	return perfetto.NewClient(ctx, conn, cleanup)
}

func (b *binding) QueryPerfettoServiceState(ctx context.Context) (*device.PerfettoCapability, error) {
	result := b.To.Configuration.PerfettoCapability
	if result == nil {
		result = &device.PerfettoCapability{
			GpuProfiling: &device.GPUProfiling{},
		}
	}
	gpu := result.GpuProfiling
	if gpu == nil {
		gpu = &device.GPUProfiling{}
		result.GpuProfiling = gpu
	}

	if b.Instance().GetConfiguration().GetOS().GetName() == "R" {
		// TODO(b/146384733): Change this to API version when it releases
		gpu.HasFrameLifecycle = true
	}

	if !b.SupportsPerfetto(ctx) {
		return result, fmt.Errorf("Perfetto is not supported on this device")
	}

	encoded, err := b.Shell("perfetto", "--query-raw", "|", "base64").Call(ctx)
	if err != nil {
		return result, log.Errf(ctx, err, "adb shell perfetto returned error: %s", encoded)
	}
	decoded, _ := base64.StdEncoding.DecodeString(encoded)
	state := &common_pb.TracingServiceState{}
	if err = proto.Unmarshal(decoded, state); err != nil {
		return result, log.Errf(ctx, err, "Unmarshal returned error")
	}

	for _, ds := range state.GetDataSources() {
		desc := ds.GetDsDescriptor()
		if desc.GetName() == gpuRenderStagesDataSourceDescriptorName {
			gpu.HasRenderStage = true
			continue
		}
		counters := desc.GetGpuCounterDescriptor().GetSpecs()
		if len(counters) != 0 {
			if gpu.GpuCounterDescriptor == nil {
				gpu.GpuCounterDescriptor = &device.GpuCounterDescriptor{}
			}
			// We mirror the Perfetto GpuCounterDescriptor proto into GAPID, hence
			// they are binary format compatible.
			data, err := proto.Marshal(desc.GetGpuCounterDescriptor())
			if err != nil {
				continue
			}
			proto.UnmarshalMerge(data, gpu.GpuCounterDescriptor)
		}
	}
	return result, nil
}

func extrasFlags(extras []android.ActionExtra) []string {
	flags := []string{}
	for _, e := range extras {
		flags = append(flags, e.Flags()...)
	}
	return flags
}

// DriverPackage queries and returns the package of the preview graphics driver.
func (b *binding) GraphicsDriver(ctx context.Context) (Driver, error) {
	// Check if there is an override setup.
	driver, err := b.SystemSetting(ctx, "global", driverOverride)
	if err != nil {
		driver = ""
	}

	if driver == "" || driver == "null" {
		driver, err = b.SystemProperty(ctx, driverProperty)
		if err != nil {
			return Driver{}, err
		}
		if driver == "" {
			// There is no prerelease driver.
			return Driver{}, nil
		}
	}

	// Check the package path of the driver.
	path, err := b.Shell("pm", "path", driver).Call(ctx)
	if err != nil {
		return Driver{}, err
	}
	if !strings.HasPrefix(path, "package:") {
		return Driver{}, nil
	}
	path = path[8:]
	if path == "" {
		return Driver{}, nil
	}

	return Driver{
		Package: driver,
		Path:    path,
	}, nil
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 @ z3q.net.
 * name : mss_service.go
 * author : jarryliu
 * date : 2016-06-11 20:51
 * description :
 * history :
 */
package dps

import (
	"go2o/core/domain/interface/mss"
)

type mssService struct {
	_rep mss.IMssRep
}

func NewMssService(rep mss.IMssRep) *mssService {
	return &mssService{
		_rep: rep,
	}
}

// 获取邮件模版
func (this *mssService) GetMailTemplate(id int) *mss.MailTemplate {
	return this._rep.GetProvider().GetMailTemplate(id)
}

// 保存邮件模板
func (this *mssService) SaveMailTemplate(v *mss.MailTemplate) (int, error) {
	return this._rep.GetProvider().SaveMailTemplate(v)
}

// 获取邮件模板
func (this *mssService) GetMailTemplates() []*mss.MailTemplate {
	return this._rep.GetProvider().GetMailTemplates()
}

// 删除邮件模板
func (this *mssService) DeleteMailTemplate(id int) error {
	return this._rep.GetProvider().DeleteMailTemplate(id)
}

// 获取邮件绑定
func (this *mssService) GetConfig() mss.Config {
	return this._rep.GetProvider().GetConfig()
}

// 保存邮件
func (this *mssService) SaveConfig(conf *mss.Config) error {
	return this._rep.GetProvider().SaveConfig(conf)
}

//可通过外部添加
func (this *mssService) RegisterNotifyItem(key string, item *mss.NotifyItem) {
	mss.RegisterNotifyItem(key, item)
}

func (this *mssService) GetAllNotifyItem() []mss.NotifyItem {
	return this._rep.GetManager().GetAllNotifyItem()
}

// 获取通知项配置
func (this *mssService) GetNotifyItem(key string) mss.NotifyItem {
	return this._rep.GetManager().GetNotifyItem(key)
}

// 保存通知项设置
func (this *mssService) SaveNotifyItem(item *mss.NotifyItem) error {
	return this._rep.GetManager().SaveNotifyItem(item)
}
<commit_msg>service<commit_after>/**
 * Copyright 2015 @ z3q.net.
 * name : mss_service.go
 * author : jarryliu
 * date : 2016-06-11 20:51
 * description :
 * history :
 */
package dps

import (
	"go2o/core/domain/interface/mss"
)

type mssService struct {
	_rep mss.IMssRep
}

func NewMssService(rep mss.IMssRep) *mssService {
	return &mssService{
		_rep: rep,
	}
}

// 获取邮件模版
func (this *mssService) GetMailTemplate(id int) *mss.MailTemplate {
	return this._rep.GetProvider().GetMailTemplate(id)
}

// 保存邮件模板
func (this *mssService) SaveMailTemplate(v *mss.MailTemplate) (int, error) {
	return this._rep.GetProvider().SaveMailTemplate(v)
}

// 获取邮件模板
func (this *mssService) GetMailTemplates() []*mss.MailTemplate {
	return this._rep.GetProvider().GetMailTemplates()
}

// 删除邮件模板
func (this *mssService) DeleteMailTemplate(id int) error {
	return this._rep.GetProvider().DeleteMailTemplate(id)
}

// 获取邮件绑定
func (this *mssService) GetConfig() mss.Config {
	return this._rep.GetProvider().GetConfig()
}

// 保存邮件
func (this *mssService) SaveConfig(conf *mss.Config) error {
	return this._rep.GetProvider().SaveConfig(conf)
}

//可通过外部添加
func (this *mssService) RegisterNotifyItem(key string, item *mss.NotifyItem) {
	mss.RegisterNotifyItem(key, item)
}

func (this *mssService) GetAllNotifyItem() []mss.NotifyItem {
	return this._rep.GetManager().GetAllNotifyItem()
}

// 获取通知项配置
func (this *mssService) GetNotifyItem(key string) mss.NotifyItem {
	return this._rep.GetManager().GetNotifyItem(key)
}

// 保存通知项设置
func (this *mssService) SaveNotifyItem(item *mss.NotifyItem) error {
	return this._rep.GetManager().SaveNotifyItem(item)
}

//todo: 考虑弄一个,确定后再发送.这样可以先在系统,然后才发送
// 发送站内通知信息,
// toRole: 为-1时发送给所有用户
// sendNow: 是否马上发送
func (this *mssService) SendSiteNotifyMessage(senderId int, toRole int,
	msg *mss.SiteMessage,sendNow bool) error {
	v := &mss.Message{
		Id: 0,
		// 消息类型
		Type: mss.TypeSiteMessage,
		// 消息用途
		UseFor: mss.UseForNotify,
		// 发送人角色
		SenderRole: mss.RoleSystem,
		// 发送人编号
		SenderId: senderId,
		// 发送的用户角色
		ToRole: -1,
		// 全系统接收
		AllUser: 1,
		// 是否只能阅读
		Readonly: 1,
	}

	if toRole == -1 {
		v.AllUser = 1
	} else {
		v.ToRole = toRole
	}
	var err error
	m := this._rep.GetManager().CreateMessage(v, msg)
	if _, err = m.Save(); err == nil {
		err = m.Send(nil)
	}
	return err
}

<|endoftext|>


<commit_before>package db

import (
	"io/ioutil"
	"os"

	log "github.com/Sirupsen/logrus"
	"gopkg.in/mgo.v2"
	"gopkg.in/yaml.v2"
)

// Config :
// define mongo struct
type Config struct {
	Mongohost string `json:"mongohost"`
	Mongoport string `json:"mongoport"`
}

// Connectmon :
// connect mongo db.
func Connectmon() *mgo.Session {
	execDirAbsPath, _ := os.Getwd()
	data, err := ioutil.ReadFile(execDirAbsPath + "/conf/app.conf.yml")
	if err != nil {
		log.Fatalf("can not read file:", err)
	}
	var config Config
	err = yaml.Unmarshal([]byte(data), &config)
	if err != nil {
		log.Fatalf("can not parse yaml file:", err)
	}
	session, err := mgo.Dial("mongodb://" + config.Mongohost + ":" + config.Mongoport)
	if err != nil {
		panic(err)

	}
	return session
}
<commit_msg>Fix build isses<commit_after>package db

import (
	"io/ioutil"
	"os"

	log "github.com/Sirupsen/logrus"
	"gopkg.in/mgo.v2"
	"gopkg.in/yaml.v2"
)

// Config :
// define mongo struct
type Config struct {
	Mongohost string `json:"mongohost"`
	Mongoport string `json:"mongoport"`
}

// Connectmon :
// connect mongo db.
func Connectmon() *mgo.Session {
	execDirAbsPath, _ := os.Getwd()
	data, err := ioutil.ReadFile(execDirAbsPath + "/conf/app.conf.yml")
	if err != nil {
		log.Fatal(err)
	}
	var config Config
	err = yaml.Unmarshal([]byte(data), &config)
	if err != nil {
		log.Fatal(err)
	}
	session, err := mgo.Dial("mongodb://" + config.Mongohost + ":" + config.Mongoport)
	if err != nil {
		panic(err)

	}
	return session
}
<|endoftext|>


<commit_before>package task

import (
	"context"
	"errors"

	"github.com/influxdata/platform"
	"github.com/influxdata/platform/task/backend"
	"github.com/influxdata/platform/task/options"
)

// PlatformAdapter wraps a task.Store into the platform.TaskService interface.
func PlatformAdapter(s backend.Store, r backend.LogReader) platform.TaskService {
	return pAdapter{s: s}
}

type pAdapter struct {
	s backend.Store
	r backend.LogReader
}

var _ platform.TaskService = pAdapter{}

func (p pAdapter) FindTaskByID(ctx context.Context, id platform.ID) (*platform.Task, error) {
	t, err := p.s.FindTaskByID(ctx, id)
	if err != nil {
		return nil, err
	}
	return toPlatformTask(*t)
}

func (p pAdapter) FindTasks(ctx context.Context, filter platform.TaskFilter) ([]*platform.Task, int, error) {
	const pageSize = 100 // According to the platform.TaskService.FindTasks API.

	params := backend.TaskSearchParams{PageSize: pageSize}
	if filter.Organization != nil {
		params.Org = *filter.Organization
	}
	if filter.User != nil {
		params.User = *filter.User
	}
	if filter.After != nil {
		params.After = *filter.After
	}
	ts, err := p.s.ListTasks(ctx, params)
	if err != nil {
		return nil, 0, err
	}

	pts := make([]*platform.Task, len(ts))
	for i, t := range ts {
		pts[i], err = toPlatformTask(t)
		if err != nil {
			return nil, 0, err
		}
	}

	totalResults := len(pts) // TODO(mr): don't lie about the total results. Update ListTasks signature?
	return pts, totalResults, nil
}

func (p pAdapter) CreateTask(ctx context.Context, t *platform.Task) error {
	opts, err := options.FromScript(t.Flux)
	if err != nil {
		return err
	}

	id, err := p.s.CreateTask(ctx, t.Organization, t.Owner.ID, t.Flux)
	if err != nil {
		return err
	}
	t.ID = id
	t.Every = opts.Every.String()
	t.Cron = opts.Cron

	return nil
}

func (p pAdapter) UpdateTask(ctx context.Context, id platform.ID, upd platform.TaskUpdate) (*platform.Task, error) {
	if upd.Flux == nil {
		return nil, errors.New("cannot update task without a script")
	}

	opts, err := options.FromScript(*upd.Flux)
	if err != nil {
		return nil, err
	}

	if err := p.s.ModifyTask(ctx, id, *upd.Flux); err != nil {
		return nil, err
	}

	return &platform.Task{
		ID:     id,
		Name:   "TODO",
		Status: "TODO",
		Owner:  platform.User{}, // TODO(mr): populate from context?
		Flux:   *upd.Flux,
		Every:  opts.Every.String(),
		Cron:   opts.Cron,
		Last:   platform.Run{}, // TODO(mr): how to get last run info?
	}, nil
}

func (p pAdapter) DeleteTask(ctx context.Context, id platform.ID) error {
	_, err := p.s.DeleteTask(ctx, id)
	// TODO(mr): Store.DeleteTask returns false, nil if ID didn't match; do we want to handle that case?
	return err
}

func (p pAdapter) FindLogs(ctx context.Context, filter platform.LogFilter) ([]*platform.Log, int, error) {
	logs, err := p.r.ListLogs(ctx, filter)
	logPointers := make([]*platform.Log, len(logs))
	for i := range logs {
		logPointers[i] = &logs[i]
	}
	return logPointers, len(logs), err
}

func (p pAdapter) FindRuns(ctx context.Context, filter platform.RunFilter) ([]*platform.Run, int, error) {
	runs, err := p.r.ListRuns(ctx, filter)
	return runs, len(runs), err
}

func (p pAdapter) FindRunByID(ctx context.Context, id platform.ID) (*platform.Run, error) {
	// TODO(lh): the inmem FindRunByID method doesnt need the taskId but we will need it PlatformAdapter
	// this call to the store is a filler until platform.TaskService gets the update to add the id
	return p.r.FindRunByID(ctx, platform.ID([]byte("replace")), id)
}

func (p pAdapter) RetryRun(ctx context.Context, id platform.ID) (*platform.Run, error) {
	return nil, errors.New("not yet implemented")
}

func toPlatformTask(t backend.StoreTask) (*platform.Task, error) {
	opts, err := options.FromScript(t.Script)
	if err != nil {
		return nil, err
	}

	return &platform.Task{
		ID:           t.ID,
		Organization: t.Org,
		Name:         t.Name,
		Status:       "", // TODO: set and update status
		Owner: platform.User{
			ID:   append([]byte(nil), t.User...), // Copy just in case.
			Name: "",                             // TODO(mr): how to get owner name?
		},
		Flux:  t.Script,
		Every: opts.Every.String(),
		Cron:  opts.Cron,
		Last:  platform.Run{}, // TODO(mr): how to get last run info?
	}, nil
}
<commit_msg>Starting refactoring task package usage of IDs<commit_after>package task

import (
	"context"
	"errors"

	"github.com/influxdata/platform"
	"github.com/influxdata/platform/task/backend"
	"github.com/influxdata/platform/task/options"
)

// PlatformAdapter wraps a task.Store into the platform.TaskService interface.
func PlatformAdapter(s backend.Store, r backend.LogReader) platform.TaskService {
	return pAdapter{s: s}
}

type pAdapter struct {
	s backend.Store
	r backend.LogReader
}

var _ platform.TaskService = pAdapter{}

func (p pAdapter) FindTaskByID(ctx context.Context, id platform.ID) (*platform.Task, error) {
	t, err := p.s.FindTaskByID(ctx, id)
	if err != nil {
		return nil, err
	}
	return toPlatformTask(*t)
}

func (p pAdapter) FindTasks(ctx context.Context, filter platform.TaskFilter) ([]*platform.Task, int, error) {
	const pageSize = 100 // According to the platform.TaskService.FindTasks API.

	params := backend.TaskSearchParams{PageSize: pageSize}
	if filter.Organization != nil {
		params.Org = *filter.Organization
	}
	if filter.User != nil {
		params.User = *filter.User
	}
	if filter.After != nil {
		params.After = *filter.After
	}
	ts, err := p.s.ListTasks(ctx, params)
	if err != nil {
		return nil, 0, err
	}

	pts := make([]*platform.Task, len(ts))
	for i, t := range ts {
		pts[i], err = toPlatformTask(t)
		if err != nil {
			return nil, 0, err
		}
	}

	totalResults := len(pts) // TODO(mr): don't lie about the total results. Update ListTasks signature?
	return pts, totalResults, nil
}

func (p pAdapter) CreateTask(ctx context.Context, t *platform.Task) error {
	opts, err := options.FromScript(t.Flux)
	if err != nil {
		return err
	}

	id, err := p.s.CreateTask(ctx, t.Organization, t.Owner.ID, t.Flux)
	if err != nil {
		return err
	}
	t.ID = *id
	t.Every = opts.Every.String()
	t.Cron = opts.Cron

	return nil
}

func (p pAdapter) UpdateTask(ctx context.Context, id platform.ID, upd platform.TaskUpdate) (*platform.Task, error) {
	if upd.Flux == nil {
		return nil, errors.New("cannot update task without a script")
	}

	opts, err := options.FromScript(*upd.Flux)
	if err != nil {
		return nil, err
	}

	if err := p.s.ModifyTask(ctx, id, *upd.Flux); err != nil {
		return nil, err
	}

	return &platform.Task{
		ID:     id,
		Name:   "TODO",
		Status: "TODO",
		Owner:  platform.User{}, // TODO(mr): populate from context?
		Flux:   *upd.Flux,
		Every:  opts.Every.String(),
		Cron:   opts.Cron,
		Last:   platform.Run{}, // TODO(mr): how to get last run info?
	}, nil
}

func (p pAdapter) DeleteTask(ctx context.Context, id platform.ID) error {
	_, err := p.s.DeleteTask(ctx, id)
	// TODO(mr): Store.DeleteTask returns false, nil if ID didn't match; do we want to handle that case?
	return err
}

func (p pAdapter) FindLogs(ctx context.Context, filter platform.LogFilter) ([]*platform.Log, int, error) {
	logs, err := p.r.ListLogs(ctx, filter)
	logPointers := make([]*platform.Log, len(logs))
	for i := range logs {
		logPointers[i] = &logs[i]
	}
	return logPointers, len(logs), err
}

func (p pAdapter) FindRuns(ctx context.Context, filter platform.RunFilter) ([]*platform.Run, int, error) {
	runs, err := p.r.ListRuns(ctx, filter)
	return runs, len(runs), err
}

func (p pAdapter) FindRunByID(ctx context.Context, id platform.ID) (*platform.Run, error) {
	// TODO(lh): the inmem FindRunByID method doesnt need the taskId but we will need it PlatformAdapter
	// this call to the store is a filler until platform.TaskService gets the update to add the id
	replaceID, _ := platform.IDFromString("0000000000000001")
	return p.r.FindRunByID(ctx, *replaceID, id)
}

func (p pAdapter) RetryRun(ctx context.Context, id platform.ID) (*platform.Run, error) {
	return nil, errors.New("not yet implemented")
}

func toPlatformTask(t backend.StoreTask) (*platform.Task, error) {
	opts, err := options.FromScript(t.Script)
	if err != nil {
		return nil, err
	}

	return &platform.Task{
		ID:           t.ID,
		Organization: t.Org,
		Name:         t.Name,
		Status:       "", // TODO: set and update status
		Owner: platform.User{
			ID:   t.User,
			Name: "", // TODO(mr): how to get owner name?
		},
		Flux:  t.Script,
		Every: opts.Every.String(),
		Cron:  opts.Cron,
		Last:  platform.Run{}, // TODO(mr): how to get last run info?
	}, nil
}
<|endoftext|>