Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 [2]  Все   Вниз
  Печать  
Автор Тема: watchdog - с чем его едят?  (Прочитано 15566 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #30 : 23-04-2010 02:52 » 

resource, с ожиданием - это подходит для случая с 1 контролируемым процессом. А если их 20-40 , то долговато ждать будет Улыбаюсь
Записан

zubr
Команда клуба

by
Offline Offline
Пол: Мужской

« Ответ #31 : 23-04-2010 04:05 » 

resource, с ожиданием - это подходит для случая с 1 контролируемым процессом. А если их 20-40 , то долговато ждать будет Улыбаюсь
Так для этого и применяется WaitForMultipleObjects, в отличие от WaitForSingleObject.
Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #32 : 23-04-2010 04:09 » 

zubr, теперь понятно ) Там же список хендлов можно, оказывается

DWORD WINAPI WaitForMultipleObjects(
  __in  DWORD nCount,
  __in  const HANDLE* lpHandles,
  __in  BOOL bWaitAll,
  __in  DWORD dwMilliseconds
);
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #33 : 23-04-2010 04:29 » 

Слав,
ну и где они, твои 25 лет? А заодно и мои тоже?  Улыбаюсь)

Ага, видимо, программный (т.е. с железом ничего общего не имеет).
Суть задачки:
Есть тест, который для своей работы стартует парочку других ехе-шников (как процессы). Так вот иногда один из этих процессов зависает, что приводит к общему зависанию теста.
Появилась идея написать эту самую собаку, которая следила бы за тестом и в случае зависания давала бы команду "убить Билла" Ага , т.е. killProcess.

Спасибочки за описание - судя по всему, все выглядит не так уж и плохо!
я почему-то сначала думала, что там должно быть больше наворотов.
Ща попробую.

как это делается у нас?
а делается это так: софтина timeoutrun (самописная тулза) получает в качестве параметров команду (фактически кусок командной строки со всеми параметрами) и timeout в течении которого должна выполнятся команда
далее она поднимает всё, что указано в параметре (просто через cmd) и запоминает id поднятого процесса
затем ждёт или завершения процесса или истечения timeout
если, что грохает всё дерево процессов

Что касается WD (WatchDog)
Примерно такой-же принцип можно использовать для построения WD
Но WD это WD и слежение за наличием процесса не единственный способ его построить и не всегда правильный
А запуск и ожидание TimeOut это другая задача, гораздо более простая
Записан

Странно всё это....
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #34 : 23-04-2010 05:44 » 

очень давно реализовали такую штукенцию.
Система тестов.
Каждый тест что-то свое делал.
Все тесты запускались из одной оболочки.
Каждому тесту было выделено поле для своего обнаружения.
Каждый тест писал свое состояние (например шаг 1, шаг 2 и т.д.)
Каждый шаг теста нормировался по времени.

На каждое поле было повешено событие onchange.
при возникновении события WD сбрасывал состояние ожидание.

Таймер регулярно взводил флаг ожидания процесса, в соответствии с его временными характеристиками.

Каждый процесс (тест) при запуске регистрировался, считывалось его дерево состояний, каждому процессу выделялось поле.

В случае зависания процесса (теста) - тест килялся.

зы написано это было на Tk/Tcl
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #35 : 23-04-2010 09:00 » 

1) resource:
В коде поста #11 timerMain - был встроен для того, чтобы раз в 15 секунд менять состояние event-а (т.о. говоря watchdog-у, что мы еще живы)
2) Леш,
я вместо Sleep() использовала timeout-параметр в функции WaitForSingleObject()
3) Слав, прости за тупость, но что имеется в виду под

Таймер регулярно взводил флаг ожидания процесса, в соответствии с его временными характеристиками.

(просто я уже все эти вещи учила по-немецки или по-английски, поэтому некоторые понятия мне неясны... Возвести флаг - означает поставить его в nonsignaled или в signaled?)

Так?
SetTimer(timeout);
SetEvent(hEvent);

4) LogRus, спасибо за идею! Сейчас посмотрю, смогу ли я ее применить, упростив себе т.о. жизнь.
Записан

холоднокровней, Маня, Ви не на работе
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #36 : 23-04-2010 09:41 » 

