weltyc / ntest

NTest othello program
27 stars 12 forks source link

uninitialized variables #12

Closed vladpetric closed 10 years ago

vladpetric commented 10 years ago

I basically pulled all the changes from your repo, and after that ntest t was failing in optimized mode (though, interestingly, not in debug mode). So I used valgrind to track the uninitialized variables.

Note that although our repos are more or less in sync, github seems to want to make a pull request with the last one as well. I have a feeling that the last pull request was merged in differently. Anyway, not a big deal, but that's why a simple dozen lines change shows up as 10 commits in this pull request.

You may want different defaults for COsClock ...

BTW, if you'd like to use valgrind, which should work on OS X as well, do the following:

a) get rid of -O3 -flto in both places in the main CMakeLists.txt b) rebuild c) run as follows: valgrind --db-attach=yes ./ntest t

weltyc commented 10 years ago

In the Java version of NBoard I recently switched a number of the COsXxxx classes (including COsClock) to be immutable - this has killed quite a few bugs.

On Wed, Feb 12, 2014 at 7:29 PM, vladpetric notifications@github.comwrote:

I basically pulled all the changes from your repo, and after that ntest t was failing in optimized mode (though, interestingly, not in debug mode). So I used valgrind to track the uninitialized variables.

Note that although our repos are more or less in sync, github seems to want to make a pull request with the last one as well. I have a feeling that the last pull request was merged in differently. Anyway, not a big deal, but that's why a simple dozen lines change shows up as 10 commits in this pull request.

You may want different defaults for COsClock ...

BTW, if you'd like to use valgrind, which should work on OS X as well, do the following:

a) get rid of -O3 -flto in both places in the main CMakeLists.txt b) rebuild

c) run as follows: valgrind --db-attach=yes ./ntest t

You can merge this Pull Request by running

git pull https://github.com/vladpetric/ntest master

Or view, comment on, or merge it at:

https://github.com/weltyc/ntest/pull/12 Commit Summary

  • Massive change to:
  • Cleanups in the license and extractor code.
  • Implement the random play tester for flips, which compares the outcome
  • Function should return void, d'oh.
  • Get rid of c++11 requirement, by using C random()
  • Add randomEvalGen - a tool to generate random play configurations and "golden value" evaluator results.
  • Added golden value test.
  • Reorder the Evaluation statements a little bit so that the debugging messages are consistent.
  • Merge pull request #2 from weltyc/master
  • Fix some uninitialized variables.

File Changes

  • M src/CMakeLists.txthttps://github.com/weltyc/ntest/pull/12/files#diff-0(4)
  • M src/odk/OsObjects.cpphttps://github.com/weltyc/ntest/pull/12/files#diff-1(4)
  • M src/odk/OsObjects.hhttps://github.com/weltyc/ntest/pull/12/files#diff-2(7)

Patch Links:

Reply to this email directly or view it on GitHubhttps://github.com/weltyc/ntest/pull/12 .

vladpetric commented 10 years ago

We can probably achieve part of that via const-ification.

Java also does the sane "everything is initialized to zero". This issue would not have arisen with Java. It's really dumb, IMNSHO, that C++ didn't pick that up in its recent revisions.

Honestly, only the engine needs to be C++ IMO. I think something like Java for the frontend is a far better choice.

While we're at it:

Vlad

On Thursday, February 13, 2014, Chris Welty notifications@github.com wrote:

In the Java version of NBoard I recently switched a number of the COsXxxx classes (including COsClock) to be immutable - this has killed quite a few bugs.

On Wed, Feb 12, 2014 at 7:29 PM, vladpetric notifications@github.com<javascript:_e(%7B%7D,'cvml','notifications@github.com');

wrote:

I basically pulled all the changes from your repo, and after that ntest t was failing in optimized mode (though, interestingly, not in debug mode). So I used valgrind to track the uninitialized variables.

Note that although our repos are more or less in sync, github seems to want to make a pull request with the last one as well. I have a feeling that the last pull request was merged in differently. Anyway, not a big deal, but that's why a simple dozen lines change shows up as 10 commits in this pull request.

You may want different defaults for COsClock ...

BTW, if you'd like to use valgrind, which should work on OS X as well, do the following:

a) get rid of -O3 -flto in both places in the main CMakeLists.txt b) rebuild

c) run as follows: valgrind --db-attach=yes ./ntest t

You can merge this Pull Request by running

git pull https://github.com/vladpetric/ntest master

Or view, comment on, or merge it at:

https://github.com/weltyc/ntest/pull/12 Commit Summary

  • Massive change to:
  • Cleanups in the license and extractor code.
  • Implement the random play tester for flips, which compares the outcome
  • Function should return void, d'oh.
  • Get rid of c++11 requirement, by using C random()
  • Add randomEvalGen - a tool to generate random play configurations and "golden value" evaluator results.
  • Added golden value test.
  • Reorder the Evaluation statements a little bit so that the debugging messages are consistent.
  • Merge pull request #2 from weltyc/master
  • Fix some uninitialized variables.

File Changes

Patch Links:

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12> .

Reply to this email directly or view it on GitHubhttps://github.com/weltyc/ntest/pull/12#issuecomment-34990323 .

weltyc commented 10 years ago

initializing to 0 would slow things down :)

What would you do instead of throwing an exception? The program should probably not continue in most of these cases:

Evaluator.cpp: throw std::string("Can't open coefficient file for conversion: ")+fn; Evaluator.cpp: throw std::string("Can't open coefficient file ")+fn; Evaluator.cpp://! \throw string if error Evaluator.cpp: throw std::string("Can't open coefficient file ")+fn; Evaluator.cpp: throw std::string("error reading from coefficients file ")+fnBase; Evaluator.cpp: throw std::string("error reading from coefficients file")+fnBase; PlayerComputer.cpp: throw std::string("can't negamax and correct book if no book exists"); SmartBook.cpp: // the book constructor only throws an exception if the book is damaged. main.cpp: throw std::string("Can't read in parameters file ")+fn; core/Store.h: //! \throw IOException if unable to write to the file core/Store.h: //! \throw IOException if an error occurred when opening the file core/Store.h: //! \throw IOException if an error occurred when opening the file core/Book.cpp://! \throw an error message core/Book.cpp: throw std::string("WARNING: BOOK ")+m_store->ToString()+" is damaged, restore a backup.\n"; core/Book.cpp://! \throw std::string if the book is corrupt or is a version that we cant read core/Book.cpp: default:throw std::string("This program can only read book formats 1 and 2"); core/MPCStats.cpp: throw(0); core/Store.cpp: throw IOException("Unable to open file", path, errno); core/Store.cpp: throw IOException("File is not open", "", -1); core/Store.cpp: throw IOException("Error closing the file", "", result); core/Store.cpp: throw IOException(os.str(), m_permanentPath, err); core/Store.cpp: throw IOException(os.str(), m_permanentPath, errno); n64/test.cpp: throw text; odk/OsObjects.cpp: throw err.str();

On Thu, Feb 13, 2014 at 10:18 AM, vladpetric notifications@github.comwrote:

We can probably achieve part of that via const-ification.

Java also does the sane "everything is initialized to zero". This issue would not have arisen with Java. It's really dumb, IMNSHO, that C++ didn't pick that up in its recent revisions.

Honestly, only the engine needs to be C++ IMO. I think something like Java for the frontend is a far better choice.

While we're at it:

  • I want to improve the checks so that you get a meaningful error message if you fail one of our asserts. The C-style asserts work fine, of course.
  • Are the exceptions ever doing anything except stop the program? I wouldn't mind just getting rid of them in the main engine.

Vlad

On Thursday, February 13, 2014, Chris Welty notifications@github.com wrote:

In the Java version of NBoard I recently switched a number of the COsXxxx classes (including COsClock) to be immutable - this has killed quite a few bugs.

On Wed, Feb 12, 2014 at 7:29 PM, vladpetric <notifications@github.com javascript:_e(%7B%7D,'cvml','notifications@github.com');

wrote:

I basically pulled all the changes from your repo, and after that ntest t was failing in optimized mode (though, interestingly, not in debug mode). So I used valgrind to track the uninitialized variables.

Note that although our repos are more or less in sync, github seems to want to make a pull request with the last one as well. I have a feeling that the last pull request was merged in differently. Anyway, not a big deal, but that's why a simple dozen lines change shows up as 10 commits in this pull request.

You may want different defaults for COsClock ...

BTW, if you'd like to use valgrind, which should work on OS X as well, do the following:

a) get rid of -O3 -flto in both places in the main CMakeLists.txt b) rebuild

c) run as follows: valgrind --db-attach=yes ./ntest t

You can merge this Pull Request by running

git pull https://github.com/vladpetric/ntest master

Or view, comment on, or merge it at:

https://github.com/weltyc/ntest/pull/12 Commit Summary

  • Massive change to:
  • Cleanups in the license and extractor code.
  • Implement the random play tester for flips, which compares the outcome
  • Function should return void, d'oh.
  • Get rid of c++11 requirement, by using C random()
  • Add randomEvalGen - a tool to generate random play configurations

and "golden value" evaluator results.

  • Added golden value test.
  • Reorder the Evaluation statements a little bit so that the debugging messages are consistent.
  • Merge pull request #2 from weltyc/master
  • Fix some uninitialized variables.

File Changes

Patch Links:

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12> .

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12#issuecomment-34990323>

.

Reply to this email directly or view it on GitHubhttps://github.com/weltyc/ntest/pull/12#issuecomment-34994827 .

weltyc commented 10 years ago

Improving the error messages sounds great.

On Thu, Feb 13, 2014 at 12:52 PM, Chris Welty chris.welty.1@gmail.comwrote:

initializing to 0 would slow things down :)

What would you do instead of throwing an exception? The program should probably not continue in most of these cases:

Evaluator.cpp: throw std::string("Can't open coefficient file for conversion: ")+fn; Evaluator.cpp: throw std::string("Can't open coefficient file ")+fn; Evaluator.cpp://! \throw string if error Evaluator.cpp: throw std::string("Can't open coefficient file ")+fn; Evaluator.cpp: throw std::string("error reading from coefficients file ")+fnBase; Evaluator.cpp: throw std::string("error reading from coefficients file")+fnBase; PlayerComputer.cpp: throw std::string("can't negamax and correct book if no book exists"); SmartBook.cpp: // the book constructor only throws an exception if the book is damaged. main.cpp: throw std::string("Can't read in parameters file ")+fn; core/Store.h: //! \throw IOException if unable to write to the file core/Store.h: //! \throw IOException if an error occurred when opening the file core/Store.h: //! \throw IOException if an error occurred when opening the file core/Book.cpp://! \throw an error message core/Book.cpp: throw std::string("WARNING: BOOK ")+m_store->ToString()+" is damaged, restore a backup.\n"; core/Book.cpp://! \throw std::string if the book is corrupt or is a version that we cant read core/Book.cpp: default:throw std::string("This program can only read book formats 1 and 2"); core/MPCStats.cpp: throw(0); core/Store.cpp: throw IOException("Unable to open file", path, errno); core/Store.cpp: throw IOException("File is not open", "", -1); core/Store.cpp: throw IOException("Error closing the file", "", result); core/Store.cpp: throw IOException(os.str(), m_permanentPath, err); core/Store.cpp: throw IOException(os.str(), m_permanentPath, errno); n64/test.cpp: throw text; odk/OsObjects.cpp: throw err.str();

On Thu, Feb 13, 2014 at 10:18 AM, vladpetric notifications@github.comwrote:

We can probably achieve part of that via const-ification.

Java also does the sane "everything is initialized to zero". This issue would not have arisen with Java. It's really dumb, IMNSHO, that C++ didn't pick that up in its recent revisions.

Honestly, only the engine needs to be C++ IMO. I think something like Java for the frontend is a far better choice.

While we're at it:

  • I want to improve the checks so that you get a meaningful error message if you fail one of our asserts. The C-style asserts work fine, of course.
  • Are the exceptions ever doing anything except stop the program? I wouldn't mind just getting rid of them in the main engine.

Vlad

On Thursday, February 13, 2014, Chris Welty notifications@github.com wrote:

In the Java version of NBoard I recently switched a number of the COsXxxx classes (including COsClock) to be immutable - this has killed quite a few bugs.

On Wed, Feb 12, 2014 at 7:29 PM, vladpetric <notifications@github.com javascript:_e(%7B%7D,'cvml','notifications@github.com');

wrote:

I basically pulled all the changes from your repo, and after that ntest t was failing in optimized mode (though, interestingly, not in debug mode). So I used valgrind to track the uninitialized variables.

Note that although our repos are more or less in sync, github seems to want to make a pull request with the last one as well. I have a feeling that the last pull request was merged in differently. Anyway, not a big deal, but that's why a simple dozen lines change shows up as 10 commits in this pull request.

You may want different defaults for COsClock ...

BTW, if you'd like to use valgrind, which should work on OS X as well, do the following:

a) get rid of -O3 -flto in both places in the main CMakeLists.txt b) rebuild

c) run as follows: valgrind --db-attach=yes ./ntest t

You can merge this Pull Request by running

git pull https://github.com/vladpetric/ntest master

Or view, comment on, or merge it at:

https://github.com/weltyc/ntest/pull/12 Commit Summary

  • Massive change to:
  • Cleanups in the license and extractor code.
  • Implement the random play tester for flips, which compares the outcome
  • Function should return void, d'oh.
  • Get rid of c++11 requirement, by using C random()
  • Add randomEvalGen - a tool to generate random play configurations

and "golden value" evaluator results.

  • Added golden value test.
  • Reorder the Evaluation statements a little bit so that the debugging messages are consistent.
  • Merge pull request #2 from weltyc/master
  • Fix some uninitialized variables.

File Changes

Patch Links:

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12> .

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12#issuecomment-34990323>

.

Reply to this email directly or view it on GitHubhttps://github.com/weltyc/ntest/pull/12#issuecomment-34994827 .

vladpetric commented 10 years ago

I think it's probably simpler if we just print an error message, which also includes the file and line number, then exit. I'm not a big fan of C++ exceptions ... I think they're totally fine in Java/.NET/Python/others. It's possible that we may get a minor speedup by disallowing exceptions for the entire C++ engine, but I'm not sure about that.

In any case, this is relatively minor. Fine with keeping things this way too.

As to my semi-philosophical rant about 0s, that's a discussion that's probably better done if we have a drink at some point :).

Vlad

On Thursday, February 13, 2014, Chris Welty notifications@github.com wrote:

initializing to 0 would slow things down :)

What would you do instead of throwing an exception? The program should probably not continue in most of these cases:

Evaluator.cpp: throw std::string("Can't open coefficient file for conversion: ")+fn; Evaluator.cpp: throw std::string("Can't open coefficient file ")+fn; Evaluator.cpp://! \throw string if error Evaluator.cpp: throw std::string("Can't open coefficient file ")+fn; Evaluator.cpp: throw std::string("error reading from coefficients file ")+fnBase; Evaluator.cpp: throw std::string("error reading from coefficients file")+fnBase; PlayerComputer.cpp: throw std::string("can't negamax and correct book if no book exists"); SmartBook.cpp: // the book constructor only throws an exception if the book is damaged. main.cpp: throw std::string("Can't read in parameters file ")+fn; core/Store.h: //! \throw IOException if unable to write to the file core/Store.h: //! \throw IOException if an error occurred when opening the file core/Store.h: //! \throw IOException if an error occurred when opening the file core/Book.cpp://! \throw an error message core/Book.cpp: throw std::string("WARNING: BOOK ")+m_store->ToString()+" is damaged, restore a backup.\n"; core/Book.cpp://! \throw std::string if the book is corrupt or is a version that we cant read core/Book.cpp: default:throw std::string("This program can only read book formats 1 and 2"); core/MPCStats.cpp: throw(0); core/Store.cpp: throw IOException("Unable to open file", path, errno); core/Store.cpp: throw IOException("File is not open", "", -1); core/Store.cpp: throw IOException("Error closing the file", "", result); core/Store.cpp: throw IOException(os.str(), m_permanentPath, err); core/Store.cpp: throw IOException(os.str(), m_permanentPath, errno); n64/test.cpp: throw text; odk/OsObjects.cpp: throw err.str();

On Thu, Feb 13, 2014 at 10:18 AM, vladpetric notifications@github.com<javascript:_e(%7B%7D,'cvml','notifications@github.com');

wrote:

We can probably achieve part of that via const-ification.

Java also does the sane "everything is initialized to zero". This issue would not have arisen with Java. It's really dumb, IMNSHO, that C++ didn't pick that up in its recent revisions.

Honestly, only the engine needs to be C++ IMO. I think something like Java for the frontend is a far better choice.

While we're at it:

  • I want to improve the checks so that you get a meaningful error message if you fail one of our asserts. The C-style asserts work fine, of course.
  • Are the exceptions ever doing anything except stop the program? I wouldn't mind just getting rid of them in the main engine.

Vlad

On Thursday, February 13, 2014, Chris Welty notifications@github.com<javascript:_e(%7B%7D,'cvml','notifications@github.com');

wrote:

In the Java version of NBoard I recently switched a number of the COsXxxx classes (including COsClock) to be immutable - this has killed quite a few bugs.

On Wed, Feb 12, 2014 at 7:29 PM, vladpetric notifications@github.com<javascript:_e(%7B%7D,'cvml','notifications@github.com'); javascript:_e(%7B%7D,'cvml','notifications@github.com<javascript:_e(%7B%7D,'cvml','notifications@github.com'); ');>

wrote:

I basically pulled all the changes from your repo, and after that ntest t was failing in optimized mode (though, interestingly, not in debug mode). So I used valgrind to track the uninitialized variables.

Note that although our repos are more or less in sync, github seems to want to make a pull request with the last one as well. I have a feeling that the last pull request was merged in differently. Anyway, not a big deal, but that's why a simple dozen lines change shows up as 10 commits in this pull request.

You may want different defaults for COsClock ...

BTW, if you'd like to use valgrind, which should work on OS X as well, do the following:

a) get rid of -O3 -flto in both places in the main CMakeLists.txt b) rebuild

c) run as follows: valgrind --db-attach=yes ./ntest t

You can merge this Pull Request by running

git pull https://github.com/vladpetric/ntest master

Or view, comment on, or merge it at:

https://github.com/weltyc/ntest/pull/12 Commit Summary

  • Massive change to:
  • Cleanups in the license and extractor code.
  • Implement the random play tester for flips, which compares the outcome
  • Function should return void, d'oh.
  • Get rid of c++11 requirement, by using C random()
  • Add randomEvalGen - a tool to generate random play configurations

and "golden value" evaluator results.

  • Added golden value test.
  • Reorder the Evaluation statements a little bit so that the debugging messages are consistent.
  • Merge pull request #2 from weltyc/master
  • Fix some uninitialized variables.

File Changes

Patch Links:

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12> .

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12#issuecomment-34990323>

.

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12#issuecomment-34994827> .

Reply to this email directly or view it on GitHubhttps://github.com/weltyc/ntest/pull/12#issuecomment-35011917 .

weltyc commented 10 years ago

print & exit is fine - I just don't want the program to continue and add incorrect values to the book.

On Thu, Feb 13, 2014 at 1:08 PM, vladpetric notifications@github.comwrote:

I think it's probably simpler if we just print an error message, which also includes the file and line number, then exit. I'm not a big fan of C++ exceptions ... I think they're totally fine in Java/.NET/Python/others. It's possible that we may get a minor speedup by disallowing exceptions for the entire C++ engine, but I'm not sure about that.

In any case, this is relatively minor. Fine with keeping things this way too.

As to my semi-philosophical rant about 0s, that's a discussion that's probably better done if we have a drink at some point :).

Vlad

On Thursday, February 13, 2014, Chris Welty notifications@github.com wrote:

initializing to 0 would slow things down :)

What would you do instead of throwing an exception? The program should probably not continue in most of these cases:

Evaluator.cpp: throw std::string("Can't open coefficient file for conversion: ")+fn; Evaluator.cpp: throw std::string("Can't open coefficient file ")+fn; Evaluator.cpp://! \throw string if error Evaluator.cpp: throw std::string("Can't open coefficient file ")+fn; Evaluator.cpp: throw std::string("error reading from coefficients file ")+fnBase; Evaluator.cpp: throw std::string("error reading from coefficients file")+fnBase; PlayerComputer.cpp: throw std::string("can't negamax and correct book if no book exists"); SmartBook.cpp: // the book constructor only throws an exception if the book is damaged. main.cpp: throw std::string("Can't read in parameters file ")+fn; core/Store.h: //! \throw IOException if unable to write to the file core/Store.h: //! \throw IOException if an error occurred when opening the file core/Store.h: //! \throw IOException if an error occurred when opening the file core/Book.cpp://! \throw an error message core/Book.cpp: throw std::string("WARNING: BOOK ")+m_store->ToString()+" is damaged, restore a backup.\n"; core/Book.cpp://! \throw std::string if the book is corrupt or is a version that we cant read core/Book.cpp: default:throw std::string("This program can only read book formats 1 and 2"); core/MPCStats.cpp: throw(0); core/Store.cpp: throw IOException("Unable to open file", path, errno); core/Store.cpp: throw IOException("File is not open", "", -1); core/Store.cpp: throw IOException("Error closing the file", "", result); core/Store.cpp: throw IOException(os.str(), m_permanentPath, err); core/Store.cpp: throw IOException(os.str(), m_permanentPath, errno); n64/test.cpp: throw text; odk/OsObjects.cpp: throw err.str();

On Thu, Feb 13, 2014 at 10:18 AM, vladpetric <notifications@github.com javascript:_e(%7B%7D,'cvml','notifications@github.com');

wrote:

We can probably achieve part of that via const-ification.

Java also does the sane "everything is initialized to zero". This issue would not have arisen with Java. It's really dumb, IMNSHO, that C++ didn't pick that up in its recent revisions.

Honestly, only the engine needs to be C++ IMO. I think something like Java for the frontend is a far better choice.

While we're at it:

  • I want to improve the checks so that you get a meaningful error message if you fail one of our asserts. The C-style asserts work fine, of course.
  • Are the exceptions ever doing anything except stop the program? I wouldn't mind just getting rid of them in the main engine.

Vlad

On Thursday, February 13, 2014, Chris Welty <notifications@github.com javascript:_e(%7B%7D,'cvml','notifications@github.com');

wrote:

In the Java version of NBoard I recently switched a number of the COsXxxx classes (including COsClock) to be immutable - this has killed quite a few bugs.

On Wed, Feb 12, 2014 at 7:29 PM, vladpetric < notifications@github.com<javascript:_e(%7B%7D,'cvml',' notifications@github.com');> <javascript:_e(%7B%7D,'cvml','notifications@github.com javascript:_e(%7B%7D,'cvml','notifications@github.com'); ');>

wrote:

I basically pulled all the changes from your repo, and after that ntest t was failing in optimized mode (though, interestingly, not in debug mode). So I used valgrind to track the uninitialized variables.

Note that although our repos are more or less in sync, github seems to want to make a pull request with the last one as well. I have a feeling that the last pull request was merged in differently. Anyway, not a big deal, but that's why a simple dozen lines change shows up as 10 commits in this pull request.

You may want different defaults for COsClock ...

BTW, if you'd like to use valgrind, which should work on OS X as well, do the following:

a) get rid of -O3 -flto in both places in the main CMakeLists.txt b) rebuild

c) run as follows: valgrind --db-attach=yes ./ntest t

You can merge this Pull Request by running

git pull https://github.com/vladpetric/ntest master

Or view, comment on, or merge it at:

https://github.com/weltyc/ntest/pull/12 Commit Summary

  • Massive change to:
  • Cleanups in the license and extractor code.
  • Implement the random play tester for flips, which compares the outcome
  • Function should return void, d'oh.
  • Get rid of c++11 requirement, by using C random()
  • Add randomEvalGen - a tool to generate random play configurations

and "golden value" evaluator results.

  • Added golden value test.
  • Reorder the Evaluation statements a little bit so that the debugging messages are consistent.
  • Merge pull request #2 from weltyc/master
  • Fix some uninitialized variables.

File Changes

Patch Links:

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12> .

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12#issuecomment-34990323>

.

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12#issuecomment-34994827> .

Reply to this email directly or view it on GitHub< https://github.com/weltyc/ntest/pull/12#issuecomment-35011917>

.

Reply to this email directly or view it on GitHubhttps://github.com/weltyc/ntest/pull/12#issuecomment-35013633 .