|
| 1 | +import unittest |
| 2 | + |
| 3 | +import ROOT |
| 4 | + |
| 5 | + |
| 6 | +class Regression20018(unittest.TestCase): |
| 7 | + """ |
| 8 | + Regression test for https://github.com/root-project/root/issues/20018 |
| 9 | +
|
| 10 | + Calling ``TColor.DefinedColors(1)`` puts the global color bookkeeping into |
| 11 | + the "always store colors" mode (``gLastDefinedColors = -1``). When a canvas |
| 12 | + is afterwards serialized to JSON for the web display - which is exactly what |
| 13 | + JupyROOT does to show a canvas inline in a notebook - ``TCanvas::Streamer`` |
| 14 | + used to unconditionally call ``fPrimitives->Add(...)`` to attach the list of |
| 15 | + colors. During the web-canvas snapshot the pad primitives are temporarily |
| 16 | + detached (``fPrimitives`` is set to ``nullptr``, see |
| 17 | + ``TWebCanvas::CreatePadSnapshot``), so this dereferenced a null pointer and |
| 18 | + crashed with a segmentation violation. |
| 19 | + """ |
| 20 | + |
| 21 | + def test_definedcolors_web_canvas_json(self): |
| 22 | + # TWebCanvas (and thus CreateCanvasJSON) is only available when ROOT is |
| 23 | + # built with the web display (root7/webgui). Without it, JupyROOT uses a |
| 24 | + # different code path that is not affected by this issue. |
| 25 | + if not hasattr(ROOT, "TWebCanvas") or not hasattr(ROOT.TWebCanvas, "CreateCanvasJSON"): |
| 26 | + self.skipTest("ROOT was built without the web display (webgui)") |
| 27 | + |
| 28 | + ROOT.gROOT.SetBatch(True) |
| 29 | + |
| 30 | + # This is what triggers the bug: force the "always store colors" mode. |
| 31 | + ROOT.TColor.DefinedColors(1) |
| 32 | + |
| 33 | + c = ROOT.TCanvas("c_regression_20018", "Basic ROOT Plot", 800, 600) |
| 34 | + h = ROOT.TH1F("h_regression_20018", "Example Histogram;X axis;Entries", 100, 0, 10) |
| 35 | + h.FillRandom("gaus", 1000) |
| 36 | + h.Draw() |
| 37 | + c.Update() |
| 38 | + |
| 39 | + # Used to segfault in TCanvas::Streamer due to a null fPrimitives. |
| 40 | + json = ROOT.TWebCanvas.CreateCanvasJSON(c, 23, True) |
| 41 | + self.assertGreater(len(json.Data()), 0) |
| 42 | + |
| 43 | + |
| 44 | +if __name__ == "__main__": |
| 45 | + unittest.main() |
0 commit comments