Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Тестовая система аля topcoder 
:(
    Опции темы
Platon
Дата 23.10.2007, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Здравствуйте, уважаемые.

Не стал раздувать предыдущий созданный топик, там о том как начать проект, а тут по конкретному проекту.

Всем наверно уже известно, что я делаю робкие попытки сделать тестовую систему.
Встали пара вопросов.
1. Использовать в своей системе JUnit, который есть не только на Java, но и на других языках. 1 вопрос, хочется проконсультироваться может ли JUnit манипулировать временем и объемом выделяемой памяти процессу. Или нет смысла? Лучше делать по программе на тест.

2. Конвертируемость тестовых данных. Т.е. думается сделать удобную ГАИшку, в которой тыкая можно выбирать число входных параметров, их тип, а затем набор данных по ним и эталонный результат, нуу, может + еще погрешность. В результате получается xml на основе которого получаем 4 тестирующих программы (на Java, C++, C#, VB) Проблема встала с массивами, как в xml описать массив, чтоб по записи можно было понять что это массив такого-то типа такой-то размерности и с такими-то данными.
PM MAIL ICQ   Вверх
powerOn
Дата 23.10.2007, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(Platon @  23.10.2007,  21:01 Найти цитируемый пост)
Проблема встала с массивами, как в xml описать массив, чтоб по записи можно было понять что это массив такого-то типа такой-то размерности и с такими-то данными. 


Код

<root>
    <myarray type="sometype">
        <element>1</element>
        <element>2</element>
        <element>3</element>
        <element>4</element>
        <element>5</element>
    </myarray>
</root>





--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
nornad
Дата 24.10.2007, 02:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1079
Регистрация: 16.2.2007
Где: в Караганде

Репутация: 16
Всего: 31



Также атрибутом можно указать и то, что тэг содержит массив. В примере powerOn я бы сделал так (если надо именно указать, что "это - массив"):
Код

<myarray vartype="array" elemtype="number">



--------------------
Три достоинства программиста: Леность, Нетерпение и Гордость
Ларри Уолл
PM MAIL WWW ICQ Skype MSN   Вверх
Platon
Дата 26.10.2007, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



А размерность массива как делать? что-то типа

Код

<argument vartype="array" elemtype="number">
    <element>
        <element>11</element>
        <element>12</element>
        <element>13</element>
    </element>
    <element>
        <element>21</element>
        <element>22</element>
        <element>23</element>
    </element>
</argument>

?
PM MAIL ICQ   Вверх
alex_nevolin
Дата 26.10.2007, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 13.8.2007

Репутация: 3
Всего: 4



Цитата(Platon @  23.10.2007,  20:01 Найти цитируемый пост)
1 вопрос, хочется проконсультироваться может ли JUnit манипулировать временем и объемом выделяемой памяти процессу. 
 Что имеется ввиду?
JUnit тесты - это те-же java классы просто подчиняющиеся определеным правилам. Т.е. если есть возможность в принципе манипулировать временем и объемом выделяемой памяти процессу, то это не составит труда реализовать в тесте. 
PM MAIL   Вверх
Platon
Дата 12.12.2007, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Так, вернемся к нашим баранам ^_^
Запустил я эту тему, так и не начав...

В общем, у меня разработана кое какая модель по генерации шаблонных тестеров. Возник вопрос по velocity... я видимо слабоват в этом направлении.
У меня получилось следующее:
Описание классов и тестовых решений в xml
Код

<class-descriptor>
    <className>Platon</className>
    <methodName>getArgumentus</methodName>
    <arg num="1" type="array">
        <param type="string" depth="1" />
    </arg>
    <arg num="2" type="string" />
    <arg num="3" type="int" />
    <arg num="4" type="long" />
</class-descriptor>

единственное, что тут может быть непонятно - это num, определяет очередность аргументов в методе
Код

<test-case>
    <case-num>1</case-num>
    <arg num="1">{"Data", "coolMan!!!"}</arg>
    <answer>"+Data+coolMan!!!+"</answer>
</test-case>

case-num - номер тестового семпла
num - номер аргумента
answer - ответ

Теперь по коду (обращайте внимание в основном на velocity и на обслуживающие классы (ClassData, MethodArgument, ArrayMethodArgument)):
Код шаблона:
Код

#macro (type $t)
#if ($t.equals("string"))
String
#elseif ($t.equals("int"))
int
#elseif ($t.equals("long"))
long
#elseif ($t.equals("double"))
double
#elseif ($t.equals("float"))
float
#end
#end

#macro (createType $t)
#if ($t.type.equals("array"))
    #type($t.param.type)
    #foreach($i in $t.type)
        []
    #end
#else
    #type($t.type)
#end
#end

#macro (generate $i)
#if ($classData.args.get($i).type.equals("string"))
c.get($i).getText()
#elseif ($classData.args.get($i).type.equals("int"))
Integer.parseInt(c.get($i).getText())
#elseif ($classData.args.get($i).type.equals("long"))
Long.parseLong(c.get($i).getText())
#elseif ($classData.args.get($i).type.equals("double"))
Double.parseDouble(c.get($i).getText())
#elseif ($classData.args.get($i).type.equals("float"))
Float.parseFloat(c.get($i).getText())
#end
#end

#macro (generateValue $i)
#if ($classData.args.get($i).type.equals("array"))
new #createType($classData.args.get($i))
() c.get($i).getText();
#end
#end
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import java.util.List;
import java.io.IOException;

public class Tester {

    public static final int OK = 0;
    public static final int TEST_ERROR_BASE = 1000;

    public static void main(String[] args) throws Exception {
        testCase(Integer.parseInt(args[0]), loadCase(Integer.parseInt(args[0])));
    }

    private static void testCase(int i, Test test) {
        System.setSecurityManager(null);
        if (!asseertEquals(new $className().$methodName(
            #foreach ($d in [1 .. $classData.args.size()])
                #if ($d != 1)
                    ,
                #end
                test.arg$d
            #end
        )))
            System.exit(TEST_ERROR_BASE + i);
        System.exit(OK);
    }

    private static Test loadCase(int testCase) throws IOException, JDOMException {
        Test t = new Test();
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(getTestcasePath(testCase));
        List<Element> c = doc.getRootElement().getChildren("arg");
        #foreach($d in [0..$classData.args.size()])
            #set($am = $d + 1)
            t.arg$am = #generateValue($d)
        #end
        return t;
    }

    private boolean assertEquals(int a, int b) {
        return a == b;
    }

    private static class Test {
    #foreach($d in [0..$agrsAmount])
        #set ($am = $d + 1)
        public #createType($classData.args.get($d)) arg$am;
    #end
    }
}

Обслуживающие классы:
Код

public class ClassData {
    public String className;
    public String methodName;
    public Vector<MethodArgument> args;
}

public class MethodArgument {
    public String type;

    public MethodArgument(String type) {
        this.type = type;
    }

    public MethodArgument() {
    }
}


public class TesterGenerator {

    public String generateTemplate(String path) throws Exception {
        VelocityEngine velocity = new VelocityEngine();
        velocity.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, System.getProperty("user.dir"));
        velocity.init();
        VelocityContext c = new VelocityContext();
        ClassData data = loadClassData(path);
        c.put("classData", data);
        c.put("className", data.className);
        c.put("methodName", data.methodName);

        StringWriter writer = new StringWriter(2500);
        Template t = velocity.getTemplate("Tester.vm");
        t.merge(c, writer);
        return writer.toString();
    }

    private ClassData loadClassData(String path) throws IOException, JDOMException {
        SAXBuilder b = new SAXBuilder();
        Element d = b.build(new FileInputStream(path)).getRootElement();
        ClassData res = new ClassData();
        res.className = d.getChild("className").getText();
        res.methodName = d.getChild("methodName").getText();
        List<Element> elements =  d.getChildren("arg");
        res.args = new Vector<MethodArgument>();
        res.args.ensureCapacity(elements.size());
        for (Element e : elements)
            res.args.add(e.getAttribute("num").getIntValue() - 1, buildNode(e));
        return res;
    }

    private MethodArgument buildNode(Element e) throws DataConversionException {
        if (e.getAttribute("type").getValue().equals("array")) {
            Element s = e.getChild("param");
            return new ArrayMethodArgument("array", s.getAttribute("type").getValue(), s.getAttribute("depth").getIntValue());
        }
        return new MethodArgument(e.getAttribute("type").getValue());
    }

    public static void main(String[] args) throws Exception {
        String s = new TesterGenerator().generateTemplate("class-descriptor.xml");
        System.out.println(s);
    }
}


Информер пишет:
Цитата

SEVERE: Right side of range operator [n..m] has null value. Operation not possible. Tester.vm [line 65, column 41]

проверил на вывод $classData - работает, $classData.args - не работает
Подумал нужны getter/setter методы, сделал, но пишет исключение:
Цитата

SEVERE: Method get threw exception for reference $classData in template Tester.vm at  [1,6]
Exception in thread "main" org.apache.velocity.exception.MethodInvocationException: Invocation of method 'get' in  class java.util.Vector threw exception java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 4 @ Tester.vm[1,22]

Черт ногу сломит, у меня в [1,22] только объявления макрокоманд, в чем может быть подвох?
PM MAIL ICQ   Вверх
Platon
Дата 12.12.2007, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



И еще доп вопрос, может я глупо сделал и решения не нашел правильного, сделал свой вариант синхронного вывода. Как не странно это звучит ^_^ люди мучаются с асинхронным, а я с синхронным, в общем я решил, что нече клиенту в разнобой слать запросы пусть шлет их последовательно в основном потоке (специфика такая)
Фича очень похожая на RMI

Примерчик:
Код

public interface AuthBridge {
    public AuthResponse authenticate(String login, String password);
}

Клиентская реализация
Код

public class AuthHandler implements AuthBridge, MessageHandler<AuthMessage> {
    private final IoSession connection;
    private ResponseWaitor<AuthResponse> authResp = new ResponseWaitor<AuthResponse>();
    public AuthHandler(IoSession connection) {
        this.connection = connection;
    }

    public AuthResponse authenticate(String login, String password) {
        connection.write(new AuthRequest(login, password));
        return authResp.getObject();
    }


    public void messageReceived(IoSession ioSession, AuthMessage authMessage) throws Exception {
        if (authMessage instanceof AuthResponse) {
            authResp.setObject((AuthResponse)authMessage);
        }
    }
}

Сервернная реализация:
Код

public class AuthHandler implements MessageHandler<AuthMessage> {

    public void messageReceived(IoSession ioSession, AuthMessage authMessage) throws Exception {
        if (authMessage instanceof AuthRequest) {
            final AuthRequest ar = (AuthRequest)authMessage;
            final AuthImpl impl = new AuthImpl(ioSession);
            ioSession.write(impl.authenticate(ar.login, ar.password));
        }
    }

    private static class AuthImpl implements AuthBridge {

        IoSession session;

        public AuthImpl(IoSession session) {
            this.session = session;
        }

        public AuthResponse authenticate(String login, String password) {
            return null;
        }
    }
}

Якобы, таким образом я хочу создать ощущение при программировании, что программируется все на одной локальной машине.

А, да, самое главное, вот класс, который ожидает приема объекта, и сразу будет поток
Код

public class ResponseWaitor<E> {
    private E resp;

    public synchronized void setObject(E resp) {
        this.resp = resp;
        notify();
    }

    public boolean isDone() {
        return resp != null;
    }

    public E getObject() {
        while(!isDone()) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return resp;
    }
}


Оцените, и покритикуйте.
PM MAIL ICQ   Вверх
Kangaroo
Дата 12.12.2007, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


AA - Aussie Animal
****


Профиль
Группа: Участник Клуба
Сообщений: 2042
Регистрация: 7.10.2006
Где: US

Репутация: 21
Всего: 104



Platon, 
нужны геттер/сеттеры, потому что Velocity их использует. Верни их обратно smile

Цитата(Platon @  12.12.2007,  12:56 Найти цитируемый пост)
Подумал нужны getter/setter методы, сделал, но пишет исключение:

Цитата    

SEVERE: Method get threw exception for reference $classData in template Tester.vm at  [1,6]
Exception in thread "main" org.apache.velocity.exception.MethodInvocationException: Invocation of method 'get' in  class java.util.Vector threw exception java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 4 @ Tester.vm[1,22]
    
Черт ногу сломит, у меня в [1,22] только объявления макрокоманд, в чем может быть подвох?

Это ж обычный ArrayIndexOutOfBoundsException. Вот в этом куске кода:
Код

#foreach ($d in [1 .. $classData.args.size()])    
                #if ($d != 1)    
                    ,    
                #end    
                test.arg$d    
            #end

У тебя $d от 1 до размера вектора, а нужно от 0 до РАЗМЕР_ВЕКТОРА-1



--------------------
Lost....
PM MAIL MSN   Вверх
Platon
Дата 12.12.2007, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Поясню некоторые моменты:
мы выполняем простую процедуру авторицации/аутентификации (точно не уверен,  что тут правильно)
Клиент пишет в сокет сервера запрос, и ставит себя в ожидание
Сервер принимает этот запрос и направляет его в своем реализованном интерфейсе AuthBridge, и сразу же отсылает ответ.
Клиентская реализация получает ответ, пробуждает поток и продолжает победное шествие.


PM MAIL ICQ   Вверх
Platon
Дата 12.12.2007, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Kangaroo, ууух, не успел запостить следующее сообщение, уже ответил! А я сижу жду ответа.

Цитата(Kangaroo @  12.12.2007,  15:13 Найти цитируемый пост)
Черт ногу сломит, у меня в [1,22] только объявления макрокоманд, в чем может быть подвох?

А как насчет того что не в ту строку указывает?
PM MAIL ICQ   Вверх
Kangaroo
Дата 12.12.2007, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


AA - Aussie Animal
****


Профиль
Группа: Участник Клуба
Сообщений: 2042
Регистрация: 7.10.2006
Где: US

Репутация: 21
Всего: 104



Цитата(Platon @  12.12.2007,  15:09 Найти цитируемый пост)
А как насчет того что не в ту строку указывает?

Это фишка Velocity - ошибки не там показывать ))..  у меня пока не доходили руки, чтобы разобраться. Сам сталкиваюсь с этим.


