Source file src/bytes/boundary_test.go

Documentation: bytes

     1  // Copyright 2017 The Go 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  // +build linux
     6  
     7  package bytes_test
     8  
     9  import (
    10  	. "bytes"
    11  	"syscall"
    12  	"testing"
    13  )
    14  
    15  // This file tests the situation where byte operations are checking
    16  // data very near to a page boundary. We want to make sure those
    17  // operations do not read across the boundary and cause a page
    18  // fault where they shouldn't.
    19  
    20  // These tests run only on linux. The code being tested is
    21  // not OS-specific, so it does not need to be tested on all
    22  // operating systems.
    23  
    24  // dangerousSlice returns a slice which is immediately
    25  // preceded and followed by a faulting page.
    26  func dangerousSlice(t *testing.T) []byte {
    27  	pagesize := syscall.Getpagesize()
    28  	b, err := syscall.Mmap(0, 0, 3*pagesize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANONYMOUS|syscall.MAP_PRIVATE)
    29  	if err != nil {
    30  		t.Fatalf("mmap failed %s", err)
    31  	}
    32  	err = syscall.Mprotect(b[:pagesize], syscall.PROT_NONE)
    33  	if err != nil {
    34  		t.Fatalf("mprotect low failed %s\n", err)
    35  	}
    36  	err = syscall.Mprotect(b[2*pagesize:], syscall.PROT_NONE)
    37  	if err != nil {
    38  		t.Fatalf("mprotect high failed %s\n", err)
    39  	}
    40  	return b[pagesize : 2*pagesize]
    41  }
    42  
    43  func TestEqualNearPageBoundary(t *testing.T) {
    44  	t.Parallel()
    45  	b := dangerousSlice(t)
    46  	for i := range b {
    47  		b[i] = 'A'
    48  	}
    49  	for i := 0; i <= len(b); i++ {
    50  		Equal(b[:i], b[len(b)-i:])
    51  		Equal(b[len(b)-i:], b[:i])
    52  	}
    53  }
    54  
    55  func TestIndexByteNearPageBoundary(t *testing.T) {
    56  	t.Parallel()
    57  	b := dangerousSlice(t)
    58  	for i := range b {
    59  		idx := IndexByte(b[i:], 1)
    60  		if idx != -1 {
    61  			t.Fatalf("IndexByte(b[%d:])=%d, want -1\n", i, idx)
    62  		}
    63  	}
    64  }
    65  
    66  func TestIndexNearPageBoundary(t *testing.T) {
    67  	t.Parallel()
    68  	var q [64]byte
    69  	b := dangerousSlice(t)
    70  	if len(b) > 256 {
    71  		// Only worry about when we're near the end of a page.
    72  		b = b[len(b)-256:]
    73  	}
    74  	for j := 1; j < len(q); j++ {
    75  		q[j-1] = 1 // difference is only found on the last byte
    76  		for i := range b {
    77  			idx := Index(b[i:], q[:j])
    78  			if idx != -1 {
    79  				t.Fatalf("Index(b[%d:], q[:%d])=%d, want -1\n", i, j, idx)
    80  			}
    81  		}
    82  		q[j-1] = 0
    83  	}
    84  }
    85  

View as plain text