Skip to content

Instantly share code, notes, and snippets.

@k-tsj
Last active August 29, 2015 14:01
Show Gist options
  • Select an option

  • Save k-tsj/deec45fc17883bf6be7c to your computer and use it in GitHub Desktop.

Select an option

Save k-tsj/deec45fc17883bf6be7c to your computer and use it in GitHub Desktop.

Revisions

  1. k-tsj revised this gist May 17, 2014. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions power_assert.rb
    Original file line number Diff line number Diff line change
    @@ -47,12 +47,12 @@ def power_assert
    end

    def print_assersion_message(line, values)
    return if values.empty?

    set_colno(line, values)

    vals = values.find_all(&:colno).sort_by(&:colno).reverse
    fmt = (vals[0].colno+1).times.map {|i| vals.find {|v| v.colno == i } ? "%<#{i}>s" : ' ' }.join + "\n"
    if vals.empty?
    return
    end
    fmt = (vals[0].colno + 1).times.map {|i| vals.find {|v| v.colno == i } ? "%<#{i}>s" : ' ' }.join + "\n"
    puts line
    printf(fmt, vals.each_with_object({}) {|v, h| h[v.colno.to_s.to_sym] = '|' })
    vals.each do |i|
    @@ -66,7 +66,7 @@ def set_colno(line, values)
    rev_values = values.reverse
    values.each do |val|
    v = rev_values.find {|i| i.method_id == val.method_id and i.colno }
    val.colno = line.index(/\b#{val.method_id}\b/, v ? v.colno + 1 : 0)
    val.colno = line.index(/\b#{Regexp.escape(val.method_id)}\b/, v ? v.colno + 1 : 0)
    end
    end

  2. k-tsj created this gist May 17, 2014.
    73 changes: 73 additions & 0 deletions power_assert.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    # power_assert.rb
    #
    # Copyright (C) 2014 Kazuki Tsujimoto, All rights reserved.
    # License: BSDL
    #
    # $ ruby power_assert.rb
    # "0".class == "3".to_i.times.map {|i| i + 1 }.class
    # | | | | |
    # | | | | Array
    # | | | [1, 2, 3]
    # | | #<Enumerator: 3:times>
    # | 3
    # String

    def main
    power_assert do
    "0".class == "3".to_i.times.map {|i| i + 1 }.class
    end
    end

    RetValue = Struct.new(:method_id, :value, :colno)

    TARGET_CALLER_DIFF = {c_return: 6, return: 7}
    TARGET_CALLER_INDEX = {c_return: 2, return: 3}

    def power_assert
    base_caller_lengh = caller_locations.length
    path = nil
    lineno = nil
    values = []
    trace = TracePoint.new(:return, :c_return) do |tp|
    locs = tp.binding.eval('caller_locations')
    if locs.length - base_caller_lengh == TARGET_CALLER_DIFF[tp.event]
    idx = TARGET_CALLER_INDEX[tp.event]
    path ||= locs[idx].path
    lineno ||= locs[idx].lineno
    if path == locs[idx].path and lineno == locs[idx].lineno
    values << RetValue[tp.method_id, tp.return_value, nil]
    end
    end
    end
    unless trace.enable { yield }
    raise unless path
    line = open(path).each_line.drop(lineno - 1).first
    print_assersion_message(line, values)
    end
    end

    def print_assersion_message(line, values)
    return if values.empty?

    set_colno(line, values)

    vals = values.find_all(&:colno).sort_by(&:colno).reverse
    fmt = (vals[0].colno+1).times.map {|i| vals.find {|v| v.colno == i } ? "%<#{i}>s" : ' ' }.join + "\n"
    puts line
    printf(fmt, vals.each_with_object({}) {|v, h| h[v.colno.to_s.to_sym] = '|' })
    vals.each do |i|
    printf(fmt, vals.each_with_object({}) do |j, h|
    h[j.colno.to_s.to_sym] = [i.value.inspect, '|', ' '][i.colno <=> j.colno]
    end)
    end
    end

    def set_colno(line, values)
    rev_values = values.reverse
    values.each do |val|
    v = rev_values.find {|i| i.method_id == val.method_id and i.colno }
    val.colno = line.index(/\b#{val.method_id}\b/, v ? v.colno + 1 : 0)
    end
    end

    main