1package parse 2 3import ( 4 "bytes" 5 "fmt" 6 "strings" 7 "testing" 8 9 "github.com/tdewolff/test" 10) 11 12func TestPosition(t *testing.T) { 13 var newlineTests = []struct { 14 offset int 15 buf string 16 line int 17 col int 18 }{ 19 // \u2028, \u2029, and \u2318 are three bytes long 20 {0, "x", 1, 1}, 21 {1, "xx", 1, 2}, 22 {2, "x\nx", 2, 1}, 23 {2, "\n\nx", 3, 1}, 24 {3, "\nxxx", 2, 3}, 25 {2, "\r\nx", 2, 1}, 26 {1, "\rx", 2, 1}, 27 {3, "\u2028x", 2, 1}, 28 {3, "\u2029x", 2, 1}, 29 30 // edge cases 31 {0, "", 1, 1}, 32 {2, "x", 1, 2}, 33 {0, "\nx", 1, 1}, 34 {1, "\r\ny", 1, 1}, 35 {-1, "x", 1, 1}, 36 {0, "\x00a", 1, 1}, 37 {2, "a\x00\n", 1, 3}, 38 39 // unicode 40 {1, "x\u2028x", 1, 2}, 41 {2, "x\u2028x", 1, 2}, 42 {3, "x\u2028x", 1, 2}, 43 {0, "x\u2318x", 1, 1}, 44 {1, "x\u2318x", 1, 2}, 45 {2, "x\u2318x", 1, 2}, 46 {3, "x\u2318x", 1, 2}, 47 {4, "x\u2318x", 1, 3}, 48 } 49 for _, tt := range newlineTests { 50 t.Run(fmt.Sprint(tt.buf, " ", tt.offset), func(t *testing.T) { 51 r := bytes.NewBufferString(tt.buf) 52 line, col, _ := Position(r, tt.offset) 53 test.T(t, line, tt.line, "line") 54 test.T(t, col, tt.col, "column") 55 }) 56 } 57} 58 59func TestPositionContext(t *testing.T) { 60 var newlineTests = []struct { 61 offset int 62 buf string 63 context string 64 }{ 65 {10, "0123456789@123456789012345678901234567890123456789012345678901234567890123456789", "0123456789@1234567890123456789012345678901234567890123456..."}, // 80 characters -> 60 characters 66 {40, "0123456789012345678901234567890123456789@123456789012345678901234567890123456789", "...01234567890123456789@12345678901234567890..."}, 67 {60, "012345678901234567890123456789012345678901234567890123456789@12345678901234567890", "...78901234567890123456789@12345678901234567890"}, 68 {60, "012345678901234567890123456789012345678901234567890123456789@12345678901234567890123", "...01234567890123456789@12345678901234567890123"}, 69 {60, "012345678901234567890123456789012345678901234567890123456789@123456789012345678901234", "...01234567890123456789@12345678901234567890..."}, 70 {60, "0123456789012345678901234567890123456789ÎÎÎÎÎÎÎÎÎÎ@123456789012345678901234567890", "...0123456789ÎÎÎÎÎÎÎÎÎÎ@12345678901234567890..."}, 71 {60, "012345678901234567890123456789012345678912456780123456789@12345678901234567890", "...789·12·45678·0123456789@12345678901234567890"}, 72 } 73 for _, tt := range newlineTests { 74 t.Run(fmt.Sprint(tt.buf, " ", tt.offset), func(t *testing.T) { 75 r := bytes.NewBufferString(tt.buf) 76 _, _, context := Position(r, tt.offset) 77 i := strings.IndexByte(context, '\n') 78 pointer := context[i+1:] 79 context = context[:i] 80 test.T(t, context[7:], tt.context) 81 82 // check if @ and ^ are at the same position 83 j := strings.IndexByte(context, '@') 84 k := strings.IndexByte(pointer, '^') 85 test.T(t, len([]rune(pointer[:k])), len([]rune(context[:j]))) 86 }) 87 } 88} 89