text:
package expression

import (
	"github.com/pingcap/tidb/ast"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/mysql"
	"github.com/pingcap/tidb/parser/opcode"
	"github.com/pingcap/tidb/util/charset"
	"github.com/pingcap/tidb/util/types"
	"github.com/pingcap/tidb/util/types/json"
	"github.com/pingcap/tipb/go-tipb"
)

// baseBuiltinFunc will be contained in every struct that implement builtinFunc interface.
type baseBuiltinFunc struct {
	args   []Expression
	ctx    context.Context
	tp     *types.FieldType
	pbCode tipb.ScalarFuncSig
}

func (b *baseBuiltinFunc) PbCode() tipb.ScalarFuncSig {
	return b.pbCode
}

func (b *baseBuiltinFunc) setPbCode(c tipb.ScalarFuncSig) {
	b.pbCode = c
}

func newBaseBuiltinFunc(ctx context.Context, args []Expression) baseBuiltinFunc {
	return baseBuiltinFunc{
		args: args,
		ctx:  ctx,
		tp:   types.NewFieldType(mysql.TypeUnspecified),
	}
}

// newBaseBuiltinFuncWithTp creates a built-in function signature with specified types of arguments and the return type of the function.
// argTps indicates the types of the args, retType indicates the return type of the built-in function.
// Every built-in function needs determined argTps and retType when we create it.
func newBaseBuiltinFuncWithTp(ctx context.Context, args []Expression, retType types.EvalType, argTps ...types.EvalType) (bf baseBuiltinFunc) {
	if len(args) != len(argTps) {
		panic("unexpected length of args and argTps")
	}
	for i := range args {
		switch argTps[i] {
		case types.ETInt:
			args[i] = WrapWithCastAsInt(ctx, args[i])
		case types.ETReal:
			args[i] = WrapWithCastAsReal(ctx, args[i])
		case types.ETDecimal:
			args[i] = WrapWithCastAsDecimal(ctx, args[i])
		case types.ETString:
			args[i] = WrapWithCastAsString(ctx, args[i])
		case types.ETDatetime:
			args[i] = WrapWithCastAsTime(ctx, args[i], types.NewFieldType(mysql.TypeDatetime))
		case types.ETTimestamp:
			args[i] = WrapWithCastAsTime(ctx, args[i], types.NewFieldType(mysql.TypeTimestamp))
		case types.ETDuration:
			args[i] = WrapWithCastAsDuration(ctx, args[i])
		case types.ETJson:
			args[i] = WrapWithCastAsJSON(ctx, args[i])
		}
	}
	var fieldType *types.FieldType
	switch retType {
	case types.ETInt:
		fieldType = &types.FieldType{
			Tp:      mysql.TypeLonglong,
			Flen:    mysql.MaxIntWidth,
			Decimal: 0,
			Flag:    mysql.BinaryFlag,
		}
	case types.ETReal:
		fieldType = &types.FieldType{
			Tp:      mysql.TypeDouble,
			Flen:    mysql.MaxRealWidth,
			Decimal: types.UnspecifiedLength,
			Flag:    mysql.BinaryFlag,
		}
	case types.ETDecimal:
		fieldType = &types.FieldType{
			Tp:      mysql.TypeNewDecimal,
			Flen:    11,
			Decimal: 0,
			Flag:    mysql.BinaryFlag,
		}
	case types.ETString:
		fieldType = &types.FieldType{
			Tp:      mysql.TypeVarString,
			Flen:    0,
			Decimal: types.UnspecifiedLength,
		}
	case types.ETDatetime:
		fieldType = &types.FieldType{
			Tp:      mysql.TypeDatetime,
			Flen:    mysql.MaxDatetimeWidthWithFsp,
			Decimal: types.MaxFsp,
			Flag:    mysql.BinaryFlag,
		}
	case types.ETTimestamp:
		fieldType = &types.FieldType{
			Tp:      mysql.TypeTimestamp,
			Flen:    mysql.MaxDatetimeWidthWithFsp,
			Decimal: types.MaxFsp,
			Flag:    mysql.BinaryFlag,
		}
	case types.ETDuration:
		fieldType = &types.FieldType{
			Tp:      mysql.TypeDuration,
			Flen:    mysql.MaxDurationWidthWithFsp,
			Decimal: types.MaxFsp,
			Flag:    mysql.BinaryFlag,
		}
	case types.ETJson:
		fieldType = &types.FieldType{
			Tp:      mysql.TypeJSON,
			Flen:    mysql.MaxBlobWidth,
			Decimal: 0,
			Charset: charset.CharsetUTF8,
			Collate: charset.CollationUTF8,
			Flag:    mysql.BinaryFlag,
		}
	}
	if mysql.HasBinaryFlag(fieldType.Flag) && fieldType.Tp != mysql.TypeJSON {
		fieldType.Charset, fieldType.Collate = charset.CharsetBin, charset.CollationBin
	} else {
		fieldType.Charset, fieldType.Collate = charset.CharsetUTF8, charset.CharsetUTF8
	}
	return baseBuiltinFunc{
		args: args,
		ctx:  ctx,
		tp:   fieldType,
	}
}

func (b *baseBuiltinFunc) getArgs() []Expression {
	return b.args
}

func (b *baseBuiltinFunc) evalInt(row []types.Datum) (int64, bool, error) {
	panic("baseBuiltinFunc.evalInt() should never be called.")
}

func (b *baseBuiltinFunc) evalReal(row []types.Datum) (float64, bool, error) {
	panic("baseBuiltinFunc.evalReal() should never be called.")
}

func (b *baseBuiltinFunc) evalString(row []types.Datum) (string, bool, error) {
	panic("baseBuiltinFunc.evalString() should never be called.")
}

func (b *baseBuiltinFunc) evalDecimal(row []types.Datum) (*types.MyDecimal, bool, error) {
	panic("baseBuiltinFunc.evalDecimal() should never be called.")
}

func (b *baseBuiltinFunc) evalTime(row []types.Datum) (types.Time, bool, error) {
	panic("baseBuiltinFunc.evalTime() should never be called.")
}

func (b *baseBuiltinFunc) evalDuration(row []types.Datum) (types.Duration, bool, error) {
	panic("baseBuiltinFunc.evalDuration() should never be called.")
}

func (b *baseBuiltinFunc) evalJSON(row []types.Datum) (json.JSON, bool, error) {
	panic("baseBuiltinFunc.evalJSON() should never be called.")
}

func (b *baseBuiltinFunc) getRetTp() *types.FieldType {
	switch b.tp.EvalType() {
	case types.ETString:
		if b.tp.Flen >= mysql.MaxBlobWidth {
			b.tp.Tp = mysql.TypeLongBlob
		} else if b.tp.Flen >= 65536 {
			b.tp.Tp = mysql.TypeMediumBlob
		}
		if len(b.tp.Charset) <= 0 {
			b.tp.Charset, b.tp.Collate = charset.CharsetUTF8, charset.CollationUTF8
		}
	}
	return b.tp
}

func (b *baseBuiltinFunc) equal(fun builtinFunc) bool {
	funArgs := fun.getArgs()
	if len(funArgs) != len(b.args) {
		return false
	}
	for i := range b.args {
		if !b.args[i].Equal(funArgs[i], b.ctx) {
			return false
		}
	}
	return true
}

func (b *baseBuiltinFunc) getCtx() context.Context {
	return b.ctx
}

// builtinFunc stands for a particular function signature.
type builtinFunc interface {
	// evalInt evaluates int result of builtinFunc by given row.
	evalInt(row []types.Datum) (val int64, isNull bool, err error)
	// evalReal evaluates real representation of builtinFunc by given row.
	evalReal(row []types.Datum) (val float64, isNull bool, err error)
	// evalString evaluates string representation of builtinFunc by given row.
	evalString(row []types.Datum) (val string, isNull bool, err error)
	// evalDecimal evaluates decimal representation of builtinFunc by given row.
	evalDecimal(row []types.Datum) (val *types.MyDecimal, isNull bool, err error)
	// evalTime evaluates DATE/DATETIME/TIMESTAMP representation of builtinFunc by given row.
	evalTime(row []types.Datum) (val types.Time, isNull bool, err error)
	// evalDuration evaluates duration representation of builtinFunc by given row.
	evalDuration(row []types.Datum) (val types.Duration, isNull bool, err error)
	// evalJSON evaluates JSON representation of builtinFunc by given row.
	evalJSON(row []types.Datum) (val json.JSON, isNull bool, err error)
	// getArgs returns the arguments expressions.
	getArgs() []Expression
	// equal check if this function equals to another function.
	equal(builtinFunc) bool
	// getCtx returns this function's context.
	getCtx() context.Context
	// getRetTp returns the return type of the built-in function.
	getRetTp() *types.FieldType
	// setPbCode sets pbCode for signature.
	setPbCode(tipb.ScalarFuncSig)
	// PbCode returns PbCode of this signature.
	PbCode() tipb.ScalarFuncSig
}

// baseFunctionClass will be contained in every struct that implement functionClass interface.
type baseFunctionClass struct {
	funcName string
	minArgs  int
	maxArgs  int
}

func (b *baseFunctionClass) verifyArgs(args []Expression) error {
	l := len(args)
	if l < b.minArgs || (b.maxArgs != -1 && l > b.maxArgs) {
		return ErrIncorrectParameterCount.GenByArgs(b.funcName)
	}
	return nil
}

// functionClass is the interface for a function which may contains multiple functions.
type functionClass interface {
	// getFunction gets a function signature by the types and the counts of given arguments.
	getFunction(ctx context.Context, args []Expression) (builtinFunc, error)
}

// funcs holds all registered builtin functions.
var funcs = map[string]functionClass{
	// common functions
	ast.Coalesce: &coalesceFunctionClass{baseFunctionClass{ast.Coalesce, 1, -1}},
	ast.IsNull:   &isNullFunctionClass{baseFunctionClass{ast.IsNull, 1, 1}},
	ast.Greatest: &greatestFunctionClass{baseFunctionClass{ast.Greatest, 2, -1}},
	ast.Least:    &leastFunctionClass{baseFunctionClass{ast.Least, 2, -1}},
	ast.Interval: &intervalFunctionClass{baseFunctionClass{ast.Interval, 2, -1}},

	// math functions
	ast.Abs:      &absFunctionClass{baseFunctionClass{ast.Abs, 1, 1}},
	ast.Acos:     &acosFunctionClass{baseFunctionClass{ast.Acos, 1, 1}},
	ast.Asin:     &asinFunctionClass{baseFunctionClass{ast.Asin, 1, 1}},
	ast.Atan:     &atanFunctionClass{baseFunctionClass{ast.Atan, 1, 2}},
	ast.Atan2:    &atanFunctionClass{baseFunctionClass{ast.Atan2, 2, 2}},
	ast.Ceil:     &ceilFunctionClass{baseFunctionClass{ast.Ceil, 1, 1}},
	ast.Ceiling:  &ceilFunctionClass{baseFunctionClass{ast.Ceiling, 1, 1}},
	ast.Conv:     &convFunctionClass{baseFunctionClass{ast.Conv, 3, 3}},
	ast.Cos:      &cosFunctionClass{baseFunctionClass{ast.Cos, 1, 1}},
	ast.Cot:      &cotFunctionClass{baseFunctionClass{ast.Cot, 1, 1}},
	ast.CRC32:    &crc32FunctionClass{baseFunctionClass{ast.CRC32, 1, 1}},
	ast.Degrees:  &degreesFunctionClass{baseFunctionClass{ast.Degrees, 1, 1}},
	ast.Exp:      &expFunctionClass{baseFunctionClass{ast.Exp, 1, 1}},
	ast.Floor:    &floorFunctionClass{baseFunctionClass{ast.Floor, 1, 1}},
	ast.Ln:       &logFunctionClass{baseFunctionClass{ast.Ln, 1, 1}},
	ast.Log:      &logFunctionClass{baseFunctionClass{ast.Log, 1, 2}},
	ast.Log2:     &log2FunctionClass{baseFunctionClass{ast.Log2, 1, 1}},
	ast.Log10:    &log10FunctionClass{baseFunctionClass{ast.Log10, 1, 1}},
	ast.PI:       &piFunctionClass{baseFunctionClass{ast.PI, 0, 0}},
	ast.Pow:      &powFunctionClass{baseFunctionClass{ast.Pow, 2, 2}},
	ast.Power:    &powFunctionClass{baseFunctionClass{ast.Power, 2, 2}},
	ast.Radians:  &radiansFunctionClass{baseFunctionClass{ast.Radians, 1, 1}},
	ast.Rand:     &randFunctionClass{baseFunctionClass{ast.Rand, 0, 1}},
	ast.Round:    &roundFunctionClass{baseFunctionClass{ast.Round, 1, 2}},
	ast.Sign:     &signFunctionClass{baseFunctionClass{ast.Sign, 1, 1}},
	ast.Sin:      &sinFunctionClass{baseFunctionClass{ast.Sin, 1, 1}},
	ast.Sqrt:     &sqrtFunctionClass{baseFunctionClass{ast.Sqrt, 1, 1}},
	ast.Tan:      &tanFunctionClass{baseFunctionClass{ast.Tan, 1, 1}},
	ast.Truncate: &truncateFunctionClass{baseFunctionClass{ast.Truncate, 2, 2}},

	// time functions
	ast.AddDate:          &addDateFunctionClass{baseFunctionClass{ast.AddDate, 3, 3}},
	ast.DateAdd:          &addDateFunctionClass{baseFunctionClass{ast.DateAdd, 3, 3}},
	ast.SubDate:          &subDateFunctionClass{baseFunctionClass{ast.SubDate, 3, 3}},
	ast.DateSub:          &subDateFunctionClass{baseFunctionClass{ast.DateSub, 3, 3}},
	ast.AddTime:          &addTimeFunctionClass{baseFunctionClass{ast.AddTime, 2, 2}},
	ast.ConvertTz:        &convertTzFunctionClass{baseFunctionClass{ast.ConvertTz, 3, 3}},
	ast.Curdate:          &currentDateFunctionClass{baseFunctionClass{ast.Curdate, 0, 0}},
	ast.CurrentDate:      &currentDateFunctionClass{baseFunctionClass{ast.CurrentDate, 0, 0}},
	ast.CurrentTime:      &currentTimeFunctionClass{baseFunctionClass{ast.CurrentTime, 0, 1}},
	ast.CurrentTimestamp: &nowFunctionClass{baseFunctionClass{ast.CurrentTimestamp, 0, 1}},
	ast.Curtime:          &currentTimeFunctionClass{baseFunctionClass{ast.Curtime, 0, 1}},
	ast.Date:             &dateFunctionClass{baseFunctionClass{ast.Date, 1, 1}},
	ast.DateLiteral:      &dateLiteralFunctionClass{baseFunctionClass{ast.DateLiteral, 1, 1}},
	ast.DateFormat:       &dateFormatFunctionClass{baseFunctionClass{ast.DateFormat, 2, 2}},
	ast.DateDiff:         &dateDiffFunctionClass{baseFunctionClass{ast.DateDiff, 2, 2}},
	ast.Day:              &dayOfMonthFunctionClass{baseFunctionClass{ast.Day, 1, 1}},
	ast.DayName:          &dayNameFunctionClass{baseFunctionClass{ast.DayName, 1, 1}},
	ast.DayOfMonth:       &dayOfMonthFunctionClass{baseFunctionClass{ast.DayOfMonth, 1, 1}},
	ast.DayOfWeek:        &dayOfWeekFunctionClass{baseFunctionClass{ast.DayOfWeek, 1, 1}},
	ast.DayOfYear:        &dayOfYearFunctionClass{baseFunctionClass{ast.DayOfYear, 1, 1}},
	ast.Extract:          &extractFunctionClass{baseFunctionClass{ast.Extract, 2, 2}},
	ast.FromDays:         &fromDaysFunctionClass{baseFunctionClass{ast.FromDays, 1, 1}},
	ast.FromUnixTime:     &fromUnixTimeFunctionClass{baseFunctionClass{ast.FromUnixTime, 1, 2}},
	ast.GetFormat:        &getFormatFunctionClass{baseFunctionClass{ast.GetFormat, 2, 2}},
	ast.Hour:             &hourFunctionClass{baseFunctionClass{ast.Hour, 1, 1}},
	ast.LocalTime:        &nowFunctionClass{baseFunctionClass{ast.LocalTime, 0, 1}},
	ast.LocalTimestamp:   &nowFunctionClass{baseFunctionClass{ast.LocalTimestamp, 0, 1}},
	ast.MakeDate:         &makeDateFunctionClass{baseFunctionClass{ast.MakeDate, 2, 2}},
	ast.MakeTime:         &makeTimeFunctionClass{baseFunctionClass{ast.MakeTime, 3, 3}},
	ast.MicroSecond:      &microSecondFunctionClass{baseFunctionClass{ast.MicroSecond, 1, 1}},
	ast.Minute:           &minuteFunctionClass{baseFunctionClass{ast.Minute, 1, 1}},
	ast.Month:            &monthFunctionClass{baseFunctionClass{ast.Month, 1, 1}},
	ast.MonthName:        &monthNameFunctionClass{baseFunctionClass{ast.MonthName, 1, 1}},
	ast.Now:              &nowFunctionClass{baseFunctionClass{ast.Now, 0, 1}},
	ast.PeriodAdd:        &periodAddFunctionClass{baseFunctionClass{ast.PeriodAdd, 2, 2}},
	ast.PeriodDiff:       &periodDiffFunctionClass{baseFunctionClass{ast.PeriodDiff, 2, 2}},
	ast.Quarter:          &quarterFunctionClass{baseFunctionClass{ast.Quarter, 1, 1}},
	ast.SecToTime:        &secToTimeFunctionClass{baseFunctionClass{ast.SecToTime, 1, 1}},
	ast.Second:           &secondFunctionClass{baseFunctionClass{ast.Second, 1, 1}},
	ast.StrToDate:        &strToDateFunctionClass{baseFunctionClass{ast.StrToDate, 2, 2}},
	ast.SubTime:          &subTimeFunctionClass{baseFunctionClass{ast.SubTime, 2, 2}},
	ast.Sysdate:          &sysDateFunctionClass{baseFunctionClass{ast.Sysdate, 0, 1}},
	ast.Time:             &timeFunctionClass{baseFunctionClass{ast.Time, 1, 1}},
	ast.TimeLiteral:      &timeLiteralFunctionClass{baseFunctionClass{ast.TimeLiteral, 1, 1}},
	ast.TimeFormat:       &timeFormatFunctionClass{baseFunctionClass{ast.TimeFormat, 2, 2}},
	ast.TimeToSec:        &timeToSecFunctionClass{baseFunctionClass{ast.TimeToSec, 1, 1}},
	ast.TimeDiff:         &timeDiffFunctionClass{baseFunctionClass{ast.TimeDiff, 2, 2}},
	ast.Timestamp:        &timestampFunctionClass{baseFunctionClass{ast.Timestamp, 1, 2}},
	ast.TimestampLiteral: &timestampLiteralFunctionClass{baseFunctionClass{ast.TimestampLiteral, 1, 2}},
	ast.TimestampAdd:     &timestampAddFunctionClass{baseFunctionClass{ast.TimestampAdd, 3, 3}},
	ast.TimestampDiff:    &timestampDiffFunctionClass{baseFunctionClass{ast.TimestampDiff, 3, 3}},
	ast.ToDays:           &toDaysFunctionClass{baseFunctionClass{ast.ToDays, 1, 1}},
	ast.ToSeconds:        &toSecondsFunctionClass{baseFunctionClass{ast.ToSeconds, 1, 1}},
	ast.UnixTimestamp:    &unixTimestampFunctionClass{baseFunctionClass{ast.UnixTimestamp, 0, 1}},
	ast.UTCDate:          &utcDateFunctionClass{baseFunctionClass{ast.UTCDate, 0, 0}},
	ast.UTCTime:          &utcTimeFunctionClass{baseFunctionClass{ast.UTCTime, 0, 1}},
	ast.UTCTimestamp:     &utcTimestampFunctionClass{baseFunctionClass{ast.UTCTimestamp, 0, 1}},
	ast.Week:             &weekFunctionClass{baseFunctionClass{ast.Week, 1, 2}},
	ast.Weekday:          &weekDayFunctionClass{baseFunctionClass{ast.Weekday, 1, 1}},
	ast.WeekOfYear:       &weekOfYearFunctionClass{baseFunctionClass{ast.WeekOfYear, 1, 1}},
	ast.Year:             &yearFunctionClass{baseFunctionClass{ast.Year, 1, 1}},
	ast.YearWeek:         &yearWeekFunctionClass{baseFunctionClass{ast.YearWeek, 1, 2}},
	ast.LastDay:          &lastDayFunctionClass{baseFunctionClass{ast.LastDay, 1, 1}},

	// string functions
	ast.ASCII:           &asciiFunctionClass{baseFunctionClass{ast.ASCII, 1, 1}},
	ast.Bin:             &binFunctionClass{baseFunctionClass{ast.Bin, 1, 1}},
	ast.Concat:          &concatFunctionClass{baseFunctionClass{ast.Concat, 1, -1}},
	ast.ConcatWS:        &concatWSFunctionClass{baseFunctionClass{ast.ConcatWS, 2, -1}},
	ast.Convert:         &convertFunctionClass{baseFunctionClass{ast.Convert, 2, 2}},
	ast.Elt:             &eltFunctionClass{baseFunctionClass{ast.Elt, 2, -1}},
	ast.ExportSet:       &exportSetFunctionClass{baseFunctionClass{ast.ExportSet, 3, 5}},
	ast.Field:           &fieldFunctionClass{baseFunctionClass{ast.Field, 2, -1}},
	ast.Format:          &formatFunctionClass{baseFunctionClass{ast.Format, 2, 3}},
	ast.FromBase64:      &fromBase64FunctionClass{baseFunctionClass{ast.FromBase64, 1, 1}},
	ast.InsertFunc:      &insertFunctionClass{baseFunctionClass{ast.InsertFunc, 4, 4}},
	ast.Instr:           &instrFunctionClass{baseFunctionClass{ast.Instr, 2, 2}},
	ast.Lcase:           &lowerFunctionClass{baseFunctionClass{ast.Lcase, 1, 1}},
	ast.Left:            &leftFunctionClass{baseFunctionClass{ast.Left, 2, 2}},
	ast.Right:           &rightFunctionClass{baseFunctionClass{ast.Right, 2, 2}},
	ast.Length:          &lengthFunctionClass{baseFunctionClass{ast.Length, 1, 1}},
	ast.LoadFile:        &loadFileFunctionClass{baseFunctionClass{ast.LoadFile, 1, 1}},
	ast.Locate:          &locateFunctionClass{baseFunctionClass{ast.Locate, 2, 3}},
	ast.Lower:           &lowerFunctionClass{baseFunctionClass{ast.Lower, 1, 1}},
	ast.Lpad:            &lpadFunctionClass{baseFunctionClass{ast.Lpad, 3, 3}},
	ast.LTrim:           &lTrimFunctionClass{baseFunctionClass{ast.LTrim, 1, 1}},
	ast.Mid:             &substringFunctionClass{baseFunctionClass{ast.Mid, 3, 3}},
	ast.MakeSet:         &makeSetFunctionClass{baseFunctionClass{ast.MakeSet, 2, -1}},
	ast.Oct:             &octFunctionClass{baseFunctionClass{ast.Oct, 1, 1}},
	ast.Ord:             &ordFunctionClass{baseFunctionClass{ast.Ord, 1, 1}},
	ast.Position:        &locateFunctionClass{baseFunctionClass{ast.Position, 2, 2}},
	ast.Quote:           &quoteFunctionClass{baseFunctionClass{ast.Quote, 1, 1}},
	ast.Repeat:          &repeatFunctionClass{baseFunctionClass{ast.Repeat, 2, 2}},
	ast.Replace:         &replaceFunctionClass{baseFunctionClass{ast.Replace, 3, 3}},
	ast.Reverse:         &reverseFunctionClass{baseFunctionClass{ast.Reverse, 1, 1}},
	ast.RTrim:           &rTrimFunctionClass{baseFunctionClass{ast.RTrim, 1, 1}},
	ast.Space:           &spaceFunctionClass{baseFunctionClass{ast.Space, 1, 1}},
	ast.Strcmp:          &strcmpFunctionClass{baseFunctionClass{ast.Strcmp, 2, 2}},
	ast.Substring:       &substringFunctionClass{baseFunctionClass{ast.Substring, 2, 3}},
	ast.Substr:          &substringFunctionClass{baseFunctionClass{ast.Substr, 2, 3}},
	ast.SubstringIndex:  &substringIndexFunctionClass{baseFunctionClass{ast.SubstringIndex, 3, 3}},
	ast.ToBase64:        &toBase64FunctionClass{baseFunctionClass{ast.ToBase64, 1, 1}},
	ast.Trim:            &trimFunctionClass{baseFunctionClass{ast.Trim, 1, 3}},
	ast.Upper:           &upperFunctionClass{baseFunctionClass{ast.Upper, 1, 1}},
	ast.Ucase:           &upperFunctionClass{baseFunctionClass{ast.Ucase, 1, 1}},
	ast.Hex:             &hexFunctionClass{baseFunctionClass{ast.Hex, 1, 1}},
	ast.Unhex:           &unhexFunctionClass{baseFunctionClass{ast.Unhex, 1, 1}},
	ast.Rpad:            &rpadFunctionClass{baseFunctionClass{ast.Rpad, 3, 3}},
	ast.BitLength:       &bitLengthFunctionClass{baseFunctionClass{ast.BitLength, 1, 1}},
	ast.CharFunc:        &charFunctionClass{baseFunctionClass{ast.CharFunc, 2, -1}},
	ast.CharLength:      &charLengthFunctionClass{baseFunctionClass{ast.CharLength, 1, 1}},
	ast.CharacterLength: &charLengthFunctionClass{baseFunctionClass{ast.CharacterLength, 1, 1}},
	ast.FindInSet:       &findInSetFunctionClass{baseFunctionClass{ast.FindInSet, 2, 2}},

	// information functions
	ast.ConnectionID: &connectionIDFunctionClass{baseFunctionClass{ast.ConnectionID, 0, 0}},
	ast.CurrentUser:  &currentUserFunctionClass{baseFunctionClass{ast.CurrentUser, 0, 0}},
	ast.Database:     &databaseFunctionClass{baseFunctionClass{ast.Database, 0, 0}},
	// This function is a synonym for DATABASE().
	// See http://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_schema
	ast.Schema:       &databaseFunctionClass{baseFunctionClass{ast.Schema, 0, 0}},
	ast.FoundRows:    &foundRowsFunctionClass{baseFunctionClass{ast.FoundRows, 0, 0}},
	ast.LastInsertId: &lastInsertIDFunctionClass{baseFunctionClass{ast.LastInsertId, 0, 1}},
	ast.User:         &userFunctionClass{baseFunctionClass{ast.User, 0, 0}},
	ast.Version:      &versionFunctionClass{baseFunctionClass{ast.Version, 0, 0}},
	ast.Benchmark:    &benchmarkFunctionClass{baseFunctionClass{ast.Benchmark, 2, 2}},
	ast.Charset:      &charsetFunctionClass{baseFunctionClass{ast.Charset, 1, 1}},
	ast.Coercibility: &coercibilityFunctionClass{baseFunctionClass{ast.Coercibility, 1, 1}},
	ast.Collation:    &collationFunctionClass{baseFunctionClass{ast.Collation, 1, 1}},
	ast.RowCount:     &rowCountFunctionClass{baseFunctionClass{ast.RowCount, 0, 0}},
	ast.SessionUser:  &userFunctionClass{baseFunctionClass{ast.SessionUser, 0, 0}},
	ast.SystemUser:   &userFunctionClass{baseFunctionClass{ast.SystemUser, 0, 0}},
	// This function is used to show tidb-server version info.
	ast.TiDBVersion: &tidbVersionFunctionClass{baseFunctionClass{ast.TiDBVersion, 0, 0}},

	// control functions
	ast.If:     &ifFunctionClass{baseFunctionClass{ast.If, 3, 3}},
	ast.Ifnull: &ifNullFunctionClass{baseFunctionClass{ast.Ifnull, 2, 2}},

	// miscellaneous functions
	ast.Sleep:           &sleepFunctionClass{baseFunctionClass{ast.Sleep, 1, 1}},
	ast.AnyValue:        &anyValueFunctionClass{baseFunctionClass{ast.AnyValue, 1, 1}},
	ast.DefaultFunc:     &defaultFunctionClass{baseFunctionClass{ast.DefaultFunc, 1, 1}},
	ast.InetAton:        &inetAtonFunctionClass{baseFunctionClass{ast.InetAton, 1, 1}},
	ast.InetNtoa:        &inetNtoaFunctionClass{baseFunctionClass{ast.InetNtoa, 1, 1}},
	ast.Inet6Aton:       &inet6AtonFunctionClass{baseFunctionClass{ast.Inet6Aton, 1, 1}},
	ast.Inet6Ntoa:       &inet6NtoaFunctionClass{baseFunctionClass{ast.Inet6Ntoa, 1, 1}},
	ast.IsFreeLock:      &isFreeLockFunctionClass{baseFunctionClass{ast.IsFreeLock, 1, 1}},
	ast.IsIPv4:          &isIPv4FunctionClass{baseFunctionClass{ast.IsIPv4, 1, 1}},
	ast.IsIPv4Compat:    &isIPv4CompatFunctionClass{baseFunctionClass{ast.IsIPv4Compat, 1, 1}},
	ast.IsIPv4Mapped:    &isIPv4MappedFunctionClass{baseFunctionClass{ast.IsIPv4Mapped, 1, 1}},
	ast.IsIPv6:          &isIPv6FunctionClass{baseFunctionClass{ast.IsIPv6, 1, 1}},
	ast.IsUsedLock:      &isUsedLockFunctionClass{baseFunctionClass{ast.IsUsedLock, 1, 1}},
	ast.MasterPosWait:   &masterPosWaitFunctionClass{baseFunctionClass{ast.MasterPosWait, 2, 4}},
	ast.NameConst:       &nameConstFunctionClass{baseFunctionClass{ast.NameConst, 2, 2}},
	ast.ReleaseAllLocks: &releaseAllLocksFunctionClass{baseFunctionClass{ast.ReleaseAllLocks, 0, 0}},
	ast.UUID:            &uuidFunctionClass{baseFunctionClass{ast.UUID, 0, 0}},
	ast.UUIDShort:       &uuidShortFunctionClass{baseFunctionClass{ast.UUIDShort, 0, 0}},

	// get_lock() and release_lock() are parsed but do nothing.
	// It is used for preventing error in Ruby's activerecord migrations.
	ast.GetLock:     &lockFunctionClass{baseFunctionClass{ast.GetLock, 2, 2}},
	ast.ReleaseLock: &releaseLockFunctionClass{baseFunctionClass{ast.ReleaseLock, 1, 1}},

	ast.LogicAnd:   &logicAndFunctionClass{baseFunctionClass{ast.LogicAnd, 2, 2}},
	ast.LogicOr:    &logicOrFunctionClass{baseFunctionClass{ast.LogicOr, 2, 2}},
	ast.LogicXor:   &logicXorFunctionClass{baseFunctionClass{ast.LogicXor, 2, 2}},
	ast.GE:         &compareFunctionClass{baseFunctionClass{ast.GE, 2, 2}, opcode.GE},
	ast.LE:         &compareFunctionClass{baseFunctionClass{ast.LE, 2, 2}, opcode.LE},
	ast.EQ:         &compareFunctionClass{baseFunctionClass{ast.EQ, 2, 2}, opcode.EQ},
	ast.NE:         &compareFunctionClass{baseFunctionClass{ast.NE, 2, 2}, opcode.NE},
	ast.LT:         &compareFunctionClass{baseFunctionClass{ast.LT, 2, 2}, opcode.LT},
	ast.GT:         &compareFunctionClass{baseFunctionClass{ast.GT, 2, 2}, opcode.GT},
	ast.NullEQ:     &compareFunctionClass{baseFunctionClass{ast.NullEQ, 2, 2}, opcode.NullEQ},
	ast.Plus:       &arithmeticPlusFunctionClass{baseFunctionClass{ast.Plus, 2, 2}},
	ast.Minus:      &arithmeticMinusFunctionClass{baseFunctionClass{ast.Minus, 2, 2}},
	ast.Mod:        &arithmeticModFunctionClass{baseFunctionClass{ast.Mod, 2, 2}},
	ast.Div:        &arithmeticDivideFunctionClass{baseFunctionClass{ast.Div, 2, 2}},
	ast.Mul:        &arithmeticMultiplyFunctionClass{baseFunctionClass{ast.Mul, 2, 2}},
	ast.IntDiv:     &arithmeticIntDivideFunctionClass{baseFunctionClass{ast.IntDiv, 2, 2}},
	ast.BitNeg:     &bitNegFunctionClass{baseFunctionClass{ast.BitNeg, 1, 1}},
	ast.And:        &bitAndFunctionClass{baseFunctionClass{ast.And, 2, 2}},
	ast.LeftShift:  &leftShiftFunctionClass{baseFunctionClass{ast.LeftShift, 2, 2}},
	ast.RightShift: &rightShiftFunctionClass{baseFunctionClass{ast.RightShift, 2, 2}},
	ast.UnaryNot:   &unaryNotFunctionClass{baseFunctionClass{ast.UnaryNot, 1, 1}},
	ast.Or:         &bitOrFunctionClass{baseFunctionClass{ast.Or, 2, 2}},
	ast.Xor:        &bitXorFunctionClass{baseFunctionClass{ast.Xor, 2, 2}},
	ast.UnaryMinus: &unaryMinusFunctionClass{baseFunctionClass{ast.UnaryMinus, 1, 1}},
	ast.IsTruth:    &isTrueOrFalseFunctionClass{baseFunctionClass{ast.IsTruth, 1, 1}, opcode.IsTruth},
	ast.IsFalsity:  &isTrueOrFalseFunctionClass{baseFunctionClass{ast.IsFalsity, 1, 1}, opcode.IsFalsity},
	ast.Like:       &likeFunctionClass{baseFunctionClass{ast.Like, 3, 3}},
	ast.Regexp:     &regexpFunctionClass{baseFunctionClass{ast.Regexp, 2, 2}},
	ast.Case:       &caseWhenFunctionClass{baseFunctionClass{ast.Case, 1, -1}},
	ast.RowFunc:    &rowFunctionClass{baseFunctionClass{ast.RowFunc, 2, -1}},
	ast.SetVar:     &setVarFunctionClass{baseFunctionClass{ast.SetVar, 2, 2}},
	ast.GetVar:     &getVarFunctionClass{baseFunctionClass{ast.GetVar, 1, 1}},
	ast.BitCount:   &bitCountFunctionClass{baseFunctionClass{ast.BitCount, 1, 1}},

	// encryption and compression functions
	ast.AesDecrypt:               &aesDecryptFunctionClass{baseFunctionClass{ast.AesDecrypt, 2, 3}},
	ast.AesEncrypt:               &aesEncryptFunctionClass{baseFunctionClass{ast.AesEncrypt, 2, 3}},
	ast.Compress:                 &compressFunctionClass{baseFunctionClass{ast.Compress, 1, 1}},
	ast.Decode:                   &decodeFunctionClass{baseFunctionClass{ast.Decode, 2, 2}},
	ast.DesDecrypt:               &desDecryptFunctionClass{baseFunctionClass{ast.DesDecrypt, 1, 2}},
	ast.DesEncrypt:               &desEncryptFunctionClass{baseFunctionClass{ast.DesEncrypt, 1, 2}},
	ast.Encode:                   &encodeFunctionClass{baseFunctionClass{ast.Encode, 2, 2}},
	ast.Encrypt:                  &encryptFunctionClass{baseFunctionClass{ast.Encrypt, 1, 2}},
	ast.MD5:                      &md5FunctionClass{baseFunctionClass{ast.MD5, 1, 1}},
	ast.OldPassword:              &oldPasswordFunctionClass{baseFunctionClass{ast.OldPassword, 1, 1}},
	ast.PasswordFunc:             &passwordFunctionClass{baseFunctionClass{ast.PasswordFunc, 1, 1}},
	ast.RandomBytes:              &randomBytesFunctionClass{baseFunctionClass{ast.RandomBytes, 1, 1}},
	ast.SHA1:                     &sha1FunctionClass{baseFunctionClass{ast.SHA1, 1, 1}},
	ast.SHA:                      &sha1FunctionClass{baseFunctionClass{ast.SHA, 1, 1}},
	ast.SHA2:                     &sha2FunctionClass{baseFunctionClass{ast.SHA2, 2, 2}},
	ast.Uncompress:               &uncompressFunctionClass{baseFunctionClass{ast.Uncompress, 1, 1}},
	ast.UncompressedLength:       &uncompressedLengthFunctionClass{baseFunctionClass{ast.UncompressedLength, 1, 1}},
	ast.ValidatePasswordStrength: &validatePasswordStrengthFunctionClass{baseFunctionClass{ast.ValidatePasswordStrength, 1, 1}},

	// json functions
	ast.JSONType:    &jsonTypeFunctionClass{baseFunctionClass{ast.JSONType, 1, 1}},
	ast.JSONExtract: &jsonExtractFunctionClass{baseFunctionClass{ast.JSONExtract, 2, -1}},
	ast.JSONUnquote: &jsonUnquoteFunctionClass{baseFunctionClass{ast.JSONUnquote, 1, 1}},
	ast.JSONSet:     &jsonSetFunctionClass{baseFunctionClass{ast.JSONSet, 3, -1}},
	ast.JSONInsert:  &jsonInsertFunctionClass{baseFunctionClass{ast.JSONInsert, 3, -1}},
	ast.JSONReplace: &jsonReplaceFunctionClass{baseFunctionClass{ast.JSONReplace, 3, -1}},
	ast.JSONRemove:  &jsonRemoveFunctionClass{baseFunctionClass{ast.JSONRemove, 2, -1}},
	ast.JSONMerge:   &jsonMergeFunctionClass{baseFunctionClass{ast.JSONMerge, 2, -1}},
	ast.JSONObject:  &jsonObjectFunctionClass{baseFunctionClass{ast.JSONObject, 0, -1}},
	ast.JSONArray:   &jsonArrayFunctionClass{baseFunctionClass{ast.JSONArray, 0, -1}},
}


text:
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; report-uri resources/save-report.php?test=eval-blocked-and-sends-report.html">
</head>
<body>
    <script>
        try {
            eval("alert('FAIL')");
        } catch (e) {
            console.log(e);
            console.log('PASS: eval() blocked.');
        }
    </script>
    <script src="resources/go-to-echo-report.js"></script>
</body>
</html>

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>
<html>
    <head>
        <title>Test</title>
        <script src="rtcpeerconnection.bundle.js"></script>
    </head>
    <video id="localVideo" autoplay muted></video>
    <video id="remoteVideo" autoplay="autoplay"></video>

    <script>
var localStream;
var remoteStream;
var pc1 = new PeerConnection({useJingle: true}, {
    optional:[
        //{ andyetBatchIce: 200}
    ]
});
var pc2 = new PeerConnection({useJingle: true}, {
    optional:[
        //{ andyetBatchIce: 200}
    ]
});
pc1.on('ice', function (candidate) {
    console.log('1 -> 2 candidate', candidate);
    pc2.processIce(candidate);
});
pc2.on('ice', function (candidate) {
    console.log('2 -> 1 candidate', candidate);
    pc1.processIce(candidate);
});

pc1.on('iceConnectionStateChange', function () {
    console.log('pc1 iceConnectionStateChange', pc1.iceConnectionState);
});
pc2.on('iceConnectionStateChange', function () {
    console.log('pc2 iceConnectionStateChange', pc2.iceConnectionState);
    if (pc2.iceConnectionState === 'connected' ||
      pc1.iceConnectionState === 'completed') {
    }
});

pc2.on('addStream', function (event) {
    console.log('addStream', event.stream);
    remoteStream = event.stream;
    document.getElementById('remoteVideo').mozSrcObject = event.stream;
});

navigator.mediaDevices.getUserMedia({audio: true, video: true})
.then(function (stream) {
    localStream = stream;
    document.getElementById('localVideo').mozSrcObject = stream;
    pc1.addStream(stream);
    pc1.offer(function (err, offer) {
        if (err) {
            console.error('failed to create offer');
            return;
        }
        console.log('created offer');
        console.log(offer);
        pc2.handleOffer(offer, function (err) {
            if (err) {
                // handle error
                console.error('error handling offer');
                return;
            }
            console.log('handled offer');

            pc2.answer(function (err, answer) {
                if (err) {
                    console.error('error handling answer');
                    return;
                }
                console.log('created answer');
                pc1.handleAnswer(answer, function (err) {
                    if (err) {
                        console.error('failed to handle answer');
                        return;
                    }
                    console.log('handled answer');
                });
            });
        });
    });
});
    </script>
</html>


text:
package org.apache.velocity.test.issues;

import org.apache.velocity.test.BaseTestCase;

/**
 * This class tests VELOCITY-532.
 */
public class Velocity532TestCase extends BaseTestCase
{
    public Velocity532TestCase(String name)
    {
       super(name);
    }

    public void test532()
    {
        String template = "#macro( test )$foreach.count#end"+
                          "#foreach( $i in [1..5] )#test()#end";
        assertEvalEquals("12345", template);
    }

    public void test532b()
    {
        // try something a little more like Matt's example
        String template = "#macro( test $baz )"+
                            "#if( $foo == $null )"+
                              "#if( $foreach.count == 3 )bar#end"+
                            "#end#end"+
                          "#foreach( $i in [1..5] )#test($i)#end";
        assertEvalEquals("bar", template);
    }

}


text:
require File.expand_path('../../../../../../test_helper', __FILE__)
begin
  require 'mocha/setup'

  class GitAdapterTest < ActiveSupport::TestCase
    REPOSITORY_PATH = Rails.root.to_s.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository'

    FELIX_UTF8 = "Felix Schäfer"
    FELIX_HEX  = "Felix Sch\xC3\xA4fer"
    CHAR_1_HEX = "\xc3\x9c"

    ## Ruby uses ANSI api to fork a process on Windows.
    ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
    ## and these are incompatible with ASCII.
    # WINDOWS_PASS = Redmine::Platform.mswin?
    WINDOWS_PASS = false

    if File.directory?(REPOSITORY_PATH)
      def setup
        @adapter = Redmine::Scm::Adapters::GitAdapter.new(
                      REPOSITORY_PATH,
                      nil,
                      nil,
                      nil,
                      'ISO-8859-1'
                      )
        assert @adapter
        @char_1        = CHAR_1_HEX.dup
        if @char_1.respond_to?(:force_encoding)
          @char_1.force_encoding('UTF-8')
        end
      end

      def test_scm_version
        to_test = { "git version 1.7.3.4\n"             => [1,7,3,4],
                    "1.6.1\n1.7\n1.8"                   => [1,6,1],
                    "1.6.2\r\n1.8.1\r\n1.9.1"           => [1,6,2]}
        to_test.each do |s, v|
          test_scm_version_for(s, v)
        end
      end

      def test_branches
        assert_equal  [
              'latin-1-path-encoding',
              'master',
              'test-latin-1',
              'test_branch',
            ], @adapter.branches
      end

      def test_tags
        assert_equal  [
              "tag00.lightweight",
              "tag01.annotated",
            ], @adapter.tags
      end

      def test_getting_all_revisions
        assert_equal 21, @adapter.revisions('',nil,nil,:all => true).length
      end

      def test_getting_certain_revisions
        assert_equal 1, @adapter.revisions('','899a15d^','899a15d').length
      end

      def test_revisions_reverse
        revs1 = @adapter.revisions('',nil,nil,{:all => true, :reverse => true })
        assert_equal 21, revs1.length
        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[0].identifier
        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[20].identifier

        since2 = Time.gm(2010, 9, 30, 0, 0, 0)
        revs2 = @adapter.revisions('',nil,nil,{:all => true, :since => since2, :reverse => true })
        assert_equal 6, revs2.length
        assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', revs2[0].identifier
        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[5].identifier
      end

      def test_getting_revisions_with_spaces_in_filename
        assert_equal 1, @adapter.revisions("filemane with spaces.txt",
                                           nil, nil, :all => true).length
      end

      def test_getting_revisions_with_leading_and_trailing_spaces_in_filename
        assert_equal " filename with a leading space.txt ",
           @adapter.revisions(" filename with a leading space.txt ",
                               nil, nil, :all => true)[0].paths[0][:path]
      end

      def test_getting_entries_with_leading_and_trailing_spaces_in_filename
        assert_equal " filename with a leading space.txt ",
           @adapter.entries('',
                   '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
      end

      def test_annotate
        annotate = @adapter.annotate('sources/watchers_controller.rb')
        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
        assert_equal 41, annotate.lines.size
        assert_equal "# This program is free software; you can redistribute it and/or",
                     annotate.lines[4].strip
        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
                      annotate.revisions[4].identifier
        assert_equal "jsmith", annotate.revisions[4].author
      end

      def test_annotate_moved_file
        annotate = @adapter.annotate('renamed_test.txt')
        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
        assert_equal 2, annotate.lines.size
      end

      def test_last_rev
        last_rev = @adapter.lastrev("README",
                                    "4f26664364207fa8b1af9f8722647ab2d4ac5d43")
        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid
        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier
        assert_equal "Adam Soltys <asoltys@gmail.com>", last_rev.author
        assert_equal "2009-06-24 05:27:38".to_time, last_rev.time
      end

      def test_last_rev_with_spaces_in_filename
        last_rev = @adapter.lastrev("filemane with spaces.txt",
                                    "ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
        str_felix_utf8 = FELIX_UTF8.dup
        str_felix_hex  = FELIX_HEX.dup
        last_rev_author = last_rev.author
        if last_rev_author.respond_to?(:force_encoding)
          last_rev_author.force_encoding('UTF-8')
        end
        assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
        assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
        assert_equal "#{str_felix_utf8} <felix@fachschaften.org>",
                       last_rev.author
        assert_equal "#{str_felix_hex} <felix@fachschaften.org>",
                       last_rev.author
        assert_equal "2010-09-18 19:59:46".to_time, last_rev.time
      end

      # TODO: need to handle edge cases of non-binary content that isn't UTF-8
      should_eventually "test_latin_1_path" do
        if WINDOWS_PASS
          #
        else
          p2 = "latin-1-dir/test-#{@char_1}-2.txt"
          ['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
            assert @adapter.diff(p2, r1)
            assert @adapter.cat(p2, r1)
            annotation = @adapter.annotate(p2, r1)
            assert annotation.present?, "No annotation returned"
            assert_equal 1, annotation.lines.length
            ['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
              assert @adapter.diff(p2, r1, r2)
            end
          end
        end
      end

      def test_entries_tag
        entries1 = @adapter.entries(nil, 'tag01.annotated')
        assert entries1
        assert_equal 3, entries1.size
        assert_equal 'sources', entries1[1].name
        assert_equal 'sources', entries1[1].path
        assert_equal 'dir', entries1[1].kind
        readme = entries1[2]
        assert_equal 'README', readme.name
        assert_equal 'README', readme.path
        assert_equal 'file', readme.kind
        assert_equal 27, readme.size
        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
        assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
      end

      def test_entries_branch
        entries1 = @adapter.entries(nil, 'test_branch')
        assert entries1
        assert_equal 4, entries1.size
        assert_equal 'sources', entries1[1].name
        assert_equal 'sources', entries1[1].path
        assert_equal 'dir', entries1[1].kind
        readme = entries1[2]
        assert_equal 'README', readme.name
        assert_equal 'README', readme.path
        assert_equal 'file', readme.kind
        assert_equal 159, readme.size
        assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
        assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
      end

      def test_entries_latin_1_files
        entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
        assert entries1
        assert_equal 3, entries1.size
        f1 = entries1[1]
        assert_equal "test-#{@char_1}-2.txt", f1.name
        assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
        assert_equal 'file', f1.kind
      end

      def test_entries_latin_1_dir
        if WINDOWS_PASS
          #
        else
          entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
                                      '1ca7f5ed')
          assert entries1
          assert_equal 3, entries1.size
          f1 = entries1[1]
          assert_equal "test-#{@char_1}-2.txt", f1.name
          assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
          assert_equal 'file', f1.kind
        end
      end

      private

      def test_scm_version_for(scm_command_version, version)
        @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
        assert_equal version, @adapter.class.scm_command_version
      end

    else
      puts "Git test repository NOT FOUND. Skipping unit tests !!!"
      def test_fake; assert true end
    end
  end

rescue LoadError
  class GitMochaFake < ActiveSupport::TestCase
    def test_fake; assert(false, "Requires mocha to run those tests")  end
  end
end


text:
package org.qcri.rheem.spark.mapping;

import org.qcri.rheem.basic.operators.ReduceByOperator;
import org.qcri.rheem.core.mapping.*;
import org.qcri.rheem.core.types.DataSetType;
import org.qcri.rheem.spark.operators.SparkReduceByOperator;
import org.qcri.rheem.spark.platform.SparkPlatform;

import java.util.Collection;
import java.util.Collections;

/**
 * Mapping from {@link ReduceByOperator} to {@link SparkReduceByOperator}.
 */
@SuppressWarnings("unchecked")
public class ReduceByMapping implements Mapping {

    @Override
    public Collection<PlanTransformation> getTransformations() {
        return Collections.singleton(new PlanTransformation(
                this.createSubplanPattern(),
                this.createReplacementSubplanFactory(),
                SparkPlatform.getInstance()
        ));
    }

    private SubplanPattern createSubplanPattern() {
        final OperatorPattern operatorPattern = new OperatorPattern(
                "reduceBy", new ReduceByOperator<>(null, null, DataSetType.none()), false
        );
        return SubplanPattern.createSingleton(operatorPattern);
    }

    private ReplacementSubplanFactory createReplacementSubplanFactory() {
        return new ReplacementSubplanFactory.OfSingleOperators<ReduceByOperator>(
                (matchedOperator, epoch) -> new SparkReduceByOperator<>(matchedOperator).at(epoch)
        );
    }
}


text: Personal site I made for Alvaro Salas using a Startup Bootstrap theme and his own copy.


text:
package com.asakusafw.runtime.core;

/**
 * Represents a data-flow view.
 * Application developers MUST NOT change the returned objects.
 * @param <T> the data type
 * @since 0.9.1
 */
public interface View<T> extends Iterable<T> {
    // no special members
}


text:
package dynamodb

import "github.com/dynport/gocloud/aws"

type PutItem struct {
	TableName                   string               `json:"TableName,omitempty"`
	Expected                    map[string]*Expected `json:"Expected,omitempty"`
	Item                        Item                 `json:"Item,omitempty"`
	ReturnValues                string               `json:"ReturnValues,omitempty"`
	ReturnConsumedCapacity      string               `json:"ReturnConsumedCapacity,omitempty"`
	ReturnItemCollectionMetrics string               `json:"ReturnItemCollectionMetrics,omitempty"`
}

type Expected struct {
	Exists string          `json:"Exists,omitempty"`
	Value  *ItemDefinition `json:"Value,omitempty"`
}

func (p *PutItem) Execute(client *aws.Client) (*PutItemResponse, error) {
	rsp := &PutItemResponse{}
	e := loadAction(client, "PutItem", p, rsp)
	return rsp, e
}

type PutItemResponse struct{}

type Item map[string]*ItemDefinition

type ItemDefinition struct {
	S  string   `json:"S,omitempty"`
	SS []string `json:"SS,omitempty"`
	B  string   `json:"B,omitempty"`
	BS []string `json:"BS,omitempty"`
	N  string   `json:"N,omitempty"`
	NS []string `json:"NS,omitempty"`
}


text: export default function Exception () {}


text:
function colourAlphaImagesc(mDis, mTime, mColourMap, fAlphaMapper, vBackgrdColour)
%
% Produces a scaled colourmap image that combines both a distance component
% (scaled into colourmap) and also a time component (used to decrease
% alpha/intensity values).
%
% INPUT:
%
% OUTPUT:
%
% @author: Jeffrey Chan, 2013
%

    disClim = [min(min(mDis)), max(max(mDis))];
    timeCLim = [min(min(mTime)), max(max(mTime))];

    colourNum = size(mColourMap,1);

%     % linear mapping into colourmap
%     mNormDis = (mDis - disClim(1)) / (disClim(2) - disClim(1));
    mIndicedDis = min(round((colourNum-1) * (mDis - disClim(1)) / (disClim(2) - disClim(1)) + 1),colourNum);

    mRgb = ind2rgb(mIndicedDis, mColourMap);

%     figure;
%     hold on;
%     subplot(1,2,1);
%     image(mRgb);
%     colormap(mColourMap);

    % linear mapping into alpha
    if timeCLim(2) ~= timeCLim(1)
        mNormTime = (mTime - timeCLim(1)) / (timeCLim(2) - timeCLim(1));
    else
        mNormTime = mTime;
    end
    mAlpha = fAlphaMapper.computeIntensity(mNormTime);

    % background colour of white
%     vBackgrdColour = [0.95,0.95,0.95];
    mNewRgb = rgba2rgb(mRgb, 1 - mAlpha, vBackgrdColour);

%     subplot(1,2,2);
    image(mNewRgb);
%     hold off;
%
%     set(h, 'AlphaData', mAlphaMap);

end % end of function


text:
package build

import (
	"fmt"
	"strings"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	buildapi "github.com/openshift/origin/pkg/build/apis/build"
	"github.com/openshift/origin/pkg/build/controller/common"
)

// buildUpdate holds a set of updates to be made to a build object.
// Only the fields defined in this struct will be updated/patched by this controller.
// The reason this exists is that there isn't separation at the API
// level between build spec and build status. Once that happens, the
// controller should only be able to update the status, while end users
// should be able to update the spec.
type buildUpdate struct {
	podNameAnnotation *string
	phase             *buildapi.BuildPhase
	reason            *buildapi.StatusReason
	message           *string
	startTime         *metav1.Time
	completionTime    *metav1.Time
	duration          *time.Duration
	outputRef         *string
}

func (u *buildUpdate) setPhase(phase buildapi.BuildPhase) {
	u.phase = &phase
}

func (u *buildUpdate) setReason(reason buildapi.StatusReason) {
	u.reason = &reason
}

func (u *buildUpdate) setMessage(message string) {
	u.message = &message
}

func (u *buildUpdate) setStartTime(startTime metav1.Time) {
	u.startTime = &startTime
}

func (u *buildUpdate) setCompletionTime(completionTime metav1.Time) {
	u.completionTime = &completionTime
}

func (u *buildUpdate) setDuration(duration time.Duration) {
	u.duration = &duration
}

func (u *buildUpdate) setOutputRef(ref string) {
	u.outputRef = &ref
}

func (u *buildUpdate) setPodNameAnnotation(podName string) {
	u.podNameAnnotation = &podName
}

func (u *buildUpdate) reset() {
	u.podNameAnnotation = nil
	u.phase = nil
	u.reason = nil
	u.message = nil
	u.startTime = nil
	u.completionTime = nil
	u.duration = nil
	u.outputRef = nil
}

func (u *buildUpdate) isEmpty() bool {
	return u.podNameAnnotation == nil &&
		u.phase == nil &&
		u.reason == nil &&
		u.message == nil &&
		u.startTime == nil &&
		u.completionTime == nil &&
		u.duration == nil &&
		u.outputRef == nil
}

func (u *buildUpdate) apply(build *buildapi.Build) {
	if u.phase != nil {
		build.Status.Phase = *u.phase
	}
	if u.reason != nil {
		build.Status.Reason = *u.reason
	}
	if u.message != nil {
		build.Status.Message = *u.message
	}
	if u.startTime != nil {
		build.Status.StartTimestamp = u.startTime
	}
	if u.completionTime != nil {
		build.Status.CompletionTimestamp = u.completionTime
	}
	if u.duration != nil {
		build.Status.Duration = *u.duration
	}
	if u.podNameAnnotation != nil {
		common.SetBuildPodNameAnnotation(build, *u.podNameAnnotation)
	}
	if u.outputRef != nil {
		build.Status.OutputDockerImageReference = *u.outputRef
	}
}

// String returns a string representation of this update
// Used with %v in string formatting
func (u *buildUpdate) String() string {
	updates := []string{}
	if u.phase != nil {
		updates = append(updates, fmt.Sprintf("phase: %q", *u.phase))
	}
	if u.reason != nil {
		updates = append(updates, fmt.Sprintf("reason: %q", *u.reason))
	}
	if u.message != nil {
		updates = append(updates, fmt.Sprintf("message: %q", *u.message))
	}
	if u.startTime != nil {
		updates = append(updates, fmt.Sprintf("startTime: %q", u.startTime.String()))
	}
	if u.completionTime != nil {
		updates = append(updates, fmt.Sprintf("completionTime: %q", u.completionTime.String()))
	}
	if u.duration != nil {
		updates = append(updates, fmt.Sprintf("duration: %q", u.duration.String()))
	}
	if u.outputRef != nil {
		updates = append(updates, fmt.Sprintf("outputRef: %q", *u.outputRef))
	}
	if u.podNameAnnotation != nil {
		updates = append(updates, fmt.Sprintf("podName: %q", *u.podNameAnnotation))
	}
	return fmt.Sprintf("buildUpdate(%s)", strings.Join(updates, ", "))
}


text:
import axios from 'axios'
import notie from 'notie'

export default async function (endpoint, token, errCb = () => {}) {
  const params = {
    // eslint-disable-next-line camelcase
    access_token: token
  }

  try {
    const data = await axios.get(`https://api.github.com/${endpoint}`, {
      params
    }).then(res => res.data)

    return data
  } catch (err) {
    errCb()
    if (err.response) {
      const { headers, status } = err.response
      if (!token && status === 403 && headers['x-ratelimit-remaining'] === '0') {
        notie.confirm({
          text: 'API rate limit exceeded, do you want to login?',
          submitCallback() {
            Event.$emit('showLogin')
          }
        })
      } else {
        notie.alert({
          type: 'error',
          text: err.response.data.message,
          time: 5
        })
      }
    } else {
      notie.alert({
        type: 'error',
        text: err.message || 'GitHub API Error'
      })
    }
  }

  return {}
}


text:
Simulation
==========

:py:mod:`mne.simulation`:

.. automodule:: mne.simulation
   :no-members:
   :no-inherited-members:

.. currentmodule:: mne.simulation

.. autosummary::
   :toctree: generated/

   add_chpi
   add_ecg
   add_eog
   add_noise
   simulate_evoked
   simulate_raw
   simulate_stc
   simulate_sparse_stc
   select_source_in_label
   SourceSimulator

:py:mod:`mne.simulation.metrics`:

.. automodule:: mne.simulation.metrics
   :no-members:
   :no-inherited-members:

.. currentmodule:: mne.simulation.metrics

.. autosummary::
   :toctree: generated/

   cosine_score
   region_localization_error
   f1_score
   precision_score
   recall_score
   roc_auc_score
   spatial_deviation_error
   peak_position_error


text:
<!doctype html>
<html ng-app="app">

<head>
  <meta charset="utf-8">
  <title>booking API Test Application</title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width">
  <meta name="theme-color" content="#2196f3">
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

  <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->

  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.1/angular-material.min.css">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

</head>

<body ng-cloak layout="column" ng-controller="AppCtrl">
  <app></app>
  <script src="bundle.js"></script>
</body>

</html>


text:
import pyspark

spark = (
    pyspark.sql.SparkSession.builder.appName("FromDatabase")
    .config("spark.driver.extraClassPath", "<driver_location>/postgresql-42.2.18.jar")
    .getOrCreate()
)

# Read table from db using Spark JDBC
def extract_movies_to_df():
    movies_df = (
        spark.read.format("jdbc")
        .option("url", "jdbc:postgresql://localhost:5432/etl_pipeline")
        .option("dbtable", "movies")
        .option("user", "<username")
        .option("password", "<password>")
        .option("driver", "org.postgresql.Driver")
        .load()
    )
    return movies_df

# Read users table from db using Spark JDBC

def extract_users_to_df():
    users_df = (
        spark.read.format("jdbc")
        .option("url", "jdbc:postgresql://localhost:5432/etl_pipeline")
        .option("dbtable", "users")
        .option("user", "<username")
        .option("password", "<password>")
        .option("driver", "org.postgresql.Driver")
        .load()
    )
    return users_df

# transforming tables
def transform_avg_ratings(movies_df, users_df):
    avg_rating = users_df.groupby("movie_id").mean("rating")
    # join movies_df and avg_rating table on id
    df = movies_df.join(avg_rating, movies_df.id == avg_rating.movies_id)
    df = df.drop("movie_id")
    return df

# Write the result into avg_ratings table in db
def load_df_to_db(df):
    mode = "overwrite"
    url = "jdbc:postgresql://localhost:5432/etl_pipeline"
    spark.write()
    properties = {
        "user": "<username>",
        "password": "<password>",
        "driver": "org.postgresql.Driver",
    }
    df.write.jdbc(url=url, table="avg_ratings", mode=mode, properties=properties)

if __name__ == "__main__":
    movies_df = extract_movies_to_df()
    users_df = extract_users_to_df()
    ratings_df = transform_avg_ratings(movies_df, users_df)
    load_df_to_db(ratings_df)


text:
require 'spec_helper'

describe Types::Relation, '.primitive' do
  subject { object.primitive }

  let(:object) { described_class }

  it_should_behave_like 'an idempotent method'

  it { should be(Relation) }
end


text:
NS_LONG_BEGIN

void TaskDataParam::pushString(std::string key, std::string value)
{
    m_strings[key] = value;
}

void TaskDataParam::pushNumber(std::string key, double value)
{
    m_numbers[key] = value;
}

std::string TaskDataParam::getStringValue(std::string key)
{
	if (m_numbers.empty())
	{
		return "";
	}
    for (auto &iter: m_strings)
    {
        if (iter.first == key)
        {
            return iter.second;
        }
    }
    return "";
}

double TaskDataParam::getNumberValue(std::string key)
{
	if (m_numbers.empty())
	{
		return 0;
	}
    for (auto &iter: m_numbers)
    {
        if (iter.first == key)
        {
            return iter.second;
        }
    }
    return 0;
}

std::string TaskData::getID()
{
    return m_id;
};

std::function<void()> TaskData::getTaskFunction()
{
    return m_taskFunction;
};

void TaskData::execute()
{
    if (m_taskFunction)
    {
        m_taskFunction();
    }
};

std::function<void(TaskDataParam *)> TaskDataCommon::getTaskFunction()
{
    return m_taskFunction;
};

void TaskDataCommon::execute()
{
    if (m_taskFunction)
    {
        m_taskFunction(m_TaskDataParam);
    }
};

LTask::LTask():
	m_pTaskData(nullptr)
{
}

    LTask::LTask(TaskData *taskData):
            m_pTaskData(taskData)
    {

    }

    LTask::LTask(std::function<void()> taskFunc)
    {
        m_pTaskData = new TaskData("normal", taskFunc);
    }

    LTask::LTask(std::function<void(TaskDataParam *)> taskFunction, TaskDataParam *dataParam)
    {
        m_pTaskData = new TaskDataCommon("common", taskFunction, dataParam);
    }

LTask::~LTask()
{

}

LTask * LTask::create(TaskData * taskData)
{
	auto task = new LTask(taskData);
	return task;
}

    LTask* LTask::create(std::function<void()> taskFunc)
    {
        auto task = new LTask(taskFunc);
        return task;
    }

    LTask* LTask::create(std::function<void(TaskDataParam *)> taskFunction, TaskDataParam *dataParam)
    {
        auto task = new LTask(taskFunction, dataParam);
        return task;
    }

TaskData * LTask::getTaskData()
{
	return m_pTaskData;
}

std::string LTask::getID()
{
	if (m_pTaskData)
	{
		return m_pTaskData->getID();
	}
	return "";
}

std::function<void()> LTask::getTaskFunction()
{
	if (m_pTaskData)
	{
		return m_pTaskData->getTaskFunction();
	}
	return nullptr;
}

void LTask::execute()
{
    if (m_pTaskData)
    {
        return m_pTaskData->execute();
    }
}

    void LTask::commit(bool addNewThread)
    {
        auto pool = LThreadPool::getInstance();
        pool->pushTask(this);

        if (addNewThread)
        {
            pool->addThread();
        }
    }

NS_LONG_END


text:
package litecartTest.launchBrowserTest;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.concurrent.TimeUnit;

/**
 * Created by Marina on 25.02.2017.
 * Launch Firefox new version with new scheme run Se (geckodriver, MARIONETTE = true by default)
 * // новая схема более явно:
 DesiredCapabilities caps = new DesiredCapabilities();
 caps.setCapability(FirefoxDriver.MARIONETTE, true);
 WebDriver driver = new FirefoxDriver(caps);
 */
public class AppFirefoxTest {

    private WebDriver driver;
    private WebDriverWait wait;

    @BeforeMethod                 // = BeforeMethod
    public void start() {
        driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        wait = new WebDriverWait(driver, 10);
    }

    @Test
    public void myFirstFirefoxTest() {
        driver.get("http://localhost/litecart/admin/");
        driver.findElement(By.name("username")).sendKeys("admin");
        driver.findElement(By.name("password")).sendKeys("admin");
        driver.findElement(By.name("login")).click();
    }

    @AfterMethod
    public void stop() {
        driver.quit();
        driver = null;
    }

}


text:
create table user (
  username varchar(50) primary key,
  password varchar(100) not null,
  email varchar(50) unique,
  year int,
  major varchar(50),
  is_admin boolean not null default false
);

create table year_name (
  year int,
  name varchar(50),

  primary key (year, name)
);

create table project (
  name varchar(200) primary key,
  description varchar(1000),
  advisor_email varchar(50),
  advisor_name varchar(50),
  est_num_students int,
  designation_name varchar(50)
);

create table project_requirement (
  name varchar(200),
  requirement varchar(50),

  primary key(name, requirement)
);

create table designation (
  name varchar(50) primary key
);

create table category (
  name varchar(50) primary key
);

create table major (
  name varchar(50) primary key,
  department_name varchar(50) not null
);

create table department (
  name varchar(50) primary key
);

create table course (
  name varchar(200) primary key,
  course_number varchar(50),
  instructor varchar(50),
  est_num_students int,
  designation_name varchar(50)
);

create table application (
  project_name varchar(200),
  student_name varchar(50),
  application_date date not null,
  status enum('pending', 'accepted', 'rejected') not null,

  primary key (project_name, student_name)
);

create table project_category (
  project_name varchar(200),
  category_name varchar(50),

  primary key (project_name, category_name)
);

create table course_category (
  course_name varchar(200),
  category_name varchar(50),

  primary key (course_name, category_name)
);

alter table user
  add constraint fk_user_major_major_name
  foreign key (major) references major(name);

alter table project
  add constraint fk_project_designation_name_designation_name
  foreign key (designation_name) references designation(name);

alter table project_requirement
  add constraint fk_project_requirement_name_project_name
  foreign key (name) references project(name);

alter table major
  add constraint fk_major_department_name_department_name
  foreign key (department_name) references department(name);

alter table course
  add constraint fk_course_designation_name_designation_name
  foreign key (designation_name) references designation(name);

alter table application
  add constraint fk_application_project_name_project_name
  foreign key (project_name) references project(name),
  add constraint fk_application_student_name_user_username
  foreign key (student_name) references user(username);

alter table project_category
  add constraint fk_project_category_project_name_project_name
  foreign key (project_name) references project(name),
  add constraint fk_project_category_category_name_category_name
  foreign key (category_name) references category(name);

alter table course_category
  add constraint fk_course_category_course_name_course_name
  foreign key (course_name) references course(name),
  add constraint fk_course_category_category_name_category_name
  foreign key (category_name) references category(name);


text:
module Bling
  class NotaFiscal < Bling::Base
    # Basic
    attr_accessor :serie, :numero, :numero_pedido_loja, :situacao

    # Valores
    attr_reader :valor_nota

    # Links
    attr_accessor :xml, :link_danfe

    # Data
    attr_reader :data_emissao

    # Other
    attr_accessor :contato, :vendedor, :chave_acesso, :codigos_rastreamento

    def initialize json = {}
      @json = json

      [:serie, :numero, :numero_pedido_loja, :situacao, :valor_nota, :xml, :link_danfe, :data_emissao, :contato, :vendedor, :chave_acesso, :codigos_rastreamento].each do |attr|

        parts = attr.to_s.split('_')
        if parts.length > 1
          parts[-1] = parts.last.capitalize
        end

        self.send("#{attr}=".to_sym, json[parts.join('')])
      end
    end

    def valor_nota= value
      if value.is_a? String
        value = value.to_f
      end

      @valor_nota = value
    end

    def data_emissao= value
      if value.is_a? String
        value = Time.zone.parse(value)
      end

      @data_emissao = value
    end

    def self.path
      "notasfiscais"
    end

    def self.object_type
      "notafiscal"
    end

    def object_identifier
      "#{self.numero}/#{self.serie}"
    end

    def self.find numero, serie = nil
      if serie.nil?
        super
      else
        super "#{numero}/#{serie}"
      end
    end
  end
end


text:
// Copyright © 2016 Mikko Ronkainen <firstname@mikkoronkainen.com>
// License: MIT, see the LICENSE file.

#pragma once

namespace Valo
{
	class Image;

	class SimpleTonemapper
	{
	public:

		void apply(const Image& inputImage, Image& outputImage);

		bool applyGamma = true;
		bool shouldClamp = true;
		float gamma = 2.2f;
		float exposure = 0.0f;
	};
}


text:
namespace stratum {
namespace hal {
namespace phal {
namespace onlp {

class OnlpEventHandler;

// Represents a callback for status changes on a specific ONLP OID.
class OnlpEventCallback {
 public:
  // Creates a new OnlpEventCallback that receives callbacks for any status
  // changes that occur for the given oid.
  explicit OnlpEventCallback(OnlpOid oid);
  OnlpEventCallback(const OnlpEventCallback& other) = delete;
  OnlpEventCallback& operator=(const OnlpEventCallback& other) = delete;
  virtual ~OnlpEventCallback();

  // Implementations should override this function to perform the desired
  // callback when the oid status changes.
  virtual ::util::Status HandleOidStatusChange(const OidInfo& oid_info) = 0;

  virtual OnlpOid GetOid() const { return oid_; }

 private:
  friend class OnlpEventHandler;
  OnlpOid oid_;
  // The OnlpEventHandler that is currently sending updates to this callback.
  OnlpEventHandler* handler_;
};

class OnlpEventHandler {
 public:
  static ::util::StatusOr<std::unique_ptr<OnlpEventHandler>> Make(
      const OnlpInterface* onlp);
  OnlpEventHandler(const OnlpEventHandler& other) = delete;
  OnlpEventHandler& operator=(const OnlpEventHandler& other) = delete;
  virtual ~OnlpEventHandler();

  // Starts sending callbacks to the given OnlpEventCallback. The specific
  // events which will be sent to this callback are specified within the given
  // OnlpEventCallback. This does not take ownership of the given callback.
  // The owner of the callback can safely destroy it at any time after this
  // call, and it will automatically unregister itself. Only one callback may
  // exist per OID.
  virtual ::util::Status RegisterEventCallback(OnlpEventCallback* callback);
  // Stops sending callbacks to the given OnlpEventCallback. This is called
  // automatically if a OnlpEventCallback is deleted.
  virtual ::util::Status UnregisterEventCallback(OnlpEventCallback* callback);

  // Adds a single callback that is called once after each time any other onlp
  // callback executes. If this callback already exists, it is overwritten. The
  // callback is passed a failing status if something went wrong while running
  // normal event callbacks.
  virtual void AddUpdateCallback(std::function<void(::util::Status)> callback);

 protected:
  explicit OnlpEventHandler(const OnlpInterface* onlp)
      : onlp_(onlp), monitor_loop_thread_id_() {}

 private:
  friend class OnlpEventHandlerTest;
  struct OidStatusMonitor {
    HwState previous_status = HW_STATE_UNKNOWN;
    OnlpEventCallback* callback = nullptr;
  };

  // Initializes and starts the thread that polls onlp for oid updates.
  ::util::Status InitializePollingThread();
  // Helper function for pthread_create.
  static void* RunPollingThread(void* onlp_event_handler_ptr);
  ::util::Status PollOids();

  const OnlpInterface* onlp_ = nullptr;
  absl::Mutex monitor_lock_;
  absl::CondVar monitor_cond_var_;
  absl::flat_hash_map<OnlpOid, OidStatusMonitor> status_monitors_
      GUARDED_BY(monitor_lock_);
  std::function<void(::util::Status)> update_callback_
      GUARDED_BY(monitor_lock_);
  OnlpPortNumber max_front_port_num_ GUARDED_BY(monitor_lock_);
  // This pointer is set whenever we are currently executing a callback. This
  // lets us freely call UnregisterEventCallback for any callback except the one
  // that is currently executing.
  OnlpEventCallback* executing_callback_ = nullptr;
  bool monitor_loop_running_ GUARDED_BY(monitor_lock_) = false;
  pthread_t monitor_loop_thread_id_;
};

}  // namespace onlp
}  // namespace phal
}  // namespace hal
}  // namespace stratum

#endif  // STRATUM_HAL_LIB_PHAL_ONLP_ONLP_EVENT_HANDLER_H_