merge from master and resolve conflicts. Add more tests in main_test.go

This commit is contained in:
Mario Izquierdo 2018-06-18 19:08:20 -07:00
Родитель 0610801bc8 717217306c
Коммит 73ec3c3003
3 изменённых файлов: 122 добавлений и 22 удалений

Просмотреть файл

@ -2,7 +2,8 @@
require 'twirp'
require_relative 'service_pb.rb'
module Example::HelloWorld
module Example
module HelloWorld
class HelloWorldService < Twirp::Service
package 'example.hello_world'
service 'HelloWorld'
@ -12,4 +13,5 @@ module Example::HelloWorld
class HelloWorldClient < Twirp::Client
client_for HelloWorldService
end
end
end

Просмотреть файл

@ -74,11 +74,12 @@ func (g *generator) generateRubyCode(file *descriptor.FileDescriptorProto, pbFil
print(b, "require_relative '%s'", pbFileRelativePath) // require generated file with messages
print(b, "")
indent := ""
indent := indentation(0)
pkgName := file.GetPackage()
if pkgName != "" {
print(b, "module %s", packageToRubyModule(pkgName))
indent = indent + " "
modules := packageToRubyModules(pkgName)
for _, m := range modules {
print(b, "%smodule %s", indent, m)
indent += 1
}
for i, service := range file.Service {
@ -104,8 +105,10 @@ func (g *generator) generateRubyCode(file *descriptor.FileDescriptorProto, pbFil
print(b, "")
}
}
if pkgName != "" {
print(b, "end")
for range modules {
indent -= 1
print(b, "%send", indent)
}
return b.String()
@ -125,6 +128,15 @@ func (g *generator) protoFilesToGenerate() []*descriptor.FileDescriptorProto {
return files
}
// indentation represents the level of Ruby indentation for a block of code. It
// implements the fmt.Stringer interface to output the correct number of spaces
// for the given level of indentation
type indentation int
func (i indentation) String() string {
return strings.Repeat(" ", int(i))
}
func print(buf *bytes.Buffer, tpl string, args ...interface{}) {
buf.WriteString(fmt.Sprintf(tpl, args...))
buf.WriteByte('\n')
@ -190,15 +202,14 @@ func writeGenResponse(w io.Writer, resp *plugin.CodeGeneratorResponse) {
}
}
// packageToModule converts a protobuf package like "my.cool.package" to a
// Ruby module constant like "My::Cool::Package".
func packageToRubyModule(pkgName string) string {
pkgParts := strings.Split(pkgName, ".")
modules := []string{}
for _, p := range pkgParts {
modules = append(modules, camelCase(p))
// Modules converts protobuf package name to a list of Ruby module names to
// represent it. e.g. packageToRubyModules("my.cool.package") => ["My", "Cool", "Package"]
func packageToRubyModules(pkgName string) []string {
parts := []string{}
for _, p := range strings.Split(pkgName, ".") {
parts = append(parts, camelCase(p))
}
return strings.Join(modules, "::")
return parts
}
// snakeCase converts a string from CamelCase to snake_case.

Просмотреть файл

@ -0,0 +1,87 @@
package main
import (
"bytes"
"reflect"
"testing"
)
func TestPrint(t *testing.T) {
b := new(bytes.Buffer)
print(b, "Hello World")
print(b, "Hello %s %d", "My Friend", 999)
actual := b.String()
expected := "Hello World\nHello My Friend 999\n"
if expected != actual {
t.Errorf("Unexpected print: %v", actual)
}
}
func TestFilePathOnlyBaseNoExtension(t *testing.T) {
tests := []struct {
actual string
expected string
}{
{noExtension("foo_bar.txt"), "foo_bar"},
{noExtension("my/filename.txt"), "my/filename"},
{onlyBase("foo_bar.txt"), "foo_bar.txt"},
{onlyBase("/long/path/stuff/foo_bar.txt"), "foo_bar.txt"},
{noExtension(onlyBase("/long/path/stuff/foo_bar.txt")), "foo_bar"},
}
for _, tt := range tests {
if tt.expected != tt.actual {
t.Errorf("expected %v; actual %v", tt.expected, tt.actual)
}
}
}
func TestPackageToRubyModules(t *testing.T) {
tests := []struct {
pkgName string
expected []string
}{
{"example", []string{"Example"}},
{"example.hello_world", []string{"Example", "HelloWorld"}},
{"m.v.p", []string{"M", "V", "P"}},
}
for _, tt := range tests {
actual := packageToRubyModules(tt.pkgName)
if !reflect.DeepEqual(actual, tt.expected) {
t.Errorf("expected %v; actual %v", tt.expected, actual)
}
}
}
func TestSnakeCase(t *testing.T) {
tests := []struct {
actual string
expected string
}{
{snakeCase("foo_bar"), "foo_bar"},
{snakeCase("FooBar"), "foo_bar"},
{snakeCase("fooBar"), "foo_bar"},
{snakeCase("myLong_miXEDName"), "my_long_mi_x_e_d_name"},
}
for _, tt := range tests {
if tt.expected != tt.actual {
t.Errorf("expected %v; actual %v", tt.expected, tt.actual)
}
}
}
func TestCamelCase(t *testing.T) {
tests := []struct {
actual string
expected string
}{
{camelCase("foo_bar"), "FooBar"},
{camelCase("FooBar"), "FooBar"},
{camelCase("fooBar"), "FooBar"},
{camelCase("myLong_miXEDName"), "MyLongMiXEDName"},
}
for _, tt := range tests {
if tt.expected != tt.actual {
t.Errorf("expected %v; actual %v", tt.expected, tt.actual)
}
}
}