func main() { fd, fd_err := syscall.Open(LOCK_PATH, syscall.O_CREAT, 0) if fd_err != nil { fmt.Printf("FD ERR:%v\n", fd_err) os.Exit(1) } flock_err := syscall.Flock(fd, syscall.LOCK_EX) if flock_err != nil { fmt.Printf("LOCK ERR:%v\n", flock_err) os.Exit(1) } // beginning of the code getting the exclusive lock fmt.Printf(".") time.Sleep(time.Second * 10) // end of the code getting the exclusive lock funlock_err := syscall.Flock(fd, syscall.LOCK_UN) if funlock_err != nil { fmt.Printf("UNLOCK ERR:%v\n", funlock_err) unlink_err := syscall.Unlink(LOCK_PATH) if unlink_err != nil { fmt.Printf("UNLINK ERR:%v\n", unlink_err) } os.Exit(1) } close_err := syscall.Close(fd) if close_err != nil { fmt.Printf("CLOSE ERR:%v\n", close_err) } unlink_err := syscall.Unlink(LOCK_PATH) if unlink_err != nil { fmt.Printf("UNLINK ERR:%v\n", unlink_err) } }
// Restore is used to restore an FSM from a snapshot. It is not called // concurrently with any other command. The FSM must discard all previous // state. // Note, this command is called concurrently with open read txns, so we handle that func (f *flotillaState) Restore(in io.ReadCloser) error { // stream to filePath.tmp tempData := f.tempPath + "/data.mdb" _ = os.Remove(tempData) tempFile, err := os.Create(tempData) if err != nil { return err } defer tempFile.Close() if _, err = io.Copy(tempFile, in); err != nil { return err } // unlink existing DB and move new one into place // can't atomically rename directories so have to lock for this f.l.Lock() defer f.l.Unlock() if err = syscall.Unlink(f.dataPath + "/data.mdb"); err != nil { return err } if err = syscall.Unlink(f.dataPath + "/lock.mdb"); err != nil { return err } if err = os.Rename(tempData, f.dataPath+"/data.mdb"); err != nil { return err } // mark existing env as closeable when all outstanding txns finish // posix holds onto our data until we release FD f.env.Close() // re-initialize env f.env, err = newenv(f.dataPath) return err }
func (m *SystemdManager) removeUnit(name string) { log.Infof("Unlinking systemd unit %s from target %s", name, m.Target.Name()) link := m.getLocalPath(path.Join(m.Target.Name()+".wants", name)) syscall.Unlink(link) file := m.getLocalPath(name) log.Infof("Removing systemd unit file %s", file) syscall.Unlink(file) }
func TestReadOneSessFile(tst *testing.T) { fn := "/tmp/abcd.aaa" syscall.Unlink(fn) s, e := readOneSessFile(fn) if s != nil || e == nil { tst.Errorf("Should return error, get s=%v, e=%v", s, e) } e = ioutil.WriteFile(fn, []byte("1234"), 0666) if e != nil { tst.Errorf("Write file error %v", e) } s, e = readOneSessFile(fn) if s != nil || e == nil { tst.Errorf("Should return error, get s=%v, e=%v", s, e) } syscall.Unlink(fn) e = ioutil.WriteFile(fn, []byte("1234\n2015\n11"), 0666) if e != nil { tst.Errorf("Write file error %v", e) } s, e = readOneSessFile(fn) if e == nil { tst.Errorf("Should return error, get s=%v, e=%v", s, e) } else { tst.Logf("return s=%v, e=%v", s, e) } // time format ok, but expired syscall.Unlink(fn) e = ioutil.WriteFile(fn, []byte("1234\n2015-01-02 12:13:14 -0700\n{}"), 0666) if e != nil { tst.Errorf("Write file error %v", e) } s, e = readOneSessFile(fn) if s != nil || e != nil { tst.Errorf("Should return not error, get s=%v, e=%v", s, e) } else { tst.Logf("return s=%v, e=%v", s, e) } // every thing ok syscall.Unlink(fn) e = ioutil.WriteFile(fn, []byte("1234\n2030-01-02 12:13:14 -0700\n{}"), 0666) if e != nil { tst.Errorf("Write file error %v", e) } s, e = readOneSessFile(fn) if s == nil || e != nil { tst.Errorf("Should return not error, get s=%v, e=%v", s, e) } else { tst.Logf("return s=%v, e=%v", s, e) } }
// close and remove all resources func (idx *Indexer) Close() { syscall.Unlink(idx.docTxtFile.Name()) idx.docTxtFile.Close() syscall.Unlink(idx.wordTxtFile.Name()) idx.wordTxtFile.Close() syscall.Unlink(idx.docCdbFile.Name()) idx.docCdbFile.Close() syscall.Unlink(idx.wordCdbFile.Name()) idx.wordCdbFile.Close() idx.wordMap = nil }
func (constor *Constor) Unlink(header *fuse.InHeader, name string) (code fuse.Status) { var stat syscall.Stat_t parent := constor.inodemap.findInodePtr(header.NodeId) if parent == nil { constor.error("parent == nil") return fuse.ENOENT } constor.log("%s %s", parent.id, name) id, err := constor.getid(-1, parent.id, name) if err != nil { constor.error("getid failed %s %s", parent.id, name) return fuse.ToStatus(err) } inode := constor.inodemap.findInodeId(id) if inode == nil { constor.error("%s %s : inode == nil", parent.id, name) return fuse.ENOENT } if inode.layer == 0 { linkcnt, err := constor.declinkscnt(inode.id) if err != nil { constor.error("declinkscnt %s : %s", inode.id, err) return fuse.ToStatus(err) } if linkcnt == 0 { path := constor.getPath(0, inode.id) if err := syscall.Unlink(path); err != nil { constor.error("Unlink failed for %s : %s", path, err) return fuse.ToStatus(err) } inode.layer = -1 } } err = constor.copyup(parent) if err != nil { constor.error("copyup failed on %s : ", parent.id, err) return fuse.ToStatus(err) } // if there is an entry path, delete it entrypath := Path.Join(constor.getPath(0, parent.id), name) if err := syscall.Lstat(entrypath, &stat); err == nil { if err := syscall.Unlink(entrypath); err != nil { constor.error("Unlink failed for %s : %s", entrypath, err) return fuse.ToStatus(err) } } // if the file is in a lower layer then create a deleted place holder file if _, err := constor.getid(-1, parent.id, name); err == nil { constor.setdeleted(entrypath) } return fuse.OK }
func TestIsEncryptedPEM(t *testing.T) { pemPKFile := writeFakeFile(pemPrivateKey) defer syscall.Unlink(pemPKFile) pemPKWPFile := writeFakeFile(pemPrivateKeyWithPass) defer syscall.Unlink(pemPKWPFile) if ssl.IsEncryptedPEM(pemPKFile) { t.Errorf("Incorrectly identified unencrypted PEM as encrypted") } if !ssl.IsEncryptedPEM(pemPKWPFile) { t.Errorf("Incorrectly identified encrypted PEM as unencrypted") } }
func TestAppendKeyPairWithPassword(t *testing.T) { c, err := ssl.NewTLSConfig("", false) if err != nil { t.Fatal(err) } pemCertFile := writeFakeFile(pemCertificate) defer syscall.Unlink(pemCertFile) pemPKFile := writeFakeFile(pemPrivateKeyWithPass) defer syscall.Unlink(pemPKFile) if err := ssl.AppendKeyPairWithPassword(c, pemCertFile, pemPKFile, []byte("testing")); err != nil { t.Errorf("Failed to append certificate and key to tls config: %s", err) } }
// DeleteItem removes an existing item from the library. func (library *Library) DeleteItem(id string, itemType int) error { if !library.ItemExists(id, itemType) { return os.ErrNotExist } // Delete sub-collections if itemType == LibraryItemCollection { for _, child := range library.Collections[id].Children { library.DeleteItem(child.ID, LibraryItemCollection) } } // Remove stored JSON if err := syscall.Unlink(library.getFilePath(id, itemType)); err != nil { return err } // Delete item from library switch itemType { case LibraryItemSourceGroup, LibraryItemMetricGroup: delete(library.Groups, id) case LibraryItemScale: delete(library.Scales, id) case LibraryItemGraph: delete(library.Graphs, id) case LibraryItemCollection: delete(library.Collections, id) } return nil }
// TODO: Build a fake CA and make sure it loads up func TestNewTLSConfig(t *testing.T) { fakeCA := writeFakeFile(pemCertificate) defer syscall.Unlink(fakeCA) conf, err := ssl.NewTLSConfig(fakeCA, true) if err != nil { t.Errorf("Could not create new TLS config: %s", err) } if conf.ClientAuth != tls.VerifyClientCertIfGiven { t.Errorf("Client certificate verification was not enabled") } if conf.ClientCAs == nil { t.Errorf("ClientCA empty even though cert provided") } conf, err = ssl.NewTLSConfig("", false) if err != nil { t.Errorf("Could not create new TLS config: %s", err) } if conf.ClientAuth == tls.VerifyClientCertIfGiven { t.Errorf("Client certificate verification was enabled unexpectedly") } if conf.ClientCAs != nil { t.Errorf("Filling in ClientCA somehow without a cert") } }
func TestBasicStore(t *testing.T) { dbfile, _ := ioutil.TempFile("", "basic-store") defer syscall.Unlink(dbfile.Name()) db, err := sql.Open("sqlite3", dbfile.Name()) if err != nil { log.Fatal(err) } store, _ := NewDBBackend(db, true) ExpectTrue(t, store.FindById(1) == nil, "Expected id:1 not to exist.") // Create record 1, set description store.EditRecord(1, func(c *Component) bool { c.Description = "foo" return true }) ExpectTrue(t, store.FindById(1) != nil, "Expected id:1 to exist now.") // Edit it, but decide not to proceed store.EditRecord(1, func(c *Component) bool { ExpectTrue(t, c.Description == "foo", "Initial value set") c.Description = "bar" return false // don't commit }) ExpectTrue(t, store.FindById(1).Description == "foo", "Unchanged in second tx") // Now change it store.EditRecord(1, func(c *Component) bool { c.Description = "bar" return true }) ExpectTrue(t, store.FindById(1).Description == "bar", "Description change") }
// Remove removes the named file or directory. // If there is an error, it will be of type *PathError. func Remove(name string) error { // System call interface forces us to know // whether name is a file or directory. // Try both: it is cheaper on average than // doing a Stat plus the right one. e := syscall.Unlink(name) if e == nil { return nil } e1 := syscall.Rmdir(name) if e1 == nil { return nil } // Both failed: figure out which error to return. // OS X and Linux differ on whether unlink(dir) // returns EISDIR, so can't use that. However, // both agree that rmdir(file) returns ENOTDIR, // so we can use that to decide which error is real. // Rmdir might also return ENOTDIR if given a bad // file path, like /etc/passwd/foo, but in that case, // both errors will be ENOTDIR, so it's okay to // use the error from unlink. if e1 != syscall.ENOTDIR { e = e1 } return &PathError{"remove", name, e} }
func (srv *Server) ListenAndServe(job *engine.Job) string { protoAddrs := job.Args chErrors := make(chan error, len(protoAddrs)) for _, protoAddr := range protoAddrs { protoAddrParts := strings.SplitN(protoAddr, "://", 2) switch protoAddrParts[0] { case "unix": if err := syscall.Unlink(protoAddrParts[1]); err != nil && !os.IsNotExist(err) { log.Fatal(err) } case "tcp": if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") { log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\") } default: return "Invalid protocol format." } go func() { // FIXME: merge Server.ListenAndServe with ListenAndServe chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], srv, job.GetenvBool("Logging")) }() } for i := 0; i < len(protoAddrs); i += 1 { err := <-chErrors if err != nil { return err.Error() } } return "0" }
func TestNewConfig(t *testing.T) { // create a test dotconfig file f, err := ioutil.TempFile("", ".dotconfig") if err != nil { log.Fatal(err) } defer syscall.Unlink(f.Name()) ioutil.WriteFile( f.Name(), []byte(payload), 0644, ) // try to read the file c, err := NewConfig(f.Name()) if err != nil { log.Fatal(err) } // c.DotPath should be the same as payload if c.DotPath != "/path/to/dotfiles" { t.Error("c.DotPath doesn't match") } // c.Files should be the same as payload if c.Files["test_file_1"] != "path-to-test-file-1" { t.Error("c.Files doesn't match") } // c.Files should be the same as payload if c.Files["test_file_2"] != "path-to-test-file-2" { t.Error("c.Files doesn't match") } }
func (constor *Constor) Create(input *fuse.CreateIn, name string, out *fuse.CreateOut) (code fuse.Status) { dirpath, err := constor.dentrymap.getPath(input.NodeId) if err != nil { constor.error("%s", err) return fuse.ToStatus(err) } constor.log("%s%s %d %d %d", dirpath, name, input.Mode, input.Uid, input.Gid) if err := constor.createPath(dirpath); err != nil { constor.error("%s", err) return fuse.ToStatus(err) } pathl := Path.Join(constor.layers[0], dirpath, name) // remove any deleted place holder entries if constor.isdeleted(pathl) { syscall.Unlink(pathl) } fd, err := syscall.Open(pathl, syscall.O_CREAT|syscall.O_RDWR, input.Mode) if err != nil { constor.error("%s", err) return fuse.ToStatus(err) } err = syscall.Chown(pathl, int(input.Uid), int(input.Gid)) if err != nil { constor.error("%s", err) return fuse.ToStatus(err) } F := new(FD) F.fd = fd F.layer = 0 constor.putfd(F) out.Fh = uint64(uintptr(unsafe.Pointer(F))) constor.log("%d", out.Fh) return constor.Lookup((*fuse.InHeader)(unsafe.Pointer(input)), name, &out.EntryOut) }
// Start starts the dockershim grpc server. func (s *DockerServer) Start() error { glog.V(2).Infof("Start dockershim grpc server") // Unlink to cleanup the previous socket file. err := syscall.Unlink(s.addr) if err != nil && !os.IsNotExist(err) { return fmt.Errorf("failed to unlink socket file %q: %v", s.addr, err) } l, err := net.Listen(unixProtocol, s.addr) if err != nil { return fmt.Errorf("failed to listen on %q: %v", s.addr, err) } // Create the grpc server and register runtime and image services. s.server = grpc.NewServer() runtimeApi.RegisterRuntimeServiceServer(s.server, s.service) runtimeApi.RegisterImageServiceServer(s.server, s.service) go func() { // Use interrupt handler to make sure the server to be stopped properly. h := interrupt.New(nil, s.Stop) err := h.Run(func() error { return s.server.Serve(l) }) if err != nil { glog.Errorf("Failed to serve connections: %v", err) } }() return nil }
// TestFleetctlRunService tests that fleetctl could start, unload and destroy // unit file. func TestFleetctlRunService() error { serviceName := "hello.service" serviceFile, err := os.Create(path.Join(os.TempDir(), serviceName)) if err != nil { return fmt.Errorf("Failed creating %v: %v", serviceName, err) } defer syscall.Unlink(serviceFile.Name()) if _, err := io.WriteString(serviceFile, serviceData); err != nil { return fmt.Errorf("Failed writing %v: %v", serviceFile.Name(), err) } defer timeoutFleetctl("destroy", serviceFile.Name()) stdout, stderr, err := timeoutFleetctl("start", serviceFile.Name()) if err != nil { return fmt.Errorf("fleetctl start failed with error: %v\nstdout: %s\nstderr: %s", err, stdout, stderr) } stdout, stderr, err = timeoutFleetctl("unload", serviceName) if err != nil { return fmt.Errorf("fleetctl unload failed with error: %v\nstdout: %s\nstderr: %s", err, stdout, stderr) } stdout, stderr, err = timeoutFleetctl("destroy", serviceName) if err != nil { return fmt.Errorf("fleetctl destroy failed with error: %v\nstdout: %s\nstderr: %s", err, stdout, stderr) } return nil }
// Unlink implements pathfs.Filesystem. func (fs *FS) Unlink(path string, context *fuse.Context) (code fuse.Status) { if fs.isFiltered(path) { return fuse.EPERM } cPath, err := fs.getBackingPath(path) if err != nil { return fuse.ToStatus(err) } cName := filepath.Base(cPath) if nametransform.IsLongContent(cName) { var dirfd *os.File dirfd, err = os.Open(filepath.Dir(cPath)) if err != nil { return fuse.ToStatus(err) } defer dirfd.Close() // Delete content err = syscallcompat.Unlinkat(int(dirfd.Fd()), cName) if err != nil { return fuse.ToStatus(err) } // Delete ".name" err = nametransform.DeleteLongName(dirfd, cName) if err != nil { tlog.Warn.Printf("Unlink: could not delete .name file: %v", err) } return fuse.ToStatus(err) } err = syscall.Unlink(cPath) return fuse.ToStatus(err) }
func main() { goopt.Suite = "XQZ coreutils" goopt.Author = "William Pearson" goopt.Version = "Unlink v0.1" goopt.Summary = "Uses unlink to remove FILE" goopt.Usage = func() string { return fmt.Sprintf("Usage:\t%s FILE\n or:\t%s OPTION\n", os.Args[0], os.Args[0]) + goopt.Summary + "\n\n" + goopt.Help() } goopt.Description = func() string { return goopt.Summary + "\n\nUnless an option is passed to it." } goopt.NoArg([]string{"-v", "--version"}, "outputs version information and exits", version) goopt.Parse(nil) switch { case len(os.Args) == 1: fmt.Println("Missing filenames") case len(os.Args) > 2: fmt.Println("Too many filenames") } if len(os.Args) != 2 { os.Exit(1) } file := os.Args[1] if err := syscall.Unlink(file); err != nil { fmt.Println("Encountered an error during unlinking: %v", err) os.Exit(1) } return }
func rmFifo(t *testing.T, i int) { name := fifoName(i) err := syscall.Unlink(name) if err != nil { t.Fatalf("rmFifo %s: %v", name, err) } }
func TestLeaveSetRegression(t *testing.T) { dbfile, _ := ioutil.TempFile("", "join-sets") defer syscall.Unlink(dbfile.Name()) db, err := sql.Open("sqlite3", dbfile.Name()) if err != nil { log.Fatal(err) } store, _ := NewDBBackend(db, true) // We store components in a slightly different // sequence. store.EditRecord(2, func(c *Component) bool { c.Value = "two"; return true }) store.EditRecord(1, func(c *Component) bool { c.Value = "one"; return true }) store.EditRecord(3, func(c *Component) bool { c.Value = "three"; return true }) store.JoinSet(2, 1) store.JoinSet(3, 1) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#1") ExpectTrue(t, store.FindById(2).Equiv_set == 1, "#2") ExpectTrue(t, store.FindById(3).Equiv_set == 1, "#3") // The way LeaveSet() was implemented, it used an SQL in a way that // SQLite didn't process correctly wrt. sequence of operations. store.LeaveSet(2) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#4") ExpectTrue(t, store.FindById(2).Equiv_set == 2, "#5") ExpectTrue(t, store.FindById(3).Equiv_set == 1, "#6") }
func newUnixListener(addr string) (net.Listener, error) { if err := syscall.Unlink(addr); err != nil && !os.IsNotExist(err) { return nil, err } // there is no way to specify the unix rights to use when // creating the socket with net.Listener, so we use umask // to create the file without rights and then we chmod // to the desired unix rights. This prevent unwanted // connections between the creation and the chmod mask := syscall.Umask(0777) defer syscall.Umask(mask) l, err := newListener("unix", addr) if err != nil { return nil, err } // only usable by the user who started swarm if err := os.Chmod(addr, 0600); err != nil { return nil, err } return l, nil }
func (file *File) unlink() error { // Remove whatever was there. // NOTE: We will generally require the // write lock to be held for this routine. if file.write_deleted { err := cleardelattr(file.write_path) if err != nil { return err } } var stat syscall.Stat_t err := syscall.Lstat(file.write_path, &stat) if err == nil { if stat.Mode&syscall.S_IFDIR != 0 { err = syscall.Rmdir(file.write_path) if err != nil { return err } } else { err = syscall.Unlink(file.write_path) if err != nil { return err } } } file.write_exists = false file.write_deleted = false return nil }
func TestServerConfigSerialization(t *testing.T) { sc := MkDefaultServerConfiguration() f, err := ioutil.TempFile("", "testserverconfig.json") if err != nil { t.Error("Cannot create temp file") } defer syscall.Unlink(f.Name()) err = sc.Save(f.Name()) if err != nil { t.Error("Cannot save server configuration: " + err.Error()) } sc2, err := LoadServerConfiguration(f.Name()) if err != nil { t.Error("Failed to load server configuration: " + err.Error()) } // Note: This test currently fails because the reading cache is // generated dynamically after each load. //if !reflect.DeepEqual(sc, *sc2) { // t.Error("Pre-stored server configuration not equal to post-stored one") //} if !(sc.Network == sc2.Network && sc.MeterTimeout == sc2.MeterTimeout && sc.Assets == sc2.Assets && sc.InfluxDB == sc2.InfluxDB) { t.Error("Pre-stored server configuration not equal to post-stored one") } }
func setupUnixHttp(addr string, job *engine.Job) (*HttpServer, error) { r, err := createRouter(job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version")) if err != nil { return nil, err } if err := syscall.Unlink(addr); err != nil && !os.IsNotExist(err) { return nil, err } mask := syscall.Umask(0777) defer syscall.Umask(mask) l, err := newListener("unix", addr, job.GetenvBool("BufferRequests")) if err != nil { return nil, err } if err := setSocketGroup(addr, job.Getenv("SocketGroup")); err != nil { return nil, err } if err := os.Chmod(addr, 0660); err != nil { return nil, err } return &HttpServer{&http.Server{Addr: addr, Handler: r}, l}, nil }
func newListener(proto, addr string, tlsConfig *tls.Config) (net.Listener, error) { var ( l net.Listener err error ) switch proto { case "unix", "unixpacket": // Unix sockets must be unlink()ed before being reused again if err := syscall.Unlink(addr); err != nil && !os.IsNotExist(err) { return nil, err } l, err = net.Listen(proto, addr) case "tcp": l, err = net.Listen(proto, addr) default: return nil, fmt.Errorf("unsupported protocol: %q", proto) } if tlsConfig != nil { tlsConfig.NextProtos = []string{"http/1.1"} l = tls.NewListener(l, tlsConfig) } return l, err }
func mkfifo(t *testing.T) { _ = syscall.Unlink(fifo) err := syscall.Mkfifo(fifo, 0666) if err != nil { t.Fatal("mkfifo:", err) } }
func TestDumpReaderToFile(t *testing.T) { testString := "TEST STRING" tempFile, err := ioutil.TempFile("", "hlpers_test_dump_") if err != nil { t.Errorf("unexpected error setting up a temporary file %v", err) } defer syscall.Unlink(tempFile.Name()) defer tempFile.Close() defer func() { if !t.Failed() { os.Remove(tempFile.Name()) } }() err = DumpReaderToFile(strings.NewReader(testString), tempFile.Name()) if err != nil { t.Errorf("error in DumpReaderToFile: %v", err) } data, err := ioutil.ReadFile(tempFile.Name()) if err != nil { t.Errorf("error when reading %s: %v", tempFile.Name(), err) } stringData := string(data) if stringData != testString { t.Fatalf("Wrong file content %s != %s", testString, stringData) } }
func (rm *RetainedMessages) remove(t Topic) { if rm._messageCache != nil { delete(rm._messageCache, t) } // look for it on disk syscall.Unlink(topicToFilename(rm.path, t)) }
func TestJoinSets(t *testing.T) { dbfile, _ := ioutil.TempFile("", "join-sets") defer syscall.Unlink(dbfile.Name()) db, err := sql.Open("sqlite3", dbfile.Name()) if err != nil { log.Fatal(err) } store, _ := NewDBBackend(db, true) // Three components, each in their own equiv-class store.EditRecord(1, func(c *Component) bool { c.Value = "one"; return true }) store.EditRecord(2, func(c *Component) bool { c.Value = "two"; return true }) store.EditRecord(3, func(c *Component) bool { c.Value = "three"; return true }) // Expecting baseline. ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#1") ExpectTrue(t, store.FindById(2).Equiv_set == 2, "#2") ExpectTrue(t, store.FindById(3).Equiv_set == 3, "#3") // Component 2 join set 3. Final equivalence-set is lowest // id of the result set. store.JoinSet(2, 3) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#4") ExpectTrue(t, store.FindById(2).Equiv_set == 2, "#5") ExpectTrue(t, store.FindById(3).Equiv_set == 2, "#6") // Break out article three out of this set. store.LeaveSet(3) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#7") ExpectTrue(t, store.FindById(2).Equiv_set == 2, "#8") ExpectTrue(t, store.FindById(3).Equiv_set == 3, "#9") // Join everything together. store.JoinSet(3, 1) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#10") ExpectTrue(t, store.FindById(2).Equiv_set == 2, "#11") ExpectTrue(t, store.FindById(3).Equiv_set == 1, "#12") store.JoinSet(2, 1) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#12") ExpectTrue(t, store.FindById(2).Equiv_set == 1, "#13") ExpectTrue(t, store.FindById(3).Equiv_set == 1, "#14") // Lowest component leaving the set leaves the equivalence set // at the lowest of the remaining. store.LeaveSet(1) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#15") ExpectTrue(t, store.FindById(2).Equiv_set == 2, "#16") ExpectTrue(t, store.FindById(3).Equiv_set == 2, "#17") // If we add lowest again, then the new equiv-set is back to 1. store.JoinSet(1, 2) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#18") ExpectTrue(t, store.FindById(2).Equiv_set == 1, "#19") ExpectTrue(t, store.FindById(3).Equiv_set == 1, "#20") store.LeaveSet(2) ExpectTrue(t, store.FindById(1).Equiv_set == 1, "#18") ExpectTrue(t, store.FindById(2).Equiv_set == 2, "#19") ExpectTrue(t, store.FindById(3).Equiv_set == 1, "#20") }