Source file src/runtime/time_test.go

     1  // Copyright 2019 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  package runtime_test
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  	"errors"
    11  	"internal/testenv"
    12  	"os/exec"
    13  	"reflect"
    14  	"runtime"
    15  	"testing"
    16  )
    17  
    18  func TestFakeTime(t *testing.T) {
    19  	if runtime.GOOS == "windows" {
    20  		t.Skip("faketime not supported on windows")
    21  	}
    22  
    23  	// Faketime is advanced in checkdead. External linking brings in cgo,
    24  	// causing checkdead not working.
    25  	testenv.MustInternalLink(t, false)
    26  
    27  	t.Parallel()
    28  
    29  	exe, err := buildTestProg(t, "testfaketime", "-tags=faketime")
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  
    34  	var stdout, stderr bytes.Buffer
    35  	cmd := exec.Command(exe)
    36  	cmd.Stdout = &stdout
    37  	cmd.Stderr = &stderr
    38  
    39  	err = testenv.CleanCmdEnv(cmd).Run()
    40  	if err != nil {
    41  		t.Fatalf("exit status: %v\n%s", err, stderr.String())
    42  	}
    43  
    44  	t.Logf("raw stdout: %q", stdout.String())
    45  	t.Logf("raw stderr: %q", stderr.String())
    46  
    47  	f1, err1 := parseFakeTime(stdout.Bytes())
    48  	if err1 != nil {
    49  		t.Fatal(err1)
    50  	}
    51  	f2, err2 := parseFakeTime(stderr.Bytes())
    52  	if err2 != nil {
    53  		t.Fatal(err2)
    54  	}
    55  
    56  	const time0 = 1257894000000000000
    57  	got := [][]fakeTimeFrame{f1, f2}
    58  	var want = [][]fakeTimeFrame{{
    59  		{time0 + 1, "line 2\n"},
    60  		{time0 + 1, "line 3\n"},
    61  		{time0 + 1e9, "line 5\n"},
    62  		{time0 + 1e9, "2009-11-10T23:00:01Z"},
    63  	}, {
    64  		{time0, "line 1\n"},
    65  		{time0 + 2, "line 4\n"},
    66  	}}
    67  	if !reflect.DeepEqual(want, got) {
    68  		t.Fatalf("want %v, got %v", want, got)
    69  	}
    70  }
    71  
    72  type fakeTimeFrame struct {
    73  	time uint64
    74  	data string
    75  }
    76  
    77  func parseFakeTime(x []byte) ([]fakeTimeFrame, error) {
    78  	var frames []fakeTimeFrame
    79  	for len(x) != 0 {
    80  		if len(x) < 4+8+4 {
    81  			return nil, errors.New("truncated header")
    82  		}
    83  		const magic = "\x00\x00PB"
    84  		if string(x[:len(magic)]) != magic {
    85  			return nil, errors.New("bad magic")
    86  		}
    87  		x = x[len(magic):]
    88  		time := binary.BigEndian.Uint64(x)
    89  		x = x[8:]
    90  		dlen := binary.BigEndian.Uint32(x)
    91  		x = x[4:]
    92  		data := string(x[:dlen])
    93  		x = x[dlen:]
    94  		frames = append(frames, fakeTimeFrame{time, data})
    95  	}
    96  	return frames, nil
    97  }
    98  

View as plain text