mirror of
https://github.com/arkadiyt/protodump.git
synced 2026-10-21 01:36:52 +02:00
Add testing
This commit is contained in:
1 parent
d57358e131
commit
1d5e583df5
7 files changed
+181
-10
No files matched your search
@@ -0,0 +1,19 @@
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Install Protoc
|
||||
run: |
|
||||
sudo apt install -y protobuf-compiler
|
||||
go install google.golang.org/protobuf/cmd/[email protected]
|
||||
- name: Test
|
||||
run: make test
|
||||
- name: Build
|
||||
run: make build
|
||||
@@ -1,5 +1,8 @@
|
||||
build:
|
||||
go build -o protodump cmd/main.go
|
||||
go build -o protodump cmd/protodump/main.go
|
||||
|
||||
fmt:
|
||||
go fmt ./...
|
||||
|
||||
test:
|
||||
go test -v ./...
|
||||
@@ -13,8 +13,6 @@ go build -o protodump cmd/protodump/main.go
|
||||
./protodump -file <file to extract from> -output <output directory>
|
||||
```
|
||||
|
||||
This was thrown together in a day and still has bugs :)
|
||||
|
||||
## Getting in touch
|
||||
|
||||
Feel free to contact me on twitter: https://twitter.com/arkadiyt
|
||||
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package helloworld;
|
||||
|
||||
option go_package = "./;helloworld";
|
||||
|
||||
service Greeter {
|
||||
rpc SayHello (HelloRequest) returns (HelloReply) {}
|
||||
rpc StreamMethodServer (StreamRequest) returns (stream StreamReply) {}
|
||||
}
|
||||
|
||||
message HelloRequest {
|
||||
message Test {
|
||||
string blah = 1;
|
||||
}
|
||||
|
||||
enum NestedEnum {
|
||||
BLAH = 0;
|
||||
}
|
||||
|
||||
string name = 1;
|
||||
helloworld.HelloRequest.Test blah = 2;
|
||||
helloworld.HelloRequest.NestedEnum blahblah = 3;
|
||||
helloworld.HelloReply blaha = 4;
|
||||
}
|
||||
|
||||
message HelloReply {
|
||||
helloworld.HelloRequest.Test blah = 2;
|
||||
helloworld.HelloRequest.NestedEnum blahblah = 3;
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message StreamRequest {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
message StreamReply {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
+56
-5
@@ -2,6 +2,7 @@ package protodump
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -204,6 +205,60 @@ func (pd *ProtoDefinition) writeImport(fileImport protoreflect.FileImport) {
|
||||
pd.write("\";\n")
|
||||
}
|
||||
|
||||
func (pd *ProtoDefinition) writeStringFileOptions(name string, value string) {
|
||||
pd.write("option ")
|
||||
pd.write(name)
|
||||
pd.write(" = \"")
|
||||
pd.write(value)
|
||||
pd.write("\";\n")
|
||||
}
|
||||
|
||||
func (pd *ProtoDefinition) writeBoolFileOptions(name string, value bool) {
|
||||
pd.writeStringFileOptions(name, strconv.FormatBool(value))
|
||||
}
|
||||
|
||||
func (pd *ProtoDefinition) writeFileOptions() {
|
||||
optionDefinitions := []struct {
|
||||
OptionName string
|
||||
FieldName string
|
||||
}{
|
||||
{"java_package", "JavaPackage"},
|
||||
{"java_outer_classname", "JavaOuterClassname"},
|
||||
{"java_multiple_files", "JavaMultipleFiles"},
|
||||
{"java_string_check_utf8", "JavaStringCheckUtf8"},
|
||||
// TODO OptimizeMode: https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto#L384
|
||||
{"go_package", "GoPackage"},
|
||||
// TODO generic services: https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto#L403
|
||||
// TODO deprecated: https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto#L412
|
||||
{"cc_enable_arenas", "CcEnableArenas"},
|
||||
{"objc_class_prefix", "ObjcClassPrefix"},
|
||||
{"csharp_namespace", "CsharpNamespace"},
|
||||
{"swift_prefix", "SwiftPrefix"},
|
||||
{"php_class_prefix", "PhpClassPrefix"},
|
||||
{"php_namespace", "PhpNamespace"},
|
||||
{"php_metadata_namespace", "PhpMetadataNamespace"},
|
||||
{"ruby_package", "RubyPackage"},
|
||||
}
|
||||
options := reflect.ValueOf(pd.pb.GetOptions()).Elem()
|
||||
printedOption := false
|
||||
for _, option := range optionDefinitions {
|
||||
elemPtr := options.FieldByName(option.FieldName)
|
||||
if !elemPtr.IsNil() {
|
||||
elem := elemPtr.Elem()
|
||||
if elem.Kind() == reflect.String {
|
||||
pd.writeStringFileOptions(option.OptionName, elem.String())
|
||||
} else if elem.Kind() == reflect.Bool {
|
||||
pd.writeBoolFileOptions(option.OptionName, elem.Bool())
|
||||
}
|
||||
printedOption = true
|
||||
}
|
||||
}
|
||||
|
||||
if printedOption {
|
||||
pd.write("\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *ProtoDefinition) writeFileDescriptor() {
|
||||
pd.write("syntax = \"")
|
||||
pd.write(pd.descriptor.Syntax().String())
|
||||
@@ -213,11 +268,7 @@ func (pd *ProtoDefinition) writeFileDescriptor() {
|
||||
pd.write(string(pd.descriptor.Package().Name()))
|
||||
pd.write(";\n\n")
|
||||
|
||||
// TODO need to handle FileOptions
|
||||
filepb := protodesc.ToFileDescriptorProto(pd.descriptor)
|
||||
options := filepb.Options
|
||||
if options != nil {
|
||||
}
|
||||
pd.writeFileOptions()
|
||||
|
||||
for i := 0; i < pd.descriptor.Imports().Len(); i++ {
|
||||
pd.writeImport(pd.descriptor.Imports().Get(i))
|
||||
|
||||
@@ -1,18 +1,78 @@
|
||||
package protodump
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const FIXTURES = "fixtures"
|
||||
|
||||
var regex = regexp.MustCompile("(?m)var .* = \\[\\]byte{([^}]*)}")
|
||||
|
||||
func convertProtoToFileDescriptor(filePath string) ([]byte, error) {
|
||||
dir, err := os.MkdirTemp("", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
err = exec.Command("protoc", fmt.Sprintf("--go_out=%s", dir), filePath).Run()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fileName := fmt.Sprintf("%s.pb.go", strings.TrimSuffix(path.Base(filePath), ".proto"))
|
||||
data, err := os.ReadFile(path.Join(dir, fileName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
match := regex.FindSubmatch(data)
|
||||
if len(match) != 2 {
|
||||
return nil, fmt.Errorf("Could not find file descriptor bytes in %s", fileName)
|
||||
}
|
||||
|
||||
var hexString strings.Builder
|
||||
for _, char := range strings.ToLower(string(bytes.ReplaceAll(match[1], []byte("0x"), []byte{}))) {
|
||||
r := rune(char)
|
||||
if (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') {
|
||||
hexString.WriteRune(r)
|
||||
}
|
||||
}
|
||||
|
||||
result, err := hex.DecodeString(hexString.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func TestDefinitions(t *testing.T) {
|
||||
files, err := os.ReadDir("fixtures")
|
||||
files, err := os.ReadDir(FIXTURES)
|
||||
assert.NoError(t, err)
|
||||
|
||||
for _, file := range files {
|
||||
t.Run(file.Name(), func(t *testing.T) {
|
||||
filePath := path.Join(FIXTURES, file.Name())
|
||||
descriptor, err := convertProtoToFileDescriptor(filePath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
expected, err := os.ReadFile(filePath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
actual, err := NewFromBytes(descriptor)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, string(expected), actual.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user