--------------------
Lost....
PM MAIL MSN   Вверх
Platon
Дата 12.12.2007, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Да ^_^ мне реально помогло , но мне не понравилось, что выход такой некозистый получился.
Пришлось написать всё в 1 строчку... чтоб было так как я хочу.
Цитата

new $className().$methodName(#foreach ($d in [1 .. $classData.args.size()])#if ($d != 1),#end test.arg$d#end))

читать такое тяжеловато.
PM MAIL ICQ   Вверх
Platon
Дата 12.12.2007, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Еще бы хотел спросить по поводу внутреннего устройства системы.
Я вижу внутренности системы так, распределенная на несколько компов.
1. Сервер, с ним идет основное общение клиентов.
2. Тестер, их несколько, коннектятся к серверу и ждут, когда он скажет им проверить ту или иную задачу.
3. Файловый сервер условий задач, тут хранятся все файлы задач.
4. Файловый сервер решенных пользователями задач.
5. База данных

насчет 3-4 я думаю, может объеденить?
А также возникают вопросы как лкчше всего эти пункты наладить между собой.
Я прикинул так, что сервер, при запросе условия задачи,  может перенаправить пользователя на файловый сервер и скачать задачу прямо с него, тогда возникает проблема тоог, что файловый сервер должен быть не просто ФС, но также минимально фильтровать тех, кто к нему коннектиться, нельзя выдавать задания раньше, чем назначено соревнование.
Сервер при взаимодействии с клиентом, формирует на Файл сервере решенных задач отправленные пользователем задачи.
При запросе от сервера к тестеру проверить определенную задачу, тестер скачивает с этого файл сервера необходимую задачу.

В итоге, получается хоть локальное взаимодействие, но внутренний трафик мыслится гигантским.
Тут очередной каскад вопросов связанных с кешированием данных. Целесообразно ли на тестере кешировать к примеру 10 последних решенных задач, если очень высока вероятность их повторного (2-кратного, 3х, 4х, 50х) запроса. Или это не так существенно и только нагрузит систему?

Что тут может не понравиться? Жду критики.

Добавлено через 1 минуту
Насчет этого поста кто, что может сказать?
PM MAIL ICQ   Вверх
Platon
Дата 14.12.2007, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Пришел к тому, что это лишняя морока разделять основной сервер от набора задач и набора решенных заданий, получается все эти 3 компонента будут в 1-й серверной программе.

Причина по которой я не смог разделить эти компоненты: 
Рассмотрим предполагаемый алгоритм, если клиент выбирает задачу, конектясь к серверу списка задач а не к главному серверу:
-- коннект к серверу списка задач(ССЗ), запрос конкретной задачи
  -- ССЗ коннектится к главному серверу (ГС), чтобы спросить можно ли выдавать задачу клиенту. (вот тут то и загвоздка)

Если сервер интегрирован, т.е. все 3 компонента в 1-й серверной программе, то проверку доступности организовать не составит труда, иначе получается, что каждый раз придется дергать БД, чтоб установить подключаемую личность, это видится мне как накладный расход.

Думал о всяких фишках типа временной подписи. Последовательного запроса клиент-ГС (запрос на получение задачи), ГС-ССЗ (приказ выдать пользователю задачу), ССЗ-клиент(коннект(!)* к клиенту и впрыскивание данных) *по безопасности такой вариант не проходит.
Думал о К->ГС, ГС->ССЗ, К->ССЗ, но тут велика вероятность конфликта синхронизации, да и тоже много темных пятен...

Слишком много вопросов и мало ответов :(
PM MAIL ICQ   Вверх
Platon
Дата 14.12.2007, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Может мне посмотреть в сторону кластеров (группы серверов)?
По вики, выглядит очень заманчиво smile необходимо только реализовать или использовать готовый кластерный менеджер.
Что можете посоветовать по этому поводу? Есть готовые менеджеры? Может это уже удел J2EE? хотя хотелось бы без него обойтись smile
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0633 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.