diff options
author | Peter Harris <pharris@opentext.com> | 2015-01-26 16:35:44 -0500 |
---|---|---|
committer | Peter Harris <pharris@opentext.com> | 2015-01-26 16:35:44 -0500 |
commit | a0fbba4fe34fd467a03288d8945978406f5f1f2f (patch) | |
tree | 5b3119dc3b7acc458712f0df97a95afddab6df03 | |
parent | 587b1a229bf351758ec93cc05406b1560251265c (diff) |
Add xts-config replacement
This saves about half a second in run-time when running remotely
(presumably due to all the extra round-trips of xset and xdpyinfo).
The savings locally are less impressive (about 0.06s by saving a bunch of
fork/exec pairs, and reducing the amount of output parsing going on).
-rw-r--r-- | config.go | 182 | ||||
-rw-r--r-- | run.go | 14 |
2 files changed, 193 insertions, 3 deletions
diff --git a/config.go b/config.go new file mode 100644 index 0000000..8e6cbca --- /dev/null +++ b/config.go @@ -0,0 +1,182 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + + "github.com/BurntSushi/xgb" + "github.com/BurntSushi/xgb/xproto" +) + +func createConfig(outdir string) error { + c, err := xgb.NewConn() + if err != nil { + return err + } + defer c.Close() + gfpCookie := xproto.GetFontPath(c) + + set := make(map[string]string) + s := xproto.Setup(c) + + set["XT_PROTOCOL_VERSION"] = strconv.Itoa(int(s.ProtocolMajorVersion)) + set["XT_PROTOCOL_REVISION"] = strconv.Itoa(int(s.ProtocolMinorVersion)) + set["XT_SERVER_VENDOR"] = s.Vendor + set["XT_VENDOR_RELEASE"] = strconv.FormatUint(uint64(s.ReleaseNumber), 10) + set["XT_DISPLAYMOTIONBUFFERSIZE"] = strconv.FormatUint(uint64(s.MotionBufferSize), 10) + set["XT_SCREEN_COUNT"] = strconv.Itoa(len(s.Roots)) + if c.DefaultScreen >= len(s.Roots) { + return fmt.Errorf("screen %d does not exist (only %d screens)", c.DefaultScreen, len(s.Roots)) + } + set["XT_ALT_SCREEN"] = "UNSUPPORTED" + if len(s.Roots) > 1 { + if c.DefaultScreen == 0 { + set["XT_ALT_SCREEN"] = "1" + } else { + set["XT_ALT_SCREEN"] = "0" + } + } + + r := s.Roots[c.DefaultScreen] + set["XT_WIDTH_MM"] = strconv.Itoa(int(r.WidthInMillimeters)) + set["XT_HEIGHT_MM"] = strconv.Itoa(int(r.HeightInMillimeters)) + set["XT_BLACK_PIXEL"] = strconv.FormatUint(uint64(r.BlackPixel), 10) + set["XT_WHITE_PIXEL"] = strconv.FormatUint(uint64(r.WhitePixel), 10) + set["XT_DOES_BACKING_STORE"] = strconv.Itoa(int(r.BackingStores)) + set["XT_DOES_SAVE_UNDERS"] = "No" + if r.SaveUnders { + set["XT_DOES_SAVE_UNDERS"] = "Yes" + } + var list []string + visuals := make(map[string]struct{}) + visType := map[byte]string{ + xproto.VisualClassStaticGray: "StaticGray", + xproto.VisualClassGrayScale: "GrayScale", + xproto.VisualClassStaticColor: "StaticColor", + xproto.VisualClassPseudoColor: "PseudoColor", + xproto.VisualClassTrueColor: "TrueColor", + xproto.VisualClassDirectColor: "DirectColor", + } + for _, v := range r.AllowedDepths { + list = append(list, strconv.Itoa(int(v.Depth))) + for _, vis := range v.Visuals { + if class, ok := visType[vis.Class]; ok { + visuals[fmt.Sprintf("%s(%d)", class, v.Depth)] = struct{}{} + } else { + return fmt.Errorf("visual type %d invalid", vis.Class) + } + } + } + set["XT_PIXMAP_DEPTHS"] = strings.Join(list, " ") + list = list[:0] + for k, _ := range visuals { + list = append(list, k) + } + set["XT_VISUAL_CLASSES"] = strings.Join(list, " ") + + // DISPLAY := os.Getenv("DISPLAY") or ":0" + tetRoot := env("TET_ROOT", "/usr/local/share") + + gfp, err := gfpCookie.Reply() + if err != nil { + return err + } + list = list[:0] + for _, v := range gfp.Path { + list = append(list, v.Name) + } + fontPath := strings.Join(list, ",") + set["XT_FONTPATH_GOOD"] = fontPath + set["XT_FONTPATH"] = filepath.Join(tetRoot, "xts5", "fonts") + "," + fontPath + + localDisplay := regexp.MustCompile(`^:\d+(\.\d+)?$`) + display := env("DISPLAY", ":0") + if localDisplay.MatchString(display) { + set["XT_LOCAL"] = "Yes" + set["XT_TCP"] = "No" + set["XT_DISPLAYHOST"] = "" + if hostname, err := os.Hostname(); err == nil { + // try connecting to the same display via TCP + tcpConn, err := xgb.NewConnDisplay(hostname + display) + if err == nil { + tcpConn.Close() + set["XT_TCP"] = "Yes" + set["XT_DISPLAYHOST"] = hostname + } + } + } else { + // Remote display + set["XT_TCP"] = "Yes" + hostname := "" + offset := strings.LastIndex(display, ":") + if offset >= 0 { + hostname = display[:offset] + } + set["XT_DISPLAYHOST"] = hostname + + // Not a local display; admin is responsible for placing + // xtest fonts on the font path before running xts-config. + set["XT_FONTPATH"] = fontPath + list = list[:0] + for _, v := range gfp.Path { + // Remove xtest directory + if !strings.Contains(strings.ToLower(v.Name), "xtest") { + list = append(list, v.Name) + } + } + fpg := strings.Join(list, ",") + // If xtest directory is not called "xtest", remove the + // last directory in the path (as it's less likely to + // be the path containing "default"/"cursor" than the + // first directory in the path). + if fpg == fontPath && len(list) > 0 { + fpg = strings.Join(list[:len(list)-1], ",") + } + set["XT_FONTPATH_GOOD"] = fpg + } + + config_in := filepath.Join(tetRoot, "xts5", "tetexec.cfg.in") + + in, err := os.Open(config_in) + if err != nil { + return err + } + defer in.Close() + o, err := os.Create(*config) + if err != nil { + return err + } + defer o.Close() + out := bufio.NewWriter(o) + defer out.Flush() + + scan := bufio.NewScanner(in) + for scan.Scan() { + text := scan.Text() + thing := strings.SplitN(text, "=", 2) + if len(thing) == 2 { + leftThing := strings.TrimSpace(thing[0]) + if rep, ok := set[leftThing]; ok { + text = thing[0] + "=" + rep + delete(set, leftThing) + } + } + fmt.Fprintln(out, text) + } + if err := scan.Err(); err != nil { + return err + } + if len(set) == 0 { + return nil + } + fmt.Fprintln(out, "\n# Undocumented variables:\n\n") + for k, v := range set { + fmt.Fprintln(out, k+"="+v) + } + return nil +} @@ -8,6 +8,8 @@ // - Creates config file in results directory (instead of $TMPDIR) // // - Adds ability to run a single (or multiple) sub-test(s) (similar to run_assert) +// +// - Avoids shelling out to xts-config (and therefore xset/xdpyinfo) (faster remote startup) package main import ( @@ -23,6 +25,7 @@ import ( var config = flag.String("config", "", "Location of xts configuration file") var output = flag.String("output", "xts-results", "Output directory to use") var version = flag.Bool("version", false, "Display version number and exit") +var extconfig = flag.Bool("extconfig", false, "Use external xts-config") func env(evar string, def string) string { rv := os.Getenv(evar) @@ -32,8 +35,7 @@ func env(evar string, def string) string { return rv } -func createConfig(outdir string) error { - *config = filepath.Join(outdir, "tetexec.cfg") +func createConfigExt(outdir string) error { perl := env("PERL", "perl") tetRoot := env("TET_ROOT", "/usr/local/share") config_in := filepath.Join(tetRoot, "xts5", "tetexec.cfg.in") @@ -104,7 +106,13 @@ func main() { // Create the config file if necessary if *config == "" { - err := createConfig(outdir) + *config = filepath.Join(outdir, "tetexec.cfg") + var err error + if *extconfig { + err = createConfigExt(outdir) + } else { + err = createConfig(outdir) + } if err != nil { fmt.Fprintln(os.Stdout, err) os.Exit(1) |