[Groonga-commit] groonga/grnci at 30b22e4 [master] Refactor command.go and partially support --columns and --drilldowns.

Back to archive index

Susumu Yata null+****@clear*****
Wed Jul 5 11:25:27 JST 2017


Susumu Yata	2017-07-05 11:25:27 +0900 (Wed, 05 Jul 2017)

  New Revision: 30b22e42251b86a968ccde9aa0a42628ef5ba146
  https://github.com/groonga/grnci/commit/30b22e42251b86a968ccde9aa0a42628ef5ba146

  Message:
    Refactor command.go and partially support --columns and --drilldowns.
    
    GitHub: fix #38

  Modified files:
    v2/command.go
    v2/command_test.go

  Modified: v2/command.go (+156 -200)
===================================================================
--- v2/command.go    2017-07-05 11:25:12 +0900 (1b21bad)
+++ v2/command.go    2017-07-05 11:25:27 +0900 (5f85bf2)
@@ -1,68 +1,64 @@
 package grnci
 
 import (
+	"fmt"
 	"io"
 	"reflect"
 	"sort"
+	"strconv"
 	"strings"
-	"time"
 )
 
-// formatParamValue is a function to format a parameter value.
-type formatParamValue func(value interface{}) (string, error)
-
-// formatParamValueDefault is the default formatParamValue.
-var formatParamValueDefault = func(value interface{}) (string, error) {
-	v := reflect.ValueOf(value)
-	switch v.Kind() {
+// formatParamValue is the default function to format a parameter value.
+func formatParamValue(key string, value interface{}) (string, error) {
+	switch v := reflect.ValueOf(value); v.Kind() {
 	case reflect.Bool:
-		return formatBool(v.Bool()), nil
+		if v.Bool() {
+			return "yes", nil
+		}
+		return "no", nil
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return formatInt(v.Int()), nil
+		return strconv.FormatInt(v.Int(), 10), nil
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		return formatUint(v.Uint()), nil
+		return strconv.FormatUint(v.Uint(), 10), nil
 	case reflect.Float32:
-		return formatFloat(v.Float(), 32), nil
+		return strconv.FormatFloat(v.Float(), 'g', -1, 32), nil
 	case reflect.Float64:
-		return formatFloat(v.Float(), 64), nil
+		return strconv.FormatFloat(v.Float(), 'g', -1, 64), nil
 	case reflect.String:
-		return formatString(v.String()), nil
-	case reflect.Struct:
-		switch v := value.(type) {
-		case time.Time:
-			return formatTime(v), nil
-		case Geo:
-			return formatGeo(v), nil
-		}
+		return v.String(), nil
+	default:
+		return "", NewError(InvalidCommand, map[string]interface{}{
+			"key":   key,
+			"value": value,
+			"type":  reflect.TypeOf(value).Name(),
+			"error": "The type is not supported.",
+		})
 	}
-	return "", NewError(InvalidCommand, map[string]interface{}{
-		"value": value,
-		"type":  reflect.TypeOf(value).Name(),
-		"error": "The type is not supported.",
-	})
 }
 
-// formatParamValueYesNo formats an 3/no value.
-func formatParamValueYesNo(value interface{}) (string, error) {
-	v := reflect.ValueOf(value)
-	switch v.Kind() {
+// formatParamBoolean formats a boolean value.
+func formatParamBoolean(key string, value interface{}, t, f string) (string, error) {
+	switch v := reflect.ValueOf(value); v.Kind() {
 	case reflect.Bool:
 		if v.Bool() {
-			return "yes", nil
+			return t, nil
 		}
-		return "no", nil
+		return f, nil
 	case reflect.String:
 		switch v := v.String(); v {
-		case "yes", "no":
+		case t, f:
 			return v, nil
 		default:
 			return "", NewError(InvalidCommand, map[string]interface{}{
+				"key":   key,
 				"value": v,
-				"error": "The value must be yes or no.",
+				"error": fmt.Sprintf("The value must be %s or %s.", t, f),
 			})
 		}
 	default:
 		return "", NewError(InvalidCommand, map[string]interface{}{
+			"key":   key,
 			"value": value,
 			"type":  reflect.TypeOf(value).Name(),
 			"error": "The type is not supported.",
@@ -70,66 +66,21 @@ func formatParamValueYesNo(value interface{}) (string, error) {
 	}
 }
 
-// formatParamValueCSV formats comma-separated values.
-func formatParamValueCSV(value interface{}) (string, error) {
-	v := reflect.ValueOf(value)
-	switch v.Kind() {
-	case reflect.String:
-		return formatString(v.String()), nil
-	case reflect.Array, reflect.Slice:
-		if v.Type().Elem().Kind() != reflect.String {
-			break
-		}
-		var buf []byte
-		n := v.Len()
-		for i := 0; i < n; i++ {
-			if i != 0 {
-				buf = append(buf, ',')
-			}
-			buf = append(buf, formatString(v.Index(i).String())...)
-		}
-		return string(buf), nil
-	}
-	return "", NewError(InvalidCommand, map[string]interface{}{
-		"value": value,
-		"type":  reflect.TypeOf(value).Name(),
-		"error": "The type is not supported.",
-	})
+// formatParamYesNo formats an yes/no value.
+func formatParamYesNo(key string, value interface{}) (string, error) {
+	return formatParamBoolean(key, value, "yes", "no")
 }
 
-// formatParamValueFlags formats pipe-separated values.
-func formatParamValueFlags(value interface{}) (string, error) {
-	v := reflect.ValueOf(value)
-	switch v.Kind() {
-	case reflect.String:
-		return formatString(v.String()), nil
-	case reflect.Array, reflect.Slice:
-		if v.Type().Elem().Kind() != reflect.String {
-			break
-		}
-		var buf []byte
-		n := v.Len()
-		for i := 0; i < n; i++ {
-			if i != 0 {
-				buf = append(buf, '|')
-			}
-			buf = append(buf, formatString(v.Index(i).String())...)
-		}
-		return string(buf), nil
-	}
-	return "", NewError(InvalidCommand, map[string]interface{}{
-		"value": value,
-		"type":  reflect.TypeOf(value).Name(),
-		"error": "The type is not supported.",
-	})
+// formatParamBorder formats an include/exclude value.
+func formatParamBorder(key string, value interface{}) (string, error) {
+	return formatParamBoolean(key, value, "include", "exclude")
 }
 
-// formatParamValueMatchColumns formats pipe-separated values.
-func formatParamValueMatchColumns(value interface{}) (string, error) {
-	v := reflect.ValueOf(value)
-	switch v.Kind() {
+// formatParamDelim formats values separated by delim.
+func formatParamDelim(key string, value interface{}, delim string) (string, error) {
+	switch v := reflect.ValueOf(value); v.Kind() {
 	case reflect.String:
-		return formatString(v.String()), nil
+		return v.String(), nil
 	case reflect.Array, reflect.Slice:
 		if v.Type().Elem().Kind() != reflect.String {
 			break
@@ -138,59 +89,48 @@ func formatParamValueMatchColumns(value interface{}) (string, error) {
 		n := v.Len()
 		for i := 0; i < n; i++ {
 			if i != 0 {
-				buf = append(buf, "||"...)
+				buf = append(buf, delim...)
 			}
-			buf = append(buf, formatString(v.Index(i).String())...)
+			buf = append(buf, v.Index(i).String()...)
 		}
 		return string(buf), nil
 	}
 	return "", NewError(InvalidCommand, map[string]interface{}{
+		"key":   key,
 		"value": value,
 		"type":  reflect.TypeOf(value).Name(),
 		"error": "The type is not supported.",
 	})
 }
 
-// formatParamValueBorder formats an include/exclude value.
-func formatParamValueBorder(value interface{}) (string, error) {
-	switch v := value.(type) {
-	case bool:
-		if v {
-			return "include", nil
-		}
-		return "exclude", nil
-	case string:
-		switch v {
-		case "include", "exclude":
-			return v, nil
-		default:
-			return "", NewError(InvalidCommand, map[string]interface{}{
-				"value": v,
-				"error": "The value must be include or exclude.",
-			})
-		}
-	default:
-		return "", NewError(InvalidCommand, map[string]interface{}{
-			"value": value,
-			"type":  reflect.TypeOf(value).Name(),
-			"error": "The type is not supported.",
-		})
-	}
+// formatParamCSV formats comma-separated values.
+func formatParamCSV(key string, value interface{}) (string, error) {
+	return formatParamDelim(key, value, ",")
 }
 
-// formatParamValueJSON returns the JSON-encoded value.
-func formatParamValueJSON(value interface{}) (string, error) {
-	return string(jsonAppendValue(nil, reflect.ValueOf(value))), nil
+// formatParamFlags formats pipe-separated values.
+func formatParamFlags(key string, value interface{}) (string, error) {
+	return formatParamDelim(key, value, "|")
+}
+
+// formatParamMatchColumns formats "||"-separated values (--match_columns).
+func formatParamMatchColumns(key string, value interface{}) (string, error) {
+	return formatParamDelim(key, value, "||")
+}
+
+// formatParamJSON returns the JSON-encoded value (delete --key).
+func formatParamJSON(key string, value interface{}) (string, error) {
+	return jsonEncodeValue(reflect.ValueOf(value)), nil
 }
 
 type paramFormat struct {
-	key      string           // Parameter key
-	format   formatParamValue // Custom function to format a parameter value.
-	required bool             // Whether or not the parameter is required
+	key      string      // Parameter key
+	format   formatParam // Custom function to format a parameter.
+	required bool        // Whether or not the parameter is required
 }
 
 // newParamFormat returns a new paramFormat.
-func newParamFormat(key string, format formatParamValue, required bool) *paramFormat {
+func newParamFormat(key string, format formatParam, required bool) *paramFormat {
 	return &paramFormat{
 		key:      key,
 		format:   format,
@@ -198,12 +138,12 @@ func newParamFormat(key string, format formatParamValue, required bool) *paramFo
 	}
 }
 
-// Format formats a parameter value.
+// Format formats a parameter.
 func (pf *paramFormat) Format(value interface{}) (string, error) {
 	if pf.format != nil {
-		return pf.format(value)
+		return pf.format(pf.key, value)
 	}
-	return formatParamValueDefault(value)
+	return formatParamDefault(pf.key, value)
 }
 
 // formatParam is a function to format a parameter.
@@ -228,13 +168,7 @@ func formatParamDefault(key string, value interface{}) (string, error) {
 			})
 		}
 	}
-	fv, err := formatParamValueDefault(value)
-	if err != nil {
-		return "", EnhanceError(err, map[string]interface{}{
-			"key": key,
-		})
-	}
-	return fv, nil
+	return formatParamValue(key, value)
 }
 
 // formatParamSelect formats a parameter of select.
@@ -261,15 +195,20 @@ func formatParamSelect(key string, value interface{}) (string, error) {
 			}
 		}
 	}
-	fv, err := formatParamValueDefault(value)
-	if err != nil {
-		return "", EnhanceError(err, map[string]interface{}{
-			"key": key,
-		})
+	// For parameters with variable keys, such as --columns[NAME] and --drilldowns[LABEL].
+	switch {
+	case strings.HasSuffix(key, "flags"):
+		return formatParamFlags(key, value)
+	case strings.HasSuffix(key, "keys"), // keys, sort_keys and group_keys
+		strings.HasSuffix(key, "output_columns"),
+		strings.HasSuffix(key, "calc_types"):
+		return formatParamCSV(key, value)
+	default:
+		return formatParamValue(key, value)
 	}
-	return fv, nil
 }
 
+// commandFormat is the format of a command.
 type commandFormat struct {
 	format         formatParam             // Custom function to format a parameter
 	params         []*paramFormat          // Fixed parameters
@@ -295,6 +234,11 @@ func newCommandFormat(format formatParam, params ...*paramFormat) *commandFormat
 	}
 }
 
+// getCommandFormat returns the format of the specified command.
+func getCommandFormat(name string) *commandFormat {
+	return commandFormats[name]
+}
+
 // Format formats a parameter.
 func (cf *commandFormat) Format(key string, value interface{}) (string, error) {
 	if pf, ok := cf.paramsByKey[key]; ok {
@@ -332,9 +276,9 @@ var commandFormats = map[string]*commandFormat{
 		nil,
 		newParamFormat("table", nil, true),
 		newParamFormat("name", nil, true),
-		newParamFormat("flags", formatParamValueFlags, true),
+		newParamFormat("flags", formatParamFlags, true),
 		newParamFormat("type", nil, true),
-		newParamFormat("source", formatParamValueCSV, false),
+		newParamFormat("source", formatParamCSV, false),
 	),
 	"column_list": newCommandFormat(
 		nil,
@@ -367,17 +311,17 @@ var commandFormats = map[string]*commandFormat{
 		nil,
 		newParamFormat("name", nil, true),
 		newParamFormat("table", nil, true),
-		newParamFormat("match_columns", formatParamValueMatchColumns, false),
+		newParamFormat("match_columns", formatParamMatchColumns, false),
 		newParamFormat("query", nil, false),
 		newParamFormat("filter", nil, false),
 		newParamFormat("scorer", nil, false),
-		newParamFormat("sortby", formatParamValueCSV, false),
-		newParamFormat("output_columns", formatParamValueCSV, false),
+		newParamFormat("sortby", formatParamCSV, false),
+		newParamFormat("output_columns", formatParamCSV, false),
 		newParamFormat("offset", nil, false),
 		newParamFormat("limit", nil, false),
-		newParamFormat("drilldown", formatParamValueCSV, false),
-		newParamFormat("drilldown_sortby", formatParamValueCSV, false),
-		newParamFormat("drilldown_output_columns", formatParamValueCSV, false),
+		newParamFormat("drilldown", formatParamCSV, false),
+		newParamFormat("drilldown_sortby", formatParamCSV, false),
+		newParamFormat("drilldown_output_columns", formatParamCSV, false),
 		newParamFormat("drilldown_offset", nil, false),
 		newParamFormat("drilldown_limit", nil, false),
 	),
@@ -389,17 +333,17 @@ var commandFormats = map[string]*commandFormat{
 	"delete": newCommandFormat(
 		nil,
 		newParamFormat("table", nil, true),
-		newParamFormat("key", formatParamValueJSON, false),
+		newParamFormat("key", formatParamJSON, false),
 		newParamFormat("id", nil, false),
 		newParamFormat("filter", nil, false),
 	),
 	"dump": newCommandFormat(
 		nil,
-		newParamFormat("tables", formatParamValueCSV, false),
-		newParamFormat("dump_plugins", formatParamValueYesNo, false),
-		newParamFormat("dump_schema", formatParamValueYesNo, false),
-		newParamFormat("dump_records", formatParamValueYesNo, false),
-		newParamFormat("dump_indexes", formatParamValueYesNo, false),
+		newParamFormat("tables", formatParamCSV, false),
+		newParamFormat("dump_plugins", formatParamYesNo, false),
+		newParamFormat("dump_schema", formatParamYesNo, false),
+		newParamFormat("dump_records", formatParamYesNo, false),
+		newParamFormat("dump_indexes", formatParamYesNo, false),
 	),
 	"io_flush": newCommandFormat(
 		nil,
@@ -410,7 +354,7 @@ var commandFormats = map[string]*commandFormat{
 		nil,
 		newParamFormat("values", nil, false), // values may be passed as a body.
 		newParamFormat("table", nil, true),
-		newParamFormat("columns", formatParamValueCSV, false),
+		newParamFormat("columns", formatParamCSV, false),
 		newParamFormat("ifexists", nil, false),
 		newParamFormat("input_type", nil, false),
 	),
@@ -441,9 +385,9 @@ var commandFormats = map[string]*commandFormat{
 		newParamFormat("logical_table", nil, true),
 		newParamFormat("shard_key", nil, true),
 		newParamFormat("min", nil, false),
-		newParamFormat("min_border", formatParamValueBorder, false),
+		newParamFormat("min_border", formatParamBorder, false),
 		newParamFormat("max", nil, false),
-		newParamFormat("max_border", formatParamValueBorder, false),
+		newParamFormat("max_border", formatParamBorder, false),
 		newParamFormat("filter", nil, false),
 	),
 	"logical_parameters": newCommandFormat(
@@ -455,39 +399,40 @@ var commandFormats = map[string]*commandFormat{
 		newParamFormat("logical_table", nil, true),
 		newParamFormat("shard_key", nil, true),
 		newParamFormat("min", nil, false),
-		newParamFormat("min_border", formatParamValueBorder, false),
+		newParamFormat("min_border", formatParamBorder, false),
 		newParamFormat("max", nil, false),
-		newParamFormat("max_border", formatParamValueBorder, false),
+		newParamFormat("max_border", formatParamBorder, false),
 		newParamFormat("order", nil, false),
 		newParamFormat("filter", nil, false),
 		newParamFormat("offset", nil, false),
 		newParamFormat("limit", nil, false),
-		newParamFormat("output_columns", formatParamValueCSV, false),
+		newParamFormat("output_columns", formatParamCSV, false),
 		newParamFormat("use_range_index", nil, false),
+		// TODO: --cache is not supported yet.
 	),
 	"logical_select": newCommandFormat(
-		nil,
+		formatParamSelect,
 		newParamFormat("logical_table", nil, true),
 		newParamFormat("shard_key", nil, true),
 		newParamFormat("min", nil, false),
-		newParamFormat("min_border", formatParamValueBorder, false),
+		newParamFormat("min_border", formatParamBorder, false),
 		newParamFormat("max", nil, false),
-		newParamFormat("max_border", formatParamValueBorder, false),
+		newParamFormat("max_border", formatParamBorder, false),
 		newParamFormat("filter", nil, false),
-		newParamFormat("sortby", formatParamValueCSV, false),
-		newParamFormat("output_columns", formatParamValueCSV, false),
+		newParamFormat("sortby", formatParamCSV, false),
+		newParamFormat("output_columns", formatParamCSV, false),
 		newParamFormat("offset", nil, false),
 		newParamFormat("limit", nil, false),
 		newParamFormat("drilldown", nil, false),
-		newParamFormat("drilldown_sortby", formatParamValueCSV, false),
-		newParamFormat("drilldown_output_columns", formatParamValueCSV, false),
+		newParamFormat("drilldown_sortby", formatParamCSV, false),
+		newParamFormat("drilldown_output_columns", formatParamCSV, false),
 		newParamFormat("drilldown_offset", nil, false),
 		newParamFormat("drilldown_limit", nil, false),
-		newParamFormat("drilldown_calc_types", formatParamValueCSV, false),
+		newParamFormat("drilldown_calc_types", formatParamCSV, false),
 		newParamFormat("drilldown_calc_target", nil, false),
-		newParamFormat("sort_keys", formatParamValueCSV, false),
-		newParamFormat("drilldown_sort_keys", formatParamValueCSV, false),
-		newParamFormat("match_columns", formatParamValueMatchColumns, false),
+		newParamFormat("sort_keys", formatParamCSV, false),
+		newParamFormat("drilldown_sort_keys", formatParamCSV, false),
+		newParamFormat("match_columns", formatParamMatchColumns, false),
 		newParamFormat("query", nil, false),
 		newParamFormat("drilldown_filter", nil, false),
 	),
@@ -500,17 +445,17 @@ var commandFormats = map[string]*commandFormat{
 		newParamFormat("logical_table", nil, true),
 		newParamFormat("shard_key", nil, true),
 		newParamFormat("min", nil, false),
-		newParamFormat("min_border", formatParamValueBorder, false),
+		newParamFormat("min_border", formatParamBorder, false),
 		newParamFormat("max", nil, false),
-		newParamFormat("max_border", formatParamValueBorder, false),
-		newParamFormat("dependent", formatParamValueYesNo, false),
-		newParamFormat("force", formatParamValueYesNo, false),
+		newParamFormat("max_border", formatParamBorder, false),
+		newParamFormat("dependent", formatParamYesNo, false),
+		newParamFormat("force", formatParamYesNo, false),
 	),
 	"normalize": newCommandFormat(
 		nil,
 		newParamFormat("normalizer", nil, true),
 		newParamFormat("string", nil, true),
-		newParamFormat("flags", formatParamValueFlags, false),
+		newParamFormat("flags", formatParamFlags, false),
 	),
 	"normalizer_list": newCommandFormat(nil),
 	"object_exist": newCommandFormat(
@@ -525,7 +470,7 @@ var commandFormats = map[string]*commandFormat{
 	"object_remove": newCommandFormat(
 		nil,
 		newParamFormat("name", nil, true),
-		newParamFormat("force", formatParamValueYesNo, false),
+		newParamFormat("force", formatParamYesNo, false),
 	),
 	"plugin_register": newCommandFormat(
 		nil,
@@ -562,30 +507,30 @@ var commandFormats = map[string]*commandFormat{
 	"select": newCommandFormat(
 		formatParamSelect,
 		newParamFormat("table", nil, true),
-		newParamFormat("match_columns", formatParamValueMatchColumns, false),
+		newParamFormat("match_columns", formatParamMatchColumns, false),
 		newParamFormat("query", nil, false),
 		newParamFormat("filter", nil, false),
 		newParamFormat("scorer", nil, false),
-		newParamFormat("sortby", formatParamValueCSV, false),
-		newParamFormat("output_columns", formatParamValueCSV, false),
+		newParamFormat("sortby", formatParamCSV, false),
+		newParamFormat("output_columns", formatParamCSV, false),
 		newParamFormat("offset", nil, false),
 		newParamFormat("limit", nil, false),
 		newParamFormat("drilldown", nil, false),
-		newParamFormat("drilldown_sortby", formatParamValueCSV, false),
-		newParamFormat("drilldown_output_columns", formatParamValueCSV, false),
+		newParamFormat("drilldown_sortby", formatParamCSV, false),
+		newParamFormat("drilldown_output_columns", formatParamCSV, false),
 		newParamFormat("drilldown_offset", nil, false),
 		newParamFormat("drilldown_limit", nil, false),
-		newParamFormat("cache", formatParamValueYesNo, false),
+		newParamFormat("cache", formatParamYesNo, false),
 		newParamFormat("match_escalation_threshold", nil, false),
 		newParamFormat("query_expansion", nil, false),
-		newParamFormat("query_flags", formatParamValueFlags, false),
+		newParamFormat("query_flags", formatParamFlags, false),
 		newParamFormat("query_expander", nil, false),
 		newParamFormat("adjuster", nil, false),
-		newParamFormat("drilldown_calc_types", formatParamValueCSV, false),
+		newParamFormat("drilldown_calc_types", formatParamCSV, false),
 		newParamFormat("drilldown_calc_target", nil, false),
 		newParamFormat("drilldown_filter", nil, false),
-		newParamFormat("sort_keys", formatParamValueCSV, false),
-		newParamFormat("drilldown_sort_keys", formatParamValueCSV, false),
+		newParamFormat("sort_keys", formatParamCSV, false),
+		newParamFormat("drilldown_sort_keys", formatParamCSV, false),
 	),
 	"shutdown": newCommandFormat(
 		nil,
@@ -594,12 +539,12 @@ var commandFormats = map[string]*commandFormat{
 	"status": newCommandFormat(nil),
 	"suggest": newCommandFormat(
 		nil,
-		newParamFormat("types", formatParamValueFlags, true),
+		newParamFormat("types", formatParamFlags, true),
 		newParamFormat("table", nil, true),
 		newParamFormat("column", nil, true),
 		newParamFormat("query", nil, true),
-		newParamFormat("sortby", formatParamValueCSV, false),
-		newParamFormat("output_columns", formatParamValueCSV, false),
+		newParamFormat("sortby", formatParamCSV, false),
+		newParamFormat("output_columns", formatParamCSV, false),
 		newParamFormat("offset", nil, false),
 		newParamFormat("limit", nil, false),
 		newParamFormat("frequency_threshold", nil, false),
@@ -614,18 +559,18 @@ var commandFormats = map[string]*commandFormat{
 	"table_create": newCommandFormat(
 		nil,
 		newParamFormat("name", nil, true),
-		newParamFormat("flags", formatParamValueFlags, false),
+		newParamFormat("flags", formatParamFlags, false),
 		newParamFormat("key_type", nil, false),
 		newParamFormat("value_type", nil, false),
 		newParamFormat("default_tokenizer", nil, false),
 		newParamFormat("normalizer", nil, false),
-		newParamFormat("token_filters", formatParamValueCSV, false),
+		newParamFormat("token_filters", formatParamCSV, false),
 	),
 	"table_list": newCommandFormat(nil),
 	"table_remove": newCommandFormat(
 		nil,
 		newParamFormat("name", nil, true),
-		newParamFormat("dependent", formatParamValueYesNo, false),
+		newParamFormat("dependent", formatParamYesNo, false),
 	),
 	"table_rename": newCommandFormat(
 		nil,
@@ -636,7 +581,7 @@ var commandFormats = map[string]*commandFormat{
 		nil,
 		newParamFormat("table", nil, true),
 		newParamFormat("string", nil, true),
-		newParamFormat("flags", formatParamValueFlags, false),
+		newParamFormat("flags", formatParamFlags, false),
 		newParamFormat("mode", nil, false),
 		newParamFormat("index_column", nil, false),
 	),
@@ -649,9 +594,9 @@ var commandFormats = map[string]*commandFormat{
 		newParamFormat("tokenizer", nil, true),
 		newParamFormat("string", nil, true),
 		newParamFormat("normalizer", nil, false),
-		newParamFormat("flags", formatParamValueFlags, false),
+		newParamFormat("flags", formatParamFlags, false),
 		newParamFormat("mode", nil, false),
-		newParamFormat("token_filters", formatParamValueCSV, false),
+		newParamFormat("token_filters", formatParamCSV, false),
 	),
 	"tokenizer_list": newCommandFormat(nil),
 	"truncate": newCommandFormat(
@@ -671,8 +616,8 @@ type Command struct {
 
 // newCommand returns a new Command.
 func newCommand(name string) (*Command, error) {
-	format, ok := commandFormats[name]
-	if !ok {
+	format := getCommandFormat(name)
+	if format == nil {
 		return nil, NewError(InvalidCommand, map[string]interface{}{
 			"name":  name,
 			"error": "The name is not defined.",
@@ -929,10 +874,21 @@ func (c *Command) String() string {
 		cmd = append(cmd, " '"...)
 		for i := 0; i < len(v); i++ {
 			switch v[i] {
-			case '\'', '\\', '\b', '\t', '\r', '\n':
-				cmd = append(cmd, '\\')
+			case '\'':
+				cmd = append(cmd, `\'`...)
+			case '\\':
+				cmd = append(cmd, `\\`...)
+			case '\b':
+				cmd = append(cmd, `\b`...)
+			case '\t':
+				cmd = append(cmd, `\t`...)
+			case '\r':
+				cmd = append(cmd, `\r`...)
+			case '\n':
+				cmd = append(cmd, `\n`...)
+			default:
+				cmd = append(cmd, v[i])
 			}
-			cmd = append(cmd, v[i])
 		}
 		cmd = append(cmd, '\'')
 	}

  Modified: v2/command_test.go (+203 -0)
===================================================================
--- v2/command_test.go    2017-07-05 11:25:12 +0900 (a8dea64)
+++ v2/command_test.go    2017-07-05 11:25:27 +0900 (3aef0b4)
@@ -4,6 +4,209 @@ import (
 	"testing"
 )
 
+func TestFormatParamValue(t *testing.T) {
+	if actual, err := formatParamValue("", true); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "yes"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", false); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "no"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+
+	if actual, err := formatParamValue("", int8(-128)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "-128"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", int16(-32768)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "-32768"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", int32(-2147483648)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "-2147483648"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", int64(-9223372036854775808)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "-9223372036854775808"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", int(-9223372036854775808)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "-9223372036854775808"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+
+	if actual, err := formatParamValue("", uint8(255)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "255"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", uint16(65535)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "65535"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", uint32(4294967295)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "4294967295"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", uint64(18446744073709551615)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "18446744073709551615"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", uint(18446744073709551615)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "18446744073709551615"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+
+	if actual, err := formatParamValue("", float32(1.234567890123456789)); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "1.2345679"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamValue("", 1.234567890123456789); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "1.2345678901234567"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+
+	if actual, err := formatParamValue("", "String"); err != nil {
+		t.Fatalf("formatParamValue failed: %v", err)
+	} else if want := "String"; actual != want {
+		t.Fatalf("formatParamValue failed: actual = %s, want = %s", actual, want)
+	}
+}
+
+func TestFormatParamYesNo(t *testing.T) {
+	if actual, err := formatParamYesNo("", true); err != nil {
+		t.Fatalf("formatParamYesNo failed: %v", err)
+	} else if want := "yes"; actual != want {
+		t.Fatalf("formatParamYesNo failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamYesNo("", false); err != nil {
+		t.Fatalf("formatParamYesNo failed: %v", err)
+	} else if want := "no"; actual != want {
+		t.Fatalf("formatParamYesNo failed: actual = %s, want = %s", actual, want)
+	}
+
+	if actual, err := formatParamYesNo("", "yes"); err != nil {
+		t.Fatalf("formatParamYesNo failed: %v", err)
+	} else if want := "yes"; actual != want {
+		t.Fatalf("formatParamYesNo failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamYesNo("", "no"); err != nil {
+		t.Fatalf("formatParamYesNo failed: %v", err)
+	} else if want := "no"; actual != want {
+		t.Fatalf("formatParamYesNo failed: actual = %s, want = %s", actual, want)
+	}
+}
+
+func TestFormatParamBorder(t *testing.T) {
+	if actual, err := formatParamBorder("", true); err != nil {
+		t.Fatalf("formatParamBorder failed: %v", err)
+	} else if want := "include"; actual != want {
+		t.Fatalf("formatParamBorder failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamBorder("", false); err != nil {
+		t.Fatalf("formatParamBorder failed: %v", err)
+	} else if want := "exclude"; actual != want {
+		t.Fatalf("formatParamBorder failed: actual = %s, want = %s", actual, want)
+	}
+
+	if actual, err := formatParamBorder("", "include"); err != nil {
+		t.Fatalf("formatParamBorder failed: %v", err)
+	} else if want := "include"; actual != want {
+		t.Fatalf("formatParamBorder failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamBorder("", "exclude"); err != nil {
+		t.Fatalf("formatParamBorder failed: %v", err)
+	} else if want := "exclude"; actual != want {
+		t.Fatalf("formatParamBorder failed: actual = %s, want = %s", actual, want)
+	}
+}
+
+func TestFormatParamCSV(t *testing.T) {
+	if actual, err := formatParamCSV("", []string{"a", "b", "c"}); err != nil {
+		t.Fatalf("formatParamCSV failed: %v", err)
+	} else if want := "a,b,c"; actual != want {
+		t.Fatalf("formatParamCSV failed: actual = %s, want = %s", actual, want)
+	}
+}
+
+func TestFormatParamFlags(t *testing.T) {
+	if actual, err := formatParamFlags("", []string{"a", "b", "c"}); err != nil {
+		t.Fatalf("formatParamFlags failed: %v", err)
+	} else if want := "a|b|c"; actual != want {
+		t.Fatalf("formatParamFlags failed: actual = %s, want = %s", actual, want)
+	}
+}
+
+func TestFormatParamMatchColumns(t *testing.T) {
+	if actual, err := formatParamMatchColumns("", []string{"a", "b", "c"}); err != nil {
+		t.Fatalf("formatParamMatchColumns failed: %v", err)
+	} else if want := "a||b||c"; actual != want {
+		t.Fatalf("formatParamMatchColumns failed: actual = %s, want = %s", actual, want)
+	}
+}
+
+func TestFormatParamJSON(t *testing.T) {
+	if actual, err := formatParamJSON("", []string{"a", "b", "c"}); err != nil {
+		t.Fatalf("formatParamJSON failed: %v", err)
+	} else if want := `["a","b","c"]`; actual != want {
+		t.Fatalf("formatParamJSON failed: actual = %s, want = %s", actual, want)
+	}
+}
+
+func TestFormatParamDefault(t *testing.T) {
+	if actual, err := formatParamDefault("", true); err == nil {
+		t.Fatalf("formatParamDefault wrongly succeeded: actual = %s", actual)
+	}
+	if actual, err := formatParamDefault("output-columns", true); err == nil {
+		t.Fatalf("formatParamDefault wrongly succeeded: actual = %s", actual)
+	}
+
+	if actual, err := formatParamDefault("cache", true); err != nil {
+		t.Fatalf("formatParamDefault failed: %v", err)
+	} else if want := "yes"; actual != want {
+		t.Fatalf("formatParamDefault failed: actual = %s, want = %s", actual, want)
+	}
+}
+
+func TestFormatParamSelect(t *testing.T) {
+	if actual, err := formatParamSelect("", true); err == nil {
+		t.Fatalf("formatParamSelect wrongly succeeded: actual = %s", actual)
+	}
+	if actual, err := formatParamSelect("output/columns", true); err == nil {
+		t.Fatalf("formatParamSelect wrongly succeeded: actual = %s", actual)
+	}
+
+	if actual, err := formatParamSelect("cache", true); err != nil {
+		t.Fatalf("formatParamSelect failed: %v", err)
+	} else if want := "yes"; actual != want {
+		t.Fatalf("formatParamSelect failed: actual = %s, want = %s", actual, want)
+	}
+
+	if actual, err := formatParamSelect("columns[NAME].flags", []string{"a", "b", "c"}); err != nil {
+		t.Fatalf("formatParamSelect failed: %v", err)
+	} else if want := "a|b|c"; actual != want {
+		t.Fatalf("formatParamSelect failed: actual = %s, want = %s", actual, want)
+	}
+	if actual, err := formatParamSelect("drilldown[LABEL].columns[NAME].flags", []string{"a", "b", "c"}); err != nil {
+		t.Fatalf("formatParamSelect failed: %v", err)
+	} else if want := "a|b|c"; actual != want {
+		t.Fatalf("formatParamSelect failed: actual = %s, want = %s", actual, want)
+	}
+}
+
 func TestNewCommand(t *testing.T) {
 	params := map[string]interface{}{
 		"table":     "Tbl",
-------------- next part --------------
HTML����������������������������...
Télécharger 



More information about the Groonga-commit mailing list
Back to archive index