<commit_before>package ipamplugin

import (
	"fmt"
	"net"
	"strings"

	"github.com/docker/libnetwork/discoverapi"
	"github.com/docker/libnetwork/ipamapi"
	"github.com/docker/libnetwork/netlabel"
	"github.com/weaveworks/weave/api"
	. "github.com/weaveworks/weave/common"
)

type ipam struct {
	weave *api.Client
}

func NewIpam(weave *api.Client) ipamapi.Ipam {
	return &ipam{weave: weave}
}

func (i *ipam) GetDefaultAddressSpaces() (string, string, error) {
	Log.Debugln("GetDefaultAddressSpaces")
	return "weavelocal", "weaveglobal", nil
}

func (i *ipam) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (poolname string, subnet *net.IPNet, data map[string]string, err error) {
	Log.Debugln("RequestPool", addressSpace, pool, subPool, options)
	defer func() { Log.Debugln("RequestPool returning", poolname, subnet, data, err) }()
	if pool == "" {
		subnet, err = i.weave.DefaultSubnet()
	} else {
		_, subnet, err = net.ParseCIDR(pool)
	}
	if err != nil {
		return
	}
	iprange := subnet
	if subPool != "" {
		if _, iprange, err = net.ParseCIDR(subPool); err != nil {
			return
		}
	}
	// Cunningly-constructed pool "name" which gives us what we need later
	poolname = strings.Join([]string{"weave", subnet.String(), iprange.String()}, "-")
	// Pass back a fake "gateway address"; we don't actually use it,
	// so just give the network address.
	data = map[string]string{netlabel.Gateway: subnet.String()}
	return
}

func (i *ipam) ReleasePool(poolID string) error {
	Log.Debugln("ReleasePool", poolID)
	return nil
}

func (i *ipam) RequestAddress(poolID string, address net.IP, options map[string]string) (ip *net.IPNet, _ map[string]string, err error) {
	Log.Debugln("RequestAddress", poolID, address, options)
	defer func() { Log.Debugln("allocateIP returned", ip, err) }()
	// If we pass magic string "_" to weave IPAM it stores the address under its own string
	if poolID == "weavepool" { // old-style
		ip, err = i.weave.AllocateIP("_")
		return
	}
	parts := strings.Split(poolID, "-")
	if len(parts) != 3 || parts[0] != "weave" {
		err = fmt.Errorf("Unrecognized pool ID: %s", poolID)
		return
	}
	var subnet, iprange *net.IPNet
	if _, subnet, err = net.ParseCIDR(parts[1]); err != nil {
		return
	}
	if address != nil { // try to claim specific address requested
		ip = &net.IPNet{IP: address, Mask: subnet.Mask}
		if err = i.weave.ClaimIP("_", ip); err != nil {
			return
		}
	} else {
		if _, iprange, err = net.ParseCIDR(parts[2]); err != nil {
			return
		}
		// We are lying slightly to IPAM here: the range is not a subnet
		if ip, err = i.weave.AllocateIPInSubnet("_", iprange); err != nil {
			return
		}
		ip.Mask = subnet.Mask // fix up the subnet we lied about
	}
	return
}

func (i *ipam) ReleaseAddress(poolID string, address net.IP) error {
	Log.Debugln("ReleaseAddress", poolID, address)
	return i.weave.ReleaseIPsFor(address.String())
}

// Functions required by ipamapi "contract" but not actually used.

func (i *ipam) DiscoverNew(discoverapi.DiscoveryType, interface{}) error {
	return nil
}

func (i *ipam) DiscoverDelete(discoverapi.DiscoveryType, interface{}) error {
	return nil
}
<commit_msg>Expose 'ipam' type so we can refer to it elsewhere<commit_after>package ipamplugin

import (
	"fmt"
	"net"
	"strings"

	"github.com/docker/libnetwork/discoverapi"
	"github.com/docker/libnetwork/netlabel"
	"github.com/weaveworks/weave/api"
	. "github.com/weaveworks/weave/common"
)

type Ipam struct {
	weave *api.Client
}

func NewIpam(weave *api.Client) *Ipam {
	return &Ipam{weave: weave}
}

func (i *Ipam) GetDefaultAddressSpaces() (string, string, error) {
	Log.Debugln("GetDefaultAddressSpaces")
	return "weavelocal", "weaveglobal", nil
}

func (i *Ipam) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (poolname string, subnet *net.IPNet, data map[string]string, err error) {
	Log.Debugln("RequestPool", addressSpace, pool, subPool, options)
	defer func() { Log.Debugln("RequestPool returning", poolname, subnet, data, err) }()
	if pool == "" {
		subnet, err = i.weave.DefaultSubnet()
	} else {
		_, subnet, err = net.ParseCIDR(pool)
	}
	if err != nil {
		return
	}
	iprange := subnet
	if subPool != "" {
		if _, iprange, err = net.ParseCIDR(subPool); err != nil {
			return
		}
	}
	// Cunningly-constructed pool "name" which gives us what we need later
	poolname = strings.Join([]string{"weave", subnet.String(), iprange.String()}, "-")
	// Pass back a fake "gateway address"; we don't actually use it,
	// so just give the network address.
	data = map[string]string{netlabel.Gateway: subnet.String()}
	return
}

func (i *Ipam) ReleasePool(poolID string) error {
	Log.Debugln("ReleasePool", poolID)
	return nil
}

func (i *Ipam) RequestAddress(poolID string, address net.IP, options map[string]string) (ip *net.IPNet, _ map[string]string, err error) {
	Log.Debugln("RequestAddress", poolID, address, options)
	defer func() { Log.Debugln("allocateIP returned", ip, err) }()
	// If we pass magic string "_" to weave IPAM it stores the address under its own string
	if poolID == "weavepool" { // old-style
		ip, err = i.weave.AllocateIP("_")
		return
	}
	parts := strings.Split(poolID, "-")
	if len(parts) != 3 || parts[0] != "weave" {
		err = fmt.Errorf("Unrecognized pool ID: %s", poolID)
		return
	}
	var subnet, iprange *net.IPNet
	if _, subnet, err = net.ParseCIDR(parts[1]); err != nil {
		return
	}
	if address != nil { // try to claim specific address requested
		ip = &net.IPNet{IP: address, Mask: subnet.Mask}
		if err = i.weave.ClaimIP("_", ip); err != nil {
			return
		}
	} else {
		if _, iprange, err = net.ParseCIDR(parts[2]); err != nil {
			return
		}
		// We are lying slightly to IPAM here: the range is not a subnet
		if ip, err = i.weave.AllocateIPInSubnet("_", iprange); err != nil {
			return
		}
		ip.Mask = subnet.Mask // fix up the subnet we lied about
	}
	return
}

func (i *Ipam) ReleaseAddress(poolID string, address net.IP) error {
	Log.Debugln("ReleaseAddress", poolID, address)
	return i.weave.ReleaseIPsFor(address.String())
}

// Functions required by ipamapi "contract" but not actually used.

func (i *Ipam) DiscoverNew(discoverapi.DiscoveryType, interface{}) error {
	return nil
}

func (i *Ipam) DiscoverDelete(discoverapi.DiscoveryType, interface{}) error {
	return nil
}
<|endoftext|>


<commit_before>package snmpquery

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/soniah/gosnmp"
)

type queryMessage struct {
	Command        string
	Destination    string
	Community      string
	Oid            string
	Timeout        int
	Retries        int
	AdditionalInfo interface{}
}

type outputMessage struct {
	Id          int
	Command     OpSnmp
	Community   string
	Oid         string
	Timeout     time.Duration
	Retries     int
	Destination string
	Response    []gosnmp.SnmpPDU
	Error       string
}

func ToJson(query *Query) (string, error) {

    d := outputMessage{
        Id: query.Id,
        Command: query.Cmd,
        Community: query.Community,
        Oid: query.Oid,
        Timeout: query.Timeout,
        Retries: query.Retries,
        Destination: query.Destination,
        Response: query.Response,
        Error: query.Error.Error(),
    }
    fmt.Println(d)
	b, err := json.Marshal(d)

	if err != nil {
		return "", err
	}

	return string(b), nil
}

func FromJson(jsonText string) (*Query, error) {
	var m queryMessage
	m.Timeout = 2
	m.Retries = 1

	b := []byte(jsonText)
	err := json.Unmarshal(b, &m)
	if err != nil {
		return nil, err
	}

	cmd, err := ConvertCommand(m.Command)
	if err != nil {
		return nil, err
	}

	q := Query{
		Cmd:         cmd,
		Community:   m.Community,
		Oid:         m.Oid,
		Destination: m.Destination,
		Timeout:     time.Duration(m.Timeout) * time.Second,
		Retries:     m.Retries,
	}
	return &q, nil
}

func ConvertCommand(command string) (OpSnmp, error) {
	switch command {
	case "walk":
		return WALK, nil
	case "get":
		return GET, nil
	default:
		return 0, fmt.Errorf("Unsupported command %s ", command)
	}
}
<commit_msg>Fixed ToJson Error.Error()<commit_after>package snmpquery

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/soniah/gosnmp"
)

type queryMessage struct {
	Command        string
	Destination    string
	Community      string
	Oid            string
	Timeout        int
	Retries        int
	AdditionalInfo interface{}
}

type outputMessage struct {
	Id          int
	Command     string
	Community   string
	Oid         string
	Timeout     time.Duration
	Retries     int
	Destination string
	Response    []gosnmp.SnmpPDU
	Error       string
}

func ToJson(query *Query) (string, error) {
   var errString string = ""
   if query.Error !=  nil {
       errString = query.Error.Error()
   }

    d := outputMessage{
        Id: query.Id,
        Command: convertCommandToCommandString(query.Cmd),
        Community: query.Community,
        Oid: query.Oid,
        Timeout: query.Timeout,
        Retries: query.Retries,
        Destination: query.Destination,
        Response: query.Response,
        Error: errString,
    }
    fmt.Println(d)
	b, err := json.Marshal(d)

	if err != nil {
		return "", err
	}

	return string(b), nil
}

func FromJson(jsonText string) (*Query, error) {
	var m queryMessage
	m.Timeout = 2
	m.Retries = 1

	b := []byte(jsonText)
	err := json.Unmarshal(b, &m)
	if err != nil {
		return nil, err
	}

	cmd, err := ConvertCommand(m.Command)
	if err != nil {
		return nil, err
	}

	q := Query{
		Cmd:         cmd,
		Community:   m.Community,
		Oid:         m.Oid,
		Destination: m.Destination,
		Timeout:     time.Duration(m.Timeout) * time.Second,
		Retries:     m.Retries,
	}
	return &q, nil
}

func convertCommandToCommandString(command OpSnmp) string {
    switch command{
        case WALK:
            return "walk"
        case  GET:
            return "get"
    }
    return ""
}

func ConvertCommand(command string) (OpSnmp, error) {
	switch command {
	case "walk":
		return WALK, nil
	case "get":
		return GET, nil
	default:
		return 0, fmt.Errorf("Unsupported command %s ", command)
	}
}
<|endoftext|>


<commit_before>package gform

import (
    "w32"
)

type Controller interface {
    Caption() string
    Enabled() bool
    Focus()
    Handle() w32.HWND
    Invalidate(erase bool)
    Parent() Controller
    Pos() (x, y int)
    Size() (w, h int)
    Height() int
    Width() int
    Visible() bool
    Bounds() *Rect
    ClientRect() *Rect
    SetCaption(s string)
    SetEnabled(b bool)
    SetPos(x, y int)
    SetSize(w, h int)
    SetDragAcceptFilesEnabled(b bool)
    Show()
    Hide()
    Font() *Font
    SetFont(font *Font)
    InvokeRequired() bool
    PreTranslateMessage(msg *w32.MSG) bool
    WndProc(msg uint, wparam, lparam uintptr) uintptr

    //General events
    OnCreate() *EventManager
    OnClose() *EventManager

    // Focus events
    OnKillFocus() *EventManager
    OnSetFocus() *EventManager

    //Drag and drop events
    OnDropFiles() *EventManager

    //Mouse events
    OnLBDown() *EventManager
    OnLBUp() *EventManager
    OnMBDown() *EventManager
    OnMBUp() *EventManager
    OnRBDown() *EventManager
    OnRBUp() *EventManager

    OnMouseHover() *EventManager
    OnMouseLeave() *EventManager

    //Keyboard events
    OnKeyUp() *EventManager

    //Paint events
    OnPaint() *EventManager
}
<commit_msg>Rename "SetDragAcceptFilesEnabled" to "EnableDragAcceptFiles".<commit_after>package gform

