blob: 99d33f727f7c49d9dbf375dba1a7fc9dd2a2ff59 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package tests
import (
"encoding/binary"
"fmt"
"math"
"strings"
"mojo/go/system/embedder"
"mojo/public/go/bindings"
"mojo/public/go/system"
)
var core system.Core
var waiter bindings.AsyncWaiter
func init() {
embedder.InitializeMojoEmbedder()
core = system.GetCore()
waiter = bindings.GetAsyncWaiter()
}
type mockHandle struct {
bindings.InvalidHandle
handle system.MojoHandle
}
func (h *mockHandle) IsValid() bool {
return true
}
func (h *mockHandle) ReleaseNativeHandle() system.MojoHandle {
return h.handle
}
func (h *mockHandle) ToUntypedHandle() system.UntypedHandle {
return h
}
func (h *mockHandle) ToConsumerHandle() system.ConsumerHandle {
return h
}
func (h *mockHandle) ToProducerHandle() system.ProducerHandle {
return h
}
func (h *mockHandle) ToMessagePipeHandle() system.MessagePipeHandle {
return h
}
func (h *mockHandle) ToSharedBufferHandle() system.SharedBufferHandle {
return h
}
// inputParser parses validation tests input format as described in
// |mojo/public/cpp/bindings/tests/validation_test_input_parser.h|
type inputParser struct {
}
type dataItem struct {
Type string
Value string
}
type pointerPlaceholder struct {
Position int
Size int
}
func (p *inputParser) parseToDataItems(s string) []dataItem {
var items []dataItem
s = strings.TrimSpace(s)
for len(s) > 0 {
// Parsing data item type.
var itemType string
if s[0] == '[' {
closeBracket := strings.Index(s, "]")
if closeBracket == -1 {
panic("unmatched left [")
}
itemType = strings.TrimSpace(s[1:closeBracket])
s = strings.TrimSpace(s[closeBracket+1:])
} else {
itemType = "u1"
}
// Parsing data item value.
itemEnd := strings.IndexAny(s, "[ \t\n\r")
if itemEnd == -1 {
items = append(items, dataItem{itemType, strings.TrimSpace(s)})
s = ""
} else {
items = append(items, dataItem{itemType, strings.TrimSpace(s[:itemEnd])})
s = strings.TrimSpace(s[itemEnd:])
}
}
return items
}
// Parse parses a validation tests input string that has no comments.
// Panics if input has errors.
func (p *inputParser) Parse(s string) ([]byte, []system.UntypedHandle) {
var bytes []byte
var buf [8]byte
// We need non-nil slice for comparing values with reflect.DeepEqual.
handles := []system.UntypedHandle{}
pointers := make(map[string]pointerPlaceholder)
for _, item := range p.parseToDataItems(s) {
switch item.Type {
case "u1":
var value uint8
fmt.Sscan(item.Value, &value)
bytes = append(bytes, byte(value))
case "u2":
var value uint16
fmt.Sscan(item.Value, &value)
binary.LittleEndian.PutUint16(buf[:2], value)
bytes = append(bytes, buf[:2]...)
case "u4":
var value uint32
fmt.Sscan(item.Value, &value)
binary.LittleEndian.PutUint32(buf[:4], value)
bytes = append(bytes, buf[:4]...)
case "u8":
var value uint64
fmt.Sscan(item.Value, &value)
binary.LittleEndian.PutUint64(buf[:8], value)
bytes = append(bytes, buf[:8]...)
case "s1":
var value int8
fmt.Sscan(item.Value, &value)
bytes = append(bytes, byte(value))
case "s2":
var value int16
fmt.Sscan(item.Value, &value)
binary.LittleEndian.PutUint16(buf[:2], uint16(value))
bytes = append(bytes, buf[:2]...)
case "s4":
var value int32
fmt.Sscan(item.Value, &value)
binary.LittleEndian.PutUint32(buf[:4], uint32(value))
bytes = append(bytes, buf[:4]...)
case "s8":
var value int64
fmt.Sscan(item.Value, &value)
binary.LittleEndian.PutUint64(buf[:8], uint64(value))
bytes = append(bytes, buf[:8]...)
case "b":
var value byte
for i := 0; i < 8; i++ {
value <<= 1
if item.Value[i] == '1' {
value++
}
}
bytes = append(bytes, value)
case "f":
var value float32
fmt.Sscan(item.Value, &value)
binary.LittleEndian.PutUint32(buf[:4], math.Float32bits(value))
bytes = append(bytes, buf[:4]...)
case "d":
var value float64
fmt.Sscan(item.Value, &value)
binary.LittleEndian.PutUint64(buf[:8], math.Float64bits(value))
bytes = append(bytes, buf[:8]...)
case "dist4":
pointers[item.Value] = pointerPlaceholder{len(bytes), 4}
bytes = append(bytes, buf[:4]...)
case "dist8":
pointers[item.Value] = pointerPlaceholder{len(bytes), 8}
bytes = append(bytes, buf[:8]...)
case "anchr":
placeholder := pointers[item.Value]
dist := len(bytes) - placeholder.Position
switch placeholder.Size {
case 4:
binary.LittleEndian.PutUint32(bytes[placeholder.Position:], uint32(dist))
case 8:
binary.LittleEndian.PutUint64(bytes[placeholder.Position:], uint64(dist))
}
delete(pointers, item.Value)
case "handles":
var value int
fmt.Sscan(item.Value, &value)
handles = make([]system.UntypedHandle, value)
for i, _ := range handles {
handles[i] = &mockHandle{handle: system.MojoHandle(i + 1)}
}
default:
panic(fmt.Sprintf("unsupported item type: %v", item.Type))
}
}
if len(pointers) != 0 {
panic(fmt.Sprintf("unmatched pointers: %v", pointers))
}
return bytes, handles
}