go-hep.org/x/hep@v0.38.1/xrootd/server_test.go (about)

     1  // Copyright ©2018 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package xrootd_test // import "go-hep.org/x/hep/xrootd"
     6  
     7  import (
     8  	"context"
     9  	"net"
    10  	"reflect"
    11  	"testing"
    12  
    13  	"go-hep.org/x/hep/xrootd"
    14  	"go-hep.org/x/hep/xrootd/internal/xrdenc"
    15  	"go-hep.org/x/hep/xrootd/xrdproto"
    16  	"go-hep.org/x/hep/xrootd/xrdproto/dirlist"
    17  	"go-hep.org/x/hep/xrootd/xrdproto/handshake"
    18  	"go-hep.org/x/hep/xrootd/xrdproto/login"
    19  	"go-hep.org/x/hep/xrootd/xrdproto/protocol"
    20  )
    21  
    22  type pipeListener struct {
    23  	conns  chan net.Conn
    24  	close  chan struct{}
    25  	closed bool
    26  }
    27  
    28  func (pl *pipeListener) Close() error {
    29  	if pl.closed {
    30  		return nil
    31  	}
    32  	pl.closed = true
    33  	pl.close <- struct{}{}
    34  	return nil
    35  }
    36  
    37  func (pl *pipeListener) Addr() net.Addr {
    38  	panic("implement me")
    39  }
    40  
    41  func (pl *pipeListener) Accept() (net.Conn, error) {
    42  	select {
    43  	case conn := <-pl.conns:
    44  		return conn, nil
    45  	case <-pl.close:
    46  		return nil, closedError{}
    47  	}
    48  }
    49  
    50  type closedError struct {
    51  }
    52  
    53  func (closedError) Error() string {
    54  	return "xrootd: pipe listener closed"
    55  }
    56  
    57  func TestServe_Handshake(t *testing.T) {
    58  	connsCh := make(chan net.Conn, 1)
    59  	p1, p2 := net.Pipe()
    60  	defer p1.Close()
    61  	defer p2.Close()
    62  
    63  	connsCh <- p1
    64  	listener := &pipeListener{conns: connsCh, close: make(chan struct{})}
    65  	defer listener.Close()
    66  
    67  	srv := xrootd.NewServer(xrootd.Default(), func(err error) {
    68  		t.Error(err)
    69  	})
    70  	defer func() {
    71  		_ = srv.Shutdown(context.Background())
    72  	}()
    73  
    74  	go func() {
    75  		req := handshake.NewRequest()
    76  		var wBuffer xrdenc.WBuffer
    77  		err := req.MarshalXrd(&wBuffer)
    78  		if err != nil {
    79  			t.Errorf("could not marshal request: %+v", err)
    80  		}
    81  		_, err = p2.Write(wBuffer.Bytes())
    82  		if err != nil {
    83  			t.Errorf("could not write buffer: %+v", err)
    84  		}
    85  		respHeader, respData, err := xrdproto.ReadResponse(p2)
    86  		if err != nil {
    87  			t.Errorf("unexpected read error: %v", err)
    88  		}
    89  
    90  		var (
    91  			handshakeResp handshake.Response
    92  			rBuffer       = xrdenc.NewRBuffer(respData)
    93  		)
    94  
    95  		if err := handshakeResp.UnmarshalXrd(rBuffer); err != nil {
    96  			t.Errorf("could not unmarshal: %v", err)
    97  		}
    98  
    99  		wantHeader := xrdproto.ResponseHeader{StreamID: xrdproto.StreamID{0}, Status: xrdproto.Ok, DataLength: 8}
   100  		if !reflect.DeepEqual(wantHeader, respHeader) {
   101  			t.Errorf("wrong response header:\ngot = %v\nwant = %v", respHeader, wantHeader)
   102  		}
   103  
   104  		want := handshake.Response{ProtocolVersion: 0x310, ServerType: xrdproto.DataServer}
   105  		if !reflect.DeepEqual(want, handshakeResp) {
   106  			t.Errorf("wrong handshake response:\ngot = %v\nwant = %v", handshakeResp, want)
   107  		}
   108  
   109  		err = srv.Shutdown(context.Background())
   110  		if err != nil {
   111  			t.Errorf("could not shutdown server: %+v", err)
   112  		}
   113  	}()
   114  
   115  	if err := srv.Serve(listener); err != nil && err != xrootd.ErrServerClosed {
   116  		t.Fatalf("unexpected error: %v", err)
   117  	}
   118  }
   119  
   120  func TestServe_Login(t *testing.T) {
   121  	connsCh := make(chan net.Conn, 1)
   122  	p1, p2 := net.Pipe()
   123  	defer p1.Close()
   124  	defer p2.Close()
   125  
   126  	connsCh <- p1
   127  	listener := &pipeListener{conns: connsCh, close: make(chan struct{})}
   128  	defer listener.Close()
   129  
   130  	srv := xrootd.NewServer(xrootd.Default(), func(err error) {
   131  		t.Error(err)
   132  	})
   133  	defer func() {
   134  		_ = srv.Shutdown(context.Background())
   135  	}()
   136  
   137  	go func() {
   138  		handshakeReq := handshake.NewRequest()
   139  		var wBuffer xrdenc.WBuffer
   140  		err := handshakeReq.MarshalXrd(&wBuffer)
   141  		if err != nil {
   142  			t.Errorf("could not marshal handshake request: %+v", err)
   143  		}
   144  		_, err = p2.Write(wBuffer.Bytes())
   145  		if err != nil {
   146  			t.Errorf("could not write buffer: %+v", err)
   147  		}
   148  		_, _, err = xrdproto.ReadResponse(p2)
   149  		if err != nil {
   150  			t.Errorf("unexpected read error: %v", err)
   151  		}
   152  
   153  		req := login.NewRequest("gopher", "")
   154  		streamID := [2]byte{0, 1}
   155  		reqHeader := xrdproto.RequestHeader{RequestID: login.RequestID, StreamID: streamID}
   156  		wBuffer = xrdenc.WBuffer{}
   157  		err = reqHeader.MarshalXrd(&wBuffer)
   158  		if err != nil {
   159  			t.Errorf("could not marshal req-header: %+v", err)
   160  		}
   161  		err = req.MarshalXrd(&wBuffer)
   162  		if err != nil {
   163  			t.Errorf("could not marshal request: %+v", err)
   164  		}
   165  		_, err = p2.Write(wBuffer.Bytes())
   166  		if err != nil {
   167  			t.Errorf("could not write buffer: %+v", err)
   168  		}
   169  		respHeader, respData, err := xrdproto.ReadResponse(p2)
   170  		if err != nil {
   171  			t.Errorf("unexpected read error: %v", err)
   172  		}
   173  
   174  		var (
   175  			loginResp login.Response
   176  			rBuffer   = xrdenc.NewRBuffer(respData)
   177  		)
   178  
   179  		if err := loginResp.UnmarshalXrd(rBuffer); err != nil {
   180  			t.Errorf("could not unmarshal: %v", err)
   181  		}
   182  
   183  		wantHeader := xrdproto.ResponseHeader{StreamID: streamID, Status: xrdproto.Ok, DataLength: 16}
   184  		if !reflect.DeepEqual(wantHeader, respHeader) {
   185  			t.Errorf("wrong response header:\ngot = %v\nwant = %v", respHeader, wantHeader)
   186  		}
   187  
   188  		// TODO: validate loginResp.
   189  
   190  		err = srv.Shutdown(context.Background())
   191  		if err != nil {
   192  			t.Errorf("could not shutdown server: %+v", err)
   193  		}
   194  	}()
   195  
   196  	if err := srv.Serve(listener); err != nil && err != xrootd.ErrServerClosed {
   197  		t.Fatalf("unexpected error: %v", err)
   198  	}
   199  }
   200  
   201  func TestServe_Protocol(t *testing.T) {
   202  	connsCh := make(chan net.Conn, 1)
   203  	p1, p2 := net.Pipe()
   204  	defer p1.Close()
   205  	defer p2.Close()
   206  
   207  	connsCh <- p1
   208  	listener := &pipeListener{conns: connsCh, close: make(chan struct{})}
   209  	defer listener.Close()
   210  
   211  	srv := xrootd.NewServer(xrootd.Default(), func(err error) {
   212  		t.Error(err)
   213  	})
   214  	defer func() {
   215  		_ = srv.Shutdown(context.Background())
   216  	}()
   217  
   218  	go func() {
   219  		var (
   220  			handshakeReq = handshake.NewRequest()
   221  			wBuffer      xrdenc.WBuffer
   222  		)
   223  		err := handshakeReq.MarshalXrd(&wBuffer)
   224  		if err != nil {
   225  			t.Errorf("could not marshal handshake request: %+v", err)
   226  		}
   227  		_, err = p2.Write(wBuffer.Bytes())
   228  		if err != nil {
   229  			t.Errorf("could not write buffer: %+v", err)
   230  		}
   231  		_, _, err = xrdproto.ReadResponse(p2)
   232  		if err != nil {
   233  			t.Errorf("unexpected read error: %v", err)
   234  		}
   235  
   236  		req := protocol.NewRequest(0x310, false)
   237  		streamID := [2]byte{0, 2}
   238  		reqHeader := xrdproto.RequestHeader{RequestID: protocol.RequestID, StreamID: streamID}
   239  		wBuffer = xrdenc.WBuffer{}
   240  		err = reqHeader.MarshalXrd(&wBuffer)
   241  		if err != nil {
   242  			t.Errorf("could not marshal request header: %+v", err)
   243  		}
   244  		err = req.MarshalXrd(&wBuffer)
   245  		if err != nil {
   246  			t.Errorf("could not marshal request: %+v", err)
   247  		}
   248  		_, err = p2.Write(wBuffer.Bytes())
   249  		if err != nil {
   250  			t.Errorf("could not write buffer: %+v", err)
   251  		}
   252  
   253  		respHeader, respData, err := xrdproto.ReadResponse(p2)
   254  		if err != nil {
   255  			t.Errorf("unexpected read error: %v", err)
   256  		}
   257  
   258  		var (
   259  			protocolResp protocol.Response
   260  			rBuffer      = xrdenc.NewRBuffer(respData)
   261  		)
   262  
   263  		if err := protocolResp.UnmarshalXrd(rBuffer); err != nil {
   264  			t.Errorf("could not unmarshal: %v", err)
   265  		}
   266  
   267  		wantHeader := xrdproto.ResponseHeader{StreamID: streamID, Status: xrdproto.Ok, DataLength: 8}
   268  		if !reflect.DeepEqual(wantHeader, respHeader) {
   269  			t.Errorf("wrong response header:\ngot = %v\nwant = %v", respHeader, wantHeader)
   270  		}
   271  
   272  		want := protocol.Response{BinaryProtocolVersion: 0x310, Flags: protocol.IsServer}
   273  		if !reflect.DeepEqual(want, protocolResp) {
   274  			t.Errorf("wrong response:\ngot = %v\nwant = %v", protocolResp, want)
   275  		}
   276  
   277  		err = srv.Shutdown(context.Background())
   278  		if err != nil {
   279  			t.Errorf("could not shutdown server: %+v", err)
   280  		}
   281  	}()
   282  
   283  	if err := srv.Serve(listener); err != nil && err != xrootd.ErrServerClosed {
   284  		t.Fatalf("unexpected error: %v", err)
   285  	}
   286  }
   287  
   288  func TestServe_Dirlist(t *testing.T) {
   289  	connsCh := make(chan net.Conn, 1)
   290  	p1, p2 := net.Pipe()
   291  	defer p1.Close()
   292  	defer p2.Close()
   293  
   294  	connsCh <- p1
   295  	listener := &pipeListener{conns: connsCh, close: make(chan struct{})}
   296  	defer listener.Close()
   297  
   298  	srv := xrootd.NewServer(xrootd.Default(), func(err error) {
   299  		t.Error(err)
   300  	})
   301  	defer func() {
   302  		_ = srv.Shutdown(context.Background())
   303  	}()
   304  
   305  	go func() {
   306  		var (
   307  			handshakeReq = handshake.NewRequest()
   308  			wBuffer      xrdenc.WBuffer
   309  		)
   310  		err := handshakeReq.MarshalXrd(&wBuffer)
   311  		if err != nil {
   312  			t.Errorf("could not marshal handshake request: %+v", err)
   313  		}
   314  		_, err = p2.Write(wBuffer.Bytes())
   315  		if err != nil {
   316  			t.Errorf("could not write buffer: %+v", err)
   317  		}
   318  		_, _, err = xrdproto.ReadResponse(p2)
   319  		if err != nil {
   320  			t.Errorf("unexpected read error: %v", err)
   321  		}
   322  
   323  		req := dirlist.NewRequest("/tmp")
   324  		streamID := [2]byte{0, 2}
   325  		reqHeader := xrdproto.RequestHeader{RequestID: dirlist.RequestID, StreamID: streamID}
   326  		wBuffer = xrdenc.WBuffer{}
   327  		err = reqHeader.MarshalXrd(&wBuffer)
   328  		if err != nil {
   329  			t.Errorf("could not marshal request header: %+v", err)
   330  		}
   331  		err = req.MarshalXrd(&wBuffer)
   332  		if err != nil {
   333  			t.Errorf("could not marshal request: %+v", err)
   334  		}
   335  		_, err = p2.Write(wBuffer.Bytes())
   336  		if err != nil {
   337  			t.Errorf("could not write buffer: %+v", err)
   338  		}
   339  
   340  		respHeader, respData, err := xrdproto.ReadResponse(p2)
   341  		if err != nil {
   342  			t.Errorf("unexpected read error: %v", err)
   343  		}
   344  
   345  		var (
   346  			errorResp xrdproto.ServerError
   347  			rBuffer   = xrdenc.NewRBuffer(respData)
   348  		)
   349  
   350  		if err := errorResp.UnmarshalXrd(rBuffer); err != nil {
   351  			t.Errorf("could not unmarshal: %v", err)
   352  		}
   353  
   354  		wantHeader := xrdproto.ResponseHeader{StreamID: streamID, Status: xrdproto.Error, DataLength: 39}
   355  		if !reflect.DeepEqual(wantHeader, respHeader) {
   356  			t.Errorf("wrong response header:\ngot = %v\nwant = %v", respHeader, wantHeader)
   357  		}
   358  
   359  		want := xrdproto.ServerError{Code: xrdproto.InvalidRequest, Message: "Dirlist request is not implemented"}
   360  		if !reflect.DeepEqual(want, errorResp) {
   361  			t.Errorf("wrong response:\ngot = %v\nwant = %v", errorResp, want)
   362  		}
   363  
   364  		err = srv.Shutdown(context.Background())
   365  		if err != nil {
   366  			t.Errorf("could not shutdown server: %+v", err)
   367  		}
   368  	}()
   369  
   370  	if err := srv.Serve(listener); err != nil && err != xrootd.ErrServerClosed {
   371  		t.Fatalf("unexpected error: %v", err)
   372  	}
   373  }