text:
namespace syncer {

class BackoffDelayProvider;

class SyncSchedulerImpl : public SyncScheduler {
 public:
  // |name| is a display string to identify the syncer thread.  Takes
  // |ownership of |syncer| and |delay_provider|.
  SyncSchedulerImpl(const std::string& name,
                    BackoffDelayProvider* delay_provider,
                    sessions::SyncSessionContext* context,
                    Syncer* syncer);

  // Calls Stop().
  virtual ~SyncSchedulerImpl();

  virtual void Start(Mode mode) OVERRIDE;
  virtual bool ScheduleConfiguration(
      const ConfigurationParams& params) OVERRIDE;
  virtual void RequestStop(const base::Closure& callback) OVERRIDE;
  virtual void ScheduleNudgeAsync(
      const base::TimeDelta& delay,
      NudgeSource source,
      ModelTypeSet types,
      const tracked_objects::Location& nudge_location) OVERRIDE;
  virtual void ScheduleNudgeWithStatesAsync(
      const base::TimeDelta& delay, NudgeSource source,
      const ModelTypeInvalidationMap& invalidation_map,
      const tracked_objects::Location& nudge_location) OVERRIDE;
  virtual void SetNotificationsEnabled(bool notifications_enabled) OVERRIDE;

  virtual base::TimeDelta GetSessionsCommitDelay() const OVERRIDE;

  virtual void OnCredentialsUpdated() OVERRIDE;
  virtual void OnConnectionStatusChange() OVERRIDE;

  // SyncSession::Delegate implementation.
  virtual void OnSilencedUntil(
      const base::TimeTicks& silenced_until) OVERRIDE;
  virtual bool IsSyncingCurrentlySilenced() OVERRIDE;
  virtual void OnReceivedShortPollIntervalUpdate(
      const base::TimeDelta& new_interval) OVERRIDE;
  virtual void OnReceivedLongPollIntervalUpdate(
      const base::TimeDelta& new_interval) OVERRIDE;
  virtual void OnReceivedSessionsCommitDelay(
      const base::TimeDelta& new_delay) OVERRIDE;
  virtual void OnShouldStopSyncingPermanently() OVERRIDE;
  virtual void OnSyncProtocolError(
      const sessions::SyncSessionSnapshot& snapshot) OVERRIDE;

 private:
  enum JobProcessDecision {
    // Indicates we should continue with the current job.
    CONTINUE,
    // Indicates that we should save it to be processed later.
    SAVE,
    // Indicates we should drop this job.
    DROP,
  };

  struct SyncSessionJob {
    // An enum used to describe jobs for scheduling purposes.
    enum SyncSessionJobPurpose {
      // Uninitialized state, should never be hit in practice.
      UNKNOWN = -1,
      // Our poll timer schedules POLL jobs periodically based on a server
      // assigned poll interval.
      POLL,
      // A nudge task can come from a variety of components needing to force
      // a sync.  The source is inferable from |session.source()|.
      NUDGE,
      // Typically used for fetching updates for a subset of the enabled types
      // during initial sync or reconfiguration.
      CONFIGURATION,
    };
    SyncSessionJob();
    SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start,
        linked_ptr<sessions::SyncSession> session, bool is_canary_job,
        const ConfigurationParams& config_params,
        const tracked_objects::Location& nudge_location);
    ~SyncSessionJob();
    static const char* GetPurposeString(SyncSessionJobPurpose purpose);

    SyncSessionJobPurpose purpose;
    base::TimeTicks scheduled_start;
    linked_ptr<sessions::SyncSession> session;
    bool is_canary_job;
    ConfigurationParams config_params;

    // This is the location the job came from.  Used for debugging.
    // In case of multiple nudges getting coalesced this stores the
    // first location that came in.
    tracked_objects::Location from_here;
  };
  friend class SyncSchedulerTest;
  friend class SyncSchedulerWhiteboxTest;
  friend class SyncerTest;

  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
      DropNudgeWhileExponentialBackOff);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, SaveNudge);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
                           SaveNudgeWhileTypeThrottled);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueNudge);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, DropPoll);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinuePoll);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueConfiguration);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
                           SaveConfigurationWhileThrottled);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
                           SaveNudgeWhileThrottled);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
                           ContinueCanaryJobConfig);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
      ContinueNudgeWhileExponentialBackOff);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest, TransientPollFailure);
  FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest, GetInitialBackoffDelay);

  struct WaitInterval {
    enum Mode {
      // Uninitialized state, should not be set in practice.
      UNKNOWN = -1,
      // A wait interval whose duration has been affected by exponential
      // backoff.
      // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval.
      EXPONENTIAL_BACKOFF,
      // A server-initiated throttled interval.  We do not allow any syncing
      // during such an interval.
      THROTTLED,
    };
    WaitInterval();
    ~WaitInterval();
    WaitInterval(Mode mode, base::TimeDelta length);

    static const char* GetModeString(Mode mode);

    Mode mode;

    // This bool is set to true if we have observed a nudge during this
    // interval and mode == EXPONENTIAL_BACKOFF.
    bool had_nudge;
    base::TimeDelta length;
    base::OneShotTimer<SyncSchedulerImpl> timer;

    // Configure jobs are saved only when backing off or throttling. So we
    // expose the pointer here.
    scoped_ptr<SyncSessionJob> pending_configure_job;
  };

  static const char* GetModeString(Mode mode);

  static const char* GetDecisionString(JobProcessDecision decision);

  // Assign |start| and |end| to appropriate SyncerStep values for the
  // specified |purpose|.
  static void SetSyncerStepsForPurpose(
      SyncSessionJob::SyncSessionJobPurpose purpose,
      SyncerStep* start, SyncerStep* end);

  // Helpers that log before posting to |sync_loop_|.  These will only post
  // the task in between calls to Start/Stop.
  void PostTask(const tracked_objects::Location& from_here,
                const char* name,
                const base::Closure& task);
  void PostDelayedTask(const tracked_objects::Location& from_here,
                       const char* name,
                       const base::Closure& task,
                       base::TimeDelta delay);

  // Helper to assemble a job and post a delayed task to sync.
  void ScheduleSyncSessionJob(const SyncSessionJob& job);

  // Invoke the Syncer to perform a sync.
  void DoSyncSessionJob(const SyncSessionJob& job);

  // Called after the Syncer has performed the sync represented by |job|, to
  // reset our state.
  void FinishSyncSessionJob(const SyncSessionJob& job);

  // Helper to FinishSyncSessionJob to schedule the next sync operation.
  void ScheduleNextSync(const SyncSessionJob& old_job);

  // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
  void AdjustPolling(const SyncSessionJob* old_job);

  // Helper to restart waiting with |wait_interval_|'s timer.
  void RestartWaiting();

  // Helper to ScheduleNextSync in case of consecutive sync errors.
  void HandleContinuationError(const SyncSessionJob& old_job);

  // Determines if it is legal to run |job| by checking current
  // operational mode, backoff or throttling, freshness
  // (so we don't make redundant syncs), and connection.
  bool ShouldRunJob(const SyncSessionJob& job);

  // Decide whether we should CONTINUE, SAVE or DROP the job.
  JobProcessDecision DecideOnJob(const SyncSessionJob& job);

  // Decide on whether to CONTINUE, SAVE or DROP the job when we are in
  // backoff mode.
  JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job);

  // Saves the job for future execution. Note: It drops all the poll jobs.
  void SaveJob(const SyncSessionJob& job);

  // Coalesces the current job with the pending nudge.
  void InitOrCoalescePendingJob(const SyncSessionJob& job);

  // 'Impl' here refers to real implementation of public functions, running on
  // |thread_|.
  void StopImpl(const base::Closure& callback);
  void ScheduleNudgeImpl(
      const base::TimeDelta& delay,
      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
      const ModelTypeInvalidationMap& invalidation_map,
      bool is_canary_job, const tracked_objects::Location& nudge_location);

  // Returns true if the client is currently in exponential backoff.
  bool IsBackingOff() const;

  // Helper to signal all listeners registered with |session_context_|.
  void Notify(SyncEngineEvent::EventCause cause);

  // Callback to change backoff state.
  void DoCanaryJob();
  void Unthrottle();

  // Executes the pending job. Called whenever an event occurs that may
  // change conditions permitting a job to run. Like when network connection is
  // re-established, mode changes etc.
  void DoPendingJobIfPossible(bool is_canary_job);

  // Called when the root cause of the current connection error is fixed.
  void OnServerConnectionErrorFixed();

  // The pointer is owned by the caller.
  sessions::SyncSession* CreateSyncSession(
      const sessions::SyncSourceInfo& info);

  // Creates a session for a poll and performs the sync.
  void PollTimerCallback();

  // Used to update |connection_code_|, see below.
  void UpdateServerConnectionManagerStatus(
      HttpResponse::ServerConnectionCode code);

  // Called once the first time thread_ is started to broadcast an initial
  // session snapshot containing data like initial_sync_ended.  Important when
  // the client starts up and does not need to perform an initial sync.
  void SendInitialSnapshot();

  // This is used for histogramming and analysis of ScheduleNudge* APIs.
  // SyncScheduler is the ultimate choke-point for all such invocations (with
  // and without InvalidationState variants, all NudgeSources, etc) and as such
  // is the most flexible place to do this bookkeeping.
  void UpdateNudgeTimeRecords(const sessions::SyncSourceInfo& info);

  virtual void OnActionableError(const sessions::SyncSessionSnapshot& snapshot);

  base::WeakPtrFactory<SyncSchedulerImpl> weak_ptr_factory_;

  // A second factory specially for weak_handle_this_, to allow the handle
  // to be const and alleviate threading concerns.
  base::WeakPtrFactory<SyncSchedulerImpl> weak_ptr_factory_for_weak_handle_;

  // For certain methods that need to worry about X-thread posting.
  const WeakHandle<SyncSchedulerImpl> weak_handle_this_;

  // Used for logging.
  const std::string name_;

  // The message loop this object is on.  Almost all methods have to
  // be called on this thread.
  MessageLoop* const sync_loop_;

  // Set in Start(), unset in Stop().
  bool started_;

  // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
  // updated by the server.
  base::TimeDelta syncer_short_poll_interval_seconds_;
  base::TimeDelta syncer_long_poll_interval_seconds_;

  // Server-tweakable sessions commit delay.
  base::TimeDelta sessions_commit_delay_;

  // Periodic timer for polling.  See AdjustPolling.
  base::RepeatingTimer<SyncSchedulerImpl> poll_timer_;

  // The mode of operation.
  Mode mode_;

  // The latest connection code we got while trying to connect.
  HttpResponse::ServerConnectionCode connection_code_;

  // Tracks in-flight nudges so we can coalesce.
  scoped_ptr<SyncSessionJob> pending_nudge_;

  // Current wait state.  Null if we're not in backoff and not throttled.
  scoped_ptr<WaitInterval> wait_interval_;

  scoped_ptr<BackoffDelayProvider> delay_provider_;

  // Invoked to run through the sync cycle.
  scoped_ptr<Syncer> syncer_;

  sessions::SyncSessionContext* session_context_;

  // A map tracking LOCAL NudgeSource invocations of ScheduleNudge* APIs,
  // organized by datatype. Each datatype that was part of the types requested
  // in the call will have its TimeTicks value updated.
  typedef std::map<ModelType, base::TimeTicks> ModelTypeTimeMap;
  ModelTypeTimeMap last_local_nudges_by_model_type_;

  // Used as an "anti-reentrancy defensive assertion".
  // While true, it is illegal for any new scheduling activity to take place.
  // Ensures that higher layers don't break this law in response to events that
  // take place during a sync cycle. We call this out because such violations
  // could result in tight sync loops hitting sync servers.
  bool no_scheduling_allowed_;

  DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl);
};

}  // namespace syncer

#endif  // SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_


text:
'use strict';

const chai = require('chai');
const {expect} = chai;

const schemaUtil = require('../schema.js');
const {SchemaType} = require('../../constant.js');
const logger = require('../../analytics/logger.js');

describe('util - schema', function() {
  before(function() {
    logger.transports.forEach((t) => (t.silent = true));
  });

  describe('validateSchemaType', function() {
    it('validates based on matched schema type', function() {
      const testSchema = {type: SchemaType.STRING};
      const testVal = ' foo bar ';
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal(testVal.trim());
    });

    it('validates based on SchemaType.CUSTOM for unmatched schema type', function() {
      const testSchema = {type: undefined};
      const testVal = ' foo bar ';
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal(testVal);
    });

    it('validates based on custom process method', function() {
      const testSchema = {
        type: SchemaType.CUSTOM,
        process: (v) => parseInt(v, 10),
      };
      const testVal = '123';
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal(123);
    });

    it('validates based on custom validate method', function() {
      const testSchema = {
        type: SchemaType.CUSTOM,
        validate: (v) => ({error: 'test failed'}),
        default: 'abc',
      };
      const testVal = '123';
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal('abc');
    });

    it('returns trimmed value if optional is true and trimmed value is empty string', function() {
      const testSchema = {
        type: SchemaType.IMAGE,
        optional: true,
      };
      const testVal = '  ';
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal('');
    });

    it('returns original value if optional is true and value is undefined', function() {
      const testSchema = {
        type: SchemaType.IMAGE,
        optional: true,
      };
      const testVal = undefined;
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal(testVal);
    });

    it('returns validated value if optional is true & value is not empty or undefined', function() {
      const testSchema = {
        type: SchemaType.STRING,
        optional: true,
      };
      const testVal = ' abc ';
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal('abc');
    });

    it('uses default value if processing failed and default is provided', function() {
      const testSchema = {
        type: SchemaType.IMAGE,
        default: 'abc',
      };
      const testVal = undefined;
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal('abc');
    });

    it('throws error if processing failed and default is not provided', function() {
      const testSchema = {
        type: SchemaType.IMAGE,
      };
      const testVal = undefined;
      expect(() => schemaUtil.validateSchemaType(testVal, testSchema)).to.throw();
    });

    it('uses default value if validation failed and default is provided', function() {
      const testSchema = {
        type: SchemaType.IMAGE,
        default: 'abc',
      };
      const testVal = 'xyz';
      const output = schemaUtil.validateSchemaType(testVal, testSchema);
      expect(output).to.equal('abc');
    });

    it('throws error if validation failed and default is not provided', function() {
      const testSchema = {
        type: SchemaType.IMAGE,
      };
      const testVal = 'xyz';
      expect(() => schemaUtil.validateSchemaType(testVal, testSchema)).to.throw();
    });
  });

  describe('validateObject', function() {
    it('validates fields that exists in fieldSchema', function() {
      const testTarget = {
        name: ' John Smith ',
        age: '29',
        password: ' secret ',
      };
      const testFieldSchema = {
        name: {
          type: SchemaType.STRING,
        },
        age: {
          type: SchemaType.INTEGER,
        },
      };
      const output = schemaUtil.validateObject(testTarget, testFieldSchema);
      expect(output.name).to.equal('John Smith');
      expect(output.age).to.equal(29);
      expect(output.password).to.equal(testTarget.password);
    });

    it('throws error if validated failed and no default value', function() {
      const testTarget1 = {
        link: 'abc',
      };
      const testFieldSchema1 = {
        link: {type: SchemaType.IMAGE},
      };
      expect(() => schemaUtil.validateObject(testTarget1, testFieldSchema1))
        .to.throw()
        .with.property('isJoi', true);

      const testTarget2 = {
        link: {},
      };
      const testFieldSchema2 = {
        link: {type: SchemaType.DATE},
      };
      expect(() => schemaUtil.validateObject(testTarget2, testFieldSchema2))
        .to.throw()
        .not.with.property('isJoi');
    });

    it('replaces property name with new alias if provided in schema', function() {
      const testTarget = {
        USER_NAME: 'abc',
      };
      const testFieldSchema = {
        USER_NAME: {alias: 'name'},
      };
      const output = schemaUtil.validateObject(testTarget, testFieldSchema);
      expect(output.name).to.equal('abc');
      expect(output.USER_NAME).to.be.undefined;
    });
  });

  describe('validateCollection', function() {
    it('validates all objects in input array via schema type', function() {
      const testTargets = [
        {
          name: ' John Smith ',
          age: '29',
        },
        {
          name: ' Kevin Owen ',
          age: '15',
        },
      ];
      const testFieldSchema = {
        name: {
          type: SchemaType.STRING,
        },
        age: {
          type: SchemaType.INTEGER,
        },
      };
      const output = schemaUtil.validateCollection(testTargets, testFieldSchema);
      expect(output).to.eql([{name: 'John Smith', age: 29}, {name: 'Kevin Owen', age: 15}]);
    });
  });

  describe('defaultSchemas', function() {
    const validator = schemaUtil.validateSchemaType;

    describe('SchemaType.CUSTOM', function() {
      const type = SchemaType.CUSTOM;
      const schema = {type};

      it('validates as any values', function() {
        expect(validator('abc', schema)).to.eql('abc');
        expect(validator(123, schema)).to.eql(123);
      });
    });

    describe('SchemaType.BOOLEAN', function() {
      const type = SchemaType.BOOLEAN;
      const schema = {type};

      it('validates truthy values as boolean true', function() {
        expect(validator(true, schema)).to.eql(true);
        expect(validator('YES', schema)).to.eql(true);
      });

      it('validates falsy values as boolean false', function() {
        expect(validator(false, schema)).to.eql(false);
        expect(validator('NO', schema)).to.eql(false);
      });
    });

    describe('SchemaType.INTEGER', function() {
      const type = SchemaType.INTEGER;
      const defaultVal = 999;
      const schema = {type, default: defaultVal};

      it('validates truthy values as integer', function() {
        expect(validator(123, schema)).to.eql(123);
        expect(validator('123', schema)).to.eql(123);
        expect(validator('-123', schema)).to.eql(-123);
      });

      it('fails falsy values', function() {
        expect(validator('abc', schema)).to.eql(defaultVal);
        expect(validator(['a'], schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.FLOAT', function() {
      const type = SchemaType.FLOAT;
      const defaultVal = 99.99;
      const schema = {type, default: defaultVal};

      it('validates truthy values as float', function() {
        expect(validator(12.3, schema)).to.eql(12.3);
        expect(validator('12.3', schema)).to.eql(12.3);
        expect(validator('-12.3', schema)).to.eql(-12.3);
      });

      it('fails falsy values', function() {
        expect(validator('abc', schema)).to.eql(defaultVal);
        expect(validator(['a'], schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.SSML', function() {
      const type = SchemaType.SSML;
      const defaultVal = '<speak>foo</speak>';
      const schema = {type, default: defaultVal};

      it('validates truthy values as cleaned ssml string', function() {
        expect(validator(' < speak> \u{1f9ff} abc \u{1f300} < /speak> ', schema)).to.eql(
          '<speak>abc</speak>'
        );
      });

      it('uses default value for falsy values', function() {
        expect(validator(undefined, schema)).to.eql(defaultVal);
        expect(validator(null, schema)).to.eql(defaultVal);
        expect(validator(false, schema)).to.eql(defaultVal);
        expect(validator(NaN, schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.STRING', function() {
      const type = SchemaType.STRING;
      const defaultVal = 'default string';
      const schema = {type, default: defaultVal};

      it('validates truthy values as trimmed string', function() {
        expect(validator('  hello ', schema)).to.eql('hello');
      });

      it('uses default value for falsy values', function() {
        expect(validator(undefined, schema)).to.eql(defaultVal);
        expect(validator(null, schema)).to.eql(defaultVal);
        expect(validator(false, schema)).to.eql(defaultVal);
        expect(validator(NaN, schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.STRING_LIST', function() {
      const type = SchemaType.STRING_LIST;
      const defaultVal = [];
      const schema = {type, default: defaultVal};

      it('validates truthy values as trimmed string array', function() {
        expect(validator([' hello '], schema)).to.eql(['hello']);
        expect(validator(' hello ', schema)).to.eql(['hello']);
      });
    });

    describe('SchemaType.IMAGE', function() {
      const type = SchemaType.IMAGE;
      const defaultVal = 'default image';
      const schema = {type, default: defaultVal};

      it('validates truthy values as image uri link value', function() {
        const link = ' https://www.google.com/ ';
        expect(validator(link, schema)).to.eql(link.trim());
        expect(validator({contentUrl: link}, schema)).to.eql(link.trim());
      });

      it('fails invalided uri image link value', function() {
        const link = 'www.google.com/';
        expect(validator(link, schema)).to.eql(defaultVal);
        expect(validator({contentUrl: link}, schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.URL', function() {
      const type = SchemaType.URL;
      const defaultVal = 'default url';
      const schema = {type, default: defaultVal};

      it('validates truthy values as uri link value', function() {
        const link = ' https://www.google.com/ ';
        expect(validator(link, schema)).to.eql(link.trim());
      });

      it('fails invalided uri link value', function() {
        const link = ' www.google.com/ ';
        expect(validator(link, schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.URL_LIST', function() {
      const type = SchemaType.URL_LIST;
      const defaultVal = 'default url';
      const schema = {type, default: defaultVal};

      it('validates truthy values as uri links', function() {
        const links = ['https://www.google.com/', 'https://www.aol.com/'];
        expect(validator(links, schema)).to.eql(links);
      });

      it('fails invalided uri links', function() {
        const links = ['www.google.com/', 'https://www.aol.com/'];
        expect(validator(links, schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.GOOGLE_FONT', function() {
      const type = SchemaType.GOOGLE_FONT;
      const defaultVal = 'default url';
      const schema = {type, default: defaultVal};

      it('validates truthy values as valid Google Font url', function() {
        const link = ' https://fonts.googleapis.com/css?family=Roboto ';
        expect(validator(link, schema)).to.eql(link.trim());
      });

      it('fails invalid uri link value', function() {
        const link = 'https://www.google.com/';
        expect(validator(link, schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.COLOR_HEX', function() {
      const type = SchemaType.COLOR_HEX;
      const defaultVal = 'default hex';
      const schema = {type, default: defaultVal};

      it('validates truthy values as cleaned color hex string', function() {
        expect(validator('CDE', schema)).to.eql('#CDE');
        expect(validator('cde', schema)).to.eql('#cde');
        expect(validator('123CDE', schema)).to.eql('#123CDE');
        expect(validator('#ABC', schema)).to.eql('#ABC');
        expect(validator('#ABC123', schema)).to.eql('#ABC123');
        expect(validator('##ABC', schema)).to.eql('#ABC');
      });

      it('fails invalided color hex', function() {
        expect(validator('', schema)).to.eql(defaultVal);
        expect(validator('#', schema)).to.eql(defaultVal);
        expect(validator('#12ABC', schema)).to.eql(defaultVal);
        expect(validator('1234ABC', schema)).to.eql(defaultVal);
        expect(validator('123XYZ', schema)).to.eql(defaultVal);
      });
    });

    describe('SchemaType.DATE', function() {
      const type = SchemaType.DATE;
      const defaultVal = 'default date';
      const schema = {type, default: defaultVal};

      it('validates truthy values as parsed date', function() {
        const convertedDate1 = new Date('2018-10-20');
        const convertedDate2 = new Date('10-20-2018');
        expect(validator('2018-10-20', schema)).to.eql(convertedDate1);
        expect(validator('2018/10/20', schema)).to.eql(convertedDate2);
        expect(validator('10-20-2018', schema)).to.eql(convertedDate2);
        expect(validator('10/20/2018', schema)).to.eql(convertedDate2);
      });

      it('fails invalid date value', function() {
        expect(validator('20a9-10-20', schema)).to.eql(defaultVal);
        expect(validator('abc', schema)).to.eql(defaultVal);
        expect(validator('5@-20-99', schema)).to.eql(defaultVal);
        expect(validator('g123', schema)).to.eql(defaultVal);
      });
    });
  });
});

redpajama_set_name: RedPajamaGithub


text:
<md-content ng-controller="prodTabParcelasController as vm">

            <md-button class="md-button"
                       ng-hide="vm.mostrarForm"
                       ng-click="vm.habilitarCreacionDeNuevaParcela()">
                <ng-md-icon icon="add"></ng-md-icon> Nueva parcela
            </md-button>

        <md-input-container ng-show="vm.mostrarForm">
            Nombre de la parcela
            <input ng-model="vm.parcelaObject.display"
                   id="parcelaInput"
                   ng-keyup="vm.checkIfEnter($event)"
                   required
                   autofocus>

Debe especificar un nombre de parcela

        </md-input-container>
        <md-input-container ng-show="vm.mostrarForm">
            Hectáreas
            <input ng-model="vm.parcelaObject.hectareas"
                   ng-keyup="vm.checkIfEnter($event)"
                   required>

Debe especificar las hectáreas

        </md-input-container>

            <md-input-container>
                Departamento
                <md-select ng-model="vm.departamentoSeleccionado" ng-change="vm.establecerDistritos()"
                           required>
                    <md-option ng-repeat="departamento in vm.departamentos" value="{{departamento.id}}">{{departamento.display}}</md-option>
                </md-select>

Debe especificar el departamento

            </md-input-container>
            <md-input-container>
                Distrito
                <md-select ng-model="vm.distritoSeleccionado"
                           required>
                    <md-option ng-repeat="distrito in vm.distritos" value="{{distrito.id}}">{{distrito.display}}</md-option>
                </md-select>

Debe especificar el distrito o municipio

            </md-input-container>

                <md-button class="md-button md-primary md-raised"
                           ng-disabled="vm.submitting || !(vm.parcelaObject.display.length > 0) || !(vm.parcelaObject.hectareas.length > 0)  || !vm.parcelaObject"
                           ng-click="vm.submit()">
                    {{vm.formIsEditing ? 'Actualizar parcela' : 'Registrar nueva parcela'}}
                </md-button>

                <md-button  ng-click="vm.cancel()" class="md-button">Cancelar</md-button>

    <md-list class="width-xs">
        <md-list-item ng-repeat="parcela in vm.parcelas"
                      ng-hide="parcela.eliminado && vm.ocultarEliminados">

 {{parcela.display}}

            {{parcela.hectareas}} ha

            <md-button class="md-icon-button md-secondary" aria-label="edit"
                       ng-if="vm.tienePermiso"
                       ng-click="vm.mostrarOpciones($event, parcela)">
                <ng-md-icon icon="more_horiz"></ng-md-icon>
            </md-button>
        </md-list-item>
    </md-list>

    <md-subheader class="md-no-sticky" ng-show="vm.parcelas.length > 0"
                  ng-if="vm.tienePermiso">
        Tiene {{vm.parcelas.length}} parcelas.
        {{vm.ocultarEliminados ? 'Mostrar' : 'Ocultar'}} parcelas eliminadas.
    </md-subheader>
    <md-subheader class="md-no-sticky"
                  ng-hide="vm.parcelas.length > 0"
                  ng-if="vm.tienePermiso">
        No tiene ninguna parcela. Registre una
    </md-subheader>
</md-content>


text:
Simple collision detection routines.

--]]

local M = {}

--- A simple circle collision test between entities.
-- A collision is true if any part of the circles, even a single point,
-- overlap in space.
-- @param ax {number} Center x of first entity.
-- @param ay {number} Center y of first entity.
-- @param ar {number} Radius of first entity.
-- @param bx {number} Center x of second entity.
-- @param by {number} Center y of second entity.
-- @param br {number} Radius of second entity.
-- @return {boolean} true if collision, false if not.
local circle = function(ax, ay, ar, bx, by, br)
    return (ax - bx)^2 + (ay - by)^2 <= (ar + br)^2;
end
-- Export
M.circle = circle

return M


text:
from openturns import *

TESTPREAMBLE()

try:
    levels = NumericalPoint(2, 0.0)
    levels.setName("levels")
    levels[0] = 4
    levels[1] = 4
    myPlane = Box(levels)
    print "myPlane = ", myPlane
    sample = myPlane.generate()
    print "sample = ", repr(sample)

except:
    import sys
    print "t_Box_std.py", sys.exc_type, sys.exc_value


text:
/**
 * Created by liuhao on 8/17/15.
 */

var user = require('../models/users');

var express = require('express');
var userRouter = express.Router();

//TODO
userRouter.get('/find/:id', user.find);
//userRouter.get(/\/find\/?/, user.find);
userRouter.post('/login', user.login);
userRouter.post('/reg', user.regist);
userRouter.post('/edit', user.edit);

module.exports = userRouter;


text:
trait Assoc {
    type Output;
}

default impl<T> Assoc for T {
    type Output = bool;
}

impl Assoc for u8 { type Output = u8; }
impl Assoc for u16 { type Output = u16; }

trait Foo {}
impl Foo for u32 {}
impl Foo for <u8 as Assoc>::Output {}
impl Foo for <u16 as Assoc>::Output {}

fn main() {}


text:
package org.jadira.usertype.dateandtime.jsr310.columnmapper;

import javax.time.calendar.LocalTime;

import org.jadira.usertype.spi.shared.AbstractIntegerColumnMapper;

public class IntegerColumnLocalTimeMapper extends AbstractIntegerColumnMapper<LocalTime> {

    private static final long serialVersionUID = -3448788221055335510L;

    @Override
    public LocalTime fromNonNullString(String s) {
        return LocalTime.parse(s);
    }

    @Override
    public LocalTime fromNonNullValue(Integer value) {
        final long nanos = value * 1000000L;
        return LocalTime.ofNanoOfDay(nanos);
    }

    @Override
    public String toNonNullString(LocalTime value) {
        return value.toString();
    }

    @Override
    public Integer toNonNullValue(LocalTime value) {
        final Integer integer = (int) (value.toNanoOfDay() / 1000000);
        return integer;
    }
}


text:
```
#### CNCF Project Name
##### Title

- Description:
- Recommended Skills:
- Mentor(s):
- Upstream Issue (URL):
```

### Sample:

#### Prometheus
##### Refactor the APIs for better readability and less maintenance overhead

- Description: Currently the HTTP API is not very well organized and needs some tidying up. The actual course of action is not decided yet, but [go-kit](https://github.com/go-kit/kit) looks like a good fit.
- Recommended Skills: golang
- Mentor(s): Krasi Georgiev (@krasi-georgiev)
- Issue: https://github.com/prometheus/prometheus/issues/3416


text:
module PrettyError

SyntaxErrorDetails = Struct.new(
  :index, :file, :line, :description, :buffer, :width, :source, :st_nodes
)

class SyntaxErrorDetails
  include BoxFormatting

  def initialize(index, file, line, error_text, buffer, width, range_width = 2)
    error_column =
      if error_text =~ /^( *)\^$/
        # then this is one of those syntax errors with extra info about
        # where in the line the syntax error occurs
        error_column = $1.length
      else 0
      end

    lines, markup = FILE_CACHE.fetch( file )

    source = lines ? extract_source( lines, line, error_column, range_width ) :
              '( unable to extract source )'
    st_nodes = markup ? extract_nodes( markup, line ) : nil

    description = ( error_text =~ /$/ && $` )  # first line
    super( index, file, line, description, buffer, width, source, st_nodes )
  end

  alias depth index

  def format
    format_head
    box_line( description, :center )
    if st_nodes and not st_nodes.empty?
      format_nodes
    else
      buffer.puts( '╠' << ( '═' * ( width - 2 ) ) << '╣' )
    end
    format_source
    return( buffer )
  end

  def location
    "#{ format_path( file ) } @ #{ line }"
  end

private

  def format_head
    super
    buffer.print( '╠═════╧' )
    buffer.print( '═' * ( width - 8 ) )
    buffer.puts( '╣' )
    box_line( description, :center )
  end

  def open_node_table( line_digits )
    buffer.print( '╠' )
    buffer.print( '═' * ( width - 8 - 2 * line_digits ) )
    2.times do
      buffer.print( '╤' )
      buffer.print( '═' * ( line_digits + 2 ) )
    end
    buffer.puts( '╣' )
  end

  def extract_source( source_lines, line_no, error_column, range_width )
    max = source_lines.length
    start  = ( line_no - range_width ).at_least( 1 )
    finish = ( line_no + range_width ).at_most( max )

    line_format = "%0#{ finish.digits }i | %s"
    code = source_lines[ start - 1 .. finish - 1 ]
    error_line = code[ line_no - start ].to_s.dup
    error_line.insert( error_line.length - $/.length, ' <~~~ ' )
    error_line.insert( error_column, ' ~~~> ' ) rescue nil
    code[ line_no - start ] = error_line
    code = code.join( '' ).expand_tabs( 4 ).fixed_indent( 0 )

    source = ''
    code.each_line.with_index do | line, offset |
      current_line = start + offset
      prefix = current_line == line_no ? '==> ' : '    '
      source << prefix << ( line_format % [ current_line, line ] )
    end

    return( source )
  end

end
end


text:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".log.LogCacheActivity" >

    <RatingBar
        android:id="@+id/gcvoteRating"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:max="5"
        android:numStars="5"
        android:stepSize="0.5"
        android:visibility="gone"
        tools:visibility="visible"
        tools:rating="2"/>

    <TextView
        android:id="@+id/voteLabel"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:padding="10dip"
        android:text="@string/log_no_rating"
        android:textSize="@dimen/textSize_detailsSecondary"
        android:visibility="gone"
        tools:visibility="visible"/>

</merge>


text:
#include "stdafx.h"
#include "../dokani.h"
#include "fileinfo.h"
#include "../Common/Log/NtLogString.h"
#include "../Common/Log/NdLog.h"

VOID OnFileOpenSucceed(
    __inout PEVENT_INFORMATION pEventInfo,
    __in DWORD dwNtDisposition,
    __in LONG status,
    __in BOOL isDirectory
    )
{
    pEventInfo->Status = STATUS_SUCCESS;
    pEventInfo->Create.Information = FILE_OPENED;

    if (dwNtDisposition == FILE_CREATE ||
        dwNtDisposition == FILE_OPEN_IF ||
        dwNtDisposition == FILE_OVERWRITE_IF)
    {
        if (status == ERROR_ALREADY_EXISTS || status == ERROR_FILE_EXISTS)
        {
            if (dwNtDisposition == FILE_OPEN_IF)
            {
                pEventInfo->Create.Information = FILE_OPENED;
            }
            else if (dwNtDisposition == FILE_OVERWRITE_IF)
            {
                pEventInfo->Create.Information = FILE_OVERWRITTEN;
            }
        }
        else
        {
            pEventInfo->Create.Information = FILE_CREATED;
        }
    }

    if ((dwNtDisposition == FILE_OVERWRITE_IF || dwNtDisposition == FILE_OVERWRITE) &&
        pEventInfo->Create.Information != FILE_CREATED)
    {
        pEventInfo->Create.Information = FILE_OVERWRITTEN;
    }

    if (isDirectory)
    {
        pEventInfo->Create.Flags |= FILE_DIRECTORY_FILE;
    }
}

VOID
DispatchCreate(
    HANDLE hDevice, // This handle is not for a file. It is for Dokan Device Driver(which is doing EVENT_WAIT).
    PEVENT_CONTEXT pEventContext,
    PDOKAN_INSTANCE	pDokanInstance)
{
    logw(L"Start");
    static int eventId = 0;
    ULONG cbEventInformation = sizeof(EVENT_INFORMATION);
    PEVENT_INFORMATION pEventInfo = (PEVENT_INFORMATION)malloc(cbEventInformation);
    int	status = STATUS_INSUFFICIENT_RESOURCES;
    DOKAN_FILE_INFO	fileInfo;
    DWORD dwNtDisposition;
    PDOKAN_OPEN_INFO pOpenInfo;
    BOOL directoryRequested = FALSE;
    DWORD options;

    CheckFileName(pEventContext->Create.FileName);

    RtlZeroMemory(pEventInfo, cbEventInformation);
    RtlZeroMemory(&fileInfo, sizeof(DOKAN_FILE_INFO));

    pEventInfo->BufferLength = 0;
    pEventInfo->SerialNumber = pEventContext->SerialNumber;

    fileInfo.ProcessId = pEventContext->ProcessId;
    fileInfo.DokanOptions = pDokanInstance->DokanOptions;

    // DOKAN_OPEN_INFO is structure for a opened file
    // this will be freed by Close
    pOpenInfo = (PDOKAN_OPEN_INFO)malloc(sizeof(DOKAN_OPEN_INFO));
    if (pOpenInfo == nullptr)
    {
        pEventInfo->Status = (ULONG)STATUS_INSUFFICIENT_RESOURCES;
        SendEventInformation(hDevice, pEventInfo, cbEventInformation, nullptr);
        return;
    }
    ZeroMemory(pOpenInfo, sizeof(DOKAN_OPEN_INFO));
    pOpenInfo->OpenCount = 2;
    pOpenInfo->EventContext = pEventContext;
    pOpenInfo->DokanInstance = pDokanInstance;
    fileInfo.DokanContext = (ULONG64)pOpenInfo;

    // pass it to driver and when the same handle is used get it back
    pEventInfo->Context = (ULONG64)pOpenInfo;

    // The high 8 bits of this parameter correspond to the Disposition parameter
    dwNtDisposition = (pEventContext->Create.CreateOptions >> 24) & 0x000000ff;

    // The low 24 bits of this member correspond to the CreateOptions parameter
    options = pEventContext->Create.CreateOptions & FILE_VALID_OPTION_FLAGS;
    //DbgPrint("Create.CreateOptions 0x%x\n", options);

    // to open directory
    // even if this flag is not specifed,
    // there is a case to open a directory
    if (options & FILE_DIRECTORY_FILE)
    {
        directoryRequested = TRUE;
    }

    // to open no directory file
    // event if this flag is not specified,
    // there is a case to open non directory file
    if (options & FILE_NON_DIRECTORY_FILE)
    {
        logw(L"FILE_NON_DIRECTORY_FILE");
    }

    if (options & FILE_DELETE_ON_CLOSE)
    {
        pEventContext->Create.FileAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
    }

    logw(L"###Create %04d", eventId);
    pOpenInfo->EventId = eventId++;

    logw(L"Path<%s>, NtDisposition<%s>, FileAttributes<>",
        pEventContext->Create.FileName,
        GetNtCreateDispositionStr(dwNtDisposition)
        );

    // make a directory or open
    if (directoryRequested)
    {
        fileInfo.IsDirectory = TRUE;

        if (dwNtDisposition == FILE_CREATE || dwNtDisposition == FILE_OPEN_IF)
        {
            if (pDokanInstance->DokanOperations->CreateDirectory)
            {
                status = pDokanInstance->DokanOperations->CreateDirectory(pEventContext->Create.FileName, &fileInfo);
            }
        }
        else if (dwNtDisposition == FILE_OPEN)
        {
            if (pDokanInstance->DokanOperations->OpenDirectory)
            {
                status = pDokanInstance->DokanOperations->OpenDirectory(pEventContext->Create.FileName, &fileInfo);
            }
        }
        else
        {
            logw(L"### Create other disposition : %d", dwNtDisposition);
        }
    }
    else
    {
        // open a file
        DWORD creationDisposition = OPEN_EXISTING;
        fileInfo.IsDirectory = FALSE;
        logw(L"   CreateDisposition %0x08X", dwNtDisposition);
        switch (dwNtDisposition)
        {
            case FILE_CREATE:
                creationDisposition = CREATE_NEW;
                break;
            case FILE_OPEN:
                creationDisposition = OPEN_EXISTING;
                break;
            case FILE_OPEN_IF:
                creationDisposition = OPEN_ALWAYS;
                break;
            case FILE_OVERWRITE:
                creationDisposition = TRUNCATE_EXISTING;
                break;
            case FILE_OVERWRITE_IF:
                creationDisposition = CREATE_ALWAYS;
                break;
            default:
                // TODO: should support FILE_SUPERSEDE ?
                logw(L"### Create other disposition : %d", dwNtDisposition);
                break;
        }

        if (pDokanInstance->DokanOperations->CreateFile)
        {
            status = pDokanInstance->DokanOperations->CreateFile(
                pEventContext->Create.FileName,
                pEventContext->Create.DesiredAccess,
                pEventContext->Create.ShareAccess,
                creationDisposition,
                pEventContext->Create.FileAttributes,
                &fileInfo);
        }
    }

    // save the information about this access in DOKAN_OPEN_INFO
    pOpenInfo->IsDirectory = fileInfo.IsDirectory;
    pOpenInfo->UserContext = fileInfo.Context;

    // FILE_CREATED
    // FILE_DOES_NOT_EXIST
    // FILE_EXISTS
    // FILE_OPENED
    // FILE_OVERWRITTEN
    // FILE_SUPERSEDED

    logw(L"CreateFile status = 0x%08X", status);
    if (status != STATUS_SUCCESS)
    {
        if (pEventContext->Flags & SL_OPEN_TARGET_DIRECTORY)
        {
            logw(L"SL_OPEN_TARGET_DIRECTORY spcefied");
        }
        pEventInfo->Create.Information = FILE_DOES_NOT_EXIST;
        pEventInfo->Status = status;

        if (status == STATUS_OBJECT_NAME_NOT_FOUND && pEventContext->Flags & SL_OPEN_TARGET_DIRECTORY)
        {
            logw(L"This case should be returned as SUCCESS");
            pEventInfo->Status = STATUS_SUCCESS;
        }

        if (status == STATUS_OBJECT_NAME_COLLISION)
        {
            pEventInfo->Create.Information = FILE_EXISTS;
        }

        if (pEventInfo->Status != STATUS_SUCCESS)
        {
            // Needs to free openInfo because Close is never called.
            free(pOpenInfo);
            pEventInfo->Context = 0;
        }
    }
    else
    {
        //
        // This is the case for opening file successfully.
        // Depending on the disposition value which came from IRP,
        // we should set the proper value to the Information field of Irp and return it to driver.
        //
        OnFileOpenSucceed(pEventInfo, dwNtDisposition, status, fileInfo.IsDirectory);
    }

    SendEventInformation(hDevice, pEventInfo, cbEventInformation, pDokanInstance);
    free(pEventInfo);
}


text:
@implementation LCSPropertyListSHA1Hash
+(NSData*)sha1HashFromPropertyList:(id)propertyList
{
    NSString* outError;
    NSData* serializedPropertyList = [NSPropertyListSerialization dataFromPropertyList:propertyList
                                                                                format:NSPropertyListBinaryFormat_v1_0
                                                                      errorDescription:&outError];
    if (!serializedPropertyList) {
        // handle error
        return nil;
    }

    unsigned char md[CC_SHA1_DIGEST_LENGTH];
    unsigned char *md_result;

    md_result = CC_SHA1([serializedPropertyList bytes], [serializedPropertyList length], md);

    if (!md_result) {
        // handle error
        return nil;
    }
    NSData *hash = [NSData dataWithBytes:md length:sizeof(md)];
    return hash;
}
@end