Система была построена приблизительно так
Тест1
  Шаг1 Время1
  Шаг2 Время2
Тест2
  Шаг1 Время1
  Шаг2 Время2
  Шаг3 Время3
  Шаг4 Время4

WD init
  Запуск Тест1 Запомнить->Тест1.Шаг1.Время1
  Запуск Тест2 Запомнить->Тест2.Шаг1.Время1

WD job
  Анализ->Тест1.Шаг1.Время1 ? (истекло) kill : (не истекло) wd.state1 = состояние_ожидание_шага
  ...

Тест1 в работе регулярно устанавливает свое состояние, соответствующее шагу  (например: шаг1 имеет два состояния 0 и 1, шаг2 - 2 и 3)
И т.д.


зы. Под это была накручена научная работа, которая, к сожалению, кандидатской не закончилась Жаль
Имелись публикации и прочее. Где их искать даже не знаю... "Все пропало ..."


Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #37 : 23-04-2010 13:05 » 

Ткните меня носом, где я сошла с ума...
Сделала тестовую программку на c++ в студии 2008: цоздала консольное приложение, попыталась потестировать собаку...
В результате уперлась в то, что не могу простестировать, т.к. у меня не срабатывает таймер Не может быть...  С ума сойти...  Где поп, а где приход... Такого я еще не видела... И в чем дело - никак не пойму!

* DiffTests_console.zip (5.27 Кб - загружено 111 раз.)
Записан

холоднокровней, Маня, Ви не на работе
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #38 : 23-04-2010 14:27 » 

Malaja, не понял, зачем так сложно...

Вот совсем простой пример - без дополнительных таймеров.
Код: (Text)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

// Таймаут проверки завершения очередного действия.
#define TIMEOUT 10000

// Событие завершения очередного действия процесса.
HANDLE processFinishActionEvent;

// Наблюдаемый процесс
void process()
{
        // Процесс работает бесконечно.
        for(;;)
        {
                // Процесс выполняет какое-то действие, что занимает случайное время.
                printf("PROCESS: Start action.\n");
                ::Sleep(rand() % (TIMEOUT * 2)); // Пусть время в худшем случае в 2 раза превышает таймаут.
                printf("PROCESS: Finish action.\n");
                // После этого он устанавливает событие о том, что действие завершил.
                ::SetEvent(processFinishActionEvent);
        }
}

// Наблюдающий процесс
DWORD WINAPI watchDog(LPVOID lpParameter)
{
        // Процесс работает бесконечно.
        for(;;)
        {
                printf("WATCHDOG: Wait the next action.\n");
                // Ждёт события в течение таймаута.
                switch(::WaitForSingleObject(processFinishActionEvent, TIMEOUT))
                {              
                case WAIT_OBJECT_0:
                        // Дождался события, значит наблюдаемый процесс жив.
                        // Сбрасывает событие и ждёт следующего.
                        printf("WATCHDOG: Action was finished - OK.\n");
                        ::ResetEvent(processFinishActionEvent);
                        break;
                case WAIT_TIMEOUT:
                        // Не дождался события за отведённое время, значит наблюдаемый процесс завис.
                        // Завершает наблюдаемый процесс.
                        printf("WATCHDOG: Action is too long - FAIL.\n");
                        printf("WATCHDOG: Terminate process.\n");
                        ::ExitProcess(0);
                        break;
                }
        }
}

// Основная программа.
int main()
{
        srand(time(NULL));
        // В начале событие завершения очередного действия процесса установлено,
        // будто до этого успешно завершилось очередное действие.
        processFinishActionEvent = ::CreateEvent(NULL, TRUE, TRUE, NULL);
        // Запускаем наблюдающий процесс.
        ::CreateThread(NULL, 0, &watchDog, NULL, 0, NULL);
        // Запускаем наблюдаемый процесс.
        process();
        return 0;
}
Что касается таймеров, то функция SetTimer предписывает Windows спустя указанное время послать процессу сообщение WM_TIMER. Но чтобы его обработать, по-моему приложение должно быть для подсистемы Windows, а не Console, с WinMain и т.д.
« Последнее редактирование: 23-04-2010 20:36 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #39 : 23-04-2010 14:51 » 

