1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
From 9689cadcc6d4b63615962552f4d90465d7c2741b Mon Sep 17 00:00:00 2001
From: Thibaut Rousseau <thibaut.rousseau@ovhcloud.com>
Date: Tue, 7 Apr 2020 11:15:18 +0200
Subject: [PATCH 1/2] fix tests by removing unnecessary check on first stack
entry
---
error_test.go | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
--- a/error_test.go
+++ b/error_test.go
@@ -10,6 +10,26 @@
"testing"
)
+func BenchmarkStackFormat(b *testing.B) {
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ func() {
+ defer func() {
+ err := recover()
+ if err != 'a' {
+ b.Fatal(err)
+ }
+
+ e := Errorf("hi")
+ _ = string(e.Stack())
+ }()
+
+ a()
+ }()
+ }
+}
+
func TestStackFormat(t *testing.T) {
defer func() {
@@ -247,7 +267,7 @@
// compareStacks will compare a stack created using the errors package (actual)
// with a reference stack created with the callers function (expected). The
-// first entry is compared inexact since the actual and expected stacks cannot
+// first entry is not compared since the actual and expected stacks cannot
// be created at the exact same program counter position so the first entry
// will always differ somewhat. Returns nil if the stacks are equal enough and
// an error containing a detailed error message otherwise.
@@ -256,12 +276,7 @@
return stackCompareError("Stacks does not have equal length", actual, expected)
}
for i, pc := range actual {
- if i == 0 {
- firstEntryDiff := (int)(expected[i]) - (int)(pc)
- if firstEntryDiff < -27 || firstEntryDiff > 27 {
- return stackCompareError(fmt.Sprintf("First entry PC diff to large (%d)", firstEntryDiff), actual, expected)
- }
- } else if pc != expected[i] {
+ if i != 0 && pc != expected[i] {
return stackCompareError(fmt.Sprintf("Stacks does not match entry %d (and maybe others)", i), actual, expected)
}
}
--- a/stackframe.go
+++ b/stackframe.go
@@ -1,9 +1,10 @@
package errors
import (
+ "bufio"
"bytes"
"fmt"
- "io/ioutil"
+ "os"
"runtime"
"strings"
)
@@ -62,18 +63,29 @@
// SourceLine gets the line of code (from File and Line) of the original source if possible.
func (frame *StackFrame) SourceLine() (string, error) {
- data, err := ioutil.ReadFile(frame.File)
+ if frame.LineNumber <= 0 {
+ return "???", nil
+ }
+ file, err := os.Open(frame.File)
if err != nil {
return "", New(err)
}
+ defer file.Close()
- lines := bytes.Split(data, []byte{'\n'})
- if frame.LineNumber <= 0 || frame.LineNumber >= len(lines) {
- return "???", nil
+ scanner := bufio.NewScanner(file)
+ currentLine := 1
+ for scanner.Scan() {
+ if currentLine == frame.LineNumber {
+ return string(bytes.Trim(scanner.Bytes(), " \t")), nil
+ }
+ currentLine++
}
- // -1 because line-numbers are 1 based, but our array is 0 based
- return string(bytes.Trim(lines[frame.LineNumber-1], " \t")), nil
+ if err := scanner.Err(); err != nil {
+ return "", New(err)
+ }
+
+ return "???", nil
}
func packageAndName(fn *runtime.Func) (string, string) {
|