<commit_before>/*
 Copyright Digital Asset Holdings, LLC 2016 All Rights Reserved.

 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 errors

import (
	"fmt"
	"testing"

	"github.com/hyperledger/fabric/flogging"
)

func TestError(t *testing.T) {
	e := Error(Utility, UtilityUnknownError)
	s := e.GetStack()
	if s != "" {
		t.Fatalf("No error stack should have been recorded.")
	}
}

// TestErrorWithArg tests creating an error with a message argument
func TestErrorWithArg(t *testing.T) {
	e := Error(Utility, UtilityErrorWithArg, "arg1")
	s := e.GetStack()
	if s != "" {
		t.Fatalf("No error stack should have been recorded.")
	}
}

func TestErrorWithCallstack(t *testing.T) {
	e := ErrorWithCallstack(Utility, UtilityUnknownError)
	s := e.GetStack()
	if s == "" {
		t.Fatalf("No error stack was recorded.")
	}
}

// TestErrorWithCallstackAndArg tests creating an error with a callstack and
// message argument
func TestErrorWithCallstackAndArg(t *testing.T) {
	e := ErrorWithCallstack(Utility, UtilityErrorWithArg, "arg1")
	s := e.GetStack()
	if s == "" {
		t.Fatalf("No error stack was recorded.")
	}
}

func ExampleError() {
	// when the 'error' module is set to anything but debug, the callstack will
	// not be appended to the error message
	flogging.SetModuleLogLevel("error", "warning")

	err := ErrorWithCallstack(Utility, UtilityUnknownError)

	if err != nil {
		fmt.Printf("%s\n", err.Error())
		fmt.Printf("%s\n", err.GetErrorCode())
		fmt.Printf("%s\n", err.GetComponentCode())
		fmt.Printf("%s\n", err.GetReasonCode())
		fmt.Printf("%s\n", err.Message())
		fmt.Printf("%s\n", err.MessageIn("en"))
		// Output:
		// An unknown error occurred.
		// Utility-UtilityUnknownError
		// Utility
		// UtilityUnknownError
		// An unknown error occurred.
		// An unknown error occurred.
	}
}

// ExampleErrorWithArg tests the output for a sample error with a message
// argument
func ExampleUtilityErrorWithArg() {
	// when the 'error' module is set to anything but debug, the callstack will
	// not be appended to the error message
	flogging.SetModuleLogLevel("error", "warning")

	err := ErrorWithCallstack(Utility, UtilityErrorWithArg, "arg1")

	if err != nil {
		fmt.Printf("%s\n", err.Error())
		fmt.Printf("%s\n", err.GetErrorCode())
		fmt.Printf("%s\n", err.GetComponentCode())
		fmt.Printf("%s\n", err.GetReasonCode())
		fmt.Printf("%s\n", err.Message())
		fmt.Printf("%s\n", err.MessageIn("en"))
		// Output:
		// An error occurred: arg1
		// Utility-UtilityErrorWithArg
		// Utility
		// UtilityErrorWithArg
		// An error occurred: arg1
		// An error occurred: arg1
	}
}

// ExampleLoggingInvalidLogLevel tests the output for a logging error where
// and an invalid log level has been provided
func ExampleLoggingInvalidLogLevel() {
	// when the 'error' module is set to anything but debug, the callstack will
	// not be appended to the error message
	flogging.SetModuleLogLevel("error", "warning")

	err := ErrorWithCallstack(Logging, LoggingInvalidLogLevel, "invalid")

	if err != nil {
		fmt.Printf("%s\n", err.Error())
		fmt.Printf("%s\n", err.GetErrorCode())
		fmt.Printf("%s\n", err.GetComponentCode())
		fmt.Printf("%s\n", err.GetReasonCode())
		fmt.Printf("%s\n", err.Message())
		fmt.Printf("%s\n", err.MessageIn("en"))
		// Output:
		// Invalid log level provided - invalid
		// Logging-LoggingInvalidLogLevel
		// Logging
		// LoggingInvalidLogLevel
		// Invalid log level provided - invalid
		// Invalid log level provided - invalid
	}
}

// ExampleLoggingInvalidLogLevel tests the output for a logging error where
// and an invalid log level has been provided and the stack trace should be
// displayed with the error message
func ExampleLoggingInvalidLogLevel_withCallstack() {
	// when the 'error' module is set to debug, the callstack will be appended
	// to the error message
	flogging.SetModuleLogLevel("error", "debug")

	err := ErrorWithCallstack(Logging, LoggingInvalidLogLevel, "invalid")

	if err != nil {
		fmt.Printf("%s", err.Error())
		fmt.Printf("%s\n", err.GetErrorCode())
		fmt.Printf("%s\n", err.GetComponentCode())
		fmt.Printf("%s\n", err.GetReasonCode())
		fmt.Printf("%s", err.Message())
		fmt.Printf("%s\n", err.MessageIn("en"))
		// Output:
		// Invalid log level provided - invalid
		// /opt/gopath/src/github.com/hyperledger/fabric/core/errors/errors_test.go:145 github.com/hyperledger/fabric/core/errors.ExampleLoggingInvalidLogLevel_withCallstack
		// /opt/go/src/testing/example.go:115 testing.runExample
		// /opt/go/src/testing/example.go:38 testing.RunExamples
		// /opt/go/src/testing/testing.go:744 testing.(*M).Run
		// github.com/hyperledger/fabric/core/errors/_test/_testmain.go:116 main.main
		// /opt/go/src/runtime/proc.go:192 runtime.main
		// /opt/go/src/runtime/asm_amd64.s:2087 runtime.goexit
		// Logging-LoggingInvalidLogLevel
		// Logging
		// LoggingInvalidLogLevel
		// Invalid log level provided - invalid
		// /opt/gopath/src/github.com/hyperledger/fabric/core/errors/errors_test.go:145 github.com/hyperledger/fabric/core/errors.ExampleLoggingInvalidLogLevel_withCallstack
		// /opt/go/src/testing/example.go:115 testing.runExample
		// /opt/go/src/testing/example.go:38 testing.RunExamples
		// /opt/go/src/testing/testing.go:744 testing.(*M).Run
		// github.com/hyperledger/fabric/core/errors/_test/_testmain.go:116 main.main
		// /opt/go/src/runtime/proc.go:192 runtime.main
		// /opt/go/src/runtime/asm_amd64.s:2087 runtime.goexit
		// Invalid log level provided - invalid
	}
}
<commit_msg>FAB-1311 errors unit test fails on z/p architectures<commit_after>/*
 Copyright Digital Asset Holdings, LLC 2016 All Rights Reserved.

 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 errors

import (
	"fmt"
	"strings"
	"testing"

	"github.com/hyperledger/fabric/flogging"
)

func TestError(t *testing.T) {
	e := Error(Utility, UtilityUnknownError)
	s := e.GetStack()
	if s != "" {
		t.Fatalf("No error stack should have been recorded.")
	}
}

// TestErrorWithArg tests creating an error with a message argument
func TestErrorWithArg(t *testing.T) {
	e := Error(Utility, UtilityErrorWithArg, "arg1")
	s := e.GetStack()
	if s != "" {
		t.Fatalf("No error stack should have been recorded.")
	}
}

func TestErrorWithCallstack(t *testing.T) {
	e := ErrorWithCallstack(Utility, UtilityUnknownError)
	s := e.GetStack()
	if s == "" {
		t.Fatalf("No error stack was recorded.")
	}
}

// TestErrorWithCallstackAndArg tests creating an error with a callstack and
// message argument
func TestErrorWithCallstackAndArg(t *testing.T) {
	e := ErrorWithCallstack(Utility, UtilityErrorWithArg, "arg1")
	s := e.GetStack()
	if s == "" {
		t.Fatalf("No error stack was recorded.")
	}
}

// TestErrorWithCallstackMessage tests the output for a logging error where
// and an invalid log level has been provided and the stack trace should be
// displayed with the error message
func TestErrorWithCallstackMessage(t *testing.T) {
	// when the 'error' module is set to debug, the callstack will be appended
	// to the error message
	flogging.SetModuleLogLevel("error", "debug")

	e := ErrorWithCallstack(Utility, UtilityUnknownError)
	s := e.GetStack()
	if s == "" {
		t.Fatalf("No error stack was recorded.")
	}

	// check that the error message contains this part of the stack trace, which
	// is non-platform specific
	if !strings.Contains(e.Error(), "github.com/hyperledger/fabric/core/errors.TestErrorWithCallstackMessage") {
		t.Fatalf("Error message does not have stack trace appended.")
	}
}

func ExampleError() {
	// when the 'error' module is set to anything but debug, the callstack will
	// not be appended to the error message
	flogging.SetModuleLogLevel("error", "warning")

	err := ErrorWithCallstack(Utility, UtilityUnknownError)

	if err != nil {
		fmt.Printf("%s\n", err.Error())
		fmt.Printf("%s\n", err.GetErrorCode())
		fmt.Printf("%s\n", err.GetComponentCode())
		fmt.Printf("%s\n", err.GetReasonCode())
		fmt.Printf("%s\n", err.Message())
		fmt.Printf("%s\n", err.MessageIn("en"))
		// Output:
		// An unknown error occurred.
		// Utility-UtilityUnknownError
		// Utility
		// UtilityUnknownError
		// An unknown error occurred.
		// An unknown error occurred.
	}
}

// ExampleErrorWithArg tests the output for a sample error with a message
// argument
func ExampleUtilityErrorWithArg() {
	// when the 'error' module is set to anything but debug, the callstack will
	// not be appended to the error message
	flogging.SetModuleLogLevel("error", "warning")

	err := ErrorWithCallstack(Utility, UtilityErrorWithArg, "arg1")

	if err != nil {
		fmt.Printf("%s\n", err.Error())
		fmt.Printf("%s\n", err.GetErrorCode())
		fmt.Printf("%s\n", err.GetComponentCode())
		fmt.Printf("%s\n", err.GetReasonCode())
		fmt.Printf("%s\n", err.Message())
		fmt.Printf("%s\n", err.MessageIn("en"))
		// Output:
		// An error occurred: arg1
		// Utility-UtilityErrorWithArg
		// Utility
		// UtilityErrorWithArg
		// An error occurred: arg1
		// An error occurred: arg1
	}
}

// ExampleLoggingInvalidLogLevel tests the output for a logging error where
// and an invalid log level has been provided
func ExampleLoggingInvalidLogLevel() {
	// when the 'error' module is set to anything but debug, the callstack will
	// not be appended to the error message
	flogging.SetModuleLogLevel("error", "warning")

	err := ErrorWithCallstack(Logging, LoggingInvalidLogLevel, "invalid")

	if err != nil {
		fmt.Printf("%s\n", err.Error())
		fmt.Printf("%s\n", err.GetErrorCode())
		fmt.Printf("%s\n", err.GetComponentCode())
		fmt.Printf("%s\n", err.GetReasonCode())
		fmt.Printf("%s\n", err.Message())
		fmt.Printf("%s\n", err.MessageIn("en"))
		// Output:
		// Invalid log level provided - invalid
		// Logging-LoggingInvalidLogLevel
		// Logging
		// LoggingInvalidLogLevel
		// Invalid log level provided - invalid
		// Invalid log level provided - invalid
	}
}
<|endoftext|>


<commit_before>package doubleratchet

import (
	"github.com/stretchr/testify/require"
	"testing"
)

func TestDhPair(t *testing.T) {
	// Arrange.
	p := dhPair{
		privateKey: [32]byte{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
		publicKey:  [32]byte{6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6},
	}

	// Act.
	var (
		privKey = p.PrivateKey()
		pubKey  = p.PublicKey()
	)

	// Assert.
	require.Equal(t, p.privateKey, privKey)
	require.Equal(t, p.publicKey, pubKey)
}

func TestDefaultCrypto_GenerateDH_Basic(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	pair, err := c.GenerateDH()

	// Assert.
	require.Nil(t, err)

	require.EqualValues(t, 0, pair.PrivateKey()[0]&7)
	require.EqualValues(t, 0, pair.PrivateKey()[31]&128)
	require.EqualValues(t, 64, pair.PrivateKey()[31]&64)

	require.NotEqual(t, [32]byte{}, pair.PrivateKey())
	require.NotEqual(t, [32]byte{}, pair.PublicKey())
	require.Len(t, pair.PrivateKey(), 32)
	require.Len(t, pair.PublicKey(), 32)
	require.NotEqual(t, pair.PublicKey(), pair.PrivateKey())
}

func TestDefaultCrypto_GenerateDH_DifferentKeysEveryTime(t *testing.T) {
	// Arrange.
	var (
		c    = DefaultCrypto{}
		keys = make(map[[32]byte]bool)
	)

	for i := 0; i < 10; i++ {
		t.Run("", func(t *testing.T) {
			// Act.
			pair, err := c.GenerateDH()

			// Assert.
			require.Nil(t, err)
			require.False(t, keys[pair.PrivateKey()])
			require.False(t, keys[pair.PublicKey()])

			// Preserve.
			keys[pair.PrivateKey()] = true
			keys[pair.PublicKey()] = true
		})
	}
}

func TestDefaultCrypto_DH(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	var (
		alicePair, err1 = c.GenerateDH()
		bobPair, err2   = c.GenerateDH()
		aliceSK         = c.DH(alicePair, bobPair.PublicKey())
		bobSK           = c.DH(bobPair, alicePair.PublicKey())
	)

	// Assert.
	require.Nil(t, err1)
	require.Nil(t, err2)
	require.NotEqual(t, [32]byte{}, aliceSK)
	require.Equal(t, aliceSK, bobSK)
}

func TestDefaultCrypto_KdfRK(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	newRK, newCK := c.KdfRK(
		[32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40},
		[32]byte{0x9c, 0x1e, 0x68, 0xab, 0x9d, 0x45, 0xf5, 0x82, 0x35, 0xc4, 0x2, 0xa8, 0x82, 0xa1, 0x46, 0x55, 0x35, 0x41, 0xf1, 0x9d, 0x87, 0x2b, 0x59, 0x24, 0x39, 0x3b, 0x91, 0xf7, 0xda, 0x46, 0x56, 0xf},
	)

	// Assert.
	require.NotEqual(t, [32]byte{}, newRK)
	require.NotEqual(t, [32]byte{}, newCK)
	require.Len(t, newRK, 32)
	require.Len(t, newCK, 32)
	require.NotEqual(t, newRK, newCK)
}

func TestDefaultCrypto_KdfCK(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	newCK, mk := c.KdfCK([32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40})

	// Assert.
	require.NotEqual(t, [32]byte{}, newCK)
	require.NotEqual(t, [32]byte{}, mk)
	require.Len(t, newCK, 32)
	require.Len(t, mk, 32)
	require.NotEqual(t, mk, newCK)
}

func TestDefaultCrypto_deriveEncKeys(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	encKey, authKey, iv := c.deriveEncKeys([32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40})

	// Assert.
	require.Len(t, encKey, 32)
	require.Len(t, authKey, 32)
	require.Len(t, iv, 16)
	require.NotEqual(t, [32]byte{}, encKey)
	require.NotEqual(t, [32]byte{}, authKey)
	require.NotContains(t, encKey, iv)
	require.NotContains(t, authKey, iv)
	require.NotEqual(t, encKey, authKey)
}

func TestDefaultCrypto_computeSignature(t *testing.T) {
	// Arrange.
	var (
		c          = DefaultCrypto{}
		ciphertext = []byte{13, 250, 114, 78}
	)

	// Act.
	signature := c.computeSignature(
		[]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40},
		ciphertext,
		nil,
	)

	// Assert.
	require.Len(t, signature, 32)
	require.NotEqual(t, [32]byte{}, signature)
}

func TestDefaultCrypto_EncryptDecrypt(t *testing.T) {
	// Arrange.
	var (
		c   = DefaultCrypto{}
		msg = []byte("1337")
		mk  = [32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40}
	)

	t.Run("no associated data", func(t *testing.T) {
		// Act.
		var (
			ciphertext     = c.Encrypt(mk, msg, nil)
			plaintext, err = c.Decrypt(mk, ciphertext, nil)
		)

		// Assert.
		require.Nil(t, err)
		require.Len(t, ciphertext, 16+len(msg)+32) // iv + plaintext length + signature
		require.Equal(t, msg, plaintext)
	})

	t.Run("same associated data", func(t *testing.T) {
		// Act.
		var (
			ciphertext     = c.Encrypt(mk, msg, []byte("any secret"))
			plaintext, err = c.Decrypt(mk, ciphertext, []byte("any secret"))
		)

		// Assert.
		require.Nil(t, err)
		require.Len(t, ciphertext, 32+16+len(msg)) // signature + iv + plaintext length
		require.Equal(t, msg, plaintext)
	})

	t.Run("different associated data", func(t *testing.T) {
		// Act.
		var (
			ciphertext = c.Encrypt(mk, msg, []byte("not secret at all"))
			_, err     = c.Decrypt(mk, ciphertext, []byte("any secret"))
		)

		// Assert.
		require.EqualError(t, err, "invalid signature")
	})

	t.Run("malformed signature", func(t *testing.T) {
		// Act.
		ciphertext := c.Encrypt(mk, msg, nil)
		ciphertext[len(ciphertext)-1] ^= 57 // Inverse the last byte in the signature.
		_, err := c.Decrypt(mk, ciphertext, nil)

		// Assert.
		require.EqualError(t, err, "invalid signature")
	})
}
<commit_msg>dhPair.String() test<commit_after>package doubleratchet

import (
	"fmt"
	"github.com/stretchr/testify/require"
	"testing"
)

func TestDhPair(t *testing.T) {
	// Arrange.
	p := dhPair{
		privateKey: [32]byte{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
		publicKey:  [32]byte{6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6},
	}

	// Act.
	var (
		privKey = p.PrivateKey()
		pubKey  = p.PublicKey()
	)

	// Assert.
	require.Equal(t, p.privateKey, privKey)
	require.Equal(t, p.publicKey, pubKey)
	require.Equal(t, fmt.Sprintf(`{privateKey: %s publicKey: %s}`, p.PrivateKey(), p.PublicKey()), p.String())
}

func TestDefaultCrypto_GenerateDH_Basic(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	pair, err := c.GenerateDH()

	// Assert.
	require.Nil(t, err)

	require.EqualValues(t, 0, pair.PrivateKey()[0]&7)
	require.EqualValues(t, 0, pair.PrivateKey()[31]&128)
	require.EqualValues(t, 64, pair.PrivateKey()[31]&64)

	require.NotEqual(t, [32]byte{}, pair.PrivateKey())
	require.NotEqual(t, [32]byte{}, pair.PublicKey())
	require.Len(t, pair.PrivateKey(), 32)
	require.Len(t, pair.PublicKey(), 32)
	require.NotEqual(t, pair.PublicKey(), pair.PrivateKey())
}

func TestDefaultCrypto_GenerateDH_DifferentKeysEveryTime(t *testing.T) {
	// Arrange.
	var (
		c    = DefaultCrypto{}
		keys = make(map[[32]byte]bool)
	)

	for i := 0; i < 10; i++ {
		t.Run("", func(t *testing.T) {
			// Act.
			pair, err := c.GenerateDH()

			// Assert.
			require.Nil(t, err)
			require.False(t, keys[pair.PrivateKey()])
			require.False(t, keys[pair.PublicKey()])

			// Preserve.
			keys[pair.PrivateKey()] = true
			keys[pair.PublicKey()] = true
		})
	}
}

func TestDefaultCrypto_DH(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	var (
		alicePair, err1 = c.GenerateDH()
		bobPair, err2   = c.GenerateDH()
		aliceSK         = c.DH(alicePair, bobPair.PublicKey())
		bobSK           = c.DH(bobPair, alicePair.PublicKey())
	)

	// Assert.
	require.Nil(t, err1)
	require.Nil(t, err2)
	require.NotEqual(t, [32]byte{}, aliceSK)
	require.Equal(t, aliceSK, bobSK)
}

func TestDefaultCrypto_KdfRK(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	newRK, newCK := c.KdfRK(
		[32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40},
		[32]byte{0x9c, 0x1e, 0x68, 0xab, 0x9d, 0x45, 0xf5, 0x82, 0x35, 0xc4, 0x2, 0xa8, 0x82, 0xa1, 0x46, 0x55, 0x35, 0x41, 0xf1, 0x9d, 0x87, 0x2b, 0x59, 0x24, 0x39, 0x3b, 0x91, 0xf7, 0xda, 0x46, 0x56, 0xf},
	)

	// Assert.
	require.NotEqual(t, [32]byte{}, newRK)
	require.NotEqual(t, [32]byte{}, newCK)
	require.Len(t, newRK, 32)
	require.Len(t, newCK, 32)
	require.NotEqual(t, newRK, newCK)
}

func TestDefaultCrypto_KdfCK(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	newCK, mk := c.KdfCK([32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40})

	// Assert.
	require.NotEqual(t, [32]byte{}, newCK)
	require.NotEqual(t, [32]byte{}, mk)
	require.Len(t, newCK, 32)
	require.Len(t, mk, 32)
	require.NotEqual(t, mk, newCK)
}

func TestDefaultCrypto_deriveEncKeys(t *testing.T) {
	// Arrange.
	c := DefaultCrypto{}

	// Act.
	encKey, authKey, iv := c.deriveEncKeys([32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40})

	// Assert.
	require.Len(t, encKey, 32)
	require.Len(t, authKey, 32)
	require.Len(t, iv, 16)
	require.NotEqual(t, [32]byte{}, encKey)
	require.NotEqual(t, [32]byte{}, authKey)
	require.NotContains(t, encKey, iv)
	require.NotContains(t, authKey, iv)
	require.NotEqual(t, encKey, authKey)
}

func TestDefaultCrypto_computeSignature(t *testing.T) {
	// Arrange.
	var (
		c          = DefaultCrypto{}
		ciphertext = []byte{13, 250, 114, 78}
	)

	// Act.
	signature := c.computeSignature(
		[]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40},
		ciphertext,
		nil,
	)

	// Assert.
	require.Len(t, signature, 32)
	require.NotEqual(t, [32]byte{}, signature)
}

func TestDefaultCrypto_EncryptDecrypt(t *testing.T) {
	// Arrange.
	var (
		c   = DefaultCrypto{}
		msg = []byte("1337")
		mk  = [32]byte{0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20, 0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a, 0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb, 0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40}
	)

	t.Run("no associated data", func(t *testing.T) {
		// Act.
		var (
			ciphertext     = c.Encrypt(mk, msg, nil)
			plaintext, err = c.Decrypt(mk, ciphertext, nil)
		)

		// Assert.
		require.Nil(t, err)
		require.Len(t, ciphertext, 16+len(msg)+32) // iv + plaintext length + signature
		require.Equal(t, msg, plaintext)
	})

	t.Run("same associated data", func(t *testing.T) {
		// Act.
		var (
			ciphertext     = c.Encrypt(mk, msg, []byte("any secret"))
			plaintext, err = c.Decrypt(mk, ciphertext, []byte("any secret"))
		)

		// Assert.
		require.Nil(t, err)
		require.Len(t, ciphertext, 32+16+len(msg)) // signature + iv + plaintext length
		require.Equal(t, msg, plaintext)
	})

	t.Run("different associated data", func(t *testing.T) {
		// Act.
		var (
			ciphertext = c.Encrypt(mk, msg, []byte("not secret at all"))
			_, err     = c.Decrypt(mk, ciphertext, []byte("any secret"))
		)

		// Assert.
		require.EqualError(t, err, "invalid signature")
	})

	t.Run("malformed signature", func(t *testing.T) {
		// Act.
		ciphertext := c.Encrypt(mk, msg, nil)
		ciphertext[len(ciphertext)-1] ^= 57 // Inverse the last byte in the signature.
		_, err := c.Decrypt(mk, ciphertext, nil)

		// Assert.
		require.EqualError(t, err, "invalid signature")
	})
}
<|endoftext|>


<commit_before>package templates

type SecurityGroupTemplateBuilder struct{}

func NewSecurityGroupTemplateBuilder() SecurityGroupTemplateBuilder {
	return SecurityGroupTemplateBuilder{}
}

func (t SecurityGroupTemplateBuilder) InternalSecurityGroup() Template {
	return Template{
		Resources: map[string]Resource{
			"InternalSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "Internal",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						{
							IpProtocol: "tcp",
							FromPort:   "0",
							ToPort:     "65535",
						},
						{
							IpProtocol: "udp",
							FromPort:   "0",
							ToPort:     "65535",
						},
						{
							CidrIp:     "0.0.0.0/0",
							IpProtocol: "icmp",
							FromPort:   "-1",
							ToPort:     "-1",
						},
					},
				},
			},
			"InternalSecurityGroupIngressTCPfromBOSH": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"BOSHSecurityGroup"},
					IpProtocol:            "tcp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
			"InternalSecurityGroupIngressUDPfromBOSH": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"BOSHSecurityGroup"},
					IpProtocol:            "udp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
			"InternalSecurityGroupIngressTCPfromSelf": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"InternalSecurityGroup"},
					IpProtocol:            "tcp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
			"InternalSecurityGroupIngressUDPfromSelf": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"InternalSecurityGroup"},
					IpProtocol:            "udp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
		},
	}
}

func (t SecurityGroupTemplateBuilder) BOSHSecurityGroup() Template {
	return Template{
		Parameters: map[string]Parameter{
			"BOSHInboundCIDR": Parameter{
				Description: "CIDR to permit access to BOSH (e.g. 205.103.216.37/32 for your specific IP)",
				Type:        "String",
				Default:     "0.0.0.0/0",
			},
		},
		Resources: map[string]Resource{
			"BOSHSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "BOSH",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						{
							CidrIp:     Ref{"BOSHInboundCIDR"},
							IpProtocol: "tcp",
							FromPort:   "22",
							ToPort:     "22",
						},

						{
							CidrIp:     Ref{"BOSHInboundCIDR"},
							IpProtocol: "tcp",
							FromPort:   "6868",
							ToPort:     "6868",
						},
						{
							CidrIp:     Ref{"BOSHInboundCIDR"},
							IpProtocol: "tcp",
							FromPort:   "25555",
							ToPort:     "25555",
						},
						{
							SourceSecurityGroupId: Ref{"InternalSecurityGroup"},
							IpProtocol:            "tcp",
							FromPort:              "0",
							ToPort:                "65535",
						},
						{
							SourceSecurityGroupId: Ref{"InternalSecurityGroup"},
							IpProtocol:            "udp",
							FromPort:              "0",
							ToPort:                "65535",
						},
					},
				},
			},
		},
		Outputs: map[string]Output{
			"BOSHSecurityGroup": Output{Value: Ref{"BOSHSecurityGroup"}},
		},
	}
}

func (t SecurityGroupTemplateBuilder) ConcourseSecurityGroup() Template {
	return Template{
		Resources: map[string]Resource{
			"ConcourseSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "Concourse",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						{
							CidrIp:     "0.0.0.0/0",
							IpProtocol: "tcp",
							FromPort:   "80",
							ToPort:     "80",
						},
						{
							CidrIp:     "0.0.0.0/0",
							IpProtocol: "tcp",
							FromPort:   "2222",
							ToPort:     "2222",
						},
						{
							CidrIp:     "0.0.0.0/0",
							IpProtocol: "tcp",
							FromPort:   "443",
							ToPort:     "443",
						},
					},
				},
			},
			"InternalSecurityGroupIngressTCPfromConcourseSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"ConcourseSecurityGroup"},
					IpProtocol:            "tcp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
			"InternalSecurityGroupIngressUDPfromConcourseSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"ConcourseSecurityGroup"},
					IpProtocol:            "udp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
		},
	}
}

func (SecurityGroupTemplateBuilder) CFRouterSecurityGroup() Template {
	return Template{
		Resources: map[string]Resource{
			"CFRouterSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "Router",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						{
							CidrIp:     "0.0.0.0/0",
							IpProtocol: "tcp",
							FromPort:   "80",
							ToPort:     "80",
						},
						{
							CidrIp:     "0.0.0.0/0",
							IpProtocol: "tcp",
							FromPort:   "2222",
							ToPort:     "2222",
						},
						{
							CidrIp:     "0.0.0.0/0",
							IpProtocol: "tcp",
							FromPort:   "443",
							ToPort:     "443",
						},
					},
				},
			},
			"InternalSecurityGroupIngressTCPfromCFRouterSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"CFRouterSecurityGroup"},
					IpProtocol:            "tcp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
			"InternalSecurityGroupIngressUDPfromCFRouterSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"CFRouterSecurityGroup"},
					IpProtocol:            "udp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
		},
	}
}

func (SecurityGroupTemplateBuilder) CFSSHProxySecurityGroup() Template {
	return Template{
		Resources: map[string]Resource{
			"CFSSHProxySecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "CFSSHProxy",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						{
							CidrIp:     "0.0.0.0/0",
							IpProtocol: "tcp",
							FromPort:   "2222",
							ToPort:     "2222",
						},
					},
				},
			},
			"InternalSecurityGroupIngressTCPfromCFSSHProxySecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroupIngress",
				Properties: SecurityGroupIngress{
					GroupId:               Ref{"InternalSecurityGroup"},
					SourceSecurityGroupId: Ref{"CFSSHProxySecurityGroup"},
					IpProtocol:            "tcp",
					FromPort:              "0",
					ToPort:                "65535",
				},
			},
		},
	}
}
<commit_msg>Extract private methods in SecurityGroupTemplateBuilder<commit_after>package templates

type SecurityGroupTemplateBuilder struct{}

func NewSecurityGroupTemplateBuilder() SecurityGroupTemplateBuilder {
	return SecurityGroupTemplateBuilder{}
}

func (s SecurityGroupTemplateBuilder) InternalSecurityGroup() Template {
	return Template{
		Resources: map[string]Resource{
			"InternalSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "Internal",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						s.securityGroupIngress(nil, "tcp", "0", "65535", nil),
						s.securityGroupIngress(nil, "udp", "0", "65535", nil),
						s.securityGroupIngress("0.0.0.0/0", "icmp", "-1", "-1", nil),
					},
				},
			},
			"InternalSecurityGroupIngressTCPfromBOSH": s.internalSecurityGroupIngress("BOSHSecurityGroup", "tcp"),
			"InternalSecurityGroupIngressUDPfromBOSH": s.internalSecurityGroupIngress("BOSHSecurityGroup", "udp"),
			"InternalSecurityGroupIngressTCPfromSelf": s.internalSecurityGroupIngress("InternalSecurityGroup", "tcp"),
			"InternalSecurityGroupIngressUDPfromSelf": s.internalSecurityGroupIngress("InternalSecurityGroup", "udp"),
		},
	}
}

func (s SecurityGroupTemplateBuilder) BOSHSecurityGroup() Template {
	return Template{
		Parameters: map[string]Parameter{
			"BOSHInboundCIDR": Parameter{
				Description: "CIDR to permit access to BOSH (e.g. 205.103.216.37/32 for your specific IP)",
				Type:        "String",
				Default:     "0.0.0.0/0",
			},
		},
		Resources: map[string]Resource{
			"BOSHSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "BOSH",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						s.securityGroupIngress(Ref{"BOSHInboundCIDR"}, "tcp", "22", "22", nil),
						s.securityGroupIngress(Ref{"BOSHInboundCIDR"}, "tcp", "6868", "6868", nil),
						s.securityGroupIngress(Ref{"BOSHInboundCIDR"}, "tcp", "25555", "25555", nil),
						s.securityGroupIngress(nil, "tcp", "0", "65535", Ref{"InternalSecurityGroup"}),
						s.securityGroupIngress(nil, "udp", "0", "65535", Ref{"InternalSecurityGroup"}),
					},
				},
			},
		},
		Outputs: map[string]Output{
			"BOSHSecurityGroup": Output{Value: Ref{"BOSHSecurityGroup"}},
		},
	}
}

func (s SecurityGroupTemplateBuilder) ConcourseSecurityGroup() Template {
	return Template{
		Resources: map[string]Resource{
			"ConcourseSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "Concourse",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						s.securityGroupIngress("0.0.0.0/0", "tcp", "80", "80", nil),
						s.securityGroupIngress("0.0.0.0/0", "tcp", "2222", "2222", nil),
						s.securityGroupIngress("0.0.0.0/0", "tcp", "443", "443", nil),
					},
				},
			},
			"InternalSecurityGroupIngressTCPfromConcourseSecurityGroup": s.internalSecurityGroupIngress("ConcourseSecurityGroup", "tcp"),
			"InternalSecurityGroupIngressUDPfromConcourseSecurityGroup": s.internalSecurityGroupIngress("ConcourseSecurityGroup", "udp"),
		},
	}
}

func (s SecurityGroupTemplateBuilder) CFRouterSecurityGroup() Template {
	return Template{
		Resources: map[string]Resource{
			"CFRouterSecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "Router",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						s.securityGroupIngress("0.0.0.0/0", "tcp", "80", "80", nil),
						s.securityGroupIngress("0.0.0.0/0", "tcp", "2222", "2222", nil),
						s.securityGroupIngress("0.0.0.0/0", "tcp", "443", "443", nil),
					},
				},
			},
			"InternalSecurityGroupIngressTCPfromCFRouterSecurityGroup": s.internalSecurityGroupIngress("CFRouterSecurityGroup", "tcp"),
			"InternalSecurityGroupIngressUDPfromCFRouterSecurityGroup": s.internalSecurityGroupIngress("CFRouterSecurityGroup", "udp"),
		},
	}
}

func (s SecurityGroupTemplateBuilder) CFSSHProxySecurityGroup() Template {
	return Template{
		Resources: map[string]Resource{
			"CFSSHProxySecurityGroup": Resource{
				Type: "AWS::EC2::SecurityGroup",
				Properties: SecurityGroup{
					VpcId:               Ref{"VPC"},
					GroupDescription:    "CFSSHProxy",
					SecurityGroupEgress: []string{},
					SecurityGroupIngress: []SecurityGroupIngress{
						s.securityGroupIngress("0.0.0.0/0", "tcp", "2222", "2222", nil),
					},
				},
			},
			"InternalSecurityGroupIngressTCPfromCFSSHProxySecurityGroup": s.internalSecurityGroupIngress("CFSSHProxySecurityGroup", "tcp"),
		},
	}
}

func (SecurityGroupTemplateBuilder) internalSecurityGroupIngress(sourceSecurityGroupId, ipProtocol string) Resource {
	return Resource{
		Type: "AWS::EC2::SecurityGroupIngress",
		Properties: SecurityGroupIngress{
			GroupId:               Ref{"InternalSecurityGroup"},
			SourceSecurityGroupId: Ref{sourceSecurityGroupId},
			IpProtocol:            ipProtocol,
			FromPort:              "0",
			ToPort:                "65535",
		},
	}
}

func (SecurityGroupTemplateBuilder) securityGroupIngress(
	cidrIP interface{}, ipProtocol string, fromPort string, toPort string,
	sourceSecurityGroupId interface{}) SecurityGroupIngress {

	return SecurityGroupIngress{
		CidrIp:                cidrIP,
		IpProtocol:            ipProtocol,
		FromPort:              fromPort,
		ToPort:                toPort,
		SourceSecurityGroupId: sourceSecurityGroupId,
	}
}
<|endoftext|>


<commit_before>package canopus

import (
	"net"
	"strconv"
	"strings"
)

// Creates a New Request Instance
func NewRequest(messageType uint8, messageMethod CoapCode, messageID uint16) CoapRequest {
	msg := NewMessage(messageType, messageMethod, messageID)
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewConfirmableGetRequest() CoapRequest {
	msg := NewMessage(MessageConfirmable, Get, GenerateMessageID())
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewConfirmablePostRequest() CoapRequest {
	msg := NewMessage(MessageConfirmable, Post, GenerateMessageID())
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewConfirmablePutRequest() CoapRequest {
	msg := NewMessage(MessageConfirmable, Put, GenerateMessageID())
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewConfirmableDeleteRequest() CoapRequest {
	msg := NewMessage(MessageConfirmable, Delete, GenerateMessageID())
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

// Creates a new request messages from a CoAP Message
func NewRequestFromMessage(msg *Message) CoapRequest {
	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewClientRequestFromMessage(msg *Message, attrs map[string]string, conn *net.UDPConn, addr *net.UDPAddr) CoapRequest {
	return &DefaultCoapRequest{
		msg:   msg,
		attrs: attrs,
		conn:  conn,
		addr:  addr,
	}
}

type CoapRequest interface {
	SetProxyURI(uri string)
	SetMediaType(mt MediaType)
	GetConnection() *net.UDPConn
	GetAddress() *net.UDPAddr
	GetAttributes() map[string]string
	GetAttribute(o string) string
	GetAttributeAsInt(o string) int
	GetMessage() *Message
	SetStringPayload(s string)
	SetRequestURI(uri string)
	SetConfirmable(con bool)
	SetToken(t string)
	GetURIQuery(q string) string
	SetURIQuery(k string, v string)
}

// Wraps a CoAP Message as a Request
// Provides various methods which proxies the Message object methods
type DefaultCoapRequest struct {
	msg    *Message
	attrs  map[string]string
	conn   *net.UDPConn
	addr   *net.UDPAddr
	server *CoapServer
}

func (c *DefaultCoapRequest) SetProxyURI(uri string) {
	c.msg.AddOption(OptionProxyURI, uri)
}

func (c *DefaultCoapRequest) SetMediaType(mt MediaType) {
	c.msg.AddOption(OptionContentFormat, mt)
}

func (c *DefaultCoapRequest) GetConnection() *net.UDPConn {
	return c.conn
}

func (c *DefaultCoapRequest) GetAddress() *net.UDPAddr {
	return c.addr
}

func (c *DefaultCoapRequest) GetAttributes() map[string]string {
	return c.attrs
}

func (c *DefaultCoapRequest) GetAttribute(o string) string {
	return c.attrs[o]
}

func (c *DefaultCoapRequest) GetAttributeAsInt(o string) int {
	attr := c.GetAttribute(o)
	i, _ := strconv.Atoi(attr)

	return i
}

func (c *DefaultCoapRequest) GetMessage() *Message {
	return c.msg
}

func (c *DefaultCoapRequest) SetStringPayload(s string) {
	c.msg.Payload = NewPlainTextPayload(s)
}

func (c *DefaultCoapRequest) SetRequestURI(uri string) {
	c.msg.AddOptions(NewPathOptions(uri))
}

func (c *DefaultCoapRequest) SetConfirmable(con bool) {
	if con {
		c.msg.MessageType = MessageConfirmable
	} else {
		c.msg.MessageType = MessageNonConfirmable
	}
}

func (c *DefaultCoapRequest) SetToken(t string) {
	c.msg.Token = []byte(t)
}

func (c *DefaultCoapRequest) GetURIQuery(q string) string {
	qs := c.GetMessage().GetOptionsAsString(OptionURIQuery)

	for _, o := range qs {
		ps := strings.Split(o, "=")
		if len(ps) == 2 {
			if ps[0] == q {
				return ps[1]
			}
		}
	}
	return ""
}

func (c *DefaultCoapRequest) SetURIQuery(k string, v string) {
	c.GetMessage().AddOption(OptionURIQuery, k+"="+v)
}
<commit_msg>SetPayload method for Request<commit_after>package canopus

import (
	"net"
	"strconv"
	"strings"
)

// Creates a New Request Instance
func NewRequest(messageType uint8, messageMethod CoapCode, messageID uint16) CoapRequest {
	msg := NewMessage(messageType, messageMethod, messageID)
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewConfirmableGetRequest() CoapRequest {
	msg := NewMessage(MessageConfirmable, Get, GenerateMessageID())
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewConfirmablePostRequest() CoapRequest {
	msg := NewMessage(MessageConfirmable, Post, GenerateMessageID())
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewConfirmablePutRequest() CoapRequest {
	msg := NewMessage(MessageConfirmable, Put, GenerateMessageID())
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewConfirmableDeleteRequest() CoapRequest {
	msg := NewMessage(MessageConfirmable, Delete, GenerateMessageID())
	msg.Token = []byte(GenerateToken(8))

	return &DefaultCoapRequest{
		msg: msg,
	}
}

// Creates a new request messages from a CoAP Message
func NewRequestFromMessage(msg *Message) CoapRequest {
	return &DefaultCoapRequest{
		msg: msg,
	}
}

func NewClientRequestFromMessage(msg *Message, attrs map[string]string, conn *net.UDPConn, addr *net.UDPAddr) CoapRequest {
	return &DefaultCoapRequest{
		msg:   msg,
		attrs: attrs,
		conn:  conn,
		addr:  addr,
	}
}

type CoapRequest interface {
	SetProxyURI(uri string)
	SetMediaType(mt MediaType)
	GetConnection() *net.UDPConn
	GetAddress() *net.UDPAddr
	GetAttributes() map[string]string
	GetAttribute(o string) string
	GetAttributeAsInt(o string) int
	GetMessage() *Message
	SetPayload([]byte)
	SetStringPayload(s string)
	SetRequestURI(uri string)
	SetConfirmable(con bool)
	SetToken(t string)
	GetURIQuery(q string) string
	SetURIQuery(k string, v string)
}

// Wraps a CoAP Message as a Request
// Provides various methods which proxies the Message object methods
type DefaultCoapRequest struct {
	msg    *Message
	attrs  map[string]string
	conn   *net.UDPConn
	addr   *net.UDPAddr
	server *CoapServer
}

func (c *DefaultCoapRequest) SetProxyURI(uri string) {
	c.msg.AddOption(OptionProxyURI, uri)
}

func (c *DefaultCoapRequest) SetMediaType(mt MediaType) {
	c.msg.AddOption(OptionContentFormat, mt)
}

func (c *DefaultCoapRequest) GetConnection() *net.UDPConn {
	return c.conn
}

func (c *DefaultCoapRequest) GetAddress() *net.UDPAddr {
	return c.addr
}

func (c *DefaultCoapRequest) GetAttributes() map[string]string {
	return c.attrs
}

func (c *DefaultCoapRequest) GetAttribute(o string) string {
	return c.attrs[o]
}

func (c *DefaultCoapRequest) GetAttributeAsInt(o string) int {
	attr := c.GetAttribute(o)
	i, _ := strconv.Atoi(attr)

	return i
}

func (c *DefaultCoapRequest) GetMessage() *Message {
	return c.msg
}

func (c *DefaultCoapRequest) SetStringPayload(s string) {
	c.msg.Payload = NewPlainTextPayload(s)
}

func (c *DefaultCoapRequest) SetPayload(b []byte) {
	c.msg.Payload = NewBytesPayload(b)
}

func (c *DefaultCoapRequest) SetRequestURI(uri string) {
	c.msg.AddOptions(NewPathOptions(uri))
}

func (c *DefaultCoapRequest) SetConfirmable(con bool) {
	if con {
		c.msg.MessageType = MessageConfirmable
	} else {
		c.msg.MessageType = MessageNonConfirmable
	}
}

func (c *DefaultCoapRequest) SetToken(t string) {
	c.msg.Token = []byte(t)
}

func (c *DefaultCoapRequest) GetURIQuery(q string) string {
	qs := c.GetMessage().GetOptionsAsString(OptionURIQuery)

	for _, o := range qs {
		ps := strings.Split(o, "=")
		if len(ps) == 2 {
			if ps[0] == q {
				return ps[1]
			}
		}
	}
	return ""
}

func (c *DefaultCoapRequest) SetURIQuery(k string, v string) {
	c.GetMessage().AddOption(OptionURIQuery, k+"="+v)
}
<|endoftext|>


<commit_before>// Copyright 2015 Vadim Kravcenko
//
// 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 gojenkins

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// Request Methods

type APIRequest struct {
	Method   string
	Endpoint string
	Payload  io.Reader
	Headers  http.Header
	Suffix   string
}

func (ar *APIRequest) SetHeader(key string, value string) *APIRequest {
	ar.Headers.Set(key, value)
	return ar
}

func NewAPIRequest(method string, endpoint string, payload io.Reader) *APIRequest {
	var headers = http.Header{}
	var suffix string
	ar := &APIRequest{method, endpoint, payload, headers, suffix}
	return ar
}

type Requester struct {
	Base      string
	BasicAuth *BasicAuth
	Client    *http.Client
	CACert    []byte
	SslVerify bool
}

func (r *Requester) SetCrumb(ar *APIRequest) error {
	crumbData := map[string]string{}
	response, _ := r.GetJSON("/crumbIssuer/api/json", &crumbData, nil)

	if response.StatusCode == 200 && crumbData["crumbRequestField"] != "" {
		ar.SetHeader(crumbData["crumbRequestField"], crumbData["crumb"])
	}

	return nil
}

func (r *Requester) PostJSON(endpoint string, payload io.Reader, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("POST", endpoint, payload)
	if err := r.SetCrumb(ar); err != nil {
		return nil, err
	}
	ar.SetHeader("Content-Type", "application/x-www-form-urlencoded")
	ar.Suffix = "api/json"
	return r.Do(ar, &responseStruct, querystring)
}

func (r *Requester) Post(endpoint string, payload io.Reader, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("POST", endpoint, payload)
	if err := r.SetCrumb(ar); err != nil {
		return nil, err
	}
	ar.SetHeader("Content-Type", "application/x-www-form-urlencoded")
	ar.Suffix = ""
	return r.Do(ar, &responseStruct, querystring)
}

func (r *Requester) PostFiles(endpoint string, payload io.Reader, responseStruct interface{}, querystring map[string]string, files []string) (*http.Response, error) {
	ar := NewAPIRequest("POST", endpoint, payload)
	if err := r.SetCrumb(ar); err != nil {
		return nil, err
	}
	return r.Do(ar, &responseStruct, querystring, files)
}

func (r *Requester) PostXML(endpoint string, xml string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	payload := bytes.NewBuffer([]byte(xml))
	ar := NewAPIRequest("POST", endpoint, payload)
	if err := r.SetCrumb(ar); err != nil {
		return nil, err
	}
	ar.SetHeader("Content-Type", "application/xml")
	ar.Suffix = ""
	return r.Do(ar, &responseStruct, querystring)
}

func (r *Requester) GetJSON(endpoint string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("GET", endpoint, nil)
	ar.SetHeader("Content-Type", "application/json")
	ar.Suffix = "api/json"
	return r.Do(ar, &responseStruct, querystring)
}

func (r *Requester) GetXML(endpoint string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("GET", endpoint, nil)
	ar.SetHeader("Content-Type", "application/xml")
	ar.Suffix = ""
	return r.Do(ar, responseStruct, querystring)
}

func (r *Requester) Get(endpoint string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("GET", endpoint, nil)
	ar.Suffix = ""
	return r.Do(ar, responseStruct, querystring)
}

func (r *Requester) SetClient(client *http.Client) *Requester {
	r.Client = client
	return r
}

//Add auth on redirect if required.
func (r *Requester) redirectPolicyFunc(req *http.Request, via []*http.Request) error {
	if r.BasicAuth != nil {
		req.SetBasicAuth(r.BasicAuth.Username, r.BasicAuth.Password)
	}
	return nil
}

func (r *Requester) Do(ar *APIRequest, responseStruct interface{}, options ...interface{}) (*http.Response, error) {
	if !strings.HasSuffix(ar.Endpoint, "/") && ar.Method != "POST" {
		ar.Endpoint += "/"
	}

	fileUpload := false
	var files []string
	URL, err := url.Parse(r.Base + ar.Endpoint + ar.Suffix)

	if err != nil {
		return nil, err
	}

	for _, o := range options {
		switch v := o.(type) {
		case map[string]string:

			querystring := make(url.Values)
			for key, val := range v {
				querystring.Set(key, val)
			}

			URL.RawQuery = querystring.Encode()
			break
		case []string:
			fileUpload = true
			files = v
		}
	}
	var req *http.Request

	if fileUpload {
		body := &bytes.Buffer{}
		writer := multipart.NewWriter(body)
		for _, file := range files {
			fileData, err := os.Open(file)
			if err != nil {
				Error.Println(err.Error())
				return nil, err
			}

			part, err := writer.CreateFormFile("file", filepath.Base(file))
			if err != nil {
				Error.Println(err.Error())
				return nil, err
			}
			if _, err = io.Copy(part, fileData); err != nil {
				return nil, err
			}
			defer fileData.Close()
		}
		var params map[string]string
		json.NewDecoder(ar.Payload).Decode(&params)
		for key, val := range params {
			if err = writer.WriteField(key, val); err != nil {
				return nil, err
			}
		}
		if err = writer.Close(); err != nil {
			return nil, err
		}
		req, err = http.NewRequest(ar.Method, URL.String(), body)
		if err != nil {
			return nil, err
		}
		req.Header.Set("Content-Type", writer.FormDataContentType())
	} else {

		req, err = http.NewRequest(ar.Method, URL.String(), ar.Payload)
		if err != nil {
			return nil, err
		}
	}

	if r.BasicAuth != nil {
		req.SetBasicAuth(r.BasicAuth.Username, r.BasicAuth.Password)
	}

	for k := range ar.Headers {
		req.Header.Add(k, ar.Headers.Get(k))
	}

	if response, err := r.Client.Do(req); err != nil {
		return nil, err
	} else {
		errorText := response.Header.Get("X-Error")
		if errorText != "" {
			return nil, errors.New(errorText)
		}
		switch responseStruct.(type) {
		case *string:
			return r.ReadRawResponse(response, responseStruct)
		default:
			return r.ReadJSONResponse(response, responseStruct)
		}

	}

}

func (r *Requester) ReadRawResponse(response *http.Response, responseStruct interface{}) (*http.Response, error) {
	defer response.Body.Close()

	content, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	if str, ok := responseStruct.(*string); ok {
		*str = string(content)
	} else {
		return nil, fmt.Errorf("Could not cast responseStruct to *string")
	}

	return response, nil
}

func (r *Requester) ReadJSONResponse(response *http.Response, responseStruct interface{}) (*http.Response, error) {
	defer response.Body.Close()

	json.NewDecoder(response.Body).Decode(responseStruct)
	return response, nil
}
<commit_msg>remove redundant break<commit_after>// Copyright 2015 Vadim Kravcenko
//
// 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 gojenkins

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// Request Methods

type APIRequest struct {
	Method   string
	Endpoint string
	Payload  io.Reader
	Headers  http.Header
	Suffix   string
}

func (ar *APIRequest) SetHeader(key string, value string) *APIRequest {
	ar.Headers.Set(key, value)
	return ar
}

func NewAPIRequest(method string, endpoint string, payload io.Reader) *APIRequest {
	var headers = http.Header{}
	var suffix string
	ar := &APIRequest{method, endpoint, payload, headers, suffix}
	return ar
}

type Requester struct {
	Base      string
	BasicAuth *BasicAuth
	Client    *http.Client
	CACert    []byte
	SslVerify bool
}

func (r *Requester) SetCrumb(ar *APIRequest) error {
	crumbData := map[string]string{}
	response, _ := r.GetJSON("/crumbIssuer/api/json", &crumbData, nil)

	if response.StatusCode == 200 && crumbData["crumbRequestField"] != "" {
		ar.SetHeader(crumbData["crumbRequestField"], crumbData["crumb"])
	}

	return nil
}

func (r *Requester) PostJSON(endpoint string, payload io.Reader, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("POST", endpoint, payload)
	if err := r.SetCrumb(ar); err != nil {
		return nil, err
	}
	ar.SetHeader("Content-Type", "application/x-www-form-urlencoded")
	ar.Suffix = "api/json"
	return r.Do(ar, &responseStruct, querystring)
}

func (r *Requester) Post(endpoint string, payload io.Reader, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("POST", endpoint, payload)
	if err := r.SetCrumb(ar); err != nil {
		return nil, err
	}
	ar.SetHeader("Content-Type", "application/x-www-form-urlencoded")
	ar.Suffix = ""
	return r.Do(ar, &responseStruct, querystring)
}

func (r *Requester) PostFiles(endpoint string, payload io.Reader, responseStruct interface{}, querystring map[string]string, files []string) (*http.Response, error) {
	ar := NewAPIRequest("POST", endpoint, payload)
	if err := r.SetCrumb(ar); err != nil {
		return nil, err
	}
	return r.Do(ar, &responseStruct, querystring, files)
}

func (r *Requester) PostXML(endpoint string, xml string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	payload := bytes.NewBuffer([]byte(xml))
	ar := NewAPIRequest("POST", endpoint, payload)
	if err := r.SetCrumb(ar); err != nil {
		return nil, err
	}
	ar.SetHeader("Content-Type", "application/xml")
	ar.Suffix = ""
	return r.Do(ar, &responseStruct, querystring)
}

func (r *Requester) GetJSON(endpoint string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("GET", endpoint, nil)
	ar.SetHeader("Content-Type", "application/json")
	ar.Suffix = "api/json"
	return r.Do(ar, &responseStruct, querystring)
}

func (r *Requester) GetXML(endpoint string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("GET", endpoint, nil)
	ar.SetHeader("Content-Type", "application/xml")
	ar.Suffix = ""
	return r.Do(ar, responseStruct, querystring)
}

func (r *Requester) Get(endpoint string, responseStruct interface{}, querystring map[string]string) (*http.Response, error) {
	ar := NewAPIRequest("GET", endpoint, nil)
	ar.Suffix = ""
	return r.Do(ar, responseStruct, querystring)
}

func (r *Requester) SetClient(client *http.Client) *Requester {
	r.Client = client
	return r
}

//Add auth on redirect if required.
func (r *Requester) redirectPolicyFunc(req *http.Request, via []*http.Request) error {
	if r.BasicAuth != nil {
		req.SetBasicAuth(r.BasicAuth.Username, r.BasicAuth.Password)
	}
	return nil
}

func (r *Requester) Do(ar *APIRequest, responseStruct interface{}, options ...interface{}) (*http.Response, error) {
	if !strings.HasSuffix(ar.Endpoint, "/") && ar.Method != "POST" {
		ar.Endpoint += "/"
	}

	fileUpload := false
	var files []string
	URL, err := url.Parse(r.Base + ar.Endpoint + ar.Suffix)

	if err != nil {
		return nil, err
	}

	for _, o := range options {
		switch v := o.(type) {
		case map[string]string:

			querystring := make(url.Values)
			for key, val := range v {
				querystring.Set(key, val)
			}

			URL.RawQuery = querystring.Encode()
		case []string:
			fileUpload = true
			files = v
		}
	}
	var req *http.Request

	if fileUpload {
		body := &bytes.Buffer{}
		writer := multipart.NewWriter(body)
		for _, file := range files {
			fileData, err := os.Open(file)
			if err != nil {
				Error.Println(err.Error())
				return nil, err
			}

			part, err := writer.CreateFormFile("file", filepath.Base(file))
			if err != nil {
				Error.Println(err.Error())
				return nil, err
			}
			if _, err = io.Copy(part, fileData); err != nil {
				return nil, err
			}
			defer fileData.Close()
		}
		var params map[string]string
		json.NewDecoder(ar.Payload).Decode(&params)
		for key, val := range params {
			if err = writer.WriteField(key, val); err != nil {
				return nil, err
			}
		}
		if err = writer.Close(); err != nil {
			return nil, err
		}
		req, err = http.NewRequest(ar.Method, URL.String(), body)
		if err != nil {
			return nil, err
		}
		req.Header.Set("Content-Type", writer.FormDataContentType())
	} else {

		req, err = http.NewRequest(ar.Method, URL.String(), ar.Payload)
		if err != nil {
			return nil, err
		}
	}

	if r.BasicAuth != nil {
		req.SetBasicAuth(r.BasicAuth.Username, r.BasicAuth.Password)
	}

	for k := range ar.Headers {
		req.Header.Add(k, ar.Headers.Get(k))
	}

	if response, err := r.Client.Do(req); err != nil {
		return nil, err
	} else {
		errorText := response.Header.Get("X-Error")
		if errorText != "" {
			return nil, errors.New(errorText)
		}
		switch responseStruct.(type) {
		case *string:
			return r.ReadRawResponse(response, responseStruct)
		default:
			return r.ReadJSONResponse(response, responseStruct)
		}

	}

}

func (r *Requester) ReadRawResponse(response *http.Response, responseStruct interface{}) (*http.Response, error) {
	defer response.Body.Close()

	content, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	if str, ok := responseStruct.(*string); ok {
		*str = string(content)
	} else {
		return nil, fmt.Errorf("Could not cast responseStruct to *string")
	}

	return response, nil
}

func (r *Requester) ReadJSONResponse(response *http.Response, responseStruct interface{}) (*http.Response, error) {
	defer response.Body.Close()

	json.NewDecoder(response.Body).Decode(responseStruct)
	return response, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"strings"

	"github.com/peterh/liner"
)

// Resolve asks the user to resolve the identifiers
func Resolve(identifiers []string, config *Config, in *bufio.Reader) map[string]string {
	line := liner.NewLiner()
	defer line.Close()
	line.SetCtrlCAborts(true)
	values := make(map[string]string, len(identifiers))
	for _, identifier := range identifiers {
		if _, ok := values[identifier]; !ok {
			prompt := fmt.Sprintf("%s: ", identifier)
			var text string
			var err error
			if in == nil {
				line.ClearHistory()
				for _, v := range config.history(identifier) {
					line.AppendHistory(v)
				}
				text, err = line.Prompt(prompt)
				if err != nil {
					if err == liner.ErrPromptAborted || err == io.EOF {
						os.Exit(1)
					}
					log.Fatal(err)
				}
			} else {
				fmt.Printf(prompt)
				text, err = in.ReadString('\n')
				if err != nil {
					log.Fatal(err)
				}
			}
			values[identifier] = strings.TrimSuffix(text, "\n")
		}
	}
	return values
}
<commit_msg>append history in reverse order<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"strings"

	"github.com/peterh/liner"
)

// Resolve asks the user to resolve the identifiers
func Resolve(identifiers []string, config *Config, in *bufio.Reader) map[string]string {
	line := liner.NewLiner()
	defer line.Close()
	line.SetCtrlCAborts(true)
	values := make(map[string]string, len(identifiers))
	for _, identifier := range identifiers {
		if _, ok := values[identifier]; !ok {
			prompt := fmt.Sprintf("%s: ", identifier)
			var text string
			var err error
			if in == nil {
				line.ClearHistory()
				hs := config.history(id)
				for i := len(hs) - 1; i >= 0; i-- {
					line.AppendHistory(hs[i])
				}
				text, err = line.Prompt(prompt)
				if err != nil {
					if err == liner.ErrPromptAborted || err == io.EOF {
						os.Exit(1)
					}
					log.Fatal(err)
				}
			} else {
				fmt.Printf(prompt)
				text, err = in.ReadString('\n')
				if err != nil {
					log.Fatal(err)
				}
			}
			values[identifier] = strings.TrimSuffix(text, "\n")
		}
	}
	return values
}
<|endoftext|>


<commit_before>package baremetal

import (
	"context"
	"fmt"
	"strings"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/dynamic"
	e2e "k8s.io/kubernetes/test/e2e/framework"

	configv1 "github.com/openshift/api/config/v1"
	exutil "github.com/openshift/origin/test/extended/util"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
)

func skipIfNotBaremetal(oc *exutil.CLI) {
	g.By("checking platform type")

	infra, err := oc.AdminConfigClient().ConfigV1().Infrastructures().Get(context.Background(), "cluster", metav1.GetOptions{})
	o.Expect(err).NotTo(o.HaveOccurred())

	if infra.Status.PlatformStatus.Type != configv1.BareMetalPlatformType {
		e2eskipper.Skipf("No baremetal platform detected")
	}
}

func baremetalClient(dc dynamic.Interface) dynamic.ResourceInterface {
	baremetalClient := dc.Resource(schema.GroupVersionResource{Group: "metal3.io", Resource: "baremetalhosts", Version: "v1alpha1"})
	return baremetalClient.Namespace("openshift-machine-api")
}

func hostfirmwaresettingsClient(dc dynamic.Interface) dynamic.ResourceInterface {
	hfsClient := dc.Resource(schema.GroupVersionResource{Group: "metal3.io", Resource: "hostfirmwaresettings", Version: "v1alpha1"})
	return hfsClient.Namespace("openshift-machine-api")
}

type FieldGetterFunc func(obj map[string]interface{}, fields ...string) (interface{}, bool, error)

func expectField(host unstructured.Unstructured, resource string, nestedField string, fieldGetter FieldGetterFunc) o.Assertion {
	fields := strings.Split(nestedField, ".")

	value, found, err := fieldGetter(host.Object, fields...)
	o.Expect(err).NotTo(o.HaveOccurred())
	o.Expect(found).To(o.BeTrue(), fmt.Sprintf("`%s` field `%s` not found", resource, nestedField))
	return o.Expect(value)
}

func expectStringField(host unstructured.Unstructured, resource string, nestedField string) o.Assertion {
	return expectField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedString(host.Object, fields...)
	})
}

func expectBoolField(host unstructured.Unstructured, resource string, nestedField string) o.Assertion {
	return expectField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedBool(host.Object, fields...)
	})
}

func expectStringMapField(host unstructured.Unstructured, resource string, nestedField string) o.Assertion {
	return expectField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedStringMap(host.Object, fields...)
	})
}

func expectSliceField(host unstructured.Unstructured, resource string, nestedField string) o.Assertion {
	return expectField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedSlice(host.Object, fields...)
	})
}

// Conditions are stored as a slice of maps, check that the type has the correct status
func checkConditionStatus(hfs unstructured.Unstructured, condType string, condStatus string) {

	conditions, _, err := unstructured.NestedSlice(hfs.Object, "status", "conditions")
	o.Expect(err).NotTo(o.HaveOccurred())
	o.Expect(conditions).ToNot(o.BeEmpty())

	for _, c := range conditions {
		condition, ok := c.(map[string]interface{})
		o.Expect(ok).To(o.BeTrue())

		t, ok := condition["type"]
		o.Expect(ok).To(o.BeTrue())
		if t == condType {
			s, ok := condition["status"]
			o.Expect(ok).To(o.BeTrue())
			o.Expect(s).To(o.Equal(condStatus))
		}
	}
}

func getField(host unstructured.Unstructured, resource string, nestedField string, fieldGetter FieldGetterFunc) string {
	fields := strings.Split(nestedField, ".")

	value, found, err := fieldGetter(host.Object, fields...)
	o.Expect(err).NotTo(o.HaveOccurred())
	o.Expect(found).To(o.BeTrue(), fmt.Sprintf("`%s` field `%s` not found", resource, nestedField))
	return value.(string)
}

func getStringField(host unstructured.Unstructured, resource string, nestedField string) string {
	return getField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedFieldNoCopy(host.Object, fields...)
	})
}

var _ = g.Describe("[sig-installer][Feature:baremetal] Baremetal platform should", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLI("baremetal")

	g.It("have a metal3 deployment", func() {
		skipIfNotBaremetal(oc)

		c, err := e2e.LoadClientset()
		o.Expect(err).ToNot(o.HaveOccurred())

		metal3, err := c.AppsV1().Deployments("openshift-machine-api").Get(context.Background(), "metal3", metav1.GetOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(metal3.Status.AvailableReplicas).To(o.BeEquivalentTo(1))

		o.Expect(metal3.Annotations).Should(o.HaveKey("baremetal.openshift.io/owned"))
		o.Expect(metal3.Labels).Should(o.HaveKeyWithValue("baremetal.openshift.io/cluster-baremetal-operator", "metal3-state"))
	})

	g.It("have baremetalhost resources", func() {
		skipIfNotBaremetal(oc)

		dc := oc.AdminDynamicClient()
		bmc := baremetalClient(dc)

		hosts, err := bmc.List(context.Background(), v1.ListOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(hosts.Items).ToNot(o.BeEmpty())

		for _, h := range hosts.Items {
			expectStringField(h, "baremetalhost", "status.provisioning.state").To(o.Or(o.BeEquivalentTo("provisioned"), o.BeEquivalentTo("externally provisioned")))
			state := getStringField(h, "baremetalhost", "status.provisioning.state")
			// When testing with CoreOS preprovisioning images, masters will faild to be adopted properly due to BZ 2032573
			// Remove this check when fix for BZ 2032573 merges
			if state != "externally provisioned" {
				hostName := getStringField(h, "baremetalhost", "metadata.name")
				g.By(fmt.Sprintf("check that baremetalhost %s operationalStatus is OK", hostName))
				expectStringField(h, "baremetalhost", "status.operationalStatus").To(o.BeEquivalentTo("OK"))
			}
			expectBoolField(h, "baremetalhost", "spec.online").To(o.BeTrue())
		}
	})

	g.It("have hostfirmwaresetting resources", func() {
		skipIfNotBaremetal(oc)

		dc := oc.AdminDynamicClient()

		bmc := baremetalClient(dc)
		hosts, err := bmc.List(context.Background(), v1.ListOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(hosts.Items).ToNot(o.BeEmpty())

		hfsClient := hostfirmwaresettingsClient(dc)

		for _, h := range hosts.Items {
			hostName := getStringField(h, "baremetalhost", "metadata.name")

			g.By(fmt.Sprintf("check that baremetalhost %s has a corresponding hostfirmwaresettings", hostName))
			hfs, err := hfsClient.Get(context.Background(), hostName, v1.GetOptions{})
			o.Expect(err).NotTo(o.HaveOccurred())
			o.Expect(hfs).NotTo(o.Equal(nil))

			// Reenable this when fix to prevent settings with 0 entries is in BMO
			// g.By("check that hostfirmwaresettings settings have been populated")
			// expectStringMapField(*hfs, "hostfirmwaresettings", "status.settings").ToNot(o.BeEmpty())

			g.By("check that hostfirmwaresettings conditions show resource is valid")
			checkConditionStatus(*hfs, "Valid", "True")

			g.By("check that hostfirmwaresettings reference a schema")
			refName := getStringField(*hfs, "hostfirmwaresettings", "status.schema.name")
			refNS := getStringField(*hfs, "hostfirmwaresettings", "status.schema.namespace")

			schemaClient := dc.Resource(schema.GroupVersionResource{Group: "metal3.io", Resource: "firmwareschemas", Version: "v1alpha1"}).Namespace(refNS)
			schema, err := schemaClient.Get(context.Background(), refName, v1.GetOptions{})
			o.Expect(err).NotTo(o.HaveOccurred())
			o.Expect(schema).NotTo(o.Equal(nil))
		}
	})

	g.It("not allow updating BootMacAddress", func() {
		skipIfNotBaremetal(oc)

		dc := oc.AdminDynamicClient()
		bmc := baremetalClient(dc)

		hosts, err := bmc.List(context.Background(), v1.ListOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(hosts.Items).ToNot(o.BeEmpty())

		host := hosts.Items[0]
		expectStringField(host, "baremetalhost", "spec.bootMACAddress").ShouldNot(o.BeNil())
		// Already verified that bootMACAddress exists
		bootMACAddress, _, _ := unstructured.NestedString(host.Object, "spec", "bootMACAddress")
		testMACAddress := "11:11:11:11:11:11"

		g.By("updating bootMACAddress which is not allowed")
		err = unstructured.SetNestedField(host.Object, testMACAddress, "spec", "bootMACAddress")
		o.Expect(err).NotTo(o.HaveOccurred())
		_, err = bmc.Update(context.Background(), &host, v1.UpdateOptions{})
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(err.Error()).To(o.ContainSubstring("bootMACAddress can not be changed once it is set"))

		g.By("verify bootMACAddress is not updated")
		h, err := bmc.Get(context.Background(), host.GetName(), v1.GetOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		check, _, _ := unstructured.NestedString(h.Object, "spec", "bootMACAddress")
		o.Expect(check).To(o.Equal(bootMACAddress))
	})
})
<commit_msg>Revert "Add workaround for baremetal resources test"<commit_after>package baremetal

import (
	"context"
	"fmt"
	"strings"

	g "github.com/onsi/ginkgo"
	o "github.com/onsi/gomega"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/dynamic"
	e2e "k8s.io/kubernetes/test/e2e/framework"

	configv1 "github.com/openshift/api/config/v1"
	exutil "github.com/openshift/origin/test/extended/util"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
)

func skipIfNotBaremetal(oc *exutil.CLI) {
	g.By("checking platform type")

	infra, err := oc.AdminConfigClient().ConfigV1().Infrastructures().Get(context.Background(), "cluster", metav1.GetOptions{})
	o.Expect(err).NotTo(o.HaveOccurred())

	if infra.Status.PlatformStatus.Type != configv1.BareMetalPlatformType {
		e2eskipper.Skipf("No baremetal platform detected")
	}
}

func baremetalClient(dc dynamic.Interface) dynamic.ResourceInterface {
	baremetalClient := dc.Resource(schema.GroupVersionResource{Group: "metal3.io", Resource: "baremetalhosts", Version: "v1alpha1"})
	return baremetalClient.Namespace("openshift-machine-api")
}

func hostfirmwaresettingsClient(dc dynamic.Interface) dynamic.ResourceInterface {
	hfsClient := dc.Resource(schema.GroupVersionResource{Group: "metal3.io", Resource: "hostfirmwaresettings", Version: "v1alpha1"})
	return hfsClient.Namespace("openshift-machine-api")
}

type FieldGetterFunc func(obj map[string]interface{}, fields ...string) (interface{}, bool, error)

func expectField(host unstructured.Unstructured, resource string, nestedField string, fieldGetter FieldGetterFunc) o.Assertion {
	fields := strings.Split(nestedField, ".")

	value, found, err := fieldGetter(host.Object, fields...)
	o.Expect(err).NotTo(o.HaveOccurred())
	o.Expect(found).To(o.BeTrue(), fmt.Sprintf("`%s` field `%s` not found", resource, nestedField))
	return o.Expect(value)
}

func expectStringField(host unstructured.Unstructured, resource string, nestedField string) o.Assertion {
	return expectField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedString(host.Object, fields...)
	})
}

func expectBoolField(host unstructured.Unstructured, resource string, nestedField string) o.Assertion {
	return expectField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedBool(host.Object, fields...)
	})
}

func expectStringMapField(host unstructured.Unstructured, resource string, nestedField string) o.Assertion {
	return expectField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedStringMap(host.Object, fields...)
	})
}

func expectSliceField(host unstructured.Unstructured, resource string, nestedField string) o.Assertion {
	return expectField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedSlice(host.Object, fields...)
	})
}

// Conditions are stored as a slice of maps, check that the type has the correct status
func checkConditionStatus(hfs unstructured.Unstructured, condType string, condStatus string) {

	conditions, _, err := unstructured.NestedSlice(hfs.Object, "status", "conditions")
	o.Expect(err).NotTo(o.HaveOccurred())
	o.Expect(conditions).ToNot(o.BeEmpty())

	for _, c := range conditions {
		condition, ok := c.(map[string]interface{})
		o.Expect(ok).To(o.BeTrue())

		t, ok := condition["type"]
		o.Expect(ok).To(o.BeTrue())
		if t == condType {
			s, ok := condition["status"]
			o.Expect(ok).To(o.BeTrue())
			o.Expect(s).To(o.Equal(condStatus))
		}
	}
}

func getField(host unstructured.Unstructured, resource string, nestedField string, fieldGetter FieldGetterFunc) string {
	fields := strings.Split(nestedField, ".")

	value, found, err := fieldGetter(host.Object, fields...)
	o.Expect(err).NotTo(o.HaveOccurred())
	o.Expect(found).To(o.BeTrue(), fmt.Sprintf("`%s` field `%s` not found", resource, nestedField))
	return value.(string)
}

func getStringField(host unstructured.Unstructured, resource string, nestedField string) string {
	return getField(host, resource, nestedField, func(obj map[string]interface{}, fields ...string) (interface{}, bool, error) {
		return unstructured.NestedFieldNoCopy(host.Object, fields...)
	})
}

var _ = g.Describe("[sig-installer][Feature:baremetal] Baremetal platform should", func() {
	defer g.GinkgoRecover()

	oc := exutil.NewCLI("baremetal")

	g.It("have a metal3 deployment", func() {
		skipIfNotBaremetal(oc)

		c, err := e2e.LoadClientset()
		o.Expect(err).ToNot(o.HaveOccurred())

		metal3, err := c.AppsV1().Deployments("openshift-machine-api").Get(context.Background(), "metal3", metav1.GetOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(metal3.Status.AvailableReplicas).To(o.BeEquivalentTo(1))

		o.Expect(metal3.Annotations).Should(o.HaveKey("baremetal.openshift.io/owned"))
		o.Expect(metal3.Labels).Should(o.HaveKeyWithValue("baremetal.openshift.io/cluster-baremetal-operator", "metal3-state"))
	})

	g.It("have baremetalhost resources", func() {
		skipIfNotBaremetal(oc)

		dc := oc.AdminDynamicClient()
		bmc := baremetalClient(dc)

		hosts, err := bmc.List(context.Background(), v1.ListOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(hosts.Items).ToNot(o.BeEmpty())

		for _, h := range hosts.Items {
			expectStringField(h, "baremetalhost", "status.operationalStatus").To(o.BeEquivalentTo("OK"))
			expectStringField(h, "baremetalhost", "status.provisioning.state").To(o.Or(o.BeEquivalentTo("provisioned"), o.BeEquivalentTo("externally provisioned")))
			expectBoolField(h, "baremetalhost", "spec.online").To(o.BeTrue())
		}
	})

	g.It("have hostfirmwaresetting resources", func() {
		skipIfNotBaremetal(oc)

		dc := oc.AdminDynamicClient()

		bmc := baremetalClient(dc)
		hosts, err := bmc.List(context.Background(), v1.ListOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(hosts.Items).ToNot(o.BeEmpty())

		hfsClient := hostfirmwaresettingsClient(dc)

		for _, h := range hosts.Items {
			hostName := getStringField(h, "baremetalhost", "metadata.name")

			g.By(fmt.Sprintf("check that baremetalhost %s has a corresponding hostfirmwaresettings", hostName))
			hfs, err := hfsClient.Get(context.Background(), hostName, v1.GetOptions{})
			o.Expect(err).NotTo(o.HaveOccurred())
			o.Expect(hfs).NotTo(o.Equal(nil))

			// Reenable this when fix to prevent settings with 0 entries is in BMO
			// g.By("check that hostfirmwaresettings settings have been populated")
			// expectStringMapField(*hfs, "hostfirmwaresettings", "status.settings").ToNot(o.BeEmpty())

			g.By("check that hostfirmwaresettings conditions show resource is valid")
			checkConditionStatus(*hfs, "Valid", "True")

			g.By("check that hostfirmwaresettings reference a schema")
			refName := getStringField(*hfs, "hostfirmwaresettings", "status.schema.name")
			refNS := getStringField(*hfs, "hostfirmwaresettings", "status.schema.namespace")

			schemaClient := dc.Resource(schema.GroupVersionResource{Group: "metal3.io", Resource: "firmwareschemas", Version: "v1alpha1"}).Namespace(refNS)
			schema, err := schemaClient.Get(context.Background(), refName, v1.GetOptions{})
			o.Expect(err).NotTo(o.HaveOccurred())
			o.Expect(schema).NotTo(o.Equal(nil))
		}
	})

	g.It("not allow updating BootMacAddress", func() {
		skipIfNotBaremetal(oc)

		dc := oc.AdminDynamicClient()
		bmc := baremetalClient(dc)

		hosts, err := bmc.List(context.Background(), v1.ListOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		o.Expect(hosts.Items).ToNot(o.BeEmpty())

		host := hosts.Items[0]
		expectStringField(host, "baremetalhost", "spec.bootMACAddress").ShouldNot(o.BeNil())
		// Already verified that bootMACAddress exists
		bootMACAddress, _, _ := unstructured.NestedString(host.Object, "spec", "bootMACAddress")
		testMACAddress := "11:11:11:11:11:11"

		g.By("updating bootMACAddress which is not allowed")
		err = unstructured.SetNestedField(host.Object, testMACAddress, "spec", "bootMACAddress")
		o.Expect(err).NotTo(o.HaveOccurred())
		_, err = bmc.Update(context.Background(), &host, v1.UpdateOptions{})
		o.Expect(err).To(o.HaveOccurred())
		o.Expect(err.Error()).To(o.ContainSubstring("bootMACAddress can not be changed once it is set"))

		g.By("verify bootMACAddress is not updated")
		h, err := bmc.Get(context.Background(), host.GetName(), v1.GetOptions{})
		o.Expect(err).NotTo(o.HaveOccurred())
		check, _, _ := unstructured.NestedString(h.Object, "spec", "bootMACAddress")
		o.Expect(check).To(o.Equal(bootMACAddress))
	})
})
<|endoftext|>