Подсистема к делу не относится. С SetTimer ничего не получится. Чтобы получить сообщение таймера WM_TIMER, нужно, чтобы наблюдаемый процесс периодически вызывал PeekMessage - функцию получения системных сообщений. Очевидно, что делать это он может лишь в перерывах между какими-то внутренними действиями - т.е. в моём примере функция process выглядела бы как:
Код: (Text)
// Наблюдаемый процесс
void process()
{
        // Процесс работает бесконечно.
        for(;;)
        {
                // Процесс выполняет какое-то действие, что занимает случайное время.
                printf("PROCESS: Start action.\n");
                ::Sleep(rand() % (TIMEOUT * 2)); // Пусть время в худшем случае в 2 раза превышает таймаут.
                printf("PROCESS: Finish action.\n");
                // После этого он получает все накопившиеся события.
                MSG msg;
                while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0)
                {
                        switch(msg.message)
                        {
                        case WM_TIMER:
                                // Если было событие таймера, сигнализирует о том, что действие завершил.
                                ::SetEvent(processFinishActionEvent);
                                break;
                        }
                }
        }
}
Только это бессмысленное усложнение.

Асинхронные таймеры тоже ничего не дадут, поскольку за их запуск будет отвечать операционная система или другой поток, и они будут исправно срабатывать вне зависимости от состояния активного процесса - последний может благополучно зависнуть, и никто об этом не узнает.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #40 : 23-04-2010 15:04 » 

Дим,
1) так я же поэтому и установила свою собственную функцию для таймера и не задала hwnd, чтобы не зависеть от WM_TIMER!
Теоретически я устанавливаю таймер на определенное время, после истечения которого и вызывается либо WinProc (если про создании таймера не указана собственная процедура и указан hwnd окна - тогда ему будет послан WM_TIMER) либо та самая своя процедура.
Или?

2) за идею спасибо! кажется, я перемудрила с таймерами - просто хотела иметь контроль над процессом постоянно.
Записан

холоднокровней, Маня, Ви не на работе
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #41 : 23-04-2010 16:23 » 

Цитата: Malaja
1) так я же поэтому и установила свою собственную функцию для таймера и не задала hwnd, чтобы не зависеть от WM_TIMER!
Теоретически я устанавливаю таймер на определенное время, после истечения которого и вызывается либо WinProc (если про создании таймера не указана собственная процедура и указан hwnd окна - тогда ему будет послан WM_TIMER) либо та самая своя процедура.
Или?
Всё же или
Цитата: MSDN
Handle to the window to be associated with the timer. This window must be owned by the calling thread. If this parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored.
Отсутствие hwnd всего лишь означает, что таймер не привязан к какому-то окну процесса. Это не позволяет использовать nIDEvent, но в данном случае это и не нужно.

Цитата: MSDN
An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.
Наличие адреса обработчика означает, что не нужно вручную писать case WM_TIMER в цикле обработки, НО при этом должна вызываться функция обработки сообщения по умолчанию DefWindowProc. В твоей программе она не используется - поэтому таймер не срабатывал. Таймер не является асинхронным - его обработчик выполняется в том же потоке, в котором таймер был установлен. Срабатывание возможно организовать только при получении потоком сообщений от системы. Это значит, что поток должен периодически проверять сообщения системы - т.е. нельзя запустить долго исполняющиеся вычисления, поток должен время от времени (и лучше регулярно) возвращаться к циклу обработки системных сообщений.
« Последнее редактирование: 23-04-2010 16:35 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #42 : 23-04-2010 17:18 » 

Дим,
спасибо! Я привыкла, что таймер у меня всегда работал... Но при этом забыла, что тут нет мфц, у которого всегда внутри есть обработчик событий...
Записан

холоднокровней, Маня, Ви не на работе
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #43 : 26-04-2010 14:04 » 

Маленькое замечание по поводу таймера в основном thread-е (как раз сейчас попробовала): он не спасает, т.е. он работает вне зависимости от того, висит ли thread или нет.
Записан

холоднокровней, Маня, Ви не на работе
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #44 : 26-04-2010 15:08 » 

