blob: 64b36768a0db605c34b0fe1ac3cb6bdc8b6c90d6 [file]
// Copyright 2020 The Chromium OS 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 baserpc
import (
"context"
"fmt"
"io/ioutil"
"net"
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"google.golang.org/grpc"
"chromiumos/tast/remote/dutfs"
"chromiumos/tast/services/cros/baserpc"
"chromiumos/tast/testutil"
)
// startTestPair starts a pair of remote file system server and client.
// It aborts the test when it encounters an error during setup. Callers are
// responsible for releasing the returned resources.
func startTestPair(t *testing.T) (*grpc.Server, *grpc.ClientConn) {
t.Helper()
s := grpc.NewServer()
// Note: We omit releasing s on setup errors because this function is for
// unit tests only and errors are rare.
baserpc.RegisterFileSystemServer(s, &FileSystemService{nil})
lis, err := net.ListenTCP("tcp", nil)
if err != nil {
t.Fatal("Failed to listen: ", err)
}
go s.Serve(lis)
conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure())
if err != nil {
t.Fatal("Failed to dial: ", err)
}
return s, conn
}
func TestReadDir(t *testing.T) {
srv, conn := startTestPair(t)
defer srv.Stop()
defer conn.Close()
cl := dutfs.NewClient(conn)
dir := testutil.TempDir(t)
defer os.RemoveAll(dir)
fis, err := cl.ReadDir(context.Background(), dir)
if err != nil {
t.Error("ReadDir failed for empty directory: ", err)
} else if len(fis) > 0 {
t.Errorf("ReadDir returned %d entries for empty directory; want 0", len(fis))
}
if err := testutil.WriteFiles(dir, map[string]string{
"foo": "12345678",
"bar": "12345",
}); err != nil {
t.Fatal("Failed to write files: ", err)
}
fis, err = cl.ReadDir(context.Background(), dir)
if err != nil {
t.Error("ReadDir failed for non-empty directory: ", err)
} else {
var got []string
for _, fi := range fis {
got = append(got, fmt.Sprintf("%s %d", fi.Name(), fi.Size()))
}
want := []string{
"bar 5",
"foo 8",
}
if diff := cmp.Diff(got, want); diff != "" {
t.Error("ReadDir returned unexpected entries for non-empty directory (-got +want):\n", diff)
}
}
_, err = cl.ReadDir(context.Background(), filepath.Join(dir, "no_such_dir"))
if !os.IsNotExist(err) {
t.Errorf("ReadDir: %v; want %v", err, os.ErrNotExist)
}
}
func TestStat(t *testing.T) {
srv, conn := startTestPair(t)
defer srv.Stop()
defer conn.Close()
cl := dutfs.NewClient(conn)
dir := testutil.TempDir(t)
defer os.RemoveAll(dir)
path := filepath.Join(dir, "foo")
if err := ioutil.WriteFile(path, []byte("12345"), 0666); err != nil {
t.Fatal("Failed to create file: ", err)
}
fi, err := cl.Stat(context.Background(), dir)
if err != nil {
t.Error("Stat failed for directory: ", err)
} else {
if !fi.IsDir() {
t.Error("IsDir = false for directory")
}
}
for _, p := range []string{dir, path} {
want, err := os.Stat(p)
if err != nil {
t.Error("os.Stat failed: ", err)
continue
}
got, err := cl.Stat(context.Background(), p)
if err != nil {
t.Error("cl.Stat failed: ", err)
continue
}
if got.Name() != want.Name() {
t.Errorf("Name = %q; want %q", got.Name(), want.Name())
}
if got.Size() != want.Size() {
t.Errorf("Size = %v; want %v", got.Size(), want.Size())
}
if got.Mode() != want.Mode() {
t.Errorf("Mode = %v; want %v", got.Mode(), want.Mode())
}
if !got.ModTime().Equal(want.ModTime()) {
t.Errorf("ModTime = %v; want %v", got.ModTime(), want.ModTime())
}
if got.IsDir() != want.IsDir() {
t.Errorf("IsDir = %v; want %v", got.IsDir(), want.IsDir())
}
}
_, err = cl.Stat(context.Background(), filepath.Join(dir, "no_such_file"))
if !os.IsNotExist(err) {
t.Errorf("Stat: %v; want %v", err, os.ErrNotExist)
}
}
func TestReadFile(t *testing.T) {
srv, conn := startTestPair(t)
defer srv.Stop()
defer conn.Close()
cl := dutfs.NewClient(conn)
dir := testutil.TempDir(t)
defer os.RemoveAll(dir)
path := filepath.Join(dir, "foo")
const content = "12345"
if err := ioutil.WriteFile(path, []byte(content), 0666); err != nil {
t.Fatal("Failed to create file: ", err)
}
data, err := cl.ReadFile(context.Background(), path)
if err != nil {
t.Error("ReadFile failed: ", err)
} else if s := string(data); s != content {
t.Errorf("ReadFile returned %q; want %q", s, content)
}
_, err = cl.ReadFile(context.Background(), filepath.Join(dir, "no_such_file"))
if !os.IsNotExist(err) {
t.Errorf("ReadFile: %v; want %v", err, os.ErrNotExist)
}
}
func TestOSErrors(t *testing.T) {
srv, conn := startTestPair(t)
defer srv.Stop()
defer conn.Close()
cl := dutfs.NewClient(conn)
dir := testutil.TempDir(t)
defer os.RemoveAll(dir)
path := filepath.Join(dir, "unreadable")
if err := ioutil.WriteFile(path, nil, 0); err != nil {
t.Fatal("Failed to create file: ", err)
}
if _, err := cl.ReadFile(context.Background(), path); err == nil {
t.Error("ReadFile succeeded unexpectedly for unreadable file (running unit tests with privilege?)")
} else if !os.IsPermission(err) {
t.Error("IsPermission = false for unreadable file")
}
}