<commit_before>#include "Course.h"

#include <iomanip>
#include <iostream>
#include <string>

using namespace std;

int main() {
  // main prompt
  bool isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
  Course course;

  string input;

  cout << "  _____            __        ___  __       \n";
  cout << " / ___/______ ____/ /__ ____/ _ \\/ /_ _____\n";
  cout << "/ (_ / __/ _ `/ _  / -_)___/ ___/ / // (_-<\n";
  cout << "\\___/_/  \\_,_/\\_,_/\\__/   /_/  /_/\\_,_/___/\n\n";
  // input loop
  while (true) {
    cout << "What would you like to do?\n";
    cout.width(6);
    cout << "\tWORK on an existing Course [W]\n\tCREATE a new Course [C]\n\tQUIT [Q]\n\t$: ";
    getline(cin, input);

    // open Course
    if (tolower(input[0]) == 'w') {
      cout << "Which Course: ";
      getline(cin, input);
      string name = input;
      cout << "Opening Course: " << name << "...\n";
      course.load(name);
      isOpen = true;
      break;
    }

    // create Course
    else if (tolower(input[0]) == 'c') {
      cout << "Please enter a unique name\n";
      cout << "Course Name: ";
      getline(cin, input);
      string name = input;
      cout << "Creating Course: " << name << endl;
      course.load(name);
      isOpen = true;
      break;
    }

    // quit
    else if (tolower(input[0]) == 'q') {
      cout << "Goodbye\n";
      break;
    }

    // invalid
    else {
      cout << "Invalid entry: " << input << endl;
    }
  } // opening loop

  // second loop while the course is open
  while (isOpen) {
    // cout << "LIST ALL THE COURSE DETAILS:\n";
    cout << "Course Name: \t" << course.getName() << "\n";
    cout << "\tSELECT students [S]\n\tSELECT assignments "
            "[A]\n\tSELECT categories [C]\n\tSELECT submissions [U]\n\tQUIT "
            "[Q]\n\t$: ";
    getline(cin, input);
    // students handler
    if (tolower(input[0]) == 's' || tolower(input[0]) == 'S') {
      course.printStudents();
      cout << "\tADD student [A]\n\tREMOVE student [R]\n\tQUIT [Q]\n\t$: ";
      getline(cin, input);
      // add student
      if (tolower(input[0]) == 'a') {
        cout << "Student ID?: ";
        getline(cin, input);
        string id = input;
        cout << "Student first name?: ";
        getline(cin, input);
        string firstName = input;
        cout << "Student last name?: ";
        getline(cin, input);
        string lastName = input;
        cout << "Student name: " << firstName << " " << lastName
             << " Student ID: " << id << endl;
        course.addStudent(id, firstName, lastName);
      }
      // modify student
      else if (tolower(input[0]) == 'a') {
        cout << "Student ID: ";
        getline(cin, input);
        string id = input;
        cout << "Student first name (or press enter to keep current one): ";
        getline(cin, input);
        string firstName = input;
        cout << "Student last name (or press enter to keep current one): ";
        getline(cin, input);
        string lastName = input;
        cout << "Student name: " << firstName << " " << lastName
             << " Student ID: " << id << endl;
        course.updateStudent(id, firstName, lastName);
      }
      // drop student
      else if (tolower(input[0]) == 'r') {
        cout << "Remove student with ID: ";
        getline(cin, input);
        string id = input;

        // call drop student function on that student
        course.deleteStudent(id);
      }
      // quit
      else if (tolower(input[0]) == 'q') {
        cout << "Goodbye\n";
        isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
      }
    }
    // ASSIGNMENTS HANDLER
    else if (tolower(input[0]) == 'a') {
      cout << "Here's a current list of all the assignments in "
           << course.getName() << ":\n";
      cout << "\t";
      course.printAssignments();
      cout << endl;
      cout.width(6);
      cout << "\tADD assignment [A]\n\tREMOVE assignment [R]\n\tMODIFY "
              "assignment [M]\n\tQUIT [Q]\n\t$: ";
      getline(cin, input);
      // add assignment
      if (tolower(input[0]) == 'a') {
        cout << "Adding a new assignment:\n";
        cout << "Assignment name: ";
        getline(cin, input);
        string name = input;
        course.printCategories();
        cout << "Category ID: ";
        getline(cin, input);
        int category = stoi(input);
        cout << "Points possible: ";
        getline(cin, input);
        int weight = stoi(input);
        course.addAssignment(category, name, weight);
      }
      // modify assignment
      else if (tolower(input[0]) == 'm') {
        cout << "Modify assignment with ID: ";
        getline(cin, input);
        int id = stoi(input);
        cout << "Assignment name (or press enter to keep current one): ";
        getline(cin, input);
        string name = input;
        course.printCategories();
        cout << "Category ID (or press enter to keep current one): ";
        getline(cin, input);
        int category = atoi(input.c_str());
        cout << "Points possible (or press enter to keep current one): ";
        getline(cin, input);
        int weight = atoi(input.c_str());
        course.updateAssignment(id, category, name, weight);
      }
      // remove assignment
      else if (tolower(input[0]) == 'r') {
        cout << "Remove assignment with ID: ";
        getline(cin, input);
        int id = stoi(input);
        // cout << "Calling course.deleteAssignment(" << id << ")\n";
        course.deleteAssignment(id);
      }
      // quit
      else if (tolower(input[0]) == 'q') {
        cout << "Goodbye\n";
        isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
      }
      // invalid
      else {
        cout << "Invalid entry: " << input << endl;
      }
    }

    // CATEGORIES HANDLER
    else if (tolower(input[0]) == 'c') {
      course.printCategories();
      cout.width(6);
      cout << "\tADD category [A]\n\tREMOVE category [R]\n\tMODIFY category "
              "[M]\n\tQUIT [Q]\n\t$: ";
      getline(cin, input);
      // add category
      if (tolower(input[0]) == 'a') {
        cout << "Adding a new category:\n";
        cout << "Category name: ";
        getline(cin, input);
        string name = input;
        cout << "Weight: ";
        getline(cin, input);
        int weight = stoi(input);
        course.addCategory(name, weight);
      }
      // modify category
      else if (tolower(input[0]) == 'm') {
        cout << "Modify category with ID: ";
        getline(cin, input);
        int id = stoi(input);
        cout << "Category name (or press enter to keep current one): ";
        getline(cin, input);
        string name = input;
        cout << "Weight (or press enter to keep current one): ";
        getline(cin, input);
        int weight = atoi(input.c_str());
        course.updateCategory(id, name, weight);
      }
      // remove category
      else if (tolower(input[0]) == 'r') {
        cout << "Remove category with ID: ";
        getline(cin, input);
        int id = stoi(input);
        course.deleteCategory(id);
      }
      // quit
      else if (tolower(input[0]) == 'q') {
        cout << "Goodbye\n";
        isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
      }
      // invalid
      else {
        cout << "Invalid entry: " << input << endl;
      }
    }

    // SUBMITTED HANDLER
    else if (tolower(input[0]) == 'u') {
      course.printSubmitted();
      cout.width(6);
      do {
        cout << "\tFILTER by student [S]\n\tFILTER by assignment [T]\n\tADD "
                "submission [A]\n\tREMOVE submission [R]\n\tMODIFY submission "
                "[M]\n\tGRADE submission [G]\n\tQUIT [Q]\n\t$: ";
        getline(cin, input);
        // filter by student
        if (tolower(input[0]) == 's') {
          cout << "Student ID: ";
          getline(cin, input);
          string studentId = input;
          course.printSubmittedOfStudent(studentId);
        }
        // filter by assignment
        else if (tolower(input[0]) == 't') {
          cout << "Assignment ID: ";
          getline(cin, input);
          int assignmentId = stoi(input);
          course.printSubmittedOfAssignment(assignmentId);
        }
      } while (tolower(input[0]) == 's' || tolower(input[0]) == 't');
      // add submitted
      if (tolower(input[0]) == 'a') {
        cout << "Adding a new submission:\n";
        cout << "Assignment ID: ";
        getline(cin, input);
        int assignmentId = stoi(input); // stoi not working with addSubmitted
        cout << "Student ID: ";
        getline(cin, input);
        string studentId = input;
        course.addSubmitted(assignmentId, studentId, NULL);
      }
      // modify submitted
      else if (tolower(input[0]) == 'm') {
        cout << "Modify submission with ID: ";
        getline(cin, input);
        int id = stoi(input);
        cout << "Assignment ID (or press enter to keep current one): ";
        getline(cin, input);
        int assignmentId = stoi(input);
        cout << "Student ID (or press enter to keep current one): ";
        getline(cin, input);
        string studentId = input;
        course.updateSubmitted(id, assignmentId, studentId, NULL);
      }
      // remove submitted
      else if (tolower(input[0]) == 'r') {
        cout << "Remove submission with ID: ";
        getline(cin, input);
        int id = stoi(input);
        course.deleteSubmitted(id);
      }
      // grade submitted
      else if (tolower(input[0]) == 'g') {
        cout << "Grade submission with ID: ";
        getline(cin, input);
        int id = stoi(input);
        cout << "Points earned: ";
        getline(cin, input);
        double pointsEarned = stod(input);
        course.updateSubmitted(id, -1, "", pointsEarned);
      }
      // quit
      else if (tolower(input[0]) == 'q') {
        cout << "Goodbye\n";
        isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
      }
      // invalid
      else {
        cout << "Invalid entry: " << input << endl;
      }
    }

    // quit
    else if (tolower(input[0]) == 'q') {
      cout << "Goodbye\n";
      isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
    }

    // else invalid
    else {
      cout << "Invalid entry: " << input << endl;
    }
  } // while course is open
}
<commit_msg>Improve navigation by adding option to go up a level<commit_after>#include "Course.h"

#include <iomanip>
#include <iostream>
#include <string>

using namespace std;

int main() {
  // main prompt
  bool isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
  Course course;

  string input;

  cout << "  _____            __        ___  __       \n";
  cout << " / ___/______ ____/ /__ ____/ _ \\/ /_ _____\n";
  cout << "/ (_ / __/ _ `/ _  / -_)___/ ___/ / // (_-<\n";
  cout << "\\___/_/  \\_,_/\\_,_/\\__/   /_/  /_/\\_,_/___/\n\n";
  // input loop
  while (true) {
    cout << "What would you like to do?\n";
    cout << "\tWORK on an existing Course [W]\n\tCREATE a new Course [C]\n\tQUIT [Q]\n\t$: ";
    getline(cin, input);

    // open Course
    if (tolower(input[0]) == 'w') {
      cout << "Which Course: ";
      getline(cin, input);
      string name = input;
      cout << "Opening Course: " << name << "...\n";
      course.load(name);
      isOpen = true;
      break;
    }

    // create Course
    else if (tolower(input[0]) == 'c') {
      cout << "Please enter a unique name\n";
      cout << "Course Name: ";
      getline(cin, input);
      string name = input;
      cout << "Creating Course: " << name << endl;
      course.load(name);
      isOpen = true;
      break;
    }

    // quit
    else if (tolower(input[0]) == 'q') {
      cout << "Goodbye\n";
      break;
    }

    // invalid
    else {
      cout << "Invalid entry: " << input << endl;
    }
  } // opening loop

  // second loop while the course is open
  while (isOpen) {
    cout << "\nCourse Name: " << course.getName() << "\n";
    cout << "\tSELECT students [S]\n\tSELECT assignments "
            "[A]\n\tSELECT categories [C]\n\tSELECT submissions [B]\n\tQUIT "
            "[Q]\n\t$: ";
    getline(cin, input);
    // students handler
    if (tolower(input[0]) == 's' || tolower(input[0]) == 'S') {
      while (true) {
        course.printStudents();
        cout << "\tADD student [A]\n\tREMOVE student [R]\n\tUP [U]\n\tQUIT [Q]\n\t$: ";
        getline(cin, input);
        // add student
        if (tolower(input[0]) == 'a') {
          cout << "Student ID?: ";
          getline(cin, input);
          string id = input;
          cout << "Student first name?: ";
          getline(cin, input);
          string firstName = input;
          cout << "Student last name?: ";
          getline(cin, input);
          string lastName = input;
          cout << "Student name: " << firstName << " " << lastName
          << " Student ID: " << id << endl;
          course.addStudent(id, firstName, lastName);
        }
        // modify student
        else if (tolower(input[0]) == 'a') {
          cout << "Student ID: ";
          getline(cin, input);
          string id = input;
          cout << "Student first name (or press enter to keep current one): ";
          getline(cin, input);
          string firstName = input;
          cout << "Student last name (or press enter to keep current one): ";
          getline(cin, input);
          string lastName = input;
          cout << "Student name: " << firstName << " " << lastName
          << " Student ID: " << id << endl;
          course.updateStudent(id, firstName, lastName);
        }
        // drop student
        else if (tolower(input[0]) == 'r') {
          cout << "Remove student with ID: ";
          getline(cin, input);
          string id = input;

          // call drop student function on that student
          course.deleteStudent(id);
        }
        // up
        else if (tolower(input[0]) == 'u') {
          break;
        }
        // quit
        else if (tolower(input[0]) == 'q') {
          cout << "Goodbye\n";
          isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
          break;
        }
      }
    }
    // ASSIGNMENTS HANDLER
    else if (tolower(input[0]) == 'a') {
      while (true) {
        course.printAssignments();
        cout << "\tADD assignment [A]\n\tREMOVE assignment [R]\n\tMODIFY "
        "assignment [M]\n\tUP [U]\n\tQUIT [Q]\n\t$: ";
        getline(cin, input);
        // add assignment
        if (tolower(input[0]) == 'a') {
          cout << "Adding a new assignment:\n";
          cout << "Assignment name: ";
          getline(cin, input);
          string name = input;
          course.printCategories();
          cout << "Category ID: ";
          getline(cin, input);
          int category = stoi(input);
          cout << "Points possible: ";
          getline(cin, input);
          int weight = stoi(input);
          course.addAssignment(category, name, weight);
        }
        // modify assignment
        else if (tolower(input[0]) == 'm') {
          cout << "Modify assignment with ID: ";
          getline(cin, input);
          int id = stoi(input);
          cout << "Assignment name (or press enter to keep current one): ";
          getline(cin, input);
          string name = input;
          course.printCategories();
          cout << "Category ID (or press enter to keep current one): ";
          getline(cin, input);
          int category = atoi(input.c_str());
          cout << "Points possible (or press enter to keep current one): ";
          getline(cin, input);
          int weight = atoi(input.c_str());
          course.updateAssignment(id, category, name, weight);
        }
        // remove assignment
        else if (tolower(input[0]) == 'r') {
          cout << "Remove assignment with ID: ";
          getline(cin, input);
          int id = stoi(input);
          // cout << "Calling course.deleteAssignment(" << id << ")\n";
          course.deleteAssignment(id);
        }
        // up
        else if (tolower(input[0]) == 'u') {
          break;
        }
        // quit
        else if (tolower(input[0]) == 'q') {
          cout << "Goodbye\n";
          isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
          break;
        }
        // invalid
        else {
          cout << "Invalid entry: " << input << endl;
        }
      }
    }

    // CATEGORIES HANDLER
    else if (tolower(input[0]) == 'c') {
      while (true) {
        course.printCategories();
        cout << "\tADD category [A]\n\tREMOVE category [R]\n\tMODIFY category "
        "[M]\n\tUP [U]\n\tQUIT [Q]\n\t$: ";
        getline(cin, input);
        // add category
        if (tolower(input[0]) == 'a') {
          cout << "Adding a new category:\n";
          cout << "Category name: ";
          getline(cin, input);
          string name = input;
          cout << "Weight: ";
          getline(cin, input);
          int weight = stoi(input);
          course.addCategory(name, weight);
        }
        // modify category
        else if (tolower(input[0]) == 'm') {
          cout << "Modify category with ID: ";
          getline(cin, input);
          int id = stoi(input);
          cout << "Category name (or press enter to keep current one): ";
          getline(cin, input);
          string name = input;
          cout << "Weight (or press enter to keep current one): ";
          getline(cin, input);
          int weight = atoi(input.c_str());
          course.updateCategory(id, name, weight);
        }
        // remove category
        else if (tolower(input[0]) == 'r') {
          cout << "Remove category with ID: ";
          getline(cin, input);
          int id = stoi(input);
          course.deleteCategory(id);
        }
        // up
        else if (tolower(input[0]) == 'u') {
          break;
        }
        // quit
        else if (tolower(input[0]) == 'q') {
          cout << "Goodbye\n";
          isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
          break;
        }
        // invalid
        else {
          cout << "Invalid entry: " << input << endl;
        }
      }
    }

    // SUBMITTED HANDLER
    else if (tolower(input[0]) == 'b') {
      while (true) {
        course.printSubmitted();
        do {
          cout << "\tSELECT student [S]\n\tSELECT assignment [T]\n\tADD "
          "submission [A]\n\tREMOVE submission [R]\n\tMODIFY submission "
          "[M]\n\tGRADE submission [G]\n\tUP [U]\n\tQUIT [Q]\n\t$: ";
          getline(cin, input);
          // filter by student
          if (tolower(input[0]) == 's') {
            cout << "Student ID: ";
            getline(cin, input);
            string studentId = input;
            course.printSubmittedOfStudent(studentId);
          }
          // filter by assignment
          else if (tolower(input[0]) == 't') {
            cout << "Assignment ID: ";
            getline(cin, input);
            int assignmentId = stoi(input);
            course.printSubmittedOfAssignment(assignmentId);
          }
        } while (tolower(input[0]) == 's' || tolower(input[0]) == 't');
        // add submitted
        if (tolower(input[0]) == 'a') {
          cout << "Adding a new submission:\n";
          cout << "Assignment ID: ";
          getline(cin, input);
          int assignmentId = stoi(input); // stoi not working with addSubmitted
          cout << "Student ID: ";
          getline(cin, input);
          string studentId = input;
          course.addSubmitted(assignmentId, studentId, NULL);
        }
        // modify submitted
        else if (tolower(input[0]) == 'm') {
          cout << "Modify submission with ID: ";
          getline(cin, input);
          int id = stoi(input);
          cout << "Assignment ID (or press enter to keep current one): ";
          getline(cin, input);
          int assignmentId = stoi(input);
          cout << "Student ID (or press enter to keep current one): ";
          getline(cin, input);
          string studentId = input;
          course.updateSubmitted(id, assignmentId, studentId, NULL);
        }
        // remove submitted
        else if (tolower(input[0]) == 'r') {
          cout << "Remove submission with ID: ";
          getline(cin, input);
          int id = stoi(input);
          course.deleteSubmitted(id);
        }
        // grade submitted
        else if (tolower(input[0]) == 'g') {
          cout << "Grade submission with ID: ";
          getline(cin, input);
          int id = stoi(input);
          cout << "Points earned: ";
          getline(cin, input);
          double pointsEarned = stod(input);
          course.updateSubmitted(id, -1, "", pointsEarned);
        }
        // up
        else if (tolower(input[0]) == 'u') {
          break;
        }
        // quit
        else if (tolower(input[0]) == 'q') {
          cout << "Goodbye\n";
          isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
          break;
        }
        // invalid
        else {
          cout << "Invalid entry: " << input << endl;
        }
      }
    }

    // quit
    else if (tolower(input[0]) == 'q') {
      cout << "Goodbye\n";
      isOpen = false; // MUST REPLACE WITH MEMBER FUNCTION FOR COURSE
    }

    // else invalid
    else {
      cout << "Invalid entry: " << input << endl;
    }
  } // while course is open
}
<|endoftext|>


<commit_before>//
//  testIO.cpp
//  TestNeuralNet
//
//  Created by Barrett Davis on 5/31/16.
//  Copyright © 2016 Tree Frog Software. All rights reserved.
//
#include "DnnBuilder.h"
#include "DnnTrainerAdaDelta.h"
#include "DnnStream.h"
#include "Error.h"
#include "testIO.hpp"

namespace tfs {

    static bool
    setupDnn( Dnn &dnn ) {                                      // Same DNN for all 2d tests.
        DnnBuilder builder( dnn, ACTIVATION_TANH );
        if( !builder.addLayerInput( 1, 1, 2 )) {                // Input layer a single x, y data point.
            return log_error( "Cannot add Input layer" );
        }
        if( !builder.addLayerFullyConnected( 8 )) {             // 8 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerFullyConnected( 6 )) {             // 6 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerFullyConnected( 2 )) {             // 2 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerSoftmax( 2 )) {                    // Output classifier, 2 classes.
            return log_error( "Cannot add Softmax layer" );
        }
        dnn.initialize();                                       // Randomize the weights.
        const unsigned long expected_count = 9;
        const unsigned long count = dnn.count();
        if( count != expected_count ) {
            return log_error( "We have set up %lu layers, expected %lu", count, expected_count );
        }
        return true;
    }

    static void
    setData( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, DNN_NUMERIC xx, DNN_NUMERIC yy, DNN_INTEGER value ) {
        data.push_back( xx );       // x,y pair
        data.push_back( yy );
        label.push_back( value );   // label
        return;
    }

    static void
    setUpDataSpiral( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, const DNN_NUMERIC count ) {
        DNN_NUMERIC val = 0.0;
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC rr = val / count * 5.0 + random( -0.1, 0.1 );
            const DNN_NUMERIC tt = 1.25 * val / count * 2.0 * M_PI + random( -0.1, 0.1 );
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 0 );
            val += 1.0;
        }
        val = 0.0;
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC rr = val / count * 5.0 + random( -0.1, 0.1 );
            const DNN_NUMERIC tt = 1.25 * val / count * 2.0 * M_PI + random( -0.1, 0.1 ) + M_PI;
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 1 );
            val += 1.0;
        }
        return;
    }

    static bool
    localTest2d( Dnn &dnn, std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label ) {
        DnnTrainerAdaDelta trainer( &dnn );
        trainer.learningRate( 0.01  );
        trainer.momentum(     0.1   );
        trainer.batchSize(   10     );
        trainer.l2Decay(      0.001 );

        Matrix *input = trainer.getMatrixInput();       // get the input matrix: x,y pair Matrix( 1, 1, 2 )
        if( input == 0 ) {
            return log_error( "Unable to obtain input matrix." );
        }
        const DNN_NUMERIC *dPtr = data.data();
        if( dPtr == 0 ) {
            return log_error( "Unable to obtain input data." );
        }
        const DNN_INTEGER *lPtr = label.data();
        if( lPtr == 0 ) {
            return log_error( "Unable to obtain input labels." );
        }
        const unsigned long DATA_COUNT = label.size();
        if( DATA_COUNT < 1 ) {
            return log_error( "Label data size < 1" );
        }
        const DNN_INTEGER *ePtr = lPtr + DATA_COUNT;

        const unsigned int MAX_ITERATION = 200;
        const DNN_NUMERIC   TARGET_LOSS  = 0.05;
        unsigned long count = 0;
        DNN_NUMERIC average_loss = 0.0;
        do {
            count++;
            average_loss = 0.0;
            for( unsigned int ii = 0; ii < MAX_ITERATION; ii++ ) {
                dPtr = data.data();
                lPtr = label.data();

                while( lPtr < ePtr ) {
                    DNN_NUMERIC *inPtr = input->data();
                    *inPtr++ = *dPtr++;     // x
                    *inPtr   = *dPtr++;     // y
                    average_loss += trainer.train( *lPtr++ );
                }
            }
            average_loss /= DATA_COUNT * MAX_ITERATION;
        } while( average_loss > TARGET_LOSS );
        log_info( "Average loss = %f/%f. Count = %lu", average_loss, TARGET_LOSS, count );

        return true;
    }

    static bool
    localTestIO( void ) {
        log_info( "Test I/O - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }

        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

        setUpDataSpiral( data, label, 100.0 );

        localTest2d( dnn, data, label );

        OutDnnStream outStream( "dnn_test.dnn" );
        if( !outStream.writeDnn( dnn )) {
            log_error( "DNN write failed" );
        }
        outStream.close();

        InDnnStream inStream( "dnn_test.dnn" );
        Dnn *otherDnn = inStream.readDnn();
        inStream.close();
        if( otherDnn == 0 ) {
            log_error( "Unable to read a DNN" );
        }

        delete otherDnn;
        log_info( "Test I/O - End" );
        return true;
    }

}  // tfs namespace

bool
testIO( void ) {
    return tfs::localTestIO();
}
<commit_msg>Testing DNN stream, looks good so far.<commit_after>//
//  testIO.cpp
//  TestNeuralNet
//
//  Created by Barrett Davis on 5/31/16.
//  Copyright © 2016 Tree Frog Software. All rights reserved.
//
#include "DnnBuilder.h"
#include "DnnTrainerAdaDelta.h"
#include "DnnStream.h"
#include "Error.h"
#include "testIO.hpp"

namespace tfs {

    static bool
    setupDnn( Dnn &dnn ) {                                      // Same DNN for all 2d tests.
        DnnBuilder builder( dnn, ACTIVATION_TANH );
        if( !builder.addLayerInput( 1, 1, 2 )) {                // Input layer a single x, y data point.
            return log_error( "Cannot add Input layer" );
        }
        if( !builder.addLayerFullyConnected( 8 )) {             // 8 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerFullyConnected( 6 )) {             // 6 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerFullyConnected( 2 )) {             // 2 Neurons
            return log_error( "Cannot add Fully Connected layer" );
        }
        if( !builder.addLayerSoftmax( 2 )) {                    // Output classifier, 2 classes.
            return log_error( "Cannot add Softmax layer" );
        }
        dnn.initialize();                                       // Randomize the weights.
        const unsigned long expected_count = 9;
        const unsigned long count = dnn.count();
        if( count != expected_count ) {
            return log_error( "We have set up %lu layers, expected %lu", count, expected_count );
        }
        return true;
    }

    static void
    setData( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, DNN_NUMERIC xx, DNN_NUMERIC yy, DNN_INTEGER value ) {
        data.push_back( xx );       // x,y pair
        data.push_back( yy );
        label.push_back( value );   // label
        return;
    }

    static void
    setUpDataSpiral( std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label, const DNN_NUMERIC count ) {
        DNN_NUMERIC val = 0.0;
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC rr = val / count * 5.0 + random( -0.1, 0.1 );
            const DNN_NUMERIC tt = 1.25 * val / count * 2.0 * M_PI + random( -0.1, 0.1 );
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 0 );
            val += 1.0;
        }
        val = 0.0;
        for( int ii = 0; ii < count; ii++ ) {
            const DNN_NUMERIC rr = val / count * 5.0 + random( -0.1, 0.1 );
            const DNN_NUMERIC tt = 1.25 * val / count * 2.0 * M_PI + random( -0.1, 0.1 ) + M_PI;
            const DNN_NUMERIC xx = rr * sin( tt );
            const DNN_NUMERIC yy = rr * cos( tt );
            setData( data, label, xx, yy, 1 );
            val += 1.0;
        }
        return;
    }

    DNN_NUMERIC
    localTest2d( Dnn &dnn, std::vector< DNN_NUMERIC > &data, std::vector< DNN_INTEGER > &label ) {
        DnnTrainerAdaDelta trainer( &dnn );
        trainer.learningRate( 0.01  );
        trainer.momentum(     0.1   );
        trainer.batchSize(   10     );
        trainer.l2Decay(      0.001 );

        Matrix *input = trainer.getMatrixInput();       // get the input matrix: x,y pair Matrix( 1, 1, 2 )
        if( input == 0 ) {
            log_error( "Unable to obtain input matrix." );
            return 0.0;
        }
        const DNN_NUMERIC *dPtr = data.data();
        if( dPtr == 0 ) {
            log_error( "Unable to obtain input data." );
            return 0.0;
        }
        const DNN_INTEGER *lPtr = label.data();
        if( lPtr == 0 ) {
            log_error( "Unable to obtain input labels." );
            return 0.0;
        }
        const unsigned long DATA_COUNT = label.size();
        if( DATA_COUNT < 1 ) {
            log_error( "Label data size < 1" );
            return 0.0;
        }
        const DNN_INTEGER *ePtr = lPtr + DATA_COUNT;

        const unsigned int MAX_ITERATION = 200;
        const DNN_NUMERIC   TARGET_LOSS  = 0.05;
        unsigned long count = 0;
        DNN_NUMERIC average_loss = 0.0;
        do {
            count++;
            average_loss = 0.0;
            for( unsigned int ii = 0; ii < MAX_ITERATION; ii++ ) {
                dPtr = data.data();
                lPtr = label.data();

                while( lPtr < ePtr ) {
                    DNN_NUMERIC *inPtr = input->data();
                    *inPtr++ = *dPtr++;     // x
                    *inPtr   = *dPtr++;     // y
                    average_loss += trainer.train( *lPtr++ );
                }
            }
            average_loss /= DATA_COUNT * MAX_ITERATION;
        } while( average_loss > TARGET_LOSS );
//        log_info( "Average loss = %f/%f. Count = %lu", average_loss, TARGET_LOSS, count );
        return average_loss;
    }

    static bool
    localTestIO( void ) {
        log_info( "Test I/O - Start" );
        Dnn dnn;
        if( !setupDnn( dnn )) {
            return false;
        }

        std::vector< DNN_NUMERIC > data;    // x,y pairs
        std::vector< DNN_INTEGER > label;   // binary labels.

        setUpDataSpiral( data, label, 100.0 );

        localTest2d( dnn, data, label );

        OutDnnStream outStream( "dnn_test.dnn" );
        if( !outStream.writeDnn( dnn )) {
            log_error( "DNN write failed" );
        }
        outStream.close();

        InDnnStream inStream( "dnn_test.dnn" );
        Dnn *otherDnn = inStream.readDnn( true );
        inStream.close();
        if( otherDnn == 0 ) {
            log_error( "Unable to read a DNN" );
        }
        DNN_NUMERIC orginal_loss = localTest2d(       dnn, data, label );
        DNN_NUMERIC other_loss   = localTest2d( *otherDnn, data, label );
        delete otherDnn;

        if( orginal_loss != other_loss ) {
            log_error( "Training loss for new dnn does not match orginial: %f/%f", other_loss, orginal_loss );
        }
        log_info( "Test I/O - End" );
        return true;
    }

}  // tfs namespace

bool
testIO( void ) {
    return tfs::localTestIO();
}
<|endoftext|>


<commit_before>#include <pybind11/eigen.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include <pybind11/stl.h>
#include <iostream>

#include <bindings.hpp>
#include <string>
#include <toppra/algorithm.hpp>
#include <toppra/constraint.hpp>
#include <toppra/constraint/joint_torque.hpp>
#include <toppra/constraint/linear_joint_acceleration.hpp>
#include <toppra/constraint/linear_joint_velocity.hpp>
#include <toppra/geometric_path.hpp>
#include <toppra/toppra.hpp>

namespace py = pybind11;

#ifdef BUILD_WITH_PINOCCHIO
// Mind that pinocchio headers **must** be included before boost headers.
#include <toppra/constraint/joint_torque/pinocchio.hpp>
#include <boost/python.hpp>

toppra::constraint::jointTorque::Pinocchio<> createJointTorque(py::object model,
    const toppra::Vector& fc)
{
  return toppra::constraint::jointTorque::Pinocchio<>(
      boost::python::extract<const pinocchio::Model&>(model.ptr()), fc);
}
#endif

namespace toppra {
namespace python {

PYBIND11_MODULE(toppra_int, m) {
  m.doc() = "toppra C++ bindings (internal)";
  py::enum_<toppra::DiscretizationType>(m, "DiscretizationType")
      .value("Collocation", toppra::DiscretizationType::Collocation)
      .value("Interpolation", toppra::DiscretizationType::Interpolation)
      .export_values();

  py::class_<PyPiecewisePolyPath>(m, "PiecewisePolyPath")
      .def(py::init<>())
      .def(py::init<const toppra::Matrices&, std::vector<toppra::value_type>>())
      .def("eval_single", &PyPiecewisePolyPath::eval_single)
      .def("eval", &PyPiecewisePolyPath::eval, py::arg("xs"), py::arg("order") = 0)
      .def("evald", &PyPiecewisePolyPath::evald, py::arg("xs"))
      .def("evaldd", &PyPiecewisePolyPath::evaldd, py::arg("xs"))
      .def("serialize", &PyPiecewisePolyPath::serialize)
      .def("deserialize", &PyPiecewisePolyPath::deserialize)
      .def("__call__", &PyPiecewisePolyPath::eval, py::arg("xs"), py::arg("order") = 0)
      .def("__call__", &PyPiecewisePolyPath::eval_single, py::arg("x"), py::arg("order") = 0)
      .def("__str__", &PyPiecewisePolyPath::__str__)
      .def("__repr__", &PyPiecewisePolyPath::__repr__)
      .def_property_readonly("dof", &PyPiecewisePolyPath::dof)
      .def_property_readonly("path_interval", &PyPiecewisePolyPath::pathInterval)
      .def_property_readonly("duration", &PyPiecewisePolyPath::duration)
      .def_static("constructHermite", &PyPiecewisePolyPath::constructHermite);

  // Abstract class must be binded for derived classes to work
  py::class_<LinearConstraint, LinearConstraintPtr>(m, "_LinearConstraint")
      .def_property_readonly("nbConstraints", &LinearConstraint::nbConstraints)
      .def_property_readonly("nbVariables", &LinearConstraint::nbVariables)
      .def_property_readonly("hasLinearInequalities",
                             &LinearConstraint::hasLinearInequalities)
      .def_property_readonly("hasUbounds", &LinearConstraint::hasUbounds)
      .def_property_readonly("hasXbounds", &LinearConstraint::hasXbounds)
      .def_property("discretizationType",
                    (DiscretizationType(LinearConstraint::*)() const) &
                        LinearConstraint::discretizationType,
                    (void (LinearConstraint::*)(DiscretizationType)) &
                        LinearConstraint::discretizationType)
    ;
  py::class_<constraint::LinearJointVelocity,
    std::shared_ptr<constraint::LinearJointVelocity>,
    LinearConstraint>(
      m, "LinearJointVelocity")
      .def(py::init<const Vector &, const Vector &>())
      ;
  py::class_<constraint::LinearJointAcceleration,
    std::shared_ptr<constraint::LinearJointAcceleration>,
    LinearConstraint>(
      m, "LinearJointAcceleration")
      .def(py::init<const Vector &, const Vector &>())
      ;

  py::class_<constraint::JointTorque,
    std::shared_ptr<constraint::JointTorque>,
    LinearConstraint>(
      m, "JointTorque");

  {
    auto mod_jointTorque = m.def_submodule("jointTorque");
#ifdef BUILD_WITH_PINOCCHIO
    py::module::import("pinocchio");
    py::class_<constraint::jointTorque::Pinocchio<>,
      std::shared_ptr<constraint::jointTorque::Pinocchio<> >,
      constraint::JointTorque>(
        mod_jointTorque, "Pinocchio")
        .def(py::init(&createJointTorque))
      ;
#endif
  }

  // algorithm
  py::enum_<toppra::ReturnCode>(m, "ReturnCode")
      .value("OK", toppra::ReturnCode::OK)
      .value("ERR_UNKNOWN", toppra::ReturnCode::ERR_UNKNOWN)
      .value("ERR_UNINITIALIZED", toppra::ReturnCode::ERR_UNINITIALIZED)
      .value("ERR_FAIL_FEASIBLE", toppra::ReturnCode::ERR_FAIL_FEASIBLE)
      .value("ERR_FAIL_CONTROLLABLE", toppra::ReturnCode::ERR_FAIL_CONTROLLABLE)
      .value("ERR_FAIL_FORWARD_PASS", toppra::ReturnCode::ERR_FAIL_FORWARD_PASS)
      .export_values();

  py::class_<toppra::ParametrizationData>(m, "ParametrizationData")
      .def(py::init<>())
      .def_readwrite("gridpoints", &toppra::ParametrizationData::gridpoints)
      .def_readwrite("parametrization", &toppra::ParametrizationData::parametrization)
      .def_readwrite("controllable_sets",
                     &toppra::ParametrizationData::controllable_sets)
      .def_readwrite("feasible_sets", &toppra::ParametrizationData::feasible_sets)
      .def_readwrite("ret_code", &toppra::ParametrizationData::ret_code);

  py::class_<PyTOPPRA>(m, "TOPPRA")
      // .def(py::init<LinearConstraintPtrs, PyPiecewisePolyPath &>())
      .def(py::init<py::list, PyPiecewisePolyPath &>())
      .def("computePathParametrization", &PyTOPPRA::computePathParametrization,
           py::arg("vel_start") = 0, py::arg("vel_end") = 0)
      .def("setN", &PyTOPPRA::setN)
      .def_property_readonly("parametrizationData", &PyTOPPRA::getParameterizationData);
}
}  // namespace python
}  // namespace toppra
<commit_msg>[cpp] Python bindings directly use the C++ interface.<commit_after>#include <pybind11/eigen.h>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include <pybind11/stl.h>
#include <iostream>

#include <bindings.hpp>
#include <string>
#include <toppra/algorithm.hpp>
#include <toppra/constraint.hpp>
#include <toppra/constraint/joint_torque.hpp>
#include <toppra/constraint/linear_joint_acceleration.hpp>
#include <toppra/constraint/linear_joint_velocity.hpp>
#include <toppra/geometric_path.hpp>
#include <toppra/toppra.hpp>

namespace py = pybind11;

#ifdef BUILD_WITH_PINOCCHIO
// Mind that pinocchio headers **must** be included before boost headers.
#include <toppra/constraint/joint_torque/pinocchio.hpp>
#include <boost/python.hpp>

toppra::constraint::jointTorque::Pinocchio<> createJointTorque(py::object model,
    const toppra::Vector& fc)
{
  return toppra::constraint::jointTorque::Pinocchio<>(
      boost::python::extract<const pinocchio::Model&>(model.ptr()), fc);
}
#endif

namespace toppra {
namespace python {

nparr path_eval (const PiecewisePolyPath& p, const Vector& xs, int order=0)
{
  return toNumpyArray(p.eval(xs,order));
}

template<int order>
nparr path_eval_tpl (const PiecewisePolyPath& p, const Vector& xs)
{
  return toNumpyArray(p.eval(xs,order));
}

PYBIND11_MODULE(toppra_int, m) {
  m.doc() = "toppra C++ bindings (internal)";
  py::enum_<toppra::DiscretizationType>(m, "DiscretizationType")
      .value("Collocation", toppra::DiscretizationType::Collocation)
      .value("Interpolation", toppra::DiscretizationType::Interpolation)
      .export_values();

  py::class_<PiecewisePolyPath, std::shared_ptr<PiecewisePolyPath> >(m, "PiecewisePolyPath")
      .def(py::init<>())
      .def(py::init<const toppra::Matrices&, std::vector<toppra::value_type>>())
      .def("eval_single", &PiecewisePolyPath::eval_single)
      .def("eval", &path_eval, py::arg("xs"), py::arg("order") = 0)
      .def("evald", &path_eval_tpl<1>)
      .def("evald", &path_eval_tpl<2>)
      .def("serialize", [](const PiecewisePolyPath& p) -> py::bytes {
            std::ostringstream ss;
            p.serialize(ss);
            return ss.str();
          })
      .def("deserialize", [](PiecewisePolyPath& p, const py::bytes& b) {
            std::stringstream ss;
            ss << b.cast<std::string>();
            p.deserialize(ss);
          })
      .def("__call__", &path_eval, py::arg("xs"), py::arg("order") = 0)
      .def("__call__", &PiecewisePolyPath::eval_single, py::arg("x"), py::arg("order") = 0)
      .def("__str__", [](const PiecewisePolyPath& p) -> std::string { return "PiecewisePolyPath(...)"; })
      .def("__repr__", [](const PiecewisePolyPath& p) -> std::string { return "PiecewisePolyPath(...)"; })
      .def_property_readonly("dof", &PiecewisePolyPath::dof)
      .def_property_readonly("path_interval", &PiecewisePolyPath::pathInterval)
      .def_property_readonly("duration",
          [] (const PiecewisePolyPath& p) -> double {
            Bound bd (p.pathInterval());
            return bd[1] - bd[0];
          })
      .def_static("constructHermite", &PiecewisePolyPath::constructHermite);

  // Abstract class must be binded for derived classes to work
  py::class_<LinearConstraint, LinearConstraintPtr>(m, "_LinearConstraint")
      .def_property_readonly("nbConstraints", &LinearConstraint::nbConstraints)
      .def_property_readonly("nbVariables", &LinearConstraint::nbVariables)
      .def_property_readonly("hasLinearInequalities",
                             &LinearConstraint::hasLinearInequalities)
      .def_property_readonly("hasUbounds", &LinearConstraint::hasUbounds)
      .def_property_readonly("hasXbounds", &LinearConstraint::hasXbounds)
      .def_property("discretizationType",
                    (DiscretizationType(LinearConstraint::*)() const) &
                        LinearConstraint::discretizationType,
                    (void (LinearConstraint::*)(DiscretizationType)) &
                        LinearConstraint::discretizationType)
    ;
  py::class_<constraint::LinearJointVelocity,
    std::shared_ptr<constraint::LinearJointVelocity>,
    LinearConstraint>(
      m, "LinearJointVelocity")
      .def(py::init<const Vector &, const Vector &>())
      ;
  py::class_<constraint::LinearJointAcceleration,
    std::shared_ptr<constraint::LinearJointAcceleration>,
    LinearConstraint>(
      m, "LinearJointAcceleration")
      .def(py::init<const Vector &, const Vector &>())
      ;

  py::class_<constraint::JointTorque,
    std::shared_ptr<constraint::JointTorque>,
    LinearConstraint>(
      m, "JointTorque");

  {
    auto mod_jointTorque = m.def_submodule("jointTorque");
#ifdef BUILD_WITH_PINOCCHIO
    py::module::import("pinocchio");
    py::class_<constraint::jointTorque::Pinocchio<>,
      std::shared_ptr<constraint::jointTorque::Pinocchio<> >,
      constraint::JointTorque>(
        mod_jointTorque, "Pinocchio")
        .def(py::init(&createJointTorque))
      ;
#endif
  }

  // algorithm
  py::enum_<toppra::ReturnCode>(m, "ReturnCode")
      .value("OK", toppra::ReturnCode::OK)
      .value("ERR_UNKNOWN", toppra::ReturnCode::ERR_UNKNOWN)
      .value("ERR_UNINITIALIZED", toppra::ReturnCode::ERR_UNINITIALIZED)
      .value("ERR_FAIL_FEASIBLE", toppra::ReturnCode::ERR_FAIL_FEASIBLE)
      .value("ERR_FAIL_CONTROLLABLE", toppra::ReturnCode::ERR_FAIL_CONTROLLABLE)
      .value("ERR_FAIL_FORWARD_PASS", toppra::ReturnCode::ERR_FAIL_FORWARD_PASS)
      .export_values();

  py::class_<toppra::ParametrizationData>(m, "ParametrizationData")
      .def(py::init<>())
      .def_readwrite("gridpoints", &toppra::ParametrizationData::gridpoints)
      .def_readwrite("parametrization", &toppra::ParametrizationData::parametrization)
      .def_readwrite("controllable_sets",
                     &toppra::ParametrizationData::controllable_sets)
      .def_readwrite("feasible_sets", &toppra::ParametrizationData::feasible_sets)
      .def_readwrite("ret_code", &toppra::ParametrizationData::ret_code);

  py::class_<algorithm::TOPPRA>(m, "TOPPRA")
      .def(py::init<LinearConstraintPtrs, const std::shared_ptr<PiecewisePolyPath> &>())
      .def("computePathParametrization", &algorithm::TOPPRA::computePathParametrization,
           py::arg("vel_start") = 0, py::arg("vel_end") = 0)
      .def("setN", &algorithm::TOPPRA::setN)
      .def_property_readonly("parametrizationData", &algorithm::TOPPRA::getParameterizationData);
}
}  // namespace python
}  // namespace toppra
<|endoftext|>


<commit_before>#include "detail/thread.hpp"
#include "python_support.hpp"

#include <boost/python/def.hpp>
#include <boost/python/class.hpp>

using namespace boost::python;
using namespace tbm;

void export_parallel() {
    class_<DeferredBase, noncopyable>{"DeferredBase", no_init}
    .def("compute", &DeferredBase::compute)
    .add_property("report", &DeferredBase::report)
    .add_property("result", internal_ref(&DeferredBase::result_uref))
    ;

    class_<Deferred<ArrayXf>, bases<DeferredBase>>{"DeferredXf", no_init};
    class_<Deferred<ArrayXd>, bases<DeferredBase>>{"DeferredXd", no_init};

    def("parallel_for", [](object sequence, object produce, object retire,
                           std::size_t num_threads, std::size_t queue_size) {
        auto const size = len(sequence);
        GILRelease main_thread_gil_release;

        parallel_for(
            size, num_threads, queue_size,
            [&produce, &sequence](size_t id) {
                GILEnsure gil_lock;
                object var = sequence[id];
                return extract<std::shared_ptr<DeferredBase>>{produce(var)}();
            },
            [](std::shared_ptr<DeferredBase>& deferred) {
                // no GIL lock -> computations run in parallel
                // but no Python code may be called here
                deferred->compute();
            },
            [&retire](std::shared_ptr<DeferredBase> deferred, size_t id) {
                GILEnsure gil_lock;
                retire(deferred, id);
                deferred.reset();
            }
        );
    }, args("sequence", "produce", "retire", "num_threads", "queue_size"));
}
<commit_msg>Fix Python GIL error<commit_after>#include "detail/thread.hpp"
#include "python_support.hpp"

#include <boost/python/def.hpp>
#include <boost/python/class.hpp>

using namespace boost::python;
using namespace tbm;

void export_parallel() {
    class_<DeferredBase, std::shared_ptr<DeferredBase>, noncopyable>{"DeferredBase", no_init}
    .def("compute", &DeferredBase::compute)
    .add_property("report", &DeferredBase::report)
    .add_property("result", internal_ref(&DeferredBase::result_uref))
    ;

    using DeferredXd = Deferred<ArrayXd>;
    class_<DeferredXd, std::shared_ptr<DeferredXd>, bases<DeferredBase>>{"DeferredXd", no_init};

    def("parallel_for", [](object sequence, object produce, object retire,
                           std::size_t num_threads, std::size_t queue_size) {
        auto const size = len(sequence);
        GILRelease main_thread_gil_release;

        parallel_for(
            size, num_threads, queue_size,
            [&produce, &sequence](size_t id) {
                GILEnsure gil_lock;
                object var = sequence[id];
                return extract<std::shared_ptr<DeferredBase>>{produce(var)}();
            },
            [](std::shared_ptr<DeferredBase>& deferred) {
                // no GIL lock -> computations run in parallel
                // but no Python code may be called here
                deferred->compute();
            },
            [&retire](std::shared_ptr<DeferredBase> deferred, size_t id) {
                GILEnsure gil_lock;
                retire(deferred, id);
                deferred.reset();
            }
        );
    }, args("sequence", "produce", "retire", "num_threads", "queue_size"));
}
<|endoftext|>


<commit_before><commit_msg>fix 32718<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/options_util.h"

#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/installer/util/google_update_settings.h"

// static
void OptionsUtil::ResetToDefaults(Profile* profile) {
  // TODO(tc): It would be nice if we could generate this list automatically so
  // changes to any of the options pages doesn't require updating this list
  // manually.
  PrefService* prefs = profile->GetPrefs();
  const wchar_t* kUserPrefs[] = {
    prefs::kAcceptLanguages,
    prefs::kAlternateErrorPagesEnabled,
    prefs::kCookieBehavior,
    prefs::kDefaultCharset,
    prefs::kDnsPrefetchingEnabled,
#if defined(OS_LINUX)
    prefs::kCertRevocationCheckingEnabled,
    prefs::kSSL2Enabled,
    prefs::kSSL3Enabled,
    prefs::kTLS1Enabled,
#endif
    prefs::kDownloadDefaultDirectory,
    prefs::kDownloadExtensionsToOpen,
    prefs::kEnableSpellCheck,
    prefs::kFormAutofillEnabled,
    prefs::kHomePage,
    prefs::kHomePageIsNewTabPage,
    prefs::kMixedContentFiltering,
    prefs::kPromptForDownload,
    prefs::kPasswordManagerEnabled,
    prefs::kRestoreOnStartup,
    prefs::kSafeBrowsingEnabled,
    prefs::kSearchSuggestEnabled,
    prefs::kShowHomeButton,
    prefs::kSpellCheckDictionary,
    prefs::kURLsToRestoreOnStartup,
    prefs::kWebKitDefaultFixedFontSize,
    prefs::kWebKitDefaultFontSize,
    prefs::kWebKitFixedFontFamily,
    prefs::kWebKitJavaEnabled,
    prefs::kWebKitJavascriptEnabled,
    prefs::kWebKitLoadsImagesAutomatically,
    prefs::kWebKitPluginsEnabled,
    prefs::kWebKitSansSerifFontFamily,
    prefs::kWebKitSerifFontFamily,
  };
  for (size_t i = 0; i < arraysize(kUserPrefs); ++i)
    prefs->ClearPref(kUserPrefs[i]);

  PrefService* local_state = g_browser_process->local_state();
  // Note that we don't reset the kMetricsReportingEnabled preference here
  // because the reset will reset it to the default setting specified in Chrome
  // source, not the default setting selected by the user on the web page where
  // they downloaded Chrome. This means that if the user ever resets their
  // settings they'll either inadvertedly enable this logging or disable it.
  // One is undesirable for them, one is undesirable for us. For now, we just
  // don't reset it.
  const wchar_t* kLocalStatePrefs[] = {
    prefs::kApplicationLocale,
    prefs::kOptionsWindowLastTabIndex,
  };
  for (size_t i = 0; i < arraysize(kLocalStatePrefs); ++i)
    local_state->ClearPref(kLocalStatePrefs[i]);
}

// static
bool OptionsUtil::ResolveMetricsReportingEnabled(bool enabled) {
  GoogleUpdateSettings::SetCollectStatsConsent(enabled);
  bool update_pref = GoogleUpdateSettings::GetCollectStatsConsent();

  if (enabled != update_pref) {
    DLOG(INFO) <<
        "OptionsUtil: Unable to set crash report status to " <<
        enabled;
  }

  // Only change the pref if GoogleUpdateSettings::GetCollectStatsConsent
  // succeeds.
  enabled = update_pref;

  MetricsService* metrics = g_browser_process->metrics_service();
  DCHECK(metrics);
  if (metrics) {
    metrics->SetUserPermitsUpload(enabled);
    if (enabled)
      metrics->Start();
    else
      metrics->Stop();
  }

  return enabled;
}
<commit_msg>Clears the "Clear auto-opening settings" button (put it in the default state, ie, disabled), when the user  clicks in "Reset to defaults" button.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/options_util.h"

#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/installer/util/google_update_settings.h"

// static
void OptionsUtil::ResetToDefaults(Profile* profile) {
  // TODO(tc): It would be nice if we could generate this list automatically so
  // changes to any of the options pages doesn't require updating this list
  // manually.
  PrefService* prefs = profile->GetPrefs();
  const wchar_t* kUserPrefs[] = {
    prefs::kAcceptLanguages,
    prefs::kAlternateErrorPagesEnabled,
    prefs::kCookieBehavior,
    prefs::kDefaultCharset,
    prefs::kDnsPrefetchingEnabled,
#if defined(OS_LINUX)
    prefs::kCertRevocationCheckingEnabled,
    prefs::kSSL2Enabled,
    prefs::kSSL3Enabled,
    prefs::kTLS1Enabled,
#endif
    prefs::kDownloadDefaultDirectory,
    prefs::kDownloadExtensionsToOpen,
    prefs::kEnableSpellCheck,
    prefs::kFormAutofillEnabled,
    prefs::kHomePage,
    prefs::kHomePageIsNewTabPage,
    prefs::kMixedContentFiltering,
    prefs::kPromptForDownload,
    prefs::kPasswordManagerEnabled,
    prefs::kRestoreOnStartup,
    prefs::kSafeBrowsingEnabled,
    prefs::kSearchSuggestEnabled,
    prefs::kShowHomeButton,
    prefs::kSpellCheckDictionary,
    prefs::kURLsToRestoreOnStartup,
    prefs::kWebKitDefaultFixedFontSize,
    prefs::kWebKitDefaultFontSize,
    prefs::kWebKitFixedFontFamily,
    prefs::kWebKitJavaEnabled,
    prefs::kWebKitJavascriptEnabled,
    prefs::kWebKitLoadsImagesAutomatically,
    prefs::kWebKitPluginsEnabled,
    prefs::kWebKitSansSerifFontFamily,
    prefs::kWebKitSerifFontFamily,
  };
  profile->GetDownloadManager()->ResetAutoOpenFiles();
  for (size_t i = 0; i < arraysize(kUserPrefs); ++i)
    prefs->ClearPref(kUserPrefs[i]);

  PrefService* local_state = g_browser_process->local_state();
  // Note that we don't reset the kMetricsReportingEnabled preference here
  // because the reset will reset it to the default setting specified in Chrome
  // source, not the default setting selected by the user on the web page where
  // they downloaded Chrome. This means that if the user ever resets their
  // settings they'll either inadvertedly enable this logging or disable it.
  // One is undesirable for them, one is undesirable for us. For now, we just
  // don't reset it.
  const wchar_t* kLocalStatePrefs[] = {
    prefs::kApplicationLocale,
    prefs::kOptionsWindowLastTabIndex,
  };
  for (size_t i = 0; i < arraysize(kLocalStatePrefs); ++i)
    local_state->ClearPref(kLocalStatePrefs[i]);
}

// static
bool OptionsUtil::ResolveMetricsReportingEnabled(bool enabled) {
  GoogleUpdateSettings::SetCollectStatsConsent(enabled);
  bool update_pref = GoogleUpdateSettings::GetCollectStatsConsent();

  if (enabled != update_pref) {
    DLOG(INFO) <<
        "OptionsUtil: Unable to set crash report status to " <<
        enabled;
  }

  // Only change the pref if GoogleUpdateSettings::GetCollectStatsConsent
  // succeeds.
  enabled = update_pref;

  MetricsService* metrics = g_browser_process->metrics_service();
  DCHECK(metrics);
  if (metrics) {
    metrics->SetUserPermitsUpload(enabled);
    if (enabled)
      metrics->Start();
    else
      metrics->Stop();
  }

  return enabled;
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/url_constants.h"

// TODO(port): Remove this header when last ifdef is removed from this file.
#include "build/build_config.h"

namespace chrome {

const char kAboutScheme[] = "about";
const char kChromeInternalScheme[] = "chrome-internal";
const char kChromeUIScheme[] = "chrome";
const char kDataScheme[] = "data";
const char kExtensionScheme[] = "chrome-extension";
const char kFileScheme[] = "file";
const char kFtpScheme[] = "ftp";
const char kGearsScheme[] = "gears";
const char kHttpScheme[] = "http";
const char kHttpsScheme[] = "https";
const char kJavaScriptScheme[] = "javascript";
const char kMailToScheme[] = "mailto";
const char kPrintScheme[] = "print";
const char kUserScriptScheme[] = "chrome-user-script";
const char kViewCacheScheme[] = "view-cache";
const char kViewSourceScheme[] = "view-source";

const char kStandardSchemeSeparator[] = "://";

const char kAboutBlankURL[] = "about:blank";
const char kAboutCacheURL[] = "about:cache";
const char kAboutCrashURL[] = "about:crash";
const char kAboutHangURL[] = "about:hang";
const char kAboutMemoryURL[] = "about:memory";
const char kAboutShorthangURL[] = "about:shorthang";

// Use an obfuscated URL to make this nondiscoverable, we only want this
// to be used for testing.
const char kAboutBrowserCrash[] = "about:inducebrowsercrashforrealz";

const char kChromeUIDevToolsURL[] = "chrome://devtools/";
const char kChromeUIDownloadsURL[] = "chrome://downloads/";
const char kChromeUIExtensionsURL[] = "chrome://extensions/";
const char kChromeUIHistoryURL[] = "chrome://history/";
const char kChromeUIIPCURL[] = "chrome://about/ipc";
const char kChromeUINetworkURL[] = "chrome://about/network";
const char kChromeUINewTabURL[] = "chrome://newtab";

const char kChromeUIDevToolsHost[] = "devtools";
const char kChromeUIDialogHost[] = "dialog";
const char kChromeUIDownloadsHost[] = "downloads";
const char kChromeUIExtensionsHost[] = "extensions";
const char kChromeUIFavIconPath[] = "favicon";
const char kChromeUIHistoryHost[] = "history";
const char kChromeUIInspectorHost[] = "inspector";
const char kChromeUINewTabHost[] = "newtab";
const char kChromeUIThumbnailPath[] = "thumb";
const char kChromeUIThemePath[] = "theme";

}  // namespace chrome
<commit_msg>Removing unused #include from url_constants.cc.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/url_constants.h"

namespace chrome {

const char kAboutScheme[] = "about";
const char kChromeInternalScheme[] = "chrome-internal";
const char kChromeUIScheme[] = "chrome";
const char kDataScheme[] = "data";
const char kExtensionScheme[] = "chrome-extension";
const char kFileScheme[] = "file";
const char kFtpScheme[] = "ftp";
const char kGearsScheme[] = "gears";
const char kHttpScheme[] = "http";
const char kHttpsScheme[] = "https";
const char kJavaScriptScheme[] = "javascript";
const char kMailToScheme[] = "mailto";
const char kPrintScheme[] = "print";
const char kUserScriptScheme[] = "chrome-user-script";
const char kViewCacheScheme[] = "view-cache";
const char kViewSourceScheme[] = "view-source";

const char kStandardSchemeSeparator[] = "://";

const char kAboutBlankURL[] = "about:blank";
const char kAboutCacheURL[] = "about:cache";
const char kAboutCrashURL[] = "about:crash";
const char kAboutHangURL[] = "about:hang";
const char kAboutMemoryURL[] = "about:memory";
const char kAboutShorthangURL[] = "about:shorthang";

// Use an obfuscated URL to make this nondiscoverable, we only want this
// to be used for testing.
const char kAboutBrowserCrash[] = "about:inducebrowsercrashforrealz";

const char kChromeUIDevToolsURL[] = "chrome://devtools/";
const char kChromeUIDownloadsURL[] = "chrome://downloads/";
const char kChromeUIExtensionsURL[] = "chrome://extensions/";
const char kChromeUIHistoryURL[] = "chrome://history/";
const char kChromeUIIPCURL[] = "chrome://about/ipc";
const char kChromeUINetworkURL[] = "chrome://about/network";
const char kChromeUINewTabURL[] = "chrome://newtab";

const char kChromeUIDevToolsHost[] = "devtools";
const char kChromeUIDialogHost[] = "dialog";
const char kChromeUIDownloadsHost[] = "downloads";
const char kChromeUIExtensionsHost[] = "extensions";
const char kChromeUIFavIconPath[] = "favicon";
const char kChromeUIHistoryHost[] = "history";
const char kChromeUIInspectorHost[] = "inspector";
const char kChromeUINewTabHost[] = "newtab";
const char kChromeUIThumbnailPath[] = "thumb";
const char kChromeUIThemePath[] = "theme";

}  // namespace chrome
<|endoftext|>


<commit_before>//
// Copyright Copyright 2009-2021, AMT – The Association For Manufacturing Technology (“AMT”)
// All rights reserved.
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//

// Ensure that gtest is the first header otherwise Windows raises an error
#include <gtest/gtest.h>
// Keep this comment to keep gtest.h above. (clang-format off/on is not working here!)

#include <chrono>

#include "observation/observation.hpp"
#include "pipeline/deliver.hpp"
#include "pipeline/delta_filter.hpp"
#include "pipeline/duplicate_filter.hpp"
#include "pipeline/period_filter.hpp"
#include "pipeline/pipeline.hpp"
#include "pipeline/shdr_token_mapper.hpp"

using namespace mtconnect;
using namespace mtconnect::pipeline;
using namespace mtconnect::observation;
using namespace mtconnect::asset;
using namespace device_model;
using namespace data_item;
using namespace entity;
using namespace std;
using namespace std::literals;
using namespace std::chrono_literals;

struct MockPipelineContract : public PipelineContract
{
  MockPipelineContract(std::map<string, DataItemPtr> &items) : m_dataItems(items) {}
  DevicePtr findDevice(const std::string &device) override { return nullptr; }
  DataItemPtr findDataItem(const std::string &device, const std::string &name) override
  {
    return m_dataItems[name];
  }
  void eachDataItem(EachDataItem fun) override {}
  void deliverObservation(observation::ObservationPtr obs) override
  {
    m_observations.push_back(obs);
  }
  void deliverAsset(AssetPtr) override {}
  void deliverAssetCommand(entity::EntityPtr) override {}
  void deliverCommand(entity::EntityPtr) override {}
  void deliverConnectStatus(entity::EntityPtr, const StringList &, bool) override {}

  std::map<string, DataItemPtr> &m_dataItems;

  std::vector<ObservationPtr> m_observations;
};

class PeriodFilterTest : public testing::Test
{
public:
  PeriodFilterTest() : m_strand(m_ioContext) {}

protected:
  void SetUp() override
  {
    m_context = make_shared<PipelineContext>();
    m_context->m_contract = make_unique<MockPipelineContract>(m_dataItems);
    m_mapper = make_shared<ShdrTokenMapper>(m_context);
    m_mapper->bind(make_shared<NullTransform>(TypeGuard<Observations>(RUN)));
  }

  void TearDown() override
  {
    m_dataItems.clear();
    m_context.reset();
    m_mapper.reset();
  }

  DataItemPtr makeDataItem(Properties attributes)
  {
    ErrorList errors;
    auto di = DataItem::make(attributes, errors);
    m_dataItems.emplace(di->getId(), di);

    return di;
  }

  const EntityPtr observe(TokenList tokens, Timestamp now = chrono::system_clock::now())
  {
    auto ts = make_shared<Timestamped>();
    ts->m_tokens = tokens;
    ts->m_timestamp = now;
    ts->setProperty("timestamp", ts->m_timestamp);

    return (*m_mapper)(ts);
  }

  void createDataItem()
  {
    ErrorList errors;
    auto f = Filter::getFactory()->create("Filter", {{"type", "PERIOD"s}, {"VALUE", 1.0}}, errors);
    EntityList list {f};
    auto filters = DataItem::getFactory()->factoryFor("DataItem")->create("Filters", list, errors);

    makeDataItem({{"id", "a"s},
                  {"type", "POSITION"s},
                  {"category", "SAMPLE"s},
                  {"units", "MILLIMETER"s},
                  {"Filters", filters}});
  }

  auto makeFilter()
  {
    auto rate = make_shared<PeriodFilter>(m_context, m_strand);
    m_mapper->bind(rate);

    auto delivery = make_shared<DeliverObservation>(m_context);
    rate->bind(delivery);

    return rate;
  }

  auto &observations()
  {
    return static_cast<MockPipelineContract *>(m_context->m_contract.get())->m_observations;
  }

  shared_ptr<ShdrTokenMapper> m_mapper;
  std::map<string, DataItemPtr> m_dataItems;
  shared_ptr<PipelineContext> m_context;
  boost::asio::io_context m_ioContext;
  boost::asio::io_context::strand m_strand;
};

TEST_F(PeriodFilterTest, test_simple_time_series)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1.5"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "1.5"}, now + 200ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "1.5"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "1.5"}, now + 1100ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(2, observations().size());
  }

  m_ioContext.run_for(1s);

  ASSERT_EQ(2, observations().size());
}

TEST_F(PeriodFilterTest, delayed_delivery)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "2"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }

  m_ioContext.run_for(750ms);

  auto obs = observations();
  ASSERT_EQ(2, obs.size());
  auto end = obs.back();
  ASSERT_EQ(2.0, end->getValue<double>());
}

TEST_F(PeriodFilterTest, delayed_delivery_with_replace)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "2"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "3"}, now + 750ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }

  m_ioContext.run_for(750ms);

  auto obs = observations();
  ASSERT_EQ(2, obs.size());
  auto end = obs.back();
  ASSERT_EQ(3.0, end->getValue<double>());
}

TEST_F(PeriodFilterTest, delayed_delivery_with_cancel)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "2"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "3"}, now + 750ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "4"}, now + 1250ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(2, observations().size());
  }

  m_ioContext.run_for(750ms);

  auto obs = observations();
  ASSERT_EQ(2, obs.size());
  auto end = obs.back();
  ASSERT_EQ(4.0, end->getValue<double>());
}

TEST_F(PeriodFilterTest, deliver_after_delayed_delivery)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "2"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }

  m_ioContext.run_for(750ms);
  m_ioContext.restart();
  auto &obs = observations();

  {
    ASSERT_EQ(2, obs.size());
    auto end = obs.back();
    ASSERT_EQ(2.0, end->getValue<double>());
  }
  {
    auto os = observe({"a", "3"}, now + 1600ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(2, observations().size());
  }

  m_ioContext.run_for(750s);

  {
    ASSERT_EQ(3, obs.size());
    auto end = obs.back();
    ASSERT_EQ(3.0, end->getValue<double>());
  }
}
<commit_msg>Added some additional steps at to test canceling and clock correction<commit_after>//
// Copyright Copyright 2009-2021, AMT – The Association For Manufacturing Technology (“AMT”)
// All rights reserved.
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//

// Ensure that gtest is the first header otherwise Windows raises an error
#include <gtest/gtest.h>
// Keep this comment to keep gtest.h above. (clang-format off/on is not working here!)

#include <chrono>

#include "observation/observation.hpp"
#include "pipeline/deliver.hpp"
#include "pipeline/delta_filter.hpp"
#include "pipeline/duplicate_filter.hpp"
#include "pipeline/period_filter.hpp"
#include "pipeline/pipeline.hpp"
#include "pipeline/shdr_token_mapper.hpp"

using namespace mtconnect;
using namespace mtconnect::pipeline;
using namespace mtconnect::observation;
using namespace mtconnect::asset;
using namespace device_model;
using namespace data_item;
using namespace entity;
using namespace std;
using namespace std::literals;
using namespace std::chrono_literals;

struct MockPipelineContract : public PipelineContract
{
  MockPipelineContract(std::map<string, DataItemPtr> &items) : m_dataItems(items) {}
  DevicePtr findDevice(const std::string &device) override { return nullptr; }
  DataItemPtr findDataItem(const std::string &device, const std::string &name) override
  {
    return m_dataItems[name];
  }
  void eachDataItem(EachDataItem fun) override {}
  void deliverObservation(observation::ObservationPtr obs) override
  {
    m_observations.push_back(obs);
  }
  void deliverAsset(AssetPtr) override {}
  void deliverAssetCommand(entity::EntityPtr) override {}
  void deliverCommand(entity::EntityPtr) override {}
  void deliverConnectStatus(entity::EntityPtr, const StringList &, bool) override {}

  std::map<string, DataItemPtr> &m_dataItems;

  std::vector<ObservationPtr> m_observations;
};

class PeriodFilterTest : public testing::Test
{
public:
  PeriodFilterTest() : m_strand(m_ioContext) {}

protected:
  void SetUp() override
  {
    m_context = make_shared<PipelineContext>();
    m_context->m_contract = make_unique<MockPipelineContract>(m_dataItems);
    m_mapper = make_shared<ShdrTokenMapper>(m_context);
    m_mapper->bind(make_shared<NullTransform>(TypeGuard<Observations>(RUN)));
  }

  void TearDown() override
  {
    m_dataItems.clear();
    m_context.reset();
    m_mapper.reset();
  }

  DataItemPtr makeDataItem(Properties attributes)
  {
    ErrorList errors;
    auto di = DataItem::make(attributes, errors);
    m_dataItems.emplace(di->getId(), di);

    return di;
  }

  const EntityPtr observe(TokenList tokens, Timestamp now = chrono::system_clock::now())
  {
    auto ts = make_shared<Timestamped>();
    ts->m_tokens = tokens;
    ts->m_timestamp = now;
    ts->setProperty("timestamp", ts->m_timestamp);

    return (*m_mapper)(ts);
  }

  void createDataItem()
  {
    ErrorList errors;
    auto f = Filter::getFactory()->create("Filter", {{"type", "PERIOD"s}, {"VALUE", 1.0}}, errors);
    EntityList list {f};
    auto filters = DataItem::getFactory()->factoryFor("DataItem")->create("Filters", list, errors);

    makeDataItem({{"id", "a"s},
                  {"type", "POSITION"s},
                  {"category", "SAMPLE"s},
                  {"units", "MILLIMETER"s},
                  {"Filters", filters}});
  }

  auto makeFilter()
  {
    auto rate = make_shared<PeriodFilter>(m_context, m_strand);
    m_mapper->bind(rate);

    auto delivery = make_shared<DeliverObservation>(m_context);
    rate->bind(delivery);

    return rate;
  }

  auto &observations()
  {
    return static_cast<MockPipelineContract *>(m_context->m_contract.get())->m_observations;
  }

  shared_ptr<ShdrTokenMapper> m_mapper;
  std::map<string, DataItemPtr> m_dataItems;
  shared_ptr<PipelineContext> m_context;
  boost::asio::io_context m_ioContext;
  boost::asio::io_context::strand m_strand;
};

TEST_F(PeriodFilterTest, test_simple_time_series)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1.5"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "1.5"}, now + 200ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "1.5"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "1.5"}, now + 1100ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(2, observations().size());
  }

  m_ioContext.run_for(1s);

  ASSERT_EQ(2, observations().size());
}

TEST_F(PeriodFilterTest, delayed_delivery)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "2"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }

  m_ioContext.run_for(750ms);

  auto obs = observations();
  ASSERT_EQ(2, obs.size());
  auto end = obs.back();
  ASSERT_EQ(2.0, end->getValue<double>());
}

TEST_F(PeriodFilterTest, delayed_delivery_with_replace)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "2"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "3"}, now + 750ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }

  m_ioContext.run_for(750ms);

  auto obs = observations();
  ASSERT_EQ(2, obs.size());
  auto end = obs.back();
  ASSERT_EQ(3.0, end->getValue<double>());
}

TEST_F(PeriodFilterTest, delayed_delivery_with_cancel)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "2"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "3"}, now + 750ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "4"}, now + 1250ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(2, observations().size());
  }

  m_ioContext.run_for(750ms);

  auto obs = observations();
  ASSERT_EQ(2, obs.size());
  auto end = obs.back();
  ASSERT_EQ(4.0, end->getValue<double>());
}

TEST_F(PeriodFilterTest, deliver_after_delayed_delivery)
{
  createDataItem();
  makeFilter();

  Timestamp now = chrono::system_clock::now();

  {
    auto os = observe({"a", "1"}, now);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(1, observations().size());
  }
  {
    auto os = observe({"a", "2"}, now + 500ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(1, observations().size());
  }

  m_ioContext.run_for(750ms);
  m_ioContext.restart();
  auto &obs = observations();

  {
    ASSERT_EQ(2, obs.size());
    auto end = obs.back();
    ASSERT_EQ(2.0, end->getValue<double>());
  }
  {
    auto os = observe({"a", "3"}, now + 1600ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(2, observations().size());
  }

  m_ioContext.run_for(750s);

  {
    ASSERT_EQ(3, obs.size());
    auto end = obs.back();
    ASSERT_EQ(3.0, end->getValue<double>());
  }

  {
    auto os = observe({"a", "4"}, now + 2600ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(0, list.size());
    ASSERT_EQ(3, observations().size());
  }
  {
    auto os = observe({"a", "5"}, now + 3200ms);
    auto list = os->getValue<EntityList>();
    ASSERT_EQ(1, list.size());
    ASSERT_EQ(4, observations().size());
  }

  m_ioContext.run_for(750s);

  {
    ASSERT_EQ(4, obs.size());
    auto end = obs.back();
    ASSERT_EQ(5.0, end->getValue<double>());
  }

}
<|endoftext|>


<commit_before><commit_msg>fix for bug: http://code.google.com/p/chromium/issues/detail?id=15547 There are cases where DidFinishDocumentLoadForFrame() and DidFinishLoadForFrame() can be called with no navigation_state.<commit_after><|endoftext|>


<commit_before>/*
 * Unit tests for the Image class.
 * Author: Dino Wernli
 */

#include <gtest/gtest.h>

#include "renderer/image.h"

namespace {

static bool ColorsEqual(Color3 c1, Color3 c2) {
  return (c1.r() == c2.r() && c1.g() == c2.g() && c1.b() == c2.b());
}

TEST(Image, ImageBlackInitially) {
  Image image(10, 20);

  EXPECT_EQ(10, image.SizeX());
  EXPECT_EQ(20, image.SizeY());

  for (size_t x = 0; x < image.SizeX(); ++x) {
    for (size_t y = 0; y < image.SizeY(); ++y) {
      EXPECT_TRUE(ColorsEqual(Color3(0, 0, 0), image.PixelAt(x, y)));
    }
  }
}

TEST(Image, ColorStoredAndRetrieved) {
  Image image(10, 20);

  for (size_t x = 0; x < image.SizeX(); ++x) {
    for (size_t y = 0; y < image.SizeY(); ++y) {
      image.PutPixel(Color3(1, 0, 1), x, y);
    }
  }

  for (size_t x = 0; x < image.SizeX(); ++x) {
    for (size_t y = 0; y < image.SizeY(); ++y) {
      EXPECT_TRUE(ColorsEqual(Color3(1, 0, 1), image.PixelAt(x, y)));
    }
  }
}

}  // namespace
<commit_msg>Add unit tests for point.<commit_after>/*
 * Unit tests for the Image class.
 * Author: Dino Wernli
 */

#include <gtest/gtest.h>

#include "renderer/image.h"

namespace {

static bool ColorsEqual(Color3 c1, Color3 c2) {
  return (c1.r() == c2.r() && c1.g() == c2.g() && c1.b() == c2.b());
}

TEST(Image, ImageBlackInitially) {
  Image image(10, 20);

  EXPECT_EQ(10, image.SizeX());
  EXPECT_EQ(20, image.SizeY());

  for (size_t x = 0; x < image.SizeX(); ++x) {
    for (size_t y = 0; y < image.SizeY(); ++y) {
      EXPECT_TRUE(ColorsEqual(Color3(0, 0, 0), image.PixelAt(x, y)));
    }
  }
}

TEST(Image, ColorStoredAndRetrieved) {
  Image image(10, 20);

  for (size_t x = 0; x < image.SizeX(); ++x) {
    for (size_t y = 0; y < image.SizeY(); ++y) {
      image.PutPixel(Color3(1, 0, 1), x, y);
    }
  }

  for (size_t x = 0; x < image.SizeX(); ++x) {
    for (size_t y = 0; y < image.SizeY(); ++y) {
      EXPECT_TRUE(ColorsEqual(Color3(1, 0, 1), image.PixelAt(x, y)));
    }
  }
}

TEST(Image, EmptyImage) {
  Image image(0, 0);
  EXPECT_EQ(0, image.SizeX());
  EXPECT_EQ(0, image.SizeY());
}

}  // namespace
<|endoftext|>


<commit_before>/*
 * Copyright (c) [2014-2015] Novell, Inc.
 * Copyright (c) [2016-2017] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "storage/Utils/HumanString.h"
#include "storage/Devices/ImplicitPtImpl.h"
#include "storage/Devices/Partitionable.h"
#include "storage/Devices/PartitionImpl.h"
#include "storage/Devicegraph.h"
#include "storage/Utils/StorageTmpl.h"
#include "storage/Utils/XmlFile.h"
#include "storage/SystemInfo/SystemInfo.h"
#include "storage/Utils/SystemCmd.h"
#include "storage/Utils/StorageDefines.h"
#include "storage/Utils/AlignmentImpl.h"

namespace storage
{

    using namespace std;

    const char* DeviceTraits<ImplicitPt>::classname = "ImplicitPt";

    ImplicitPt::Impl::Impl(const xmlNode* node)
	: PartitionTable::Impl(node)
    {
    }

    void
    ImplicitPt::Impl::save(xmlNode* node) const
    {
	PartitionTable::Impl::save(node);
    }

    void
    ImplicitPt::Impl::probe_pass_1c(Prober& prober)
    {
	// TODO Maybe check that the implicit partition already created really
	// matches the one reported by parted.
    }

    void
    ImplicitPt::Impl::check(const CheckCallbacks* check_callbacks) const
    {
	PartitionTable::Impl::check(check_callbacks);
    }

    Region
    ImplicitPt::Impl::get_usable_region() const
    {
	return get_partitionable()->get_region();
    }

    vector<PartitionSlot>
    ImplicitPt::Impl::get_unused_partition_slots(AlignPolicy align_policy,
						 AlignType align_type) const
    {
	return { };
    }

    bool
    ImplicitPt::Impl::equal(const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	if (!PartitionTable::Impl::equal(rhs))
	    return false;

	return true;
    }

    void
    ImplicitPt::Impl::log_diff(std::ostream& log, const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	PartitionTable::Impl::log_diff(log, rhs);
    }

    void
    ImplicitPt::Impl::print(std::ostream& out) const
    {
	PartitionTable::Impl::print(out);
    }

    bool
    ImplicitPt::Impl::is_partition_type_supported(PartitionType type) const
    {
	return type == PartitionType::PRIMARY;
    }

    bool
    ImplicitPt::Impl::is_partition_id_supported(unsigned int id) const
    {
	static const vector<unsigned int> supported_ids = {
	    ID_UNKNOWN, ID_LINUX
	};

	return contains(supported_ids, id);
    }

    unsigned int
    ImplicitPt::Impl::max_primary() const
    {
	return min(1U, get_partitionable()->get_range() - 1);
    }

    void
    ImplicitPt::Impl::create_implicit_partition()
    {
	const Dasd* dasd = to_dasd(get_partitionable());

	unsigned long long start = 0;

	if (dasd->get_type() == DasdType::ECKD && dasd->get_format() == DasdFormat::LDL)
	    start = 3;
	else if (dasd->get_type() == DasdType::FBA)
	    start = 2;
	else
	    ST_THROW(Exception("cannot create implicit partition on device " + dasd->get_name()));

	Region region(start, dasd->get_region().get_length() - start,
		      dasd->get_region().get_block_size());

	create_partition(dasd->partition_name(1), region, PartitionType::PRIMARY);
    }

    void
    ImplicitPt::Impl::add_create_actions(Actiongraph::Impl& actiongraph) const
    {
	vector<Action::Base*> actions;

	actions.push_back(new Action::Create(get_sid(), false, true));

	actiongraph.add_chain(actions);
    }

    void
    ImplicitPt::Impl::add_delete_actions(Actiongraph::Impl& actiongraph) const
    {
	vector<Action::Base*> actions;

	actions.push_back(new Action::Delete(get_sid(), false, true));

	actiongraph.add_chain(actions);
    }

    Text
    ImplicitPt::Impl::do_create_text(Tense tense) const
    {
	const Partitionable* partitionable = get_partitionable();

	Text text = tenser(tense,
			   // TRANSLATORS: displayed before action,
			   // %1$s is replaced by device name (e.g. /dev/dasda)
			   _("Create implicit partition table on %1$s"),
			   // TRANSLATORS: displayed during action,
			   // %1$s is replaced by device name (e.g. /dev/dasda)
			   _("Creating implicit partition table on %1$s"));

	return sformat(text, partitionable->get_displayname().c_str());
    }

    Text
    ImplicitPt::Impl::do_delete_text(Tense tense) const
    {
	const Partitionable* partitionable = get_partitionable();

	Text text = tenser(tense,
			   // TRANSLATORS: displayed before action,
			   // %1$s is replaced by device name (e.g. /dev/dasda)
			   _("Delete implicit partition table on %1$s"),
			   // TRANSLATORS: displayed during action,
			   // %1$s is replaced by device name (e.g. /dev/dasda)
			   _("Deleting implicit partition table on %1$s"));

	return sformat(text, partitionable->get_displayname().c_str());
    }

}
<commit_msg>- moved code<commit_after>/*
 * Copyright (c) [2014-2015] Novell, Inc.
 * Copyright (c) [2016-2017] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "storage/Utils/HumanString.h"
#include "storage/Devices/ImplicitPtImpl.h"
#include "storage/Devices/Partitionable.h"
#include "storage/Devices/PartitionImpl.h"
#include "storage/Devicegraph.h"
#include "storage/Utils/StorageTmpl.h"
#include "storage/Utils/XmlFile.h"
#include "storage/SystemInfo/SystemInfo.h"
#include "storage/Utils/SystemCmd.h"
#include "storage/Utils/StorageDefines.h"
#include "storage/Utils/AlignmentImpl.h"

namespace storage
{

    using namespace std;

    const char* DeviceTraits<ImplicitPt>::classname = "ImplicitPt";

    ImplicitPt::Impl::Impl(const xmlNode* node)
	: PartitionTable::Impl(node)
    {
    }

    void
    ImplicitPt::Impl::save(xmlNode* node) const
    {
	PartitionTable::Impl::save(node);
    }

    void
    ImplicitPt::Impl::probe_pass_1c(Prober& prober)
    {
	// TODO Maybe check that the implicit partition already created really
	// matches the one reported by parted.
    }

    void
    ImplicitPt::Impl::check(const CheckCallbacks* check_callbacks) const
    {
	PartitionTable::Impl::check(check_callbacks);
    }

    Region
    ImplicitPt::Impl::get_usable_region() const
    {
	// The usable region matches the implicit partition. The start and end
	// values must match what the kernel does.

	const Dasd* dasd = to_dasd(get_partitionable());

	unsigned long long start = 0;

	if (dasd->get_type() == DasdType::ECKD && dasd->get_format() == DasdFormat::LDL)
	    start = 3;
	else if (dasd->get_type() == DasdType::FBA)
	    start = 2;
	else
	    ST_THROW(Exception("usable region is unknown for device " + dasd->get_name()));

	return Region(start, dasd->get_region().get_length() - start,
		      dasd->get_region().get_block_size());
    }

    vector<PartitionSlot>
    ImplicitPt::Impl::get_unused_partition_slots(AlignPolicy align_policy,
						 AlignType align_type) const
    {
	return { };
    }

    bool
    ImplicitPt::Impl::equal(const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	if (!PartitionTable::Impl::equal(rhs))
	    return false;

	return true;
    }

    void
    ImplicitPt::Impl::log_diff(std::ostream& log, const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	PartitionTable::Impl::log_diff(log, rhs);
    }

    void
    ImplicitPt::Impl::print(std::ostream& out) const
    {
	PartitionTable::Impl::print(out);
    }

    bool
    ImplicitPt::Impl::is_partition_type_supported(PartitionType type) const
    {
	return type == PartitionType::PRIMARY;
    }

    bool
    ImplicitPt::Impl::is_partition_id_supported(unsigned int id) const
    {
	static const vector<unsigned int> supported_ids = {
	    ID_UNKNOWN, ID_LINUX
	};

	return contains(supported_ids, id);
    }

    unsigned int
    ImplicitPt::Impl::max_primary() const
    {
	return min(1U, get_partitionable()->get_range() - 1);
    }

    void
    ImplicitPt::Impl::create_implicit_partition()
    {
	// The usable region matches the implicit partition.

	create_partition(get_partitionable()->partition_name(1), get_usable_region(),
			 PartitionType::PRIMARY);
    }

    void
    ImplicitPt::Impl::add_create_actions(Actiongraph::Impl& actiongraph) const
    {
	vector<Action::Base*> actions;

	actions.push_back(new Action::Create(get_sid(), false, true));

	actiongraph.add_chain(actions);
    }

    void
    ImplicitPt::Impl::add_delete_actions(Actiongraph::Impl& actiongraph) const
    {
	vector<Action::Base*> actions;

	actions.push_back(new Action::Delete(get_sid(), false, true));

	actiongraph.add_chain(actions);
    }

    Text
    ImplicitPt::Impl::do_create_text(Tense tense) const
    {
	const Partitionable* partitionable = get_partitionable();

	Text text = tenser(tense,
			   // TRANSLATORS: displayed before action,
			   // %1$s is replaced by device name (e.g. /dev/dasda)
			   _("Create implicit partition table on %1$s"),
			   // TRANSLATORS: displayed during action,
			   // %1$s is replaced by device name (e.g. /dev/dasda)
			   _("Creating implicit partition table on %1$s"));

	return sformat(text, partitionable->get_displayname().c_str());
    }

    Text
    ImplicitPt::Impl::do_delete_text(Tense tense) const
    {
	const Partitionable* partitionable = get_partitionable();

	Text text = tenser(tense,
			   // TRANSLATORS: displayed before action,
			   // %1$s is replaced by device name (e.g. /dev/dasda)
			   _("Delete implicit partition table on %1$s"),
			   // TRANSLATORS: displayed during action,
			   // %1$s is replaced by device name (e.g. /dev/dasda)
			   _("Deleting implicit partition table on %1$s"));

	return sformat(text, partitionable->get_displayname().c_str());
    }

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/experimental/symbolizer/StackTrace.h>
#include <folly/experimental/symbolizer/Symbolizer.h>
#include <folly/fibers/FiberManager.h>
#include <folly/fibers/SimpleLoopController.h>
#include <folly/init/Init.h>

#include <folly/portability/GTest.h>

using namespace folly::fibers;
using namespace folly::symbolizer;

constexpr size_t kMaxAddresses = 1000;

void fBaseline(FrameArray<kMaxAddresses>& /* unused */) {
  auto ffa = std::make_unique<FrameArray<kMaxAddresses>>();
  (void)ffa;
}

void fStack(FrameArray<kMaxAddresses>& fa) {
  auto ffa = std::make_unique<FrameArray<kMaxAddresses>>();
  (void)ffa;
  getStackTrace(fa);
}

void fHeap(FrameArray<kMaxAddresses>& fa) {
  auto ffa = std::make_unique<FrameArray<kMaxAddresses>>();
  (void)ffa;
  getStackTraceHeap(fa);
}

// Check that the requires stacks for capturing a stack trace do not
// exceed reasonable levels surprisingly.
TEST(StackTraceSizeLimitTest, FiberLimit) {
  FiberManager::Options opts;
  opts.recordStackEvery = 1;

  auto t = [&](folly::Function<void(FrameArray<kMaxAddresses>&)> f,
               size_t highWaterMark) {
    FiberManager manager(std::make_unique<SimpleLoopController>(), opts);
    auto& loopController =
        dynamic_cast<SimpleLoopController&>(manager.loopController());

    bool checkRan = false;
    FrameArray<kMaxAddresses> fa;
    manager.addTask([&] {
      checkRan = true;
      f(fa);
    });

    EXPECT_EQ(manager.stackHighWatermark(), 0);

    loopController.loop([&]() { loopController.stop(); });

    EXPECT_LE(manager.stackHighWatermark(), highWaterMark);

    EXPECT_TRUE(checkRan);
  };
  // Initial run
  t(fBaseline, 10000);

  // The amount of stack needed varies based on compilation modes.
  if (folly::kIsDebug) {
    if (folly::kIsSanitizeAddress) {
      t(fBaseline, 0);
      t(fStack, 0);
      t(fHeap, 0);
    } else {
      t(fBaseline, 3700);
      t(fStack, 10000);
      t(fHeap, 5000);
    }
  } else {
    if (folly::kIsSanitizeThread) {
      t(fBaseline, 2500);
      t(fStack, 6800);
      t(fHeap, 3500);
    } else {
      t(fBaseline, 1600);
      t(fStack, 6800);
      t(fHeap, 2200);
    }
  }
}
<commit_msg>Relax the stack trace limit for opt mode too.<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/experimental/symbolizer/StackTrace.h>
#include <folly/experimental/symbolizer/Symbolizer.h>
#include <folly/fibers/FiberManager.h>
#include <folly/fibers/SimpleLoopController.h>
#include <folly/init/Init.h>

#include <folly/portability/GTest.h>

using namespace folly::fibers;
using namespace folly::symbolizer;

constexpr size_t kMaxAddresses = 1000;

void fBaseline(FrameArray<kMaxAddresses>& /* unused */) {
  auto ffa = std::make_unique<FrameArray<kMaxAddresses>>();
  (void)ffa;
}

void fStack(FrameArray<kMaxAddresses>& fa) {
  auto ffa = std::make_unique<FrameArray<kMaxAddresses>>();
  (void)ffa;
  getStackTrace(fa);
}

void fHeap(FrameArray<kMaxAddresses>& fa) {
  auto ffa = std::make_unique<FrameArray<kMaxAddresses>>();
  (void)ffa;
  getStackTraceHeap(fa);
}

// Check that the requires stacks for capturing a stack trace do not
// exceed reasonable levels surprisingly.
TEST(StackTraceSizeLimitTest, FiberLimit) {
  FiberManager::Options opts;
  opts.recordStackEvery = 1;

  auto t = [&](folly::Function<void(FrameArray<kMaxAddresses>&)> f,
               size_t highWaterMark) {
    FiberManager manager(std::make_unique<SimpleLoopController>(), opts);
    auto& loopController =
        dynamic_cast<SimpleLoopController&>(manager.loopController());

    bool checkRan = false;
    FrameArray<kMaxAddresses> fa;
    manager.addTask([&] {
      checkRan = true;
      f(fa);
    });

    EXPECT_EQ(manager.stackHighWatermark(), 0);

    loopController.loop([&]() { loopController.stop(); });

    EXPECT_LE(manager.stackHighWatermark(), highWaterMark);

    EXPECT_TRUE(checkRan);
  };
  // Initial run
  t(fBaseline, 10000);

  // The amount of stack needed varies based on compilation modes.
  if (folly::kIsDebug) {
    if (folly::kIsSanitizeAddress) {
      t(fBaseline, 0);
      t(fStack, 0);
      t(fHeap, 0);
    } else {
      t(fBaseline, 3700);
      t(fStack, 10000);
      t(fHeap, 5000);
    }
  } else {
    if (folly::kIsSanitizeThread) {
      t(fBaseline, 2500);
      t(fStack, 9000);
      t(fHeap, 3500);
    } else {
      t(fBaseline, 1600);
      t(fStack, 9000);
      t(fHeap, 2200);
    }
  }
}
<|endoftext|>