Malaja, я об этом и сказал
Цитата: dimka
Асинхронные таймеры тоже ничего не дадут, поскольку за их запуск будет отвечать операционная система или другой поток, и они будут исправно срабатывать вне зависимости от состояния активного процесса - последний может благополучно зависнуть, и никто об этом не узнает.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #45 : 27-04-2010 02:35 » 

По моему, что-то у вас всё слишком сложно получается
Почему бы не создать внешний watchdog который просто ждёт N секунд до завершения процесса, какая разница в какой именно точке повис тест, важно, что он повис. (потом можно логи почитать для анализа)
Главный бонус, что не надо модифицировать тесты для работы с таким WD
Записан

Странно всё это....
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #46 : 27-04-2010 05:25 » 

LogRus, согласен. Правда в тесте всё равно конечно должен быть код, связанный с wd, но код этот должен быть минимальным, просто чтоб сигналить, что процесс еще живой.
 Однако, чтобы не заморачиваться очередью сообщений в тесте (ну если она там уже обрабатывается, то и проблемы нет), придется пользоваться любыми функциями времени (хоть GetTickCount). Это конечно грубовато, но поскольку речь идет о секундах, а не о миллисекундах, то вполне подойдет.
 В самом wd, лучше наверное обрабатывать сообщения. Окно ведь для этого необязательно.
Записан
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #47 : 27-04-2010 08:16 » 

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

LogRus, resource:
идея была в следующем - отслеживать не только целый тест (а их там > 100), а и внутри теста проводить контрольные выстрелы (т.е. в процессе выполнения всего цикла тестов каждые n-секунд проверять приложение на предмет наличия жизни).
С другой стороны, не хотелось ничего особо модифицировать, а изменения сделать очень компактными (почему я и схватилась за таймер - написал себе процедуру для него и все!).
Короче, хотелось красивых решений Ага
Но из этого ничего не вышло - придется таки в wachdog-е просто устанавливать контрольное время исходя из самого длинного теста, выполняемого на самой медленной машине...
Записан

холоднокровней, Маня, Ви не на работе
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #48 : 27-04-2010 09:33 » 

Malaja, неправильно ты дядя Федор бутерброд кушаешь.

Я про время тестов...
Нужен контрольный тест времени и от него все времена пересчитывать.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #49 : 27-04-2010 10:12 » 

Слав,
что ты имеешь в виду?
Записан

холоднокровней, Маня, Ви не на работе
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #50 : 27-04-2010 11:00 » 

запускаешь тест времени на Любой машине и запоминаешь
Потом запускаешь его на другой и получаешь время выполнения теста.
Рассчитываешь коэф. и применяешь его (коэф) ко всем тестам

Тест времени на контрольной машине = 10
Время test1 =30

Тест времени на тестируемой 20
коэф = 2
Время test1 на тестируемой 30*2


Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #51 : 27-04-2010 11:11 » 

LogRus, согласен. Правда в тесте всё равно конечно должен быть код, связанный с wd, но код этот должен быть минимальным, просто чтоб сигналить, что процесс еще живой.

Зачем? Улыбаюсь сказано тест должен завершиться за 2 минуты, не завершился, значит рубим, он или завис или тормозит или не корректный таймаут под конкретный тест.
Из опыта: у нас тысячи тестов и пока ни один понятия не имеет, что его запускают из WD.

LogRus, resource:
идея была в следующем - отслеживать не только целый тест (а их там > 100), а и внутри теста проводить контрольные выстрелы (т.е. в процессе выполнения всего цикла тестов каждые n-секунд проверять приложение на предмет наличия жизни).
Какая цель теста? Найти проблему, если тест не выполнился за N секунд значит он провален, задача достигнута, разработчик получает письмо о проваленном тесте с логами теста в атаче и начинает разбираться.

.................
Короче, хотелось красивых решений Ага
.................
так это и есть красивое решение Улыбаюсь просто и красиво, а главное дёшево

тест зациклился, но что-то делает и что-то пишет в лог:
как понять, что он зациклился?
а если цикл не просто for, а сложный каскад обработки сообщений?
Записан

Странно всё это....
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #52 : 27-04-2010 11:17 » 

запускаешь тест времени на Любой машине и запоминаешь
Потом запускаешь его на другой и получаешь время выполнения теста.
Рассчитываешь коэф. и применяешь его (коэф) ко всем тестам

Из опыта:
у нас рядом с каждым тестом есть некоторый файл настроек (пускай его читает WD, а точнее скрипты автосборки)
в файле максимальное время выполнения теста (+ целевая платформа или еще какие параметры)
если время в файле не задано, то тест выполняется минуту
для длительных тестов разработчик прописывает время с некоторым запасом (таких немного)
на этом настройка времени заканчивается
понятно, что большинство тестов выполняется гораздо быстрее, чем за минуту, так же понятно, что если тест завис, то он завис
и именно по этому, не надо заморачиваться попытками посчитать время выполнения теста

тесты производительности это отдельная песня
Записан

Странно всё это....
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #53 : 27-04-2010 11:33 » 

LogRus, конечно про настройки теста и идет речь. Какие дефолтные значения могут приниматься - зависит от разработчиков.

Тесты могут гоняться на разных по мощности машинах, соответственно, разное время выполнения.

Временной тест - это часть самодиагностики. будет она реализована в отдельном тесте или зашита в сам WD, не суть важно. Важно его наличие.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #54 : 27-04-2010 12:20 » 

Слав,
спасибо - теперь поняла! Именно это я и хотела сделать, но для простоты (ибо тестовых машин у нас 7 штук) сделать измерения на одной и волевым решением ввести коэффициент = 2, т.к. машины не могут настолько уж различаться в быстродействии.
 
LogRus,

Цитата
Какая цель теста? Найти проблему, если тест не выполнился за N секунд значит он провален, задача достигнута, разработчик получает письмо о проваленном тесте с логами теста в атаче и начинает разбираться.

Ты прав на все 100 - это я перемудрила. Скромно так... В принципе, если тест где-то завис, то это уже найденная проблема, а что конкретно не так - головная боль разработчика.  Отлично

Еще раз всем огромное спасибо за терпение и объяснения!
Записан

холоднокровней, Маня, Ви не на работе
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #55 : 27-04-2010 13:44 » 

LogRus, понял. Согласен.
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #56 : 28-04-2010 03:37 » 

Опыт Улыбаюсь
Записан

Странно всё это....
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #57 : 03-05-2010 11:58 » 

Небольшое дополнение к теме:
если нужен watchdog для использования его затем в NUnit-тесте, то тут возникают шероховатости:
в обычной жизни NUnit сам запускает тесты по очереди, что позволяет им находиться в основном треде и посылать сообщения об ошибках непосредственно самому NUnit-у, который, в свою очередь, имеет возможность реагировать в соответствии с обстановкой (т.е. в случае Assert-ов просто прекращать тест).
При использовании watchdog-а ситуация меняется: теперь watchdog оказывается в основном треде, а тесты - в дополнительном, который запускает наш watchdog.
При этом возникает проблема передачи сообщений от теста оболочке NUnit.
Для разруливания надо создать какой-нибудь свой класс, который будет в случае возникновения ошибок их либо накапливать, дабы по окончании теста выдать в лог (если речь идет о некритических ошибках), либо прерывать тест, а затем прописать всю инфу по ошибкам в наш лог.

Я сделала для себя пример, дабы убедиться в том, что идея правильная и будет работать. НУ а затем решила его для всех выложить (вдруг кому-то еще пригодится).
Если вы считаете, что это никому не надо - удаляйте.

* NunitTest.zip (11.62 Кб - загружено 106 раз.)
Записан

холоднокровней, Маня, Ви не на работе
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #58 : 03-05-2010 13:16 » 

Удалять ничего не надо имхо. 11 кило жрать не просят, а нормальных исходников не так много выкладывается
Записан
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #59 : 03-05-2010 14:36 » 

Забыла дописать (предупредитъ)!
Дело в том, что 1:1 это тоже исполъзовать не выйдет - все равно надо делать какие-то поправки с учетом конкретной реализации (у каждого свое построение теста, необходимые действия на старте и в конце, ну и т.д.), поэтому это, к сожалению,  не 100%-ный рецепт, который можно пустить в дело не глядя и не разбирая.
Записан

холоднокровней, Маня, Ви не на работе
Страниц: 1 [2]  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines