...

Source file src/github.com/jezek/xgb/xgb_test.go

Documentation: github.com/jezek/xgb

     1  package xgb
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func TestConnOnNonBlockingDummyXServer(t *testing.T) {
    11  	timeout := 10 * time.Millisecond
    12  	checkedReply := func(wantError bool) func(*Conn) error {
    13  		request := "reply"
    14  		if wantError {
    15  			request = "error"
    16  		}
    17  		return func(c *Conn) error {
    18  			cookie := c.NewCookie(true, true)
    19  			c.NewRequest([]byte(request), cookie)
    20  			_, err := cookie.Reply()
    21  			if wantError && err == nil {
    22  				return errors.New(fmt.Sprintf("checked request \"%v\" with reply resulted in nil error, want some error", request))
    23  			}
    24  			if !wantError && err != nil {
    25  				return errors.New(fmt.Sprintf("checked request \"%v\" with reply resulted in error %v, want nil error", request, err))
    26  			}
    27  			return nil
    28  		}
    29  	}
    30  	checkedNoreply := func(wantError bool) func(*Conn) error {
    31  		request := "noreply"
    32  		if wantError {
    33  			request = "error"
    34  		}
    35  		return func(c *Conn) error {
    36  			cookie := c.NewCookie(true, false)
    37  			c.NewRequest([]byte(request), cookie)
    38  			err := cookie.Check()
    39  			if wantError && err == nil {
    40  				return errors.New(fmt.Sprintf("checked request \"%v\" with no reply resulted in nil error, want some error", request))
    41  			}
    42  			if !wantError && err != nil {
    43  				return errors.New(fmt.Sprintf("checked request \"%v\" with no reply resulted in error %v, want nil error", request, err))
    44  			}
    45  			return nil
    46  		}
    47  	}
    48  	uncheckedReply := func(wantError bool) func(*Conn) error {
    49  		request := "reply"
    50  		if wantError {
    51  			request = "error"
    52  		}
    53  		return func(c *Conn) error {
    54  			cookie := c.NewCookie(false, true)
    55  			c.NewRequest([]byte(request), cookie)
    56  			_, err := cookie.Reply()
    57  			if err != nil {
    58  				return errors.New(fmt.Sprintf("unchecked request \"%v\" with reply resulted in %v, want nil", request, err))
    59  			}
    60  			return nil
    61  		}
    62  	}
    63  	uncheckedNoreply := func(wantError bool) func(*Conn) error {
    64  		request := "noreply"
    65  		if wantError {
    66  			request = "error"
    67  		}
    68  		return func(c *Conn) error {
    69  			cookie := c.NewCookie(false, false)
    70  			c.NewRequest([]byte(request), cookie)
    71  			return nil
    72  		}
    73  	}
    74  	event := func() func(*Conn) error {
    75  		return func(c *Conn) error {
    76  			_, err := c.conn.Write([]byte("event"))
    77  			if err != nil {
    78  				return errors.New(fmt.Sprintf("asked dummy server to send event, but resulted in error: %v\n", err))
    79  			}
    80  			return err
    81  		}
    82  	}
    83  	waitEvent := func(wantError bool) func(*Conn) error {
    84  		return func(c *Conn) error {
    85  			_, err := c.WaitForEvent()
    86  			if wantError && err == nil {
    87  				return errors.New(fmt.Sprintf("wait for event resulted in nil error, want some error"))
    88  			}
    89  			if !wantError && err != nil {
    90  				return errors.New(fmt.Sprintf("wait for event resulted in error %v, want nil error", err))
    91  			}
    92  			return nil
    93  		}
    94  	}
    95  	checkClosed := func(c *Conn) error {
    96  		select {
    97  		case eoe, ok := <-c.eventChan:
    98  			if ok {
    99  				return fmt.Errorf("(*Conn).eventChan should be closed, but is not and returns %v", eoe)
   100  			}
   101  		case <-time.After(timeout):
   102  			return fmt.Errorf("(*Conn).eventChan should be closed, but is not and was blocking for %v", timeout)
   103  		}
   104  		return nil
   105  	}
   106  
   107  	testCases := []struct {
   108  		description string
   109  		actions     []func(*Conn) error
   110  	}{
   111  		{"close",
   112  			[]func(*Conn) error{},
   113  		},
   114  		{"double close",
   115  			[]func(*Conn) error{
   116  				func(c *Conn) error {
   117  					c.Close()
   118  					return nil
   119  				},
   120  			},
   121  		},
   122  		{"checked requests with reply",
   123  			[]func(*Conn) error{
   124  				checkedReply(false),
   125  				checkedReply(true),
   126  				checkedReply(false),
   127  				checkedReply(true),
   128  			},
   129  		},
   130  		{"checked requests no reply",
   131  			[]func(*Conn) error{
   132  				checkedNoreply(false),
   133  				checkedNoreply(true),
   134  				checkedNoreply(false),
   135  				checkedNoreply(true),
   136  			},
   137  		},
   138  		{"unchecked requests with reply",
   139  			[]func(*Conn) error{
   140  				uncheckedReply(false),
   141  				uncheckedReply(true),
   142  				waitEvent(true),
   143  				uncheckedReply(false),
   144  				event(),
   145  				waitEvent(false),
   146  			},
   147  		},
   148  		{"unchecked requests no reply",
   149  			[]func(*Conn) error{
   150  				uncheckedNoreply(false),
   151  				uncheckedNoreply(true),
   152  				waitEvent(true),
   153  				uncheckedNoreply(false),
   154  				event(),
   155  				waitEvent(false),
   156  			},
   157  		},
   158  		{"close with pending requests",
   159  			[]func(*Conn) error{
   160  				func(c *Conn) error {
   161  					c.conn.(*dNC).ReadLock()
   162  					defer c.conn.(*dNC).ReadUnlock()
   163  					c.NewRequest([]byte("reply"), c.NewCookie(false, true))
   164  					c.Close()
   165  					return nil
   166  				},
   167  				checkClosed,
   168  			},
   169  		},
   170  		{"unexpected conn close",
   171  			[]func(*Conn) error{
   172  				func(c *Conn) error {
   173  					c.conn.Close()
   174  					if ev, err := c.WaitForEvent(); ev != nil || err != nil {
   175  						return fmt.Errorf("WaitForEvent() = (%v, %v), want (nil, nil)", ev, err)
   176  					}
   177  					return nil
   178  				},
   179  				checkClosed,
   180  			},
   181  		},
   182  	}
   183  	for _, tc := range testCases {
   184  		t.Run(tc.description, func(t *testing.T) {
   185  			sclm := leaksMonitor("after server close, before testcase exit")
   186  			defer sclm.checkTesting(t)
   187  
   188  			s := newDummyNetConn("dummyX", newDummyXServerReplier())
   189  			defer s.Close()
   190  
   191  			c, err := postNewConn(&Conn{conn: s})
   192  			if err != nil {
   193  				t.Errorf("connect to dummy server error: %v", err)
   194  				return
   195  			}
   196  
   197  			defer leaksMonitor("after actions end", sclm).checkTesting(t)
   198  
   199  			for _, action := range tc.actions {
   200  				if err := action(c); err != nil {
   201  					t.Error(err)
   202  					break
   203  				}
   204  			}
   205  
   206  			recovered := false
   207  			func() {
   208  				defer func() {
   209  					if err := recover(); err != nil {
   210  						t.Errorf("(*Conn).Close() panic recover: %v", err)
   211  						recovered = true
   212  					}
   213  				}()
   214  
   215  				c.Close()
   216  			}()
   217  			if !recovered {
   218  				if err := checkClosed(c); err != nil {
   219  					t.Error(err)
   220  				}
   221  			}
   222  
   223  		})
   224  	}
   225  }
   226  

View as plain text