...

Source file src/k8s.io/utils/io/read_test.go

Documentation: k8s.io/utils/io

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package io
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"path/filepath"
    24  	"strings"
    25  	"syscall"
    26  	"testing"
    27  )
    28  
    29  func writeToPipe(namedPipe string, flaky bool, i int) {
    30  	pipe, err := os.OpenFile(namedPipe, os.O_WRONLY, 0600)
    31  	if err != nil {
    32  		return
    33  	}
    34  
    35  	// The first two reads should never be consistent but all
    36  	// subsequent reads should be
    37  	outstr := fmt.Sprintf("Foobar %t", (i <= 0))
    38  
    39  	if flaky {
    40  		outstr = fmt.Sprintf("Foobar %d", i)
    41  	}
    42  
    43  	pipe.Write([]byte(outstr))
    44  	pipe.Close()
    45  }
    46  
    47  func makePipe(t *testing.T) string {
    48  	tmp, err := ioutil.TempDir("", "pipe-test")
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	pipe := filepath.Join(tmp, "pipe")
    54  	syscall.Mkfifo(pipe, 0600)
    55  
    56  	return pipe
    57  }
    58  
    59  func writer(namedPipe string, flaky bool, c <-chan int, d <-chan bool) {
    60  	// Make sure something is in the fifo otherwise the first iteration of
    61  	// ConsistentRead will block forever
    62  	writeToPipe(namedPipe, flaky, -1)
    63  
    64  	for {
    65  		select {
    66  		case i := <-c:
    67  			writeToPipe(namedPipe, flaky, i)
    68  		case <-d:
    69  			os.RemoveAll(namedPipe)
    70  			return
    71  		}
    72  	}
    73  }
    74  
    75  func TestConsistentRead(t *testing.T) {
    76  	pipe := makePipe(t)
    77  	prog, done := make(chan int), make(chan bool)
    78  	go writer(pipe, false, prog, done)
    79  
    80  	if _, err := consistentReadSync(pipe, 3, func(i int) { prog <- i }); err != nil {
    81  		t.Fatal(err)
    82  	}
    83  
    84  	done <- true
    85  }
    86  
    87  func TestConsistentReadFlakyReader(t *testing.T) {
    88  	pipe := makePipe(t)
    89  	prog, done := make(chan int), make(chan bool)
    90  	go writer(pipe, true, prog, done)
    91  
    92  	var err error
    93  	if _, err = consistentReadSync(pipe, 3, func(i int) { prog <- i }); err == nil {
    94  		t.Fatal("flaky reader returned consistent results")
    95  	}
    96  	if !IsInconsistentReadError(err) {
    97  		t.Errorf("Unexpected error returned, expected InconsistentReadError, got: %T / %q", err, err)
    98  	}
    99  }
   100  
   101  func TestReadAtMost(t *testing.T) {
   102  	testCases := []struct {
   103  		limit  int64
   104  		data   string
   105  		errMsg string
   106  	}{
   107  		{4, "hell", "the read limit is reached"},
   108  		{5, "hello", "the read limit is reached"},
   109  		{6, "hello", ""},
   110  	}
   111  
   112  	for _, tc := range testCases {
   113  		r := strings.NewReader("hello")
   114  		data, err := ReadAtMost(r, tc.limit)
   115  		if string(data) != tc.data {
   116  			t.Errorf("Read limit %d: expected \"%s\", got \"%s\"", tc.limit, tc.data, string(data))
   117  		}
   118  
   119  		if err == nil && tc.errMsg != "" {
   120  			t.Errorf("Read limit %d: expected error with message \"%s\", got no error", tc.limit, tc.errMsg)
   121  		}
   122  
   123  		if err != nil && err.Error() != tc.errMsg {
   124  			t.Errorf("Read limit %d: expected error with message \"%s\", got error with message \"%s\"", tc.limit, tc.errMsg, err.Error())
   125  		}
   126  	}
   127  }
   128  

View as plain text