import (
    "w32"
)

type Controller interface {
    Caption() string
    Enabled() bool
    Focus()
    Handle() w32.HWND
    Invalidate(erase bool)
    Parent() Controller
    Pos() (x, y int)
    Size() (w, h int)
    Height() int
    Width() int
    Visible() bool
    Bounds() *Rect
    ClientRect() *Rect
    SetCaption(s string)
    SetEnabled(b bool)
    SetPos(x, y int)
    SetSize(w, h int)
    EnableDragAcceptFiles(b bool)
    Show()
    Hide()
    Font() *Font
    SetFont(font *Font)
    InvokeRequired() bool
    PreTranslateMessage(msg *w32.MSG) bool
    WndProc(msg uint, wparam, lparam uintptr) uintptr

    //General events
    OnCreate() *EventManager
    OnClose() *EventManager

    // Focus events
    OnKillFocus() *EventManager
    OnSetFocus() *EventManager

    //Drag and drop events
    OnDropFiles() *EventManager

    //Mouse events
    OnLBDown() *EventManager
    OnLBUp() *EventManager
    OnMBDown() *EventManager
    OnMBUp() *EventManager
    OnRBDown() *EventManager
    OnRBUp() *EventManager

    OnMouseHover() *EventManager
    OnMouseLeave() *EventManager

    //Keyboard events
    OnKeyUp() *EventManager

    //Paint events
    OnPaint() *EventManager
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    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 settings

import (
	"regexp"
	"strings"

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

	"k8s.io/ingress-nginx/test/e2e/framework"
)

var _ = framework.IngressNginxDescribe("Configmap change", func() {
	f := framework.NewDefaultFramework("configmap-change")

	BeforeEach(func() {
		f.NewEchoDeployment()
	})

	AfterEach(func() {
	})

	It("should reload after an update in the configuration", func() {
		host := "configmap-change"

		ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, nil)
		f.EnsureIngress(ing)

		wlKey := "whitelist-source-range"
		wlValue := "1.1.1.1"

		By("adding a whitelist-source-range")

		f.UpdateNginxConfigMapData(wlKey, wlValue)

		checksumRegex := regexp.MustCompile("Configuration checksum:\\s+(\\d+)")
		checksum := ""

		f.WaitForNginxConfiguration(
			func(cfg string) bool {
				// before returning, extract the current checksum
				match := checksumRegex.FindStringSubmatch(cfg)
				if len(match) > 0 {
					checksum = match[1]
				}

				return strings.Contains(cfg, "geo $the_real_ip $deny_") &&
					strings.Contains(cfg, "1.1.1.1 0")
			})
		Expect(checksum).NotTo(BeEmpty())

		By("changing error-log-level")

		f.UpdateNginxConfigMapData("error-log-level", "debug")

		newChecksum := ""
		f.WaitForNginxConfiguration(
			func(cfg string) bool {
				match := checksumRegex.FindStringSubmatch(cfg)
				if len(match) > 0 {
					newChecksum = match[1]
				}

				return strings.ContainsAny(cfg, "error_log  /var/log/nginx/error.log debug;")
			})
		Expect(checksum).NotTo(BeEquivalentTo(newChecksum))
	})
})
<commit_msg><commit_after>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    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 settings

import (
	"regexp"
	"strings"

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

	"k8s.io/ingress-nginx/test/e2e/framework"
)

var _ = framework.IngressNginxDescribe("Configmap change", func() {
	f := framework.NewDefaultFramework("configmap-change")

	BeforeEach(func() {
		f.NewEchoDeployment()
	})

	AfterEach(func() {
	})

	It("should reload after an update in the configuration", func() {
		host := "configmap-change"

		ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, nil)
		f.EnsureIngress(ing)

		wlKey := "whitelist-source-range"
		wlValue := "1.1.1.1"

		By("adding a whitelist-source-range")

		f.UpdateNginxConfigMapData(wlKey, wlValue)

		checksumRegex := regexp.MustCompile("Configuration checksum:\\s+(\\d+)")
		checksum := ""

		f.WaitForNginxConfiguration(
			func(cfg string) bool {
				// before returning, extract the current checksum
				match := checksumRegex.FindStringSubmatch(cfg)
				if len(match) > 0 {
					checksum = match[1]
				}

				return strings.Contains(cfg, "allow 1.1.1.1;")
			})
		Expect(checksum).NotTo(BeEmpty())

		By("changing error-log-level")

		f.UpdateNginxConfigMapData("error-log-level", "debug")

		newChecksum := ""
		f.WaitForNginxConfiguration(
			func(cfg string) bool {
				match := checksumRegex.FindStringSubmatch(cfg)
				if len(match) > 0 {
					newChecksum = match[1]
				}

				return strings.ContainsAny(cfg, "error_log  /var/log/nginx/error.log debug;")
			})
		Expect(checksum).NotTo(BeEquivalentTo(newChecksum))
	})
})
<|endoftext|>


<commit_before>package vindexes

import (
	"encoding/hex"
	"reflect"
	"testing"

	"github.com/youtube/vitess/go/vt/tabletserver/querytypes"
)

var lookupUnique Vindex

func init() {
	h, err := CreateVindex("lookup_unique", "lookupUnique", map[string]string{"table": "t", "from": "fromc", "to": "toc"})
	if err != nil {
		panic(err)
	}
	lookupUnique = h
}

func TestLookupUniqueCost(t *testing.T) {
	if lookupUnique.Cost() != 10 {
		t.Errorf("Cost(): %d, want 10", lookupUnique.Cost())
	}
}

func TestLookupUniqueVerify(t *testing.T) {
	vc := &vcursor{numRows: 1}
	success, err := lookupUnique.Verify(vc, 1, []byte("test"))
	if err != nil {
		t.Error(err)
	}
	if !success {
		t.Errorf("Verify(): %+v, want true", success)
	}
}

func TestLookupUniqueCreate(t *testing.T) {
	vc := &vcursor{}
	err := lookupUnique.(Lookup).Create(vc, 1, []byte("test"))
	if err != nil {
		t.Error(err)
	}
	wantQuery := &querytypes.BoundQuery{
		Sql: "insert into t(fromc, toc) values(:fromc, :toc)",
		BindVariables: map[string]interface{}{
			"fromc": 1,
			"toc":   hex.EncodeToString([]byte("test")),
		},
	}
	if !reflect.DeepEqual(vc.bq, wantQuery) {
		t.Errorf("vc.query = %#v, want %#v", vc.bq, wantQuery)
	}
}

func TestLookupUniqueReverse(t *testing.T) {
	_, ok := lookupUnique.(Reversible)
	if ok {
		t.Errorf("lhu.(Reversible): true, want false")
	}
}

func TestLookupUniqueDelete(t *testing.T) {
	vc := &vcursor{}
	err := lookupUnique.(Lookup).Delete(vc, []interface{}{1}, []byte("test"))
	if err != nil {
		t.Error(err)
	}
	wantQuery := &querytypes.BoundQuery{
		Sql: "delete from t where fromc = :fromc and toc = :toc",
		BindVariables: map[string]interface{}{
			"fromc": 1,
			"toc":   hex.EncodeToString([]byte("test")),
		},
	}
	if !reflect.DeepEqual(vc.bq, wantQuery) {
		t.Errorf("vc.query = %#v, want %#v", vc.bq, wantQuery)
	}
}
<commit_msg>Enhancing test for LookupNonUnique<commit_after>package vindexes

import (
	"encoding/hex"
	"reflect"
	"testing"

	"github.com/youtube/vitess/go/vt/tabletserver/querytypes"
)

var lookupUnique Vindex
var lookupNonUnique Vindex

func init() {
	lunique, err := CreateVindex("lookup_unique", "lookupUnique", map[string]string{"table": "t", "from": "fromc", "to": "toc"})
	if err != nil {
		panic(err)
	}
	lnonunique, err := CreateVindex("lookup", "lookupNonUnique", map[string]string{"table": "t", "from": "fromc", "to": "toc"})
	lookupUnique = lunique
	lookupNonUnique = lnonunique
}

func TestLookupUniqueCost(t *testing.T) {
	if lookupUnique.Cost() != 10 {
		t.Errorf("Cost(): %d, want 10", lookupUnique.Cost())
	}
}

func TestLookupNonUniqueCost(t *testing.T) {
	if lookupNonUnique.Cost() != 20 {
		t.Errorf("Cost(): %d, want 20", lookupUnique.Cost())
	}
}

func TestLookupUniqueVerify(t *testing.T) {
	vc := &vcursor{numRows: 1}
	success, err := lookupUnique.Verify(vc, 1, []byte("test"))
	if err != nil {
		t.Error(err)
	}
	if !success {
		t.Errorf("Verify(): %+v, want true", success)
	}
}

func TestLookupUniqueCreate(t *testing.T) {
	vc := &vcursor{}
	err := lookupUnique.(Lookup).Create(vc, 1, []byte("test"))
	if err != nil {
		t.Error(err)
	}
	wantQuery := &querytypes.BoundQuery{
		Sql: "insert into t(fromc, toc) values(:fromc, :toc)",
		BindVariables: map[string]interface{}{
			"fromc": 1,
			"toc":   hex.EncodeToString([]byte("test")),
		},
	}
	if !reflect.DeepEqual(vc.bq, wantQuery) {
		t.Errorf("vc.query = %#v, want %#v", vc.bq, wantQuery)
	}
}

func TestLookupUniqueReverse(t *testing.T) {
	_, ok := lookupUnique.(Reversible)
	if ok {
		t.Errorf("lhu.(Reversible): true, want false")
	}
}

func TestLookupUniqueDelete(t *testing.T) {
	vc := &vcursor{}
	err := lookupUnique.(Lookup).Delete(vc, []interface{}{1}, []byte("test"))
	if err != nil {
		t.Error(err)
	}
	wantQuery := &querytypes.BoundQuery{
		Sql: "delete from t where fromc = :fromc and toc = :toc",
		BindVariables: map[string]interface{}{
			"fromc": 1,
			"toc":   hex.EncodeToString([]byte("test")),
		},
	}
	if !reflect.DeepEqual(vc.bq, wantQuery) {
		t.Errorf("vc.query = %#v, want %#v", vc.bq, wantQuery)
	}
}
<|endoftext|>


<commit_before>package adminack

import (
	"context"
	"time"

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

	exutil "github.com/openshift/origin/test/extended/util"
	"github.com/openshift/origin/test/extended/util/openshift/clusterversionoperator"

	restclient "k8s.io/client-go/rest"
	"k8s.io/kubernetes/test/e2e/framework"
	"k8s.io/kubernetes/test/e2e/upgrades"
)

// UpgradeTest contains artifacts used during test
type UpgradeTest struct {
	oc     *exutil.CLI
	config *restclient.Config
}

func (UpgradeTest) Name() string { return "check-for-admin-acks" }
func (UpgradeTest) DisplayName() string {
	return "[bz-Cluster Version Operator] Verify presence of admin ack gate blocks upgrade until acknowledged"
}

// Setup creates artifacts to be used by Test
func (t *UpgradeTest) Setup(f *framework.Framework) {
	g.By("Setting up admin ack test")
	oc := exutil.NewCLIWithFramework(f)
	t.oc = oc
	config, err := framework.LoadConfig()
	o.Expect(err).NotTo(o.HaveOccurred())
	t.config = config
	framework.Logf("Admin ack test setup complete")
}

// Test simply returns successfully if admin ack functionality is not part the baseline being tested. Otherwise,
// test first verifies that Upgradeable condition is false for correct reason and with correct message. It then
// modifies the admin-acks configmap to ack the necessary admin-ack gate and then waits for the Upgradeable
// condition to change to true.
func (t *UpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) {
	ctx := context.Background()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go func() {
		<-done
		cancel()
	}()

	adminAckTest := &clusterversionoperator.AdminAckTest{Oc: t.oc, Config: t.config, Poll: 10 * time.Minute}
	adminAckTest.Test(ctx)
}

// Teardown cleans up any remaining objects.
func (t *UpgradeTest) Teardown(f *framework.Framework) {
	// rely on the namespace deletion to clean up everything
}
<commit_msg>test/e2e/upgrade/adminack: Remove redundant context.Background()<commit_after>package adminack

import (
	"context"
	"time"

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

	exutil "github.com/openshift/origin/test/extended/util"
	"github.com/openshift/origin/test/extended/util/openshift/clusterversionoperator"

	restclient "k8s.io/client-go/rest"
	"k8s.io/kubernetes/test/e2e/framework"
	"k8s.io/kubernetes/test/e2e/upgrades"
)

// UpgradeTest contains artifacts used during test
type UpgradeTest struct {
	oc     *exutil.CLI
	config *restclient.Config
}

func (UpgradeTest) Name() string { return "check-for-admin-acks" }
func (UpgradeTest) DisplayName() string {
	return "[bz-Cluster Version Operator] Verify presence of admin ack gate blocks upgrade until acknowledged"
}

// Setup creates artifacts to be used by Test
func (t *UpgradeTest) Setup(f *framework.Framework) {
	g.By("Setting up admin ack test")
	oc := exutil.NewCLIWithFramework(f)
	t.oc = oc
	config, err := framework.LoadConfig()
	o.Expect(err).NotTo(o.HaveOccurred())
	t.config = config
	framework.Logf("Admin ack test setup complete")
}

// Test simply returns successfully if admin ack functionality is not part the baseline being tested. Otherwise,
// test first verifies that Upgradeable condition is false for correct reason and with correct message. It then
// modifies the admin-acks configmap to ack the necessary admin-ack gate and then waits for the Upgradeable
// condition to change to true.
func (t *UpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go func() {
		<-done
		cancel()
	}()

	adminAckTest := &clusterversionoperator.AdminAckTest{Oc: t.oc, Config: t.config, Poll: 10 * time.Minute}
	adminAckTest.Test(ctx)
}

// Teardown cleans up any remaining objects.
func (t *UpgradeTest) Teardown(f *framework.Framework) {
	// rely on the namespace deletion to clean up everything
}
<|endoftext|>


<commit_before>// Package blake2 provides an optimized Go wrapper around the public domain
// implementation of BLAKE2.
// The cryptographic hash function BLAKE2 is an improved version of the SHA-3
// finalist BLAKE. Like BLAKE or SHA-3, BLAKE2 offers the highest security, yet
// is fast as MD5 on 64-bit platforms and requires at least 33% less RAM than
// SHA-2 or SHA-3 on low-end systems.
package blake2

import (
	// #cgo CFLAGS: -O3
	// #include "blake2.h"
	"C"
	"hash"
	"unsafe"
)

type digest struct {
	state *C.blake2b_state
	key   []byte
	size  int
}

// NewBlake2B returns a new 512-bit BLAKE2B hash.
func NewBlake2B() hash.Hash {
	d := new(digest)
	d.size = 64
	d.Reset()
	return d
}

// NewKeyedBlake2B returns a new 512-bit BLAKE2B hash with the given secret key.
func NewKeyedBlake2B(key []byte) hash.Hash {
	d := new(digest)
	d.size = 64
	d.key = key
	d.Reset()
	return d
}

func (*digest) BlockSize() int {
	return 128
}

func (d *digest) Size() int {
	return d.size
}

func (d *digest) Reset() {
	d.state = new(C.blake2b_state)
	if len(d.key) == 0 {
		if C.blake2b_init(d.state, C.uint8_t(d.Size())) < 0 {
			panic("blake2: unable to reset")
		}
	} else {
		if C.blake2b_init_key(d.state, C.uint8_t(d.Size()), unsafe.Pointer(&d.key[0]), C.uint8_t(len(d.key))) < 0 {
			panic("blake2: unable to reset")
		}
	}
}

func (d *digest) Sum(buf []byte) []byte {
	digest := make([]byte, d.Size())
	C.blake2b_final(d.state, (*C.uint8_t)(&digest[0]), C.uint8_t(d.Size()))
	return append(buf, digest...)
}

func (d *digest) Write(buf []byte) (int, error) {
	if len(buf) > 0 {
		c := &buf[0]
		C.blake2b_update(d.state, (*C.uint8_t)(c), C.uint64_t(len(buf)))
	}
	return len(buf), nil
}
<commit_msg>Simplify Sum.<commit_after>// Package blake2 provides an optimized Go wrapper around the public domain
// implementation of BLAKE2.
// The cryptographic hash function BLAKE2 is an improved version of the SHA-3
// finalist BLAKE. Like BLAKE or SHA-3, BLAKE2 offers the highest security, yet
// is fast as MD5 on 64-bit platforms and requires at least 33% less RAM than
// SHA-2 or SHA-3 on low-end systems.
package blake2

import (
	// #cgo CFLAGS: -O3
	// #include "blake2.h"
	"C"
	"hash"
	"unsafe"
)

type digest struct {
	state *C.blake2b_state
	key   []byte
	size  int
}

// NewBlake2B returns a new 512-bit BLAKE2B hash.
func NewBlake2B() hash.Hash {
	d := new(digest)
	d.size = 64
	d.Reset()
	return d
}

// NewKeyedBlake2B returns a new 512-bit BLAKE2B hash with the given secret key.
func NewKeyedBlake2B(key []byte) hash.Hash {
	d := new(digest)
	d.size = 64
	d.key = key
	d.Reset()
	return d
}

func (*digest) BlockSize() int {
	return 128
}

func (d *digest) Size() int {
	return d.size
}

func (d *digest) Reset() {
	d.state = new(C.blake2b_state)
	if len(d.key) == 0 {
		if C.blake2b_init(d.state, C.uint8_t(d.Size())) < 0 {
			panic("blake2: unable to reset")
		}
	} else {
		if C.blake2b_init_key(d.state, C.uint8_t(d.Size()), unsafe.Pointer(&d.key[0]), C.uint8_t(len(d.key))) < 0 {
			panic("blake2: unable to reset")
		}
	}
}

func (d *digest) Sum(buf []byte) []byte {
	digest := make([]byte, d.Size())
	C.blake2b_final(d.state, (*C.uint8_t)(&digest[0]), C.uint8_t(d.Size()))
	return append(buf, digest...)
}

func (d *digest) Write(buf []byte) (int, error) {
	if len(buf) > 0 {
		C.blake2b_update(d.state, (*C.uint8_t)(&buf[0]), C.uint64_t(len(buf)))
	}
	return len(buf), nil
}
<|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 gles

import (
	"bytes"
	"context"
	"encoding/base64"
	"fmt"
	goimg "image"
	"image/color"
	"image/png"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/google/gapid/core/data/endian"
	gpuimg "github.com/google/gapid/core/image"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/core/os/device"
	"github.com/google/gapid/core/stream"
)

// storeReferenceImage replaces the reference image with img.
func storeReferenceImage(ctx context.Context, outputDir string, name string, img *gpuimg.Data) {
	ctx = log.V{"name": name}.Bind(ctx)
	data := &bytes.Buffer{}
	i, err := toGoImage(img)
	if err != nil {
		log.F(ctx, "Failed to convert GPU image to Go image: %v", err)
	}
	if err := png.Encode(data, i); err != nil {
		log.F(ctx, "Failed to encode reference image: %v", err)
	}
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		log.F(ctx, "Failed to create reference image directory: %v", err)
	}
	path := filepath.Join(outputDir, name+".png")
	if err := ioutil.WriteFile(path, data.Bytes(), 0666); err != nil {
		log.F(ctx, "Failed to store reference image: %v", err)
	}
}

// loadReferenceImage loads the reference image with the specified name.
func loadReferenceImage(ctx context.Context, name string) *gpuimg.Data {
	ctx = log.V{"name": name}.Bind(ctx)
	b64, found := embedded[filepath.Join("reference", name+".png")]
	if !found {
		log.F(ctx, "Embedded reference image '%s' not found", name)
	}
	data, err := base64.StdEncoding.DecodeString(b64)
	if err != nil {
		log.F(ctx, "Failed to load reference image: %v", err)
	}
	img, err := png.Decode(bytes.NewBuffer(data))
	if err != nil {
		log.F(ctx, "Failed to decode reference image: %v", err)
	}
	out, err := toGPUImage(img)
	if err != nil {
		log.F(ctx, "Failed to convert Go image to GPU image: %v", err)
	}
	return out
}

func toGoImage(in *gpuimg.Data) (goimg.Image, error) {
	rect := goimg.Rect(0, 0, int(in.Width), int(in.Height))
	switch in.Format.Key() {
	case gpuimg.RGBA_U8_NORM.Key():
		out := goimg.NewNRGBA(rect)
		out.Pix = in.Bytes
		return out, nil

	case gpuimg.D_U16_NORM.Key():
		out := goimg.NewGray16(rect)
		out.Pix = make([]byte, len(in.Bytes))
		// Endian-swap.
		for i, c := 0, len(in.Bytes); i < c; i += 2 {
			out.Pix[i+0], out.Pix[i+1] = in.Bytes[i+1], in.Bytes[i+0]
		}
		return out, nil

	default:
		uncompressed := in.Format.GetUncompressed()
		var converted *gpuimg.Data
		var err error
		if depth, _ := uncompressed.Format.Component(stream.Channel_Depth); depth != nil {
			converted, err = in.Convert(gpuimg.D_U16_NORM)
		} else {
			converted, err = in.Convert(gpuimg.RGBA_U8_NORM)
		}
		if err != nil {
			return nil, err
		}
		return toGoImage(converted)
	}
}

func toGPUImage(in goimg.Image) (*gpuimg.Data, error) {
	w, h := in.Bounds().Dx(), in.Bounds().Dy()
	out := &gpuimg.Data{Width: uint32(w), Height: uint32(h)}
	buf := &bytes.Buffer{}
	e := endian.Writer(buf, device.BigEndian)

	switch in.ColorModel() {
	case color.RGBAModel, color.NRGBAModel:
		out.Format = gpuimg.RGBA_U8_NORM
		for y := 0; y < h; y++ {
			for x := 0; x < w; x++ {
				r, g, b, a := in.At(x, y).RGBA()
				e.Uint8(uint8(r >> 8))
				e.Uint8(uint8(g >> 8))
				e.Uint8(uint8(b >> 8))
				e.Uint8(uint8(a >> 8))
			}
		}
	case color.Gray16Model:
		out.Format = gpuimg.D_U16_NORM
		for y := 0; y < h; y++ {
			for x := 0; x < w; x++ {
				d, _, _, _ := in.At(x, y).RGBA()
				e.Uint16(uint16(d))
			}
		}
	default:
		return nil, fmt.Errorf("Unsupported color model %v", in.ColorModel())
	}

	out.Bytes = buf.Bytes()
	return out, nil
}

func quantizeImage(in *gpuimg.Data) *gpuimg.Data {
	tmp, err := toGoImage(in)
	if err != nil {
		panic(err)
	}
	out, err := toGPUImage(tmp)
	if err != nil {
		panic(err)
	}
	return out
}
<commit_msg>Integration tests: Set image depth<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 gles

import (
	"bytes"
	"context"
	"encoding/base64"
	"fmt"
	goimg "image"
	"image/color"
	"image/png"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/google/gapid/core/data/endian"
	gpuimg "github.com/google/gapid/core/image"
	"github.com/google/gapid/core/log"
	"github.com/google/gapid/core/os/device"
	"github.com/google/gapid/core/stream"
)

// storeReferenceImage replaces the reference image with img.
func storeReferenceImage(ctx context.Context, outputDir string, name string, img *gpuimg.Data) {
	ctx = log.V{"name": name}.Bind(ctx)
	data := &bytes.Buffer{}
	i, err := toGoImage(img)
	if err != nil {
		log.F(ctx, "Failed to convert GPU image to Go image: %v", err)
	}
	if err := png.Encode(data, i); err != nil {
		log.F(ctx, "Failed to encode reference image: %v", err)
	}
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		log.F(ctx, "Failed to create reference image directory: %v", err)
	}
	path := filepath.Join(outputDir, name+".png")
	if err := ioutil.WriteFile(path, data.Bytes(), 0666); err != nil {
		log.F(ctx, "Failed to store reference image: %v", err)
	}
}

// loadReferenceImage loads the reference image with the specified name.
func loadReferenceImage(ctx context.Context, name string) *gpuimg.Data {
	ctx = log.V{"name": name}.Bind(ctx)
	b64, found := embedded[filepath.Join("reference", name+".png")]
	if !found {
		log.F(ctx, "Embedded reference image '%s' not found", name)
	}
	data, err := base64.StdEncoding.DecodeString(b64)
	if err != nil {
		log.F(ctx, "Failed to load reference image: %v", err)
	}
	img, err := png.Decode(bytes.NewBuffer(data))
	if err != nil {
		log.F(ctx, "Failed to decode reference image: %v", err)
	}
	out, err := toGPUImage(img)
	if err != nil {
		log.F(ctx, "Failed to convert Go image to GPU image: %v", err)
	}
	return out
}

func toGoImage(in *gpuimg.Data) (goimg.Image, error) {
	rect := goimg.Rect(0, 0, int(in.Width), int(in.Height))
	switch in.Format.Key() {
	case gpuimg.RGBA_U8_NORM.Key():
		out := goimg.NewNRGBA(rect)
		out.Pix = in.Bytes
		return out, nil

	case gpuimg.D_U16_NORM.Key():
		out := goimg.NewGray16(rect)
		out.Pix = make([]byte, len(in.Bytes))
		// Endian-swap.
		for i, c := 0, len(in.Bytes); i < c; i += 2 {
			out.Pix[i+0], out.Pix[i+1] = in.Bytes[i+1], in.Bytes[i+0]
		}
		return out, nil

	default:
		uncompressed := in.Format.GetUncompressed()
		var converted *gpuimg.Data
		var err error
		if depth, _ := uncompressed.Format.Component(stream.Channel_Depth); depth != nil {
			converted, err = in.Convert(gpuimg.D_U16_NORM)
		} else {
			converted, err = in.Convert(gpuimg.RGBA_U8_NORM)
		}
		if err != nil {
			return nil, err
		}
		return toGoImage(converted)
	}
}

func toGPUImage(in goimg.Image) (*gpuimg.Data, error) {
	w, h := in.Bounds().Dx(), in.Bounds().Dy()
	out := &gpuimg.Data{Width: uint32(w), Height: uint32(h), Depth: 1}
	buf := &bytes.Buffer{}
	e := endian.Writer(buf, device.BigEndian)

	switch in.ColorModel() {
	case color.RGBAModel, color.NRGBAModel:
		out.Format = gpuimg.RGBA_U8_NORM
		for y := 0; y < h; y++ {
			for x := 0; x < w; x++ {
				r, g, b, a := in.At(x, y).RGBA()
				e.Uint8(uint8(r >> 8))
				e.Uint8(uint8(g >> 8))
				e.Uint8(uint8(b >> 8))
				e.Uint8(uint8(a >> 8))
			}
		}
	case color.Gray16Model:
		out.Format = gpuimg.D_U16_NORM
		for y := 0; y < h; y++ {
			for x := 0; x < w; x++ {
				d, _, _, _ := in.At(x, y).RGBA()
				e.Uint16(uint16(d))
			}
		}
	default:
		return nil, fmt.Errorf("Unsupported color model %v", in.ColorModel())
	}

	out.Bytes = buf.Bytes()
	return out, nil
}

func quantizeImage(in *gpuimg.Data) *gpuimg.Data {
	tmp, err := toGoImage(in)
	if err != nil {
		panic(err)
	}
	out, err := toGPUImage(tmp)
	if err != nil {
		panic(err)
	}
	return out
}
<|endoftext|>


<commit_before>// Copyright 2018-2021 the u-root 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 uzip

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func TestFromZip(t *testing.T) {
	tmpDir := t.TempDir()

	f := filepath.Join(tmpDir, "test.zip")
	if err := ToZip("testdata/testFolder", f, ""); err != nil {
		t.Fatalf(`ToZip("testdata/testFolder", %q, "") = %v, want nil`, f, err)
	}

	z, err := os.ReadFile(f)
	if err != nil {
		t.Fatalf(`os.ReadFile(%q) = %v, want nil`, f, err)
	}
	if len(z) == 0 {
		t.Errorf("len(%v) == %d, want not 0", z, len(z))
	}
	if len(z) < 1 {
		t.Errorf("no content read from file %q", f)
	}

	out := filepath.Join(tmpDir, "unziped")
	if err := os.MkdirAll(out, os.ModePerm); err != nil {
		t.Fatalf(`os.MkdirAll(%q, %v)  = %v, want nil`, out, os.ModePerm, err)
	}

	if err := FromZip(f, out); err != nil {
		t.Fatalf(`FromZip(%q, %q) = %v, want nil`, f, out, err)
	}

	f1 := filepath.Join(out, "file1")
	f2 := filepath.Join(out, "file2")
	f3 := filepath.Join(out, "subFolder", "file3")
	f4 := filepath.Join(out, "subFolder", "file4")

	f1Expected, err := os.ReadFile("testdata/testFolder/file1")
	if err != nil {
		t.Fatalf(`os.ReadFile("testdata/testFolder/file1") = _, %v, want nil`, err)
	}
	f2Expected, err := os.ReadFile("testdata/testFolder/file2")
	if err != nil {
		t.Fatalf(`os.ReadFile("testdata/testFolder/file2") = _, %v, want nil`, err)
	}
	f3Expected, err := os.ReadFile("testdata/testFolder/subFolder/file3")
	if err != nil {
		t.Fatalf(`os.ReadFile("testdata/testFolder/subFolder/file3") = _, %v, want nil`, err)
	}
	f4Expected, err := os.ReadFile("testdata/testFolder/subFolder/file4")
	if err != nil {
		t.Fatalf(`os.ReadFile("testdata/testFolder/subFolder/file4") = _, %v, want nil`, err)
	}

	var x []byte

	x, err = ioutil.ReadFile(f1)
	if err != nil {
		t.Errorf("open file: %q failed with: %q", f1, err)
	}
	if !bytes.Equal(x, f1Expected) {
		t.Errorf("file %q and file %q are not equal", f1, "testdata/testFolder/file1")
	}
	x, err = ioutil.ReadFile(f2)
	if err != nil {
		t.Errorf("open file: %q failed with: %q", f2, err)
	}
	if !bytes.Equal(x, f2Expected) {
		t.Errorf("file %q and file %q are not equal", f2, "testdata/testFolder/file2")
	}

	x, err = ioutil.ReadFile(f3)
	if err != nil {
		t.Errorf("open file: %q failed with: %q", f3, err)
	}
	if !bytes.Equal(x, f3Expected) {
		t.Errorf("file %q and file %q are not equal", f3, "testdata/testFolder/file3")
	}

	x, err = ioutil.ReadFile(f4)
	if err != nil {
		t.Errorf("open file: %q failed with: %q", f4, err)
	}
	if !bytes.Equal(x, f4Expected) {
		t.Errorf("file %q and file %q are not equal", f4, "testdata/testFolder/file4")
	}
}

func TestFromZipNoValidFile(t *testing.T) {
	f, err := ioutil.TempFile("", "testfile-")
	if err != nil {
		t.Error(err)
	}
	defer f.Close()
	if err := FromZip(f.Name(), "someDir"); err == nil {
		t.Errorf("FromZip succeeded but shouldn't")
	}
}

func TestAppendZip(t *testing.T) {
	_, err := os.Create("appendTest.zip")
	if err != nil {
		t.Error(err)
	}
	defer os.Remove("appendTest.zip")

	if err := AppendZip("testdata/testFolder", "appendTest.zip", "Test append zip"); err != nil {
		t.Error(err)
	}
}

func TestAppendZipNoDir1(t *testing.T) {
	if err := AppendZip("doesNotExist", "alsoNotExist", "Whythough"); err == nil {
		t.Error("AppendZip succeeded but shouldn't")
	}
}

func TestAppendZipNoDir2(t *testing.T) {
	f, err := ioutil.TempFile("", "testfile")
	if err != nil {
		t.Errorf("creating testfile failed: %v", err)
	}
	defer f.Close()
	if err := AppendZip(f.Name(), f.Name(), "no comment"); err == nil {
		t.Error("AppendZip succeeded but shouldn't")
	}
}

func TestComment(t *testing.T) {
	comment, err := Comment("test.zip")
	if err != nil {
		t.Error(err)
	}
	fmt.Println(comment)
}

func TestToZip(t *testing.T) {
	if err := ToZip(".", "testfile.zip", "test comment"); err != nil {
		t.Error(err)
	}
	defer os.Remove("testfile.zip")
}

func TestToZipInvalidDir(t *testing.T) {
	f, err := ioutil.TempFile("", "testfile-")
	if err != nil {
		t.Error(err)
	}
	defer f.Close()
	if err := ToZip(f.Name(), "invalid", "no need"); err == nil {
		t.Errorf("ToZip succeeded but shouldn't")
	}
}
<commit_msg>Correct some error messages<commit_after>// Copyright 2018-2021 the u-root 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 uzip

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func TestFromZip(t *testing.T) {
	tmpDir := t.TempDir()

	f := filepath.Join(tmpDir, "test.zip")
	if err := ToZip("testdata/testFolder", f, ""); err != nil {
		t.Fatalf(`ToZip("testdata/testFolder", %q, "") = %v, want nil`, f, err)
	}

	z, err := os.ReadFile(f)
	if err != nil {
		t.Fatalf(`os.ReadFile(%q) = %v, want nil`, f, err)
	}
	if len(z) == 0 {
		t.Errorf("len(%v) == %d, want not 0", z, len(z))
	}
	if len(z) < 1 {
		t.Errorf("no content read from file %q", f)
	}

	out := filepath.Join(tmpDir, "unziped")
	if err := os.MkdirAll(out, os.ModePerm); err != nil {
		t.Fatalf(`os.MkdirAll(%q, %v)  = %v, want nil`, out, os.ModePerm, err)
	}

	if err := FromZip(f, out); err != nil {
		t.Fatalf(`FromZip(%q, %q) = %v, want nil`, f, out, err)
	}

	f1 := filepath.Join(out, "file1")
	f2 := filepath.Join(out, "file2")
	f3 := filepath.Join(out, "subFolder", "file3")
	f4 := filepath.Join(out, "subFolder", "file4")

	f1Expected, err := os.ReadFile("testdata/testFolder/file1")
	if err != nil {
		t.Fatalf(`os.ReadFile("testdata/testFolder/file1") = _, %v, want nil`, err)
	}
	f2Expected, err := os.ReadFile("testdata/testFolder/file2")
	if err != nil {
		t.Fatalf(`os.ReadFile("testdata/testFolder/file2") = _, %v, want nil`, err)
	}
	f3Expected, err := os.ReadFile("testdata/testFolder/subFolder/file3")
	if err != nil {
		t.Fatalf(`os.ReadFile("testdata/testFolder/subFolder/file3") = _, %v, want nil`, err)
	}
	f4Expected, err := os.ReadFile("testdata/testFolder/subFolder/file4")
	if err != nil {
		t.Fatalf(`os.ReadFile("testdata/testFolder/subFolder/file4") = _, %v, want nil`, err)
	}

	var x []byte

	x, err = ioutil.ReadFile(f1)
	if err != nil {
		t.Errorf("open file: %q failed with: %q", f1, err)
	}
	if !bytes.Equal(x, f1Expected) {
		t.Errorf("file %q and file %q are not equal", f1, "testdata/testFolder/file1")
	}
	x, err = ioutil.ReadFile(f2)
	if err != nil {
		t.Errorf("open file: %q failed with: %q", f2, err)
	}
	if !bytes.Equal(x, f2Expected) {
		t.Errorf("file %q and file %q are not equal", f2, "testdata/testFolder/file2")
	}

	x, err = ioutil.ReadFile(f3)
	if err != nil {
		t.Errorf("open file: %q failed with: %q", f3, err)
	}
	if !bytes.Equal(x, f3Expected) {
		t.Errorf("file %q and file %q are not equal", f3, "testdata/testFolder/file3")
	}

	x, err = ioutil.ReadFile(f4)
	if err != nil {
		t.Errorf("open file: %q failed with: %q", f4, err)
	}
	if !bytes.Equal(x, f4Expected) {
		t.Errorf("file %q and file %q are not equal", f4, "testdata/testFolder/file4")
	}
}

func TestFromZipNoValidFile(t *testing.T) {
	f, err := ioutil.TempFile("", "testfile-")
	if err != nil {
		t.Errorf("TestFromZipNoValidFile failed: %q", err)
	}
	defer f.Close()
	if err := FromZip(f.Name(), "someDir"); err == nil {
		t.Errorf("FromZip succeeded but shouldn't")
	}
}

func TestAppendZip(t *testing.T) {
	_, err := os.Create("appendTest.zip")
	if err != nil {
		t.Errorf("TestAppendZip failed: %q", err)
	}
	defer os.Remove("appendTest.zip")

	if err := AppendZip("testdata/testFolder", "appendTest.zip", "Test append zip"); err != nil {
		t.Errorf("TestAppendZip failed: %q", err)
	}
}

func TestAppendZipNoDir1(t *testing.T) {
	if err := AppendZip("doesNotExist", "alsoNotExist", "Whythough"); err == nil {
		t.Error("TestAppendZipNoDir1 failed but shouldn't")
	}
}

func TestAppendZipNoDir2(t *testing.T) {
	f, err := ioutil.TempFile("", "testfile")
	if err != nil {
		t.Errorf("TestAppendZipNoDir2 failed: %v", err)
	}
	defer f.Close()
	if err := AppendZip(f.Name(), f.Name(), "no comment"); err == nil {
		t.Error("TestAppendZipNoDir2 failed but shouldn't")
	}
}

func TestComment(t *testing.T) {
	comment, err := Comment("test.zip")
	if err != nil {
		t.Errorf("TestComment failed: %q", err)
	}
	fmt.Println(comment)
}

func TestToZip(t *testing.T) {
	if err := ToZip(".", "testfile.zip", "test comment"); err != nil {
		t.Errorf("TestToZip failed: %q", err)
	}
	defer os.Remove("testfile.zip")
}

func TestToZipInvalidDir(t *testing.T) {
	f, err := ioutil.TempFile("", "testfile-")
	if err != nil {
		t.Errorf("TestToZipInvalidDir failed: %q", err)
	}
	defer f.Close()
	if err := ToZip(f.Name(), "invalid", "no need"); err == nil {
		t.Errorf("ToZip succeeded but shouldn't")
	}
}
<|endoftext|>


<commit_before>package converter

import (
	"bytes"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"reflect"
	"strings"

	"github.com/alecthomas/template"
	caseconv "github.com/minodisk/go-caseconv"
)

const implTmpl = `package {{ .Name }}

import "github.com/minodisk/sqlabble/statement"

{{ range .Tables }}
{{ $receiver := .Reciever }}
{{ $type := .GoName }}
func ({{ $receiver }} {{ $type }}) Table() statement.Table {
	return statement.NewTable("{{ .DBName }}")
}

func ({{ $receiver }} {{ $type }}) Columns() []statement.Column {
	return []statement.Column{ {{ range .Columns }}
		{{ $receiver }}.Column{{ .GoName }}(),{{ end }}
	}
}

{{ range .Columns }}

func ({{ $receiver }} {{ $type }}) Column{{ .GoName }}() statement.Column {
	return statement.NewColumn("{{ .DBName }}")
}
{{ end }}
{{ end }}
`

var impl *template.Template

func init() {
	var err error
	impl, err = template.New("impl").Parse(implTmpl)
	if err != nil {
		panic(err)
	}
}

func Generate(input []byte) ([]byte, error) {
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "dummy.go", input, parser.ParseComments)
	if err != nil {
		return nil, err
	}

	if ok := ast.FileExports(file); !ok {
		return nil, nil
	}

	pkg := ParsePackage(fset, file)
	if len(pkg.Tables) == 0 {
		return nil, nil
	}

	// fmt.Printf("%+v\n", pkg)

	var buf bytes.Buffer
	if err := impl.Execute(&buf, pkg); err != nil {
		return nil, err
	}

	bytes, err := format.Source(buf.Bytes())
	if err != nil {
		return nil, err
	}

	return bytes, nil
}

//db:"packages"
type Package struct {
	Name   string
	Tables []Table
}

type Table struct {
	GoName   string
	DBName   string
	Columns  []Column
	Reciever string
}

// db:"columns"
type Column struct {
	GoName string
	DBName string
}

// db:""
type Comment struct {
	Position  token.Position
	TableName string
}

type Comments []Comment

func (cs Comments) Find(from, to int) (Comment, bool) {
	for _, c := range cs {
		if from <= c.Position.Line && c.Position.Line <= to {
			return c, true
		}
	}
	return Comment{}, false
}

func ParsePackage(fset *token.FileSet, file *ast.File) Package {
	comments := Comments{}
	for _, comment := range file.Comments {
		// fmt.Println("=========")
		// fmt.Println(comment.Text(), comment.List)
		for _, c := range comment.List {
			// fmt.Println(c.Slash, c.Text)
			if n, ok := ParseDB(strings.TrimPrefix(c.Text, "//")); ok {
				comments = append(comments, Comment{
					Position:  fset.Position(c.Pos()),
					TableName: n,
				})
				// fmt.Println(c.End(), n)
			}
		}
	}

	// fmt.Println(comments)

	p := Package{Name: file.Name.Name}
	ast.Inspect(file, func(node ast.Node) bool {
		switch s := node.(type) {
		case *ast.TypeSpec:
			start := fset.Position(node.Pos()).Line
			end := fset.Position(node.End()).Line
			c, ok := comments.Find(start-1, end)
			if !ok {
				return false
			}

			t := ParseTable(fset, s)
			if c.TableName != "" {
				t.DBName = c.TableName
			}
			p.Tables = append(p.Tables, t)

			return false
			// default:
			// 	if node == nil {
			// 		return true
			// 	}
			// 	fmt.Println(node.Pos(), node.End())
		}
		return true
	})

	return p
}

func ParseTable(fset *token.FileSet, typ *ast.TypeSpec) Table {
	var (
		table Table
		found bool
	)
	ast.Inspect(typ, func(node ast.Node) bool {
		if found {
			return false
		}

		switch s := node.(type) {
		case *ast.StructType:
			// fmt.Println("============")
			// fmt.Println(typ.Name)
			// fmt.Println(typ.Comment)
			if typ.Name.Name == "" {
				return true
			}
			table = Table{
				GoName:   typ.Name.Name,
				Reciever: string(strings.ToLower(typ.Name.Name)[0]),
				DBName:   caseconv.LowerSnakeCase(typ.Name.Name),
			}
			for _, field := range s.Fields.List {
				column := ParseColumn(fset, field)
				if column != nil {
					table.Columns = append(table.Columns, *column)
				}
			}

			found = true
			return false
		}

		return true
	})

	return table
}

func ParseColumn(fset *token.FileSet, field *ast.Field) *Column {
	// fmt.Println("-----")
	var (
		ident *ast.Ident
		tag   *ast.BasicLit
	)
	ast.Inspect(field, func(node ast.Node) bool {
		if node == nil {
			return false
		}
		// fmt.Println("-----")
		// fmt.Printf("[%d:%d] %T %v\n\n%s\n", node.Pos(), node.End(), node, node, input[node.Pos()-1:node.End()-1])
		switch t := node.(type) {
		case *ast.Ident:
			if ident == nil {
				// fmt.Println(t.Obj.Data, t.Obj.Decl, t.Obj.Kind, t.Obj.Name, t.Obj.Type)
				ident = t
			}
		case *ast.BasicLit:
			if t.Kind == token.STRING {
				tag = t
			}
		}
		return true
	})

	var name string
	if tag != nil {
		if n, ok := ParseDB(strings.Trim(tag.Value, "`")); ok {
			name = n
		}
	}
	switch name {
	case "-":
		return nil
	case "":
		name = caseconv.LowerSnakeCase(ident.Name)
	}
	// fmt.Println("field name:", name)
	return &Column{
		GoName: ident.Name,
		DBName: name,
	}
}

func ParseDB(s string) (string, bool) {
	return reflect.StructTag(s).Lookup("db")
}
<commit_msg>Update packages<commit_after>package converter

import (
	"bytes"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"html/template"
	"reflect"
	"strings"

	"github.com/minodisk/caseconv"
)

const implTmpl = `package {{ .Name }}

import "github.com/minodisk/sqlabble/statement"

{{ range .Tables }}
{{ $receiver := .Reciever }}
{{ $type := .GoName }}
func ({{ $receiver }} {{ $type }}) Table() statement.Table {
	return statement.NewTable("{{ .DBName }}")
}

func ({{ $receiver }} {{ $type }}) Columns() []statement.Column {
	return []statement.Column{ {{ range .Columns }}
		{{ $receiver }}.Column{{ .GoName }}(),{{ end }}
	}
}

{{ range .Columns }}

func ({{ $receiver }} {{ $type }}) Column{{ .GoName }}() statement.Column {
	return statement.NewColumn("{{ .DBName }}")
}
{{ end }}
{{ end }}
`

var impl *template.Template

func init() {
	var err error
	impl, err = template.New("impl").Parse(implTmpl)
	if err != nil {
		panic(err)
	}
}

func Generate(input []byte) ([]byte, error) {
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "dummy.go", input, parser.ParseComments)
	if err != nil {
		return nil, err
	}

	if ok := ast.FileExports(file); !ok {
		return nil, nil
	}

	pkg := ParsePackage(fset, file)
	if len(pkg.Tables) == 0 {
		return nil, nil
	}

	// fmt.Printf("%+v\n", pkg)

	var buf bytes.Buffer
	if err := impl.Execute(&buf, pkg); err != nil {
		return nil, err
	}

	bytes, err := format.Source(buf.Bytes())
	if err != nil {
		return nil, err
	}

	return bytes, nil
}

//db:"packages"
type Package struct {
	Name   string
	Tables []Table
}

type Table struct {
	GoName   string
	DBName   string
	Columns  []Column
	Reciever string
}

// db:"columns"
type Column struct {
	GoName string
	DBName string
}

// db:""
type Comment struct {
	Position  token.Position
	TableName string
}

type Comments []Comment

func (cs Comments) Find(from, to int) (Comment, bool) {
	for _, c := range cs {
		if from <= c.Position.Line && c.Position.Line <= to {
			return c, true
		}
	}
	return Comment{}, false
}

func ParsePackage(fset *token.FileSet, file *ast.File) Package {
	comments := Comments{}
	for _, comment := range file.Comments {
		// fmt.Println("=========")
		// fmt.Println(comment.Text(), comment.List)
		for _, c := range comment.List {
			// fmt.Println(c.Slash, c.Text)
			if n, ok := ParseDB(strings.TrimPrefix(c.Text, "//")); ok {
				comments = append(comments, Comment{
					Position:  fset.Position(c.Pos()),
					TableName: n,
				})
				// fmt.Println(c.End(), n)
			}
		}
	}

	// fmt.Println(comments)

	p := Package{Name: file.Name.Name}
	ast.Inspect(file, func(node ast.Node) bool {
		switch s := node.(type) {
		case *ast.TypeSpec:
			start := fset.Position(node.Pos()).Line
			end := fset.Position(node.End()).Line
			c, ok := comments.Find(start-1, end)
			if !ok {
				return false
			}

			t := ParseTable(fset, s)
			if c.TableName != "" {
				t.DBName = c.TableName
			}
			p.Tables = append(p.Tables, t)

			return false
			// default:
			// 	if node == nil {
			// 		return true
			// 	}
			// 	fmt.Println(node.Pos(), node.End())
		}
		return true
	})

	return p
}

func ParseTable(fset *token.FileSet, typ *ast.TypeSpec) Table {
	var (
		table Table
		found bool
	)
	ast.Inspect(typ, func(node ast.Node) bool {
		if found {
			return false
		}

		switch s := node.(type) {
		case *ast.StructType:
			// fmt.Println("============")
			// fmt.Println(typ.Name)
			// fmt.Println(typ.Comment)
			if typ.Name.Name == "" {
				return true
			}
			table = Table{
				GoName:   typ.Name.Name,
				Reciever: string(strings.ToLower(typ.Name.Name)[0]),
				DBName:   caseconv.LowerSnakeCase(typ.Name.Name),
			}
			for _, field := range s.Fields.List {
				column := ParseColumn(fset, field)
				if column != nil {
					table.Columns = append(table.Columns, *column)
				}
			}

			found = true
			return false
		}

		return true
	})

	return table
}

func ParseColumn(fset *token.FileSet, field *ast.Field) *Column {
	// fmt.Println("-----")
	var (
		ident *ast.Ident
		tag   *ast.BasicLit
	)
	ast.Inspect(field, func(node ast.Node) bool {
		if node == nil {
			return false
		}
		// fmt.Println("-----")
		// fmt.Printf("[%d:%d] %T %v\n\n%s\n", node.Pos(), node.End(), node, node, input[node.Pos()-1:node.End()-1])
		switch t := node.(type) {
		case *ast.Ident:
			if ident == nil {
				// fmt.Println(t.Obj.Data, t.Obj.Decl, t.Obj.Kind, t.Obj.Name, t.Obj.Type)
				ident = t
			}
		case *ast.BasicLit:
			if t.Kind == token.STRING {
				tag = t
			}
		}
		return true
	})

	var name string
	if tag != nil {
		if n, ok := ParseDB(strings.Trim(tag.Value, "`")); ok {
			name = n
		}
	}
	switch name {
	case "-":
		return nil
	case "":
		name = caseconv.LowerSnakeCase(ident.Name)
	}
	// fmt.Println("field name:", name)
	return &Column{
		GoName: ident.Name,
		DBName: name,
	}
}

func ParseDB(s string) (string, bool) {
	return reflect.StructTag(s).Lookup("db")
}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package unit_test

import (
	"github.com/juju/errors"
	gitjujutesting "github.com/juju/testing"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/agent"
	"github.com/juju/juju/api/base"
	"github.com/juju/juju/cmd/jujud/agent/unit"
	"github.com/juju/juju/testing"
	"github.com/juju/juju/worker"
	"github.com/juju/juju/worker/dependency"
)

type ManifoldsSuite struct {
	testing.BaseSuite

	stub *gitjujutesting.Stub
}

var _ = gc.Suite(&ManifoldsSuite{})

func (s *ManifoldsSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)

	s.stub = &gitjujutesting.Stub{}
}

func (s *ManifoldsSuite) TearDownTest(c *gc.C) {
	for name := range unit.RegisteredManifolds {
		delete(unit.RegisteredManifolds, name)
	}

	s.BaseSuite.TearDownTest(c)
}

func (s *ManifoldsSuite) getResourceFunc(apiCaller base.APICaller) dependency.GetResourceFunc {
	return func(name string, out interface{}) error {
		s.stub.AddCall("getResource", name, out)
		if err := s.stub.NextErr(); err != nil {
			return errors.Trace(err)
		}

		unpacked := out.(*base.APICaller)
		*unpacked = apiCaller
		return nil
	}
}

func (s *ManifoldsSuite) newManifold(config unit.ManifoldsConfig) (dependency.Manifold, error) {
	var manifold dependency.Manifold

	s.stub.AddCall("newManifold", config)
	if err := s.stub.NextErr(); err != nil {
		return manifold, errors.Trace(err)
	}

	manifold.Start = func(getResource dependency.GetResourceFunc) (worker.Worker, error) {
		s.stub.AddCall("Start", getResource)
		if err := s.stub.NextErr(); err != nil {
			return nil, errors.Trace(err)
		}

		loop := func(stopCh <-chan struct{}) error {
			s.stub.AddCall("loop", stopCh)
			if err := s.stub.NextErr(); err != nil {
				return errors.Trace(err)
			}

			return nil
		}
		return worker.NewSimpleWorker(loop), nil
	}
	return manifold, nil
}

func (s *ManifoldsSuite) TestRegisterManifold(c *gc.C) {
	err := unit.RegisterManifold("spam", s.newManifold)
	c.Assert(err, jc.ErrorIsNil)

	// We can't compare functions so we jump through hoops instead.
	c.Check(unit.RegisteredManifolds, gc.HasLen, 1)
	var config unit.ManifoldsConfig
	registered := unit.RegisteredManifolds["spam"]
	manifold, err := registered(config)
	c.Assert(err, jc.ErrorIsNil)
	manifold.Start(nil)
	s.stub.CheckCallNames(c, "newManifold", "Start")
}

func (s *ManifoldsSuite) TestStartFuncs(c *gc.C) {
	for _, name := range []string{"spam", "eggs"} {
		err := unit.RegisterManifold(name, s.newManifold)
		c.Assert(err, jc.ErrorIsNil)
	}

	config := unit.ManifoldsConfig{
		Agent: fakeAgent{},
	}
	manifolds, err := unit.Manifolds(config)
	c.Assert(err, jc.ErrorIsNil)

	var names []string
	for name, manifold := range manifolds {
		c.Logf("checking %q manifold", name)
		c.Check(manifold.Start, gc.NotNil)
		names = append(names, name)
	}
	c.Check(names, jc.SameContents, []string{
		unit.AgentName,
		unit.APIAdddressUpdaterName,
		unit.APICallerName,
		unit.APIInfoGateName,
		unit.LeadershipTrackerName,
		unit.LoggingConfigUpdaterName,
		unit.LogSenderName,
		unit.MachineLockName,
		unit.ProxyConfigUpdaterName,
		unit.RsyslogConfigUpdaterName,
		unit.UniterName,
		unit.UpgraderName,
		"spam",
		"eggs",
	})
	s.stub.CheckCallNames(c, "newManifold", "newManifold")
	s.stub.ResetCalls()
	manifolds["spam"].Start(s.getResourceFunc(nil))
	s.stub.CheckCallNames(c, "Start")
}

// TODO(cmars) 2015/08/10: rework this into builtin Engine cycle checker.
func (s *ManifoldsSuite) TestAcyclic(c *gc.C) {
	manifolds, err := unit.Manifolds(unit.ManifoldsConfig{
		Agent: fakeAgent{},
	})
	c.Assert(err, jc.ErrorIsNil)
	count := len(manifolds)

	// Set of vars for depth-first topological sort of manifolds. (Note that,
	// because we've already got outgoing links stored conveniently, we're
	// actually checking the transpose of the dependency graph. Cycles will
	// still be cycles in either direction, though.)
	done := make(map[string]bool)
	doing := make(map[string]bool)
	sorted := make([]string, 0, count)

	// Stupid _-suffix malarkey allows recursion. Seems cleaner to keep these
	// considerations inside this func than to embody the algorithm in a type.
	visit := func(node string) {}
	visit_ := func(node string) {
		if doing[node] {
			c.Fatalf("cycle detected at %q (considering: %v)", node, doing)
		}
		if !done[node] {
			doing[node] = true
			for _, input := range manifolds[node].Inputs {
				visit(input)
			}
			done[node] = true
			doing[node] = false
			sorted = append(sorted, node)
		}
	}
	visit = visit_

	// Actually sort them, or fail if we find a cycle.
	for node := range manifolds {
		visit(node)
	}
	c.Logf("got: %v", sorted)
	c.Check(sorted, gc.HasLen, count) // Final sanity check.
}

type fakeAgent struct {
	agent.Agent
}
<commit_msg>Drop ManifoldsSuite.getResourceFunc.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package unit_test

import (
	"github.com/juju/errors"
	gitjujutesting "github.com/juju/testing"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/agent"
	"github.com/juju/juju/cmd/jujud/agent/unit"
	"github.com/juju/juju/testing"
	"github.com/juju/juju/worker"
	"github.com/juju/juju/worker/dependency"
	deptesting "github.com/juju/juju/worker/dependency/testing"
)

type ManifoldsSuite struct {
	testing.BaseSuite

	stub *gitjujutesting.Stub
}

var _ = gc.Suite(&ManifoldsSuite{})

func (s *ManifoldsSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)

	s.stub = &gitjujutesting.Stub{}
}

func (s *ManifoldsSuite) TearDownTest(c *gc.C) {
	for name := range unit.RegisteredManifolds {
		delete(unit.RegisteredManifolds, name)
	}

	s.BaseSuite.TearDownTest(c)
}

func (s *ManifoldsSuite) newManifold(config unit.ManifoldsConfig) (dependency.Manifold, error) {
	var manifold dependency.Manifold

	s.stub.AddCall("newManifold", config)
	if err := s.stub.NextErr(); err != nil {
		return manifold, errors.Trace(err)
	}

	manifold.Start = func(getResource dependency.GetResourceFunc) (worker.Worker, error) {
		s.stub.AddCall("Start", getResource)
		if err := s.stub.NextErr(); err != nil {
			return nil, errors.Trace(err)
		}

		loop := func(stopCh <-chan struct{}) error {
			s.stub.AddCall("loop", stopCh)
			if err := s.stub.NextErr(); err != nil {
				return errors.Trace(err)
			}

			return nil
		}
		return worker.NewSimpleWorker(loop), nil
	}
	return manifold, nil
}

func (s *ManifoldsSuite) TestRegisterManifold(c *gc.C) {
	err := unit.RegisterManifold("spam", s.newManifold)
	c.Assert(err, jc.ErrorIsNil)

	// We can't compare functions so we jump through hoops instead.
	c.Check(unit.RegisteredManifolds, gc.HasLen, 1)
	var config unit.ManifoldsConfig
	registered := unit.RegisteredManifolds["spam"]
	manifold, err := registered(config)
	c.Assert(err, jc.ErrorIsNil)
	manifold.Start(nil)
	s.stub.CheckCallNames(c, "newManifold", "Start")
}

func (s *ManifoldsSuite) TestStartFuncs(c *gc.C) {
	for _, name := range []string{"spam", "eggs"} {
		err := unit.RegisterManifold(name, s.newManifold)
		c.Assert(err, jc.ErrorIsNil)
	}

	config := unit.ManifoldsConfig{
		Agent: fakeAgent{},
	}
	manifolds, err := unit.Manifolds(config)
	c.Assert(err, jc.ErrorIsNil)

	var names []string
	for name, manifold := range manifolds {
		c.Logf("checking %q manifold", name)
		c.Check(manifold.Start, gc.NotNil)
		names = append(names, name)
	}
	c.Check(names, jc.SameContents, []string{
		unit.AgentName,
		unit.APIAdddressUpdaterName,
		unit.APICallerName,
		unit.APIInfoGateName,
		unit.LeadershipTrackerName,
		unit.LoggingConfigUpdaterName,
		unit.LogSenderName,
		unit.MachineLockName,
		unit.ProxyConfigUpdaterName,
		unit.RsyslogConfigUpdaterName,
		unit.UniterName,
		unit.UpgraderName,
		"spam",
		"eggs",
	})
	s.stub.CheckCallNames(c, "newManifold", "newManifold")
	s.stub.ResetCalls()
	manifolds["spam"].Start(deptesting.StubGetResource(nil))
	s.stub.CheckCallNames(c, "Start")
}

// TODO(cmars) 2015/08/10: rework this into builtin Engine cycle checker.
func (s *ManifoldsSuite) TestAcyclic(c *gc.C) {
	manifolds, err := unit.Manifolds(unit.ManifoldsConfig{
		Agent: fakeAgent{},
	})
	c.Assert(err, jc.ErrorIsNil)
	count := len(manifolds)

	// Set of vars for depth-first topological sort of manifolds. (Note that,
	// because we've already got outgoing links stored conveniently, we're
	// actually checking the transpose of the dependency graph. Cycles will
	// still be cycles in either direction, though.)
	done := make(map[string]bool)
	doing := make(map[string]bool)
	sorted := make([]string, 0, count)

	// Stupid _-suffix malarkey allows recursion. Seems cleaner to keep these
	// considerations inside this func than to embody the algorithm in a type.
	visit := func(node string) {}
	visit_ := func(node string) {
		if doing[node] {
			c.Fatalf("cycle detected at %q (considering: %v)", node, doing)
		}
		if !done[node] {
			doing[node] = true
			for _, input := range manifolds[node].Inputs {
				visit(input)
			}
			done[node] = true
			doing[node] = false
			sorted = append(sorted, node)
		}
	}
	visit = visit_

	// Actually sort them, or fail if we find a cycle.
	for node := range manifolds {
		visit(node)
	}
	c.Logf("got: %v", sorted)
	c.Check(sorted, gc.HasLen, count) // Final sanity check.
}

type fakeAgent struct {
	agent.Agent
}
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms.

package main

import (
	"github.com/ardielle/ardielle-go/rdl"
	"bufio"
	"strings"
	"log"
	"flag"
	"io/ioutil"
	"fmt"
	"encoding/json"
	"os"
	"github.com/yahoo/parsec-rdl-gen/utils"
	"text/template"
)

type javaClientGenerator struct {
	registry rdl.TypeRegistry
	schema   *rdl.Schema
	name     string
	writer   *bufio.Writer
	err      error
	banner   string
	ns       string
	base     string
}

func main() {
	pOutdir := flag.String("o", ".", "Output directory")
	flag.String("s", "", "RDL source file")
	namespace := flag.String("ns", "", "Namespace")
	flag.Parse()
	data, err := ioutil.ReadAll(os.Stdin)
	banner := "parsec-rdl-gen (development version)"

	if err == nil {
		var schema rdl.Schema
		err = json.Unmarshal(data, &schema)
		if err == nil {
			GenerateJavaClient(banner, &schema, *pOutdir, *namespace, "")
			os.Exit(0)
		}
	}
	fmt.Fprintf(os.Stderr, "*** %v\n", err)
	os.Exit(1)
}

// GenerateJavaClient generates the client code to talk to the server
func GenerateJavaClient(banner string, schema *rdl.Schema, outdir string, ns string, base string) error {

	reg := rdl.NewTypeRegistry(schema)

	packageSrcDir, err := utils.JavaGenerationSourceDir(schema, ns)
	if err != nil {
		return err
	}

	cName := utils.Capitalize(string(schema.Name))

	_, filePath := utils.GetOutputPathInfo(packageSrcDir, cName, "ClientImpl.java")
	if _, err := os.Stat(filePath); err == nil {
		fmt.Fprintln(os.Stderr, "Warning: interface implementation class exists, ignore: ", filePath)
	} else {
		out, file, _, err := utils.OutputWriter(packageSrcDir, cName, "ClientImpl.java")
		if err != nil {
			return err
		}
		gen := &javaClientGenerator{reg, schema, cName, out, nil, banner, ns, base}
		gen.processTemplate(javaClientTemplate)
		out.Flush()
		file.Close()
		if gen.err != nil {
			return gen.err
		}
	}

	_, filePath = utils.GetOutputPathInfo(packageSrcDir, cName, "Client.java")
	if _, err := os.Stat(filePath); err == nil {
		fmt.Fprintln(os.Stderr, "Warning: interface class exists, ignore: ", filePath)
	} else {
		out, file, _, err := utils.OutputWriter(packageSrcDir, cName, "Client.java")
		if err != nil {
			return err
		}
		gen := &javaClientGenerator{reg, schema, cName, out, nil, banner, ns, base}
		gen.processTemplate(javaClientInterfaceTemplate)
		out.Flush()
		file.Close()
		if gen.err != nil {
			return gen.err
		}
	}

	packageDir, err := utils.JavaGenerationDir(outdir, schema, ns)

	//ResourceException - the throawable wrapper for alternate return types
	out, file, _, err := utils.OutputWriter(packageDir, "ResourceException", ".java")
	if err != nil {
		return err
	}
	err = utils.JavaGenerateResourceException(schema, out, ns)
	out.Flush()
	file.Close()
	if err != nil {
		return err
	}

	//ResourceError - the default data object for an error
	out, file, _, err = utils.OutputWriter(packageDir, "ResourceError", ".java")
	if err != nil {
		return err
	}
	err = utils.JavaGenerateResourceError(schema, out, ns)
	out.Flush()
	file.Close()
	return err
}

func (gen *javaClientGenerator) processTemplate(templateSource string) error {
	commentFun := func(s string) string {
		return utils.FormatComment(s, 0, 80)
	}
	needExpectFunc := func(r *rdl.Resource) bool {
		if (r.Expected != "OK" || len(r.Alternatives) > 0) {
			return true
		}
		return false
	}
	funcMap := template.FuncMap{
		"header":      func() string { return utils.JavaGenerationHeader(gen.banner) },
		"package":     func() string { return utils.JavaGenerationPackage(gen.schema, gen.ns) },
		"comment":     commentFun,
		"methodSig":   func(r *rdl.Resource) string { return "public "+ gen.clientMethodSignature(r) },
		"name":        func() string { return gen.name },
		"cName":       func() string { return utils.Capitalize(gen.name) },
		"lName":       func() string { return utils.Uncapitalize(gen.name) },
		"needBody":    func(r *rdl.Resource) bool { return gen.needBody(r) },
		"bodyObj":     func(r *rdl.Resource) string { return gen.getBodyObj(r) },
		"iMethod":     func(r *rdl.Resource) string { return gen.clientMethodSignature(r) + ";" },
		"builderExt":  func(r *rdl.Resource) string { return gen.builderExt(r) },
		"origPackage": func() string { return utils.JavaGenerationOrigPackage(gen.schema, gen.ns) },
		"origHeader":  func() string { return utils.JavaGenerationOrigHeader(gen.banner) },
		"returnType":  func(r *rdl.Resource) string { return utils.JavaType(gen.registry, r.Type, true, "", "")},
		"needExpect":  needExpectFunc,
	}
	t := template.Must(template.New(gen.name).Funcs(funcMap).Parse(templateSource))
	return t.Execute(gen.writer, gen.schema)
}

func (gen* javaClientGenerator) builderExt(r *rdl.Resource) string {
	code := "\n"
	spacePad := "                            "
	for _, input := range r.Inputs {
		iname := javaName(input.Name)
		if input.PathParam {
			code += spacePad + ".resolveTemplate(\"" + iname + "\", " + iname + ")\n"
		} else if input.QueryParam != "" {
			code += spacePad + ".queryParam(\"" + iname + "\", " + iname + ")\n"
		}
	}
	code += spacePad + ".build();"
	return code
}

func (gen* javaClientGenerator) getBodyObj(r *rdl.Resource) string {
	idx, ok := gen.findFirstUserDefType(r.Inputs)
	if ok { return javaName(r.Inputs[idx].Name) }
	return ""
}

func (gen* javaClientGenerator) findFirstUserDefType(resInputs []*rdl.ResourceInput) (int, bool) {
	for idx, input := range resInputs {
		userType := gen.registry.FindBaseType(input.Type)
		// todo: need consider map or array case
		if userType == rdl.BaseTypeStruct {
			return idx, true
		}
	}
	return -1, false
}

func (gen *javaClientGenerator) needBody(r *rdl.Resource) bool {
	// check inputs is user defined type or not
	_, ok := gen.findFirstUserDefType(r.Inputs)
	return ok
}

const javaClientInterfaceTemplate = `{{origHeader}}
package {{origPackage}};

import java.util.concurrent.CompletableFuture;
import {{package}}.ResourceException;
{{range .Types}}{{if .StructTypeDef}}{{if .StructTypeDef.Name}}import {{package}}.{{.StructTypeDef.Name}};
{{end}}{{end}}{{end}}

public interface {{cName}}Client {
{{range .Resources}}
    {{iMethod .}}{{end}}
}
`
const javaClientTemplate = `{{origHeader}}
package {{origPackage}};

import {{package}}.ResourceException;
{{range .Types}}{{if .StructTypeDef}}{{if .StructTypeDef.Name}}import {{package}}.{{.StructTypeDef.Name}};
{{end}}{{end}}{{end}}
import com.ning.http.client.AsyncHandler;
import com.yahoo.parsec.clients.DefaultAsyncCompletionHandler;
import com.yahoo.parsec.clients.ParsecAsyncHttpClient;
import com.yahoo.parsec.clients.ParsecAsyncHttpRequest;
import com.yahoo.parsec.clients.ParsecAsyncHttpRequest.Builder;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class {{cName}}ClientImpl implements {{cName}}Client {

    /** Logger. */
    private static final Logger LOGGER = LoggerFactory.getLogger(SampleClientImpl.class);

    /** ParsecAsyncHttpClient. */
    private final ParsecAsyncHttpClient parsecAsyncHttpClient;

    /** Object mapper */
    private final ObjectMapper objectMapper;

    /** URL. */
    private String url;

    /** Headers. */
    private final Map<String, String> headers;

    /**
     * connection timeout.
     */
    private static final int IDLE_CONNECTION_TIMEOUT_IN_MS = 15000;

    /**
     * total connections.
     */
    private static final int MAXIMUM_CONNECTIONS_TOTAL = 50;

    public {{cName}}ClientImpl(
        String url,
        Map<String, String> headers
    ) {

        ParsecAsyncHttpClient client  = null;
        try {
            client = new ParsecAsyncHttpClient.Builder()
                .setAcceptAnyCertificate(true)
                .setAllowPoolingConnections(true)
                .setPooledConnectionIdleTimeout(IDLE_CONNECTION_TIMEOUT_IN_MS)
                .setMaxConnections(MAXIMUM_CONNECTIONS_TOTAL)
                .build();
        } catch (ExecutionException e) {
            LOGGER.error("create ParsecAsyncHttpClient failed. " + e.getMessage());
            throw new ResourceException(ResourceException.INTERNAL_SERVER_ERROR, e.getMessage());
        }
        this.parsecAsyncHttpClient = client;
        this.objectMapper = new ObjectMapper();
        this.url = url;
        this.headers = headers;
    }

    public {{cName}}ClientImpl (
            ParsecAsyncHttpClient client,
            ObjectMapper objectMapper,
            String url,
            Map<String, String> headers)
    {
        this.parsecAsyncHttpClient = client;
        this.objectMapper = objectMapper;
        this.url = url;
        this.headers = headers;
    }

    private ParsecAsyncHttpRequest getRequest(String method, URI uri, String body) throws ResourceException {
        Builder builder = new Builder();

        builder.setUri(uri);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }

        builder.setMethod(method);

        builder.setBody(body).setBodyEncoding("UTF-8");

        ParsecAsyncHttpRequest request = null;
        try {
            request = builder.build();
        } catch (Exception e) {
            LOGGER.error("builder build failed: " + e.getMessage());
            throw new ResourceException(ResourceException.INTERNAL_SERVER_ERROR, e.getMessage());
        }
        return request;
    }
{{range .Resources}}
    @Override
    {{methodSig .}} {
        String path = "{{.Path}}";
        String body = null;
{{if needBody .}}
        try {
            body = objectMapper.writeValueAsString({{bodyObj .}});
        } catch (JsonProcessingException e) {
            LOGGER.error("JsonProcessingException: " + e.getMessage());
            throw new ResourceException(ResourceException.INTERNAL_SERVER_ERROR, e.getMessage());
        }
{{end}}
        URI uri = UriBuilder.fromUri(url).path(path){{builderExt .}}
        ParsecAsyncHttpRequest request = getRequest("{{.Method}}", uri, body);

{{if needExpect .}}
        Set<Integer> expectedStatus = new HashSet<>();
        expectedStatus.add(ResourceException.{{.Expected}});
        {{if .Alternatives}}{{range .Alternatives}}expectedStatus.add(ResourceException.{{.}});
{{end}}{{end}}
        AsyncHandler<{{returnType .}}> asyncHandler = new DefaultAsyncCompletionHandler<>({{returnType .}}.class, expectedStatus);
{{else}}
        AsyncHandler<{{returnType .}}> asyncHandler = new DefaultAsyncCompletionHandler<>({{returnType .}}.class);
{{end}}
        return parsecAsyncHttpClient.criticalExecute(request, asyncHandler);
    }
{{end}}
}
`

// todo: copy from go-schema.go
func safeTypeVarName(rtype rdl.TypeRef) rdl.TypeName {
	tokens := strings.Split(string(rtype), ".")
	return rdl.TypeName(utils.Capitalize(strings.Join(tokens, "")))
}

// todo: duplicate with server code, need integrate
func javaMethodName(reg rdl.TypeRegistry, r *rdl.Resource) (string, []string) {
	var params []string
	bodyType := string(safeTypeVarName(r.Type))
	for _, v := range r.Inputs {
		if v.Context != "" { //ignore these legacy things
			log.Println("Warning: v1 style context param ignored:", v.Name, v.Context)
			continue
		}
		k := v.Name
		if v.QueryParam == "" && !v.PathParam && v.Header == "" {
			bodyType = string(safeTypeVarName(v.Type))
		}
		optional := false // but different with server code, how?
		params = append(params, utils.JavaType(reg, v.Type, optional, "", "")+" "+javaName(k))
	}
	return strings.ToLower(string(r.Method)) + string(bodyType), params
}

// todo: duplicate with java-server.go
func javaName(name rdl.Identifier) string {
	switch name {
	case "type", "default": //other reserved words
		return "_" + string(name)
	default:
		return string(name)
	}
}

func (gen *javaClientGenerator) clientMethodSignature(r *rdl.Resource) string {
	reg := gen.registry
	returnType := utils.JavaType(reg, r.Type, true, "", "")
	methName, params := javaMethodName(reg, r)
	sparams := ""
	if len(params) > 0 {
		sparams = strings.Join(params, ", ")
	}
	if len(r.Outputs) > 0 {
		if sparams == "" {
			sparams = "java.util.Map<String,java.util.List<String>> headers"
		} else {
			sparams = sparams + ", java.util.Map<String,java.util.List<String>> headers"
		}
	}
	return "CompletableFuture<" + returnType + "> " + methName + "(" + sparams + ") throws ResourceException"
}

<commit_msg>remove unused import<commit_after>// Copyright 2016 Yahoo Inc.
// Licensed under the terms of the Apache license. Please see LICENSE.md file distributed with this work for terms.

package main

import (
	"github.com/ardielle/ardielle-go/rdl"
	"bufio"
	"strings"
	"log"
	"flag"
	"io/ioutil"
	"fmt"
	"encoding/json"
	"os"
	"github.com/yahoo/parsec-rdl-gen/utils"
	"text/template"
)

type javaClientGenerator struct {
	registry rdl.TypeRegistry
	schema   *rdl.Schema
	name     string
	writer   *bufio.Writer
	err      error
	banner   string
	ns       string
	base     string
}

func main() {
	pOutdir := flag.String("o", ".", "Output directory")
	flag.String("s", "", "RDL source file")
	namespace := flag.String("ns", "", "Namespace")
	flag.Parse()
	data, err := ioutil.ReadAll(os.Stdin)
	banner := "parsec-rdl-gen (development version)"

	if err == nil {
		var schema rdl.Schema
		err = json.Unmarshal(data, &schema)
		if err == nil {
			GenerateJavaClient(banner, &schema, *pOutdir, *namespace, "")
			os.Exit(0)
		}
	}
	fmt.Fprintf(os.Stderr, "*** %v\n", err)
	os.Exit(1)
}

// GenerateJavaClient generates the client code to talk to the server
func GenerateJavaClient(banner string, schema *rdl.Schema, outdir string, ns string, base string) error {

	reg := rdl.NewTypeRegistry(schema)

	packageSrcDir, err := utils.JavaGenerationSourceDir(schema, ns)
	if err != nil {
		return err
	}

	cName := utils.Capitalize(string(schema.Name))

	_, filePath := utils.GetOutputPathInfo(packageSrcDir, cName, "ClientImpl.java")
	if _, err := os.Stat(filePath); err == nil {
		fmt.Fprintln(os.Stderr, "Warning: interface implementation class exists, ignore: ", filePath)
	} else {
		out, file, _, err := utils.OutputWriter(packageSrcDir, cName, "ClientImpl.java")
		if err != nil {
			return err
		}
		gen := &javaClientGenerator{reg, schema, cName, out, nil, banner, ns, base}
		gen.processTemplate(javaClientTemplate)
		out.Flush()
		file.Close()
		if gen.err != nil {
			return gen.err
		}
	}

	_, filePath = utils.GetOutputPathInfo(packageSrcDir, cName, "Client.java")
	if _, err := os.Stat(filePath); err == nil {
		fmt.Fprintln(os.Stderr, "Warning: interface class exists, ignore: ", filePath)
	} else {
		out, file, _, err := utils.OutputWriter(packageSrcDir, cName, "Client.java")
		if err != nil {
			return err
		}
		gen := &javaClientGenerator{reg, schema, cName, out, nil, banner, ns, base}
		gen.processTemplate(javaClientInterfaceTemplate)
		out.Flush()
		file.Close()
		if gen.err != nil {
			return gen.err
		}
	}

	packageDir, err := utils.JavaGenerationDir(outdir, schema, ns)

	//ResourceException - the throawable wrapper for alternate return types
	out, file, _, err := utils.OutputWriter(packageDir, "ResourceException", ".java")
	if err != nil {
		return err
	}
	err = utils.JavaGenerateResourceException(schema, out, ns)
	out.Flush()
	file.Close()
	if err != nil {
		return err
	}

	//ResourceError - the default data object for an error
	out, file, _, err = utils.OutputWriter(packageDir, "ResourceError", ".java")
	if err != nil {
		return err
	}
	err = utils.JavaGenerateResourceError(schema, out, ns)
	out.Flush()
	file.Close()
	return err
}

func (gen *javaClientGenerator) processTemplate(templateSource string) error {
	commentFun := func(s string) string {
		return utils.FormatComment(s, 0, 80)
	}
	needExpectFunc := func(r *rdl.Resource) bool {
		if (r.Expected != "OK" || len(r.Alternatives) > 0) {
			return true
		}
		return false
	}
	funcMap := template.FuncMap{
		"header":      func() string { return utils.JavaGenerationHeader(gen.banner) },
		"package":     func() string { return utils.JavaGenerationPackage(gen.schema, gen.ns) },
		"comment":     commentFun,
		"methodSig":   func(r *rdl.Resource) string { return "public "+ gen.clientMethodSignature(r) },
		"name":        func() string { return gen.name },
		"cName":       func() string { return utils.Capitalize(gen.name) },
		"lName":       func() string { return utils.Uncapitalize(gen.name) },
		"needBody":    func(r *rdl.Resource) bool { return gen.needBody(r) },
		"bodyObj":     func(r *rdl.Resource) string { return gen.getBodyObj(r) },
		"iMethod":     func(r *rdl.Resource) string { return gen.clientMethodSignature(r) + ";" },
		"builderExt":  func(r *rdl.Resource) string { return gen.builderExt(r) },
		"origPackage": func() string { return utils.JavaGenerationOrigPackage(gen.schema, gen.ns) },
		"origHeader":  func() string { return utils.JavaGenerationOrigHeader(gen.banner) },
		"returnType":  func(r *rdl.Resource) string { return utils.JavaType(gen.registry, r.Type, true, "", "")},
		"needExpect":  needExpectFunc,
	}
	t := template.Must(template.New(gen.name).Funcs(funcMap).Parse(templateSource))
	return t.Execute(gen.writer, gen.schema)
}

func (gen* javaClientGenerator) builderExt(r *rdl.Resource) string {
	code := "\n"
	spacePad := "                            "
	for _, input := range r.Inputs {
		iname := javaName(input.Name)
		if input.PathParam {
			code += spacePad + ".resolveTemplate(\"" + iname + "\", " + iname + ")\n"
		} else if input.QueryParam != "" {
			code += spacePad + ".queryParam(\"" + iname + "\", " + iname + ")\n"
		}
	}
	code += spacePad + ".build();"
	return code
}

func (gen* javaClientGenerator) getBodyObj(r *rdl.Resource) string {
	idx, ok := gen.findFirstUserDefType(r.Inputs)
	if ok { return javaName(r.Inputs[idx].Name) }
	return ""
}

func (gen* javaClientGenerator) findFirstUserDefType(resInputs []*rdl.ResourceInput) (int, bool) {
	for idx, input := range resInputs {
		userType := gen.registry.FindBaseType(input.Type)
		// todo: need consider map or array case
		if userType == rdl.BaseTypeStruct {
			return idx, true
		}
	}
	return -1, false
}

func (gen *javaClientGenerator) needBody(r *rdl.Resource) bool {
	// check inputs is user defined type or not
	_, ok := gen.findFirstUserDefType(r.Inputs)
	return ok
}

const javaClientInterfaceTemplate = `{{origHeader}}
package {{origPackage}};

import java.util.concurrent.CompletableFuture;
import {{package}}.ResourceException;
{{range .Types}}{{if .StructTypeDef}}{{if .StructTypeDef.Name}}import {{package}}.{{.StructTypeDef.Name}};
{{end}}{{end}}{{end}}

public interface {{cName}}Client {
{{range .Resources}}
    {{iMethod .}}{{end}}
}
`
const javaClientTemplate = `{{origHeader}}
package {{origPackage}};

import {{package}}.ResourceException;
{{range .Types}}{{if .StructTypeDef}}{{if .StructTypeDef.Name}}import {{package}}.{{.StructTypeDef.Name}};
{{end}}{{end}}{{end}}
import com.ning.http.client.AsyncHandler;
import com.yahoo.parsec.clients.DefaultAsyncCompletionHandler;
import com.yahoo.parsec.clients.ParsecAsyncHttpClient;
import com.yahoo.parsec.clients.ParsecAsyncHttpRequest;
import com.yahoo.parsec.clients.ParsecAsyncHttpRequest.Builder;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.core.UriBuilder;
import java.net.URI;
{{if needExpect .}}import java.util.HashSet;
import java.util.Set;{{end}}
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class {{cName}}ClientImpl implements {{cName}}Client {

    /** Logger. */
    private static final Logger LOGGER = LoggerFactory.getLogger(SampleClientImpl.class);

    /** ParsecAsyncHttpClient. */
    private final ParsecAsyncHttpClient parsecAsyncHttpClient;

    /** Object mapper */
    private final ObjectMapper objectMapper;

    /** URL. */
    private String url;

    /** Headers. */
    private final Map<String, String> headers;

    /**
     * connection timeout.
     */
    private static final int IDLE_CONNECTION_TIMEOUT_IN_MS = 15000;

    /**
     * total connections.
     */
    private static final int MAXIMUM_CONNECTIONS_TOTAL = 50;

    public {{cName}}ClientImpl(
        String url,
        Map<String, String> headers
    ) {

        ParsecAsyncHttpClient client  = null;
        try {
            client = new ParsecAsyncHttpClient.Builder()
                .setAcceptAnyCertificate(true)
                .setAllowPoolingConnections(true)
                .setPooledConnectionIdleTimeout(IDLE_CONNECTION_TIMEOUT_IN_MS)
                .setMaxConnections(MAXIMUM_CONNECTIONS_TOTAL)
                .build();
        } catch (ExecutionException e) {
            LOGGER.error("create ParsecAsyncHttpClient failed. " + e.getMessage());
            throw new ResourceException(ResourceException.INTERNAL_SERVER_ERROR, e.getMessage());
        }
        this.parsecAsyncHttpClient = client;
        this.objectMapper = new ObjectMapper();
        this.url = url;
        this.headers = headers;
    }

    public {{cName}}ClientImpl (
            ParsecAsyncHttpClient client,
            ObjectMapper objectMapper,
            String url,
            Map<String, String> headers)
    {
        this.parsecAsyncHttpClient = client;
        this.objectMapper = objectMapper;
        this.url = url;
        this.headers = headers;
    }

    private ParsecAsyncHttpRequest getRequest(String method, URI uri, String body) throws ResourceException {
        Builder builder = new Builder();

        builder.setUri(uri);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }

        builder.setMethod(method);

        builder.setBody(body).setBodyEncoding("UTF-8");

        ParsecAsyncHttpRequest request = null;
        try {
            request = builder.build();
        } catch (Exception e) {
            LOGGER.error("builder build failed: " + e.getMessage());
            throw new ResourceException(ResourceException.INTERNAL_SERVER_ERROR, e.getMessage());
        }
        return request;
    }
{{range .Resources}}
    @Override
    {{methodSig .}} {
        String path = "{{.Path}}";
        String body = null;
{{if needBody .}}
        try {
            body = objectMapper.writeValueAsString({{bodyObj .}});
        } catch (JsonProcessingException e) {
            LOGGER.error("JsonProcessingException: " + e.getMessage());
            throw new ResourceException(ResourceException.INTERNAL_SERVER_ERROR, e.getMessage());
        }
{{end}}
        URI uri = UriBuilder.fromUri(url).path(path){{builderExt .}}
        ParsecAsyncHttpRequest request = getRequest("{{.Method}}", uri, body);

{{if needExpect .}}
        Set<Integer> expectedStatus = new HashSet<>();
        expectedStatus.add(ResourceException.{{.Expected}});
        {{if .Alternatives}}{{range .Alternatives}}expectedStatus.add(ResourceException.{{.}});
{{end}}{{end}}
        AsyncHandler<{{returnType .}}> asyncHandler = new DefaultAsyncCompletionHandler<>({{returnType .}}.class, expectedStatus);
{{else}}
        AsyncHandler<{{returnType .}}> asyncHandler = new DefaultAsyncCompletionHandler<>({{returnType .}}.class);
{{end}}
        return parsecAsyncHttpClient.criticalExecute(request, asyncHandler);
    }
{{end}}
}
`

// todo: copy from go-schema.go
func safeTypeVarName(rtype rdl.TypeRef) rdl.TypeName {
	tokens := strings.Split(string(rtype), ".")
	return rdl.TypeName(utils.Capitalize(strings.Join(tokens, "")))
}

// todo: duplicate with server code, need integrate
func javaMethodName(reg rdl.TypeRegistry, r *rdl.Resource) (string, []string) {
	var params []string
	bodyType := string(safeTypeVarName(r.Type))
	for _, v := range r.Inputs {
		if v.Context != "" { //ignore these legacy things
			log.Println("Warning: v1 style context param ignored:", v.Name, v.Context)
			continue
		}
		k := v.Name
		if v.QueryParam == "" && !v.PathParam && v.Header == "" {
			bodyType = string(safeTypeVarName(v.Type))
		}
		optional := false // but different with server code, how?
		params = append(params, utils.JavaType(reg, v.Type, optional, "", "")+" "+javaName(k))
	}
	return strings.ToLower(string(r.Method)) + string(bodyType), params
}

// todo: duplicate with java-server.go
func javaName(name rdl.Identifier) string {
	switch name {
	case "type", "default": //other reserved words
		return "_" + string(name)
	default:
		return string(name)
	}
}

func (gen *javaClientGenerator) clientMethodSignature(r *rdl.Resource) string {
	reg := gen.registry
	returnType := utils.JavaType(reg, r.Type, true, "", "")
	methName, params := javaMethodName(reg, r)
	sparams := ""
	if len(params) > 0 {
		sparams = strings.Join(params, ", ")
	}
	if len(r.Outputs) > 0 {
		if sparams == "" {
			sparams = "java.util.Map<String,java.util.List<String>> headers"
		} else {
			sparams = sparams + ", java.util.Map<String,java.util.List<String>> headers"
		}
	}
	return "CompletableFuture<" + returnType + "> " + methName + "(" + sparams + ") throws ResourceException"
}

<|endoftext|>