blob: 0dd5a2ead9b507027feeb15b49642bb48693e118 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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.
// Matching the unix-like build tags in the Golang source i.e. https://github.com/golang/go/blob/912f0750472dd4f674b69ca1616bfaf377af1805/src/os/file_unix.go#L6
//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris
// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris
package netrc
import (
"bytes"
"fmt"
"os"
"path/filepath"
"strings"
"testing"
)
import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
import (
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/app"
)
func TestGetMachineForName(t *testing.T) {
t.Parallel()
testGetMachineForNameSuccess(
t,
"foo.com",
"testdata/unix/home1",
"foo.com",
"bar",
"baz",
)
testGetMachineForNameNil(
t,
"api.foo.com",
"testdata/unix/home1",
)
testGetMachineForNameNil(
t,
"bar.com",
"testdata/unix/home1",
)
testGetMachineForNameSuccess(
t,
"foo.com",
"testdata/unix/home2",
"",
"bar",
"baz",
)
testGetMachineForNameSuccess(
t,
"api.foo.com",
"testdata/unix/home2",
"",
"bar",
"baz",
)
testGetMachineForNameSuccess(
t,
"bar.com",
"testdata/unix/home2",
"",
"bar",
"baz",
)
testGetMachineForNameNil(
t,
"foo.com",
"testdata/unix/home3",
)
testGetMachineForNameNil(
t,
"api.foo.com",
"testdata/unix/home3",
)
testGetMachineForNameNil(
t,
"bar.com",
"testdata/unix/home1",
)
}
func TestPutMachines(t *testing.T) {
t.Parallel()
testPutMachinesSuccess(
t,
false,
NewMachine(
"foo.com",
"test@foo.com",
"password",
),
)
testPutMachinesSuccess(
t,
true,
NewMachine(
"foo.com",
"test@foo.com",
"password",
),
)
testPutMachinesSuccess(
t,
false,
NewMachine(
"bar.com",
"test@bar.com",
"password",
),
NewMachine(
"baz.com",
"test@baz.com",
"password",
),
)
}
// https://github.com/ProtobufMan/bufman-cli/issues/611
func TestPutLotsOfBigMachinesSingleLineFiles(t *testing.T) {
t.Parallel()
size := 10
password := strings.Repeat("abcdefghijklmnopqrstuvwxyz", size)
machines := make([]Machine, 0, size)
buffer := bytes.NewBuffer(nil)
for i := 0; i < size; i++ {
// Write the file manually in single-line format as this is where the failure happens.
_, _ = buffer.WriteString(fmt.Sprintf("machine foo%d login bar%d password %s\n", i, i, password))
machines = append(
machines,
NewMachine(
fmt.Sprintf("foo%d", i),
fmt.Sprintf("bar%d", i),
password,
),
)
}
filePath := filepath.Join(t.TempDir(), netrcFilename)
err := os.WriteFile(filePath, buffer.Bytes(), 0o600)
require.NoError(t, err)
envContainer := app.NewEnvContainer(map[string]string{"NETRC": filePath})
for _, machine := range machines {
// Make sure the existing file can be parsed.
actualMachine, err := GetMachineForName(envContainer, machine.Name())
require.NoError(t, err)
require.Equal(t, machine, actualMachine)
}
// Now, modify the file with an extra machine. This is when the file got corrupted.
extraMachine := NewMachine(
"baz.com",
"test@baz.com",
"password",
)
err = PutMachines(envContainer, extraMachine)
require.NoError(t, err)
machines = append(machines, extraMachine)
for _, machine := range machines {
// Verify all the machines work. This failed previously.
actualMachine, err := GetMachineForName(envContainer, machine.Name())
require.NoError(t, err)
require.Equal(t, machine, actualMachine)
}
// Modify some of the existing machines.
machines = make([]Machine, 0, size)
for i := 0; i < size; i++ {
modifiedPassword := password
if i%2 == 0 {
modifiedPassword = modifiedPassword + "Z"
}
machine := NewMachine(
fmt.Sprintf("foo%d", i),
fmt.Sprintf("bar%d", i),
modifiedPassword,
)
machines = append(machines, machine)
if i%2 == 0 {
err = PutMachines(envContainer, machine)
require.NoError(t, err)
}
}
machines = append(machines, extraMachine)
for _, machine := range machines {
actualMachine, err := GetMachineForName(envContainer, machine.Name())
require.NoError(t, err)
require.Equal(t, machine, actualMachine)
}
}
func TestDeleteMachineForName(t *testing.T) {
t.Parallel()
filePath := filepath.Join(t.TempDir(), netrcFilename)
envContainer := app.NewEnvContainer(map[string]string{"NETRC": filePath})
err := PutMachines(
envContainer,
NewMachine(
"bar.com",
"test@bar.com",
"password",
),
NewMachine(
"baz.com",
"test@baz.com",
"password",
),
)
require.NoError(t, err)
exists, err := DeleteMachineForName(envContainer, "bar.com")
require.NoError(t, err)
require.True(t, exists)
machine, err := GetMachineForName(envContainer, "bar.com")
require.NoError(t, err)
assert.Nil(t, machine)
machine, err = GetMachineForName(envContainer, "baz.com")
require.NoError(t, err)
assert.NotNil(t, machine)
exists, err = DeleteMachineForName(envContainer, "bar.com")
require.NoError(t, err)
require.False(t, exists)
}
func testPutMachinesSuccess(
t *testing.T,
createNetrcBeforePut bool,
machines ...Machine,
) {
filePath := filepath.Join(t.TempDir(), netrcFilename)
envContainer := app.NewEnvContainer(map[string]string{"NETRC": filePath})
for _, machine := range machines {
machine, err := GetMachineForName(envContainer, machine.Name())
require.NoError(t, err)
require.Nil(t, machine)
}
if createNetrcBeforePut {
_, err := os.Create(filePath)
require.NoError(t, err)
}
err := PutMachines(envContainer, machines...)
require.NoError(t, err)
for _, machine := range machines {
actualMachine, err := GetMachineForName(envContainer, machine.Name())
require.NoError(t, err)
assert.Equal(t, machine, actualMachine)
}
}
func testGetMachineForNameSuccess(
t *testing.T,
name string,
homeDirPath string,
expectedName string,
expectedLogin string,
expectedPassword string,
) {
machine, err := GetMachineForName(app.NewEnvContainer(map[string]string{"HOME": homeDirPath}), name)
require.NoError(t, err)
require.NotNil(t, machine)
assert.Equal(t, expectedName, machine.Name())
assert.Equal(t, expectedLogin, machine.Login())
assert.Equal(t, expectedPassword, machine.Password())
}
func testGetMachineForNameNil(
t *testing.T,
name string,
homeDirPath string,
) {
machine, err := GetMachineForName(app.NewEnvContainer(map[string]string{"HOME": homeDirPath}), name)
require.NoError(t, err)
require.Nil(t, machine)
}