# RUN: %PYTHON %s | FileCheck %s
import gc
from mlir.ir import *
def run(f):
print("\nTEST:", f.__name__)
f()
gc.collect()
assert Context._get_live_count() == 0
return f
@run
def testLifecycleContextDestroy():
ctx = Context()
def callback(foo):
...
handler = ctx.attach_diagnostic_handler(callback)
assert handler.attached
# If context is destroyed before the handler, it should auto-detach.
ctx = None
gc.collect()
assert not handler.attached
# And finally collecting the handler should be fine.
handler = None
gc.collect()
@run
def testLifecycleExplicitDetach():
ctx = Context()
def callback(foo):
...
handler = ctx.attach_diagnostic_handler(callback)
assert handler.attached
handler.detach()
assert not handler.attached
@run
def testLifecycleWith():
ctx = Context()
def callback(foo):
...
with ctx.attach_diagnostic_handler(callback) as handler:
assert handler.attached
assert not handler.attached
@run
def testLifecycleWithAndExplicitDetach():
ctx = Context()
def callback(foo):
...
with ctx.attach_diagnostic_handler(callback) as handler:
assert handler.attached
handler.detach()
assert not handler.attached
# CHECK-LABEL: TEST: testDiagnosticCallback
@run
def testDiagnosticCallback():
ctx = Context()
def callback(d):
# CHECK: DIAGNOSTIC: message='foobar', severity=DiagnosticSeverity.ERROR, loc=loc(unknown)
print(
f"DIAGNOSTIC: message='{d.message}', severity={d.severity}, loc={d.location}"
)
return True
handler = ctx.attach_diagnostic_handler(callback)
loc = Location.unknown(ctx)
loc.emit_error("foobar")
assert not handler.had_error
# CHECK-LABEL: TEST: testDiagnosticEmptyNotes
# TODO: Come up with a way to inject a diagnostic with notes from this API.
@run
def testDiagnosticEmptyNotes():
ctx = Context()
def callback(d):
# CHECK: DIAGNOSTIC: notes=()
print(f"DIAGNOSTIC: notes={d.notes}")
return True
handler = ctx.attach_diagnostic_handler(callback)
loc = Location.unknown(ctx)
loc.emit_error("foobar")
assert not handler.had_error
# CHECK-LABEL: TEST: testDiagnosticNonEmptyNotes
@run
def testDiagnosticNonEmptyNotes():
ctx = Context()
ctx.emit_error_diagnostics = True
def callback(d):
# CHECK: DIAGNOSTIC:
# CHECK: message='arith.addi' op requires one result
# CHECK: notes=['see current operation: "arith.addi"() {{.*}} : () -> ()']
print(f"DIAGNOSTIC:")
print(f" message={d.message}")
print(f" notes={list(map(str, d.notes))}")
return True
handler = ctx.attach_diagnostic_handler(callback)
loc = Location.unknown(ctx)
try:
Operation.create("arith.addi", loc=loc).verify()
except MLIRError:
pass
assert not handler.had_error
# CHECK-LABEL: TEST: testDiagnosticCallbackException
@run
def testDiagnosticCallbackException():
ctx = Context()
def callback(d):
raise ValueError("Error in handler")
handler = ctx.attach_diagnostic_handler(callback)
loc = Location.unknown(ctx)
loc.emit_error("foobar")
assert handler.had_error
# CHECK-LABEL: TEST: testEscapingDiagnostic
@run
def testEscapingDiagnostic():
ctx = Context()
diags = []
def callback(d):
diags.append(d)
return True
handler = ctx.attach_diagnostic_handler(callback)
loc = Location.unknown(ctx)
loc.emit_error("foobar")
assert not handler.had_error
# CHECK: DIAGNOSTIC: <Invalid Diagnostic>
print(f"DIAGNOSTIC: {str(diags[0])}")
try:
diags[0].severity
raise RuntimeError("expected exception")
except ValueError:
pass
try:
diags[0].location
raise RuntimeError("expected exception")
except ValueError:
pass
try:
diags[0].message
raise RuntimeError("expected exception")
except ValueError:
pass
try:
diags[0].notes
raise RuntimeError("expected exception")
except ValueError:
pass
# CHECK-LABEL: TEST: testDiagnosticReturnTrueHandles
@run
def testDiagnosticReturnTrueHandles():
ctx = Context()
def callback1(d):
print(f"CALLBACK1: {d}")
return True
def callback2(d):
print(f"CALLBACK2: {d}")
return True
ctx.attach_diagnostic_handler(callback1)
ctx.attach_diagnostic_handler(callback2)
loc = Location.unknown(ctx)
# CHECK-NOT: CALLBACK1
# CHECK: CALLBACK2: foobar
# CHECK-NOT: CALLBACK1
loc.emit_error("foobar")
# CHECK-LABEL: TEST: testDiagnosticReturnFalseDoesNotHandle
@run
def testDiagnosticReturnFalseDoesNotHandle():
ctx = Context()
def callback1(d):
print(f"CALLBACK1: {d}")
return True
def callback2(d):
print(f"CALLBACK2: {d}")
return False
ctx.attach_diagnostic_handler(callback1)
ctx.attach_diagnostic_handler(callback2)
loc = Location.unknown(ctx)
# CHECK: CALLBACK2: foobar
# CHECK: CALLBACK1: foobar
loc.emit_error("foobar")