Beispiel #1
0
// rpcUsage returns one-line usage for all support RPC commands.
//
// This function is safe for concurrent access.
func (c *helpCacher) rpcUsage(includeWebsockets bool) (string, error) {
	c.Lock()
	defer c.Unlock()

	// Return the cached usage if it is available.
	if c.usage != "" {
		return c.usage, nil
	}

	// Generate a list of one-line usage for every command.
	usageTexts := make([]string, 0, len(rpcHandlers))
	for k := range rpcHandlers {
		usage, err := btcjson.MethodUsageText(k)
		if err != nil {
			return "", err
		}
		usageTexts = append(usageTexts, usage)
	}

	// Include websockets commands if requested.
	if includeWebsockets {
		for k := range wsHandlers {
			usage, err := btcjson.MethodUsageText(k)
			if err != nil {
				return "", err
			}
			usageTexts = append(usageTexts, usage)
		}
	}

	sort.Sort(sort.StringSlice(usageTexts))
	c.usage = strings.Join(usageTexts, "\n")
	return c.usage, nil
}
Beispiel #2
0
// TestRPCMethodUsageGeneration ensures that single line usage text can be
// generated for every supported request of the RPC server.
func TestRPCMethodUsageGeneration(t *testing.T) {
	needsGenerate := false

	defer func() {
		if needsGenerate && !t.Failed() {
			t.Error("Generated help usages are out of date: run 'go generate'")
			return
		}
		if t.Failed() {
			t.Log("Regenerate help usage with 'go generate' after fixing")
		}
	}()

	svrMethods := serverMethods()
	usageStrs := make([]string, 0, len(rpchelp.Methods))
	for _, m := range rpchelp.Methods {
		delete(svrMethods, m.Method)

		usage, err := btcjson.MethodUsageText(m.Method)
		if err != nil {
			t.Errorf("Cannot generate single line usage for method '%s': %v",
				m.Method, err)
		}

		if !t.Failed() {
			usageStrs = append(usageStrs, usage)
		}
	}

	if !t.Failed() {
		usages := strings.Join(usageStrs, "\n")
		needsGenerate = usages != requestUsages
	}
}
Beispiel #3
0
func writeUsage() {
	usageStrs := make([]string, len(rpchelp.Methods))
	var err error
	for i := range rpchelp.Methods {
		usageStrs[i], err = btcjson.MethodUsageText(rpchelp.Methods[i].Method)
		if err != nil {
			log.Fatal(err)
		}
	}
	usages := strings.Join(usageStrs, "\n")
	writefln("var requestUsages = %q", usages)
}
Beispiel #4
0
// commandUsage display the usage for a specific command.
func commandUsage(method string) {
	usage, err := btcjson.MethodUsageText(method)
	if err != nil {
		// This should never happen since the method was already checked
		// before calling this function, but be safe.
		fmt.Fprintln(os.Stderr, "Failed to obtain command usage:", err)
		return
	}

	fmt.Fprintln(os.Stderr, "Usage:")
	fmt.Fprintf(os.Stderr, "  %s\n", usage)
}
Beispiel #5
0
// listCommands categorizes and lists all of the usable commands along with
// their one-line usage.
func listCommands() {
	const (
		categoryChain uint8 = iota
		categoryWallet
		numCategories
	)

	// Get a list of registered commands and categorize and filter them.
	cmdMethods := btcjson.RegisteredCmdMethods()
	categorized := make([][]string, numCategories)
	for _, method := range cmdMethods {
		flags, err := btcjson.MethodUsageFlags(method)
		if err != nil {
			// This should never happen since the method was just
			// returned from the package, but be safe.
			continue
		}

		// Skip the commands that aren't usable from this utility.
		if flags&unusableFlags != 0 {
			continue
		}

		usage, err := btcjson.MethodUsageText(method)
		if err != nil {
			// This should never happen since the method was just
			// returned from the package, but be safe.
			continue
		}

		// Categorize the command based on the usage flags.
		category := categoryChain
		if flags&btcjson.UFWalletOnly != 0 {
			category = categoryWallet
		}
		categorized[category] = append(categorized[category], usage)
	}

	// Display the command according to their categories.
	categoryTitles := make([]string, numCategories)
	categoryTitles[categoryChain] = "Chain Server Commands:"
	categoryTitles[categoryWallet] = "Wallet Server Commands (--wallet):"
	for category := uint8(0); category < numCategories; category++ {
		fmt.Println(categoryTitles[category])
		for _, usage := range categorized[category] {
			fmt.Println(usage)
		}
		fmt.Println()
	}
}
Beispiel #6
0
// TestMethodUsageText tests the MethodUsageText function ensure it returns the
// expected text.
func TestMethodUsageText(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name     string
		method   string
		err      error
		expected string
	}{
		{
			name:   "unregistered type",
			method: "bogusmethod",
			err:    btcjson.Error{ErrorCode: btcjson.ErrUnregisteredMethod},
		},
		{
			name:     "getblockcount",
			method:   "getblockcount",
			expected: "getblockcount",
		},
		{
			name:     "getblock",
			method:   "getblock",
			expected: `getblock "hash" (verbose=true verbosetx=false)`,
		},
	}

	t.Logf("Running %d tests", len(tests))
	for i, test := range tests {
		usage, err := btcjson.MethodUsageText(test.method)
		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
			t.Errorf("Test #%d (%s) wrong error - got %T (%[3]v), "+
				"want %T", i, test.name, err, test.err)
			continue
		}
		if err != nil {
			gotErrorCode := err.(btcjson.Error).ErrorCode
			if gotErrorCode != test.err.(btcjson.Error).ErrorCode {
				t.Errorf("Test #%d (%s) mismatched error code "+
					"- got %v (%v), want %v", i, test.name,
					gotErrorCode, err,
					test.err.(btcjson.Error).ErrorCode)
				continue
			}

			continue
		}

		// Ensure usage matches the expected value.
		if usage != test.expected {
			t.Errorf("Test #%d (%s) mismatched usage - got %v, "+
				"want %v", i, test.name, usage, test.expected)
			continue
		}

		// Get the usage again to excerise caching.
		usage, err = btcjson.MethodUsageText(test.method)
		if err != nil {
			t.Errorf("Test #%d (%s) unexpected error: %v", i,
				test.name, err)
			continue
		}

		// Ensure usage still matches the expected value.
		if usage != test.expected {
			t.Errorf("Test #%d (%s) mismatched usage - got %v, "+
				"want %v", i, test.name, usage, test.expected)
			continue
		}
	}
}