TDD args 第一遍

roblem Description

Most of us have had to parse command-line arguments from time to time. If we don’t have a convenient utility, then we simply walk the array of strings that is passed into the main function. There are several good utilities available from various sources, but they probably don’t do exactly what we want. So let’s write another one!

The arguments passed to the program consist of flags and values. Flags should be one character, preceded by a minus sign. Each flag should have zero, or one value associated with it.

You should write a parser for this kind of arguments. This parser takes a schema detailing what arguments the program expects. The schema specifies the number and types of flags and values the program expects.

Once the schema has been specified, the program should pass the actual argument list to the args parser. It will verify that the arguments match the schema. The program can then ask the args parser for each of the values, using the names of the flags. The values are returned with the correct types, as specified in the schema.

For example if the program is to be called with these arguments:

-l -p 8080 -d /usr/logs

this indicates a schema with 3 flags: l, p, d. The “l” (logging) flag has no values associated with it, it is a boolean flag, True if present, False if not. the “p” (port) flag has an integer value, and the “d” (directory) flag has a string value.

If a flag mentioned in the schema is missing in the arguments, a suitable default value should be returned. For example “False” for a boolean, 0 for a number, and “” for a string. If the arguments given do not match the schema, it is important that a good error message is given, explaining exactly what is wrong.

If you are feeling ambitious, extend your code to support lists eg

-g this,is,a,list -d 1,2,-3,5

So the “g” flag indicates a list of strings, [“this”, “is”, “a”, “list”] and the “d” flag indicates a list of integers, [1, 2, -3, 5].

Make sure your code is extensible, in that it is straightforward and obvious how to add new types of values.

Clues

What the schema should look like and how to specify it is deliberately left vague in the Kata description. An important part of the Kata is to design a concise yet readable format for it.

package org.dojo.args;

import cn.org.dojo.args.Args;
import org.apache.ibatis.annotations.Arg;
import org.junit.Assert;
import org.junit.Test;

/**
 * @program: seckill
 * @description:
 * @author: 
 * @create: 2019-08-31 06:31
 **/
public class ArgsTest {

    @Test
    public void show_parse_args(){
        Args args = new Args("l:boolean,p:int,d:string","-l -p 8080 -d /usr/logs");
        Assert.assertEquals(args.getValue("l"),Boolean.TRUE);
        Assert.assertEquals(args.getValue("p"), new Integer(8080));
        Assert.assertEquals(args.getValue("d"), "/usr/logs");
    }

    @Test
    public void show_parse_number(){
        Args args = new Args("l:boolean,p:int,d:string","-l false -p 8080 -d /usr/logs");
    }

}
View Code

Args

package cn.org.dojo.args;

import com.sun.org.apache.xerces.internal.util.FeatureState;

/**
 * @program: seckill
 * @description:
 * @author: zgl
 * @create: 2019-08-31 06:34
 **/
public class Args {
    private final Commnd commnd;
    private final Scheams scheam;

    public Args(String scheam, String commnd) {
        this.scheam = new Scheams(scheam);
        this.commnd = new Commnd(commnd);
    }


    public Object getValue(String name) {
        return scheam.getVaule(name, commnd.getValue(name));
    }
}
View Code
Scheam
package cn.org.dojo.args;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import static java.lang.Boolean.TRUE;

/**
 * @program: seckill
 * @description:
 * @author: zgl
 * @create: 2019-08-31 07:07
 **/
public class Scheams {
    Map<String, String> scheams;
    public Scheams(String scheamsConf) {
        scheams = new HashMap<>();
        Arrays.asList(scheamsConf.split(","))
        .stream()
        .forEach(falg->{
            String[] nameValue = falg.split(":");
            scheams.put(nameValue[0], nameValue[1]);
        });
    }

    public Object getVaule(String name, String strValue) {
        String type = scheams.get(name);
        switch (type){
            case "bool":
                return "true".equalsIgnoreCase(strValue);
            case "int":
                return Integer.parseInt(strValue);
            case "string":
                return strValue;
            default:
                return  true;
        }
    }
}
View Code
ScheamTest
package org.dojo.args;

import cn.org.dojo.args.Scheams;
import org.junit.Assert;
import org.junit.Test;

/**
 * @program: seckill
 * @description:
 * @author: zgl
 * @create: 2019-08-31 07:03
 **/
public class ScheamTest {

    @Test
    public void test_bool(){
        Scheams scheam = new Scheams("l:bool");
        Assert.assertEquals(scheam.getVaule("l","true"),Boolean.TRUE);
        Assert.assertEquals(scheam.getVaule("l","false"),Boolean.FALSE);
        Assert.assertEquals(scheam.getVaule("l",null),Boolean.FALSE);
    }

    @Test
    public void test_int(){
        Scheams scheams = new Scheams("l:int");
        Assert.assertEquals(scheams.getVaule("l","1"),new Integer(1));
    }

    @Test
    public void test_string(){
        Scheams scheams = new Scheams("l:string");
        Assert.assertEquals(scheams.getVaule("l","hellon"),"hellon");
    }

}
View Code

Commd

package cn.org.dojo.args;

import java.util.Arrays;
import java.util.HashMap;
import java.util.ListIterator;
import java.util.Map;

/**
 * @program: seckill
 * @description:
 * @author: zgl
 * @create: 2019-08-31 14:38
 **/
public class Commnd {
    Map<String, String> values;
    public Commnd(String commdLine) {
        values = new HashMap<>();
        ListIterator<String> commdIterator =
                Arrays.asList(commdLine.split("\\s+")).listIterator();
        while(commdIterator.hasNext()){
            String name = commdIterator.next().substring(1);
            if (commdIterator.hasNext()){
              String value = commdIterator.next();
              if (isValue(value)){
                    values.put(name, value);
              } else{
                  commdIterator.previous();
              }
            }
        }

    }

    private boolean isValue(String value) {
        if (value.charAt(0) == '-'){
            if (value.length() > 2){
                return true;
            }
            if (value.charAt(1) >= '0' && value.charAt(1) <='9'){
                return true;
            }
            return false;
        }
        return  true;
    }

    public String getValue(String name) {
        return values.get(name);
    }
}
View Code

CommdTest

package org.dojo.args;

import cn.org.dojo.args.Commnd;
import org.junit.Assert;
import org.junit.Test;

/**
 * @program: seckill
 * @description:
 * @author: zgl
 * @create: 2019-08-31 14:30
 **/
public class CommndTest {
    @Test
    public void test_commmd_has_value(){
        Commnd commnds = new Commnd("-l true -d /use/log");
        Assert.assertEquals(commnds.getValue("l"), "true");
        Assert.assertEquals(commnds.getValue("d"), "/use/log");
    }

    @Test
    public void test_commd_no_value(){
        Commnd commnds = new Commnd("-l -d /use/log");
        Assert.assertNull(commnds.getValue("l"));
        Assert.assertEquals(commnds.getValue("d"),"/use/log");
    }

    @Test
    public void test_commd_negetive(){
        Commnd commnd = new Commnd("-l -p -9 -d /use/log");
        Assert.assertNull(commnd.getValue("l"));
        Assert.assertEquals(commnd.getValue("p"),"-9");
        Assert.assertNotNull(commnd.getValue("d"),"/use/log");

    }


}
View Code

猜你喜欢

转载自www.cnblogs.com/ptbx/p/11503490.html