/** Scenario: loads on one label shouldn't translate to load on another label. */
  public void testLabels() throws Exception {
    BulkChange bc = new BulkChange(hudson);
    try {
      DummyCloudImpl cloud = initHudson(0);
      Label blue = hudson.getLabel("blue");
      Label red = hudson.getLabel("red");
      cloud.label = red;

      // red jobs
      List<FreeStyleProject> redJobs = create5SlowJobs(new Latch(5));
      for (FreeStyleProject p : redJobs) p.setAssignedLabel(red);

      // blue jobs
      List<FreeStyleProject> blueJobs = create5SlowJobs(new Latch(5));
      for (FreeStyleProject p : blueJobs) p.setAssignedLabel(blue);

      // build all
      List<Future<FreeStyleBuild>> blueBuilds = buildAll(blueJobs);
      verifySuccessfulCompletion(buildAll(redJobs));

      // cloud should only give us 5 nodes for 5 red jobs
      assertEquals(5, cloud.numProvisioned);

      // and all blue jobs should be still stuck in the queue
      for (Future<FreeStyleBuild> bb : blueBuilds) assertFalse(bb.isDone());
    } finally {
      bc.abort();
    }
  }
  /** Verifies the queueing behavior in the presence of the expression. */
  public void testQueueBehavior() throws Exception {
    DumbSlave w32 = createSlave("win 32bit", null);
    DumbSlave w64 = createSlave("win 64bit", null);
    createSlave("linux 32bit", null);

    final SequenceLock seq = new SequenceLock();

    FreeStyleProject p1 = createFreeStyleProject();
    p1.getBuildersList()
        .add(
            new TestBuilder() {
              public boolean perform(
                  AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
                  throws InterruptedException, IOException {
                seq.phase(0); // first, make sure the w32 slave is occupied
                seq.phase(2);
                seq.done();
                return true;
              }
            });
    p1.setAssignedLabel(jenkins.getLabel("win && 32bit"));

    FreeStyleProject p2 = createFreeStyleProject();
    p2.setAssignedLabel(jenkins.getLabel("win && 32bit"));

    FreeStyleProject p3 = createFreeStyleProject();
    p3.setAssignedLabel(jenkins.getLabel("win"));

    Future<FreeStyleBuild> f1 = p1.scheduleBuild2(0);

    seq.phase(1); // we schedule p2 build after w32 slave is occupied
    Future<FreeStyleBuild> f2 = p2.scheduleBuild2(0);

    Thread.sleep(1000); // time window to ensure queue has tried to assign f2 build

    // p3 is tied to 'win', so even though p1 is busy, this should still go ahead and complete
    FreeStyleBuild b3 = assertBuildStatusSuccess(p3.scheduleBuild2(0));
    assertSame(w64, b3.getBuiltOn());

    seq.phase(3); // once we confirm that p3 build is over, we let p1 proceed

    // p1 should have been built on w32
    FreeStyleBuild b1 = assertBuildStatusSuccess(f1);
    assertSame(w32, b1.getBuiltOn());

    // and so is p2
    FreeStyleBuild b2 = assertBuildStatusSuccess(f2);
    assertSame(w32, b2.getBuiltOn());
  }
  public void testDataCompatibilityWithHostNameWithWhitespace() throws Exception {
    DumbSlave slave =
        new DumbSlave(
            "abc def (xyz) : test",
            "dummy",
            createTmpDir().getPath(),
            "1",
            Mode.NORMAL,
            "",
            createComputerLauncher(null),
            RetentionStrategy.NOOP,
            Collections.EMPTY_LIST);
    jenkins.addNode(slave);

    FreeStyleProject p = createFreeStyleProject();
    p.setAssignedLabel(jenkins.getLabel("abc def"));
    assertEquals("abc def", p.getAssignedLabel().getName());
    assertEquals("\"abc def\"", p.getAssignedLabel().getExpression());

    // expression should be persisted, not the name
    Field f = AbstractProject.class.getDeclaredField("assignedNode");
    f.setAccessible(true);
    assertEquals("\"abc def\"", f.get(p));

    // but if the name is set, we'd still like to parse it
    f.set(p, "a:b c");
    assertEquals("a:b c", p.getAssignedLabel().getName());
  }
 private FreeStyleProject createJob(Builder builder) throws IOException {
   FreeStyleProject p = createFreeStyleProject();
   p.setAssignedLabel(
       null); // let it roam free, or else it ties itself to the master since we have no slaves
   p.getBuildersList().add(builder);
   return p;
 }
  /**
   * Push the build around to different nodes via the assignment to make sure it gets where we need
   * it to.
   */
  public void testQueueBehavior2() throws Exception {
    DumbSlave s = createSlave("win", null);

    FreeStyleProject p = createFreeStyleProject();

    p.setAssignedLabel(jenkins.getLabel("!win"));
    FreeStyleBuild b = assertBuildStatusSuccess(p.scheduleBuild2(0));
    assertSame(jenkins, b.getBuiltOn());

    p.setAssignedLabel(jenkins.getLabel("win"));
    b = assertBuildStatusSuccess(p.scheduleBuild2(0));
    assertSame(s, b.getBuiltOn());

    p.setAssignedLabel(jenkins.getLabel("!win"));
    b = assertBuildStatusSuccess(p.scheduleBuild2(0));
    assertSame(jenkins, b.getBuiltOn());
  }
 public void setUp() throws Exception {
   super.setUp();
   EnvVars env = new EnvVars();
   // we don't want Maven, Ant, etc. to be discovered in the path for this test to work,
   // but on Unix these tools rely on other basic Unix tools (like env) for its operation,
   // so empty path breaks the test.
   env.put("PATH", "/bin:/usr/bin");
   env.put("M2_HOME", "empty");
   slave = createSlave(new LabelAtom("slave"), env);
   project = createFreeStyleProject();
   project.setAssignedLabel(slave.getSelfLabel());
 }
  /**
   * Returns the future object for a newly created project.
   *
   * @param blockingJobName the name for the project
   * @param shell the shell command task to add
   * @param label the label to bind to master or slave
   * @return the future object for a newly created project
   * @throws IOException
   */
  private Future<FreeStyleBuild> createBlockingProject(
      String blockingJobName, Shell shell, Label label) throws IOException {
    FreeStyleProject blockingProject = this.createFreeStyleProject(blockingJobName);
    blockingProject.setAssignedLabel(label);

    blockingProject.getBuildersList().add(shell);
    Future<FreeStyleBuild> future = blockingProject.scheduleBuild2(0);

    while (!blockingProject.isBuilding()) {
      // wait until job is started
    }

    return future;
  }
  /**
   * One test for all for faster execution.
   *
   * @throws Exception
   */
  public void testCanRun() throws Exception {
    // init slave
    LabelAtom slaveLabel = new LabelAtom("slave");
    LabelAtom masterLabel = new LabelAtom("master");

    DumbSlave slave = this.createSlave(slaveLabel);
    SlaveComputer c = slave.getComputer();
    c.connect(false).get(); // wait until it's connected
    if (c.isOffline()) {
      fail("Slave failed to go online: " + c.getLog());
    }

    BuildBlockerQueueTaskDispatcher dispatcher = new BuildBlockerQueueTaskDispatcher();

    String blockingJobName = "blockingJob";

    Shell shell = new Shell("sleep 1");

    Future<FreeStyleBuild> future1 = createBlockingProject("xxx", shell, masterLabel);
    Future<FreeStyleBuild> future2 = createBlockingProject(blockingJobName, shell, masterLabel);
    Future<FreeStyleBuild> future3 = createBlockingProject("yyy", shell, slaveLabel);
    // add project to slave
    FreeStyleProject project = this.createFreeStyleProject();
    project.setAssignedLabel(slaveLabel);

    Queue.BuildableItem item =
        new Queue.BuildableItem(
            new Queue.WaitingItem(Calendar.getInstance(), project, new ArrayList<Action>()));

    CauseOfBlockage causeOfBlockage = dispatcher.canRun(item);

    assertNull(causeOfBlockage);

    BuildBlockerProperty property = new BuildBlockerProperty();

    property.setBlockingJobs(".*ocki.*");

    project.addProperty(property);

    causeOfBlockage = dispatcher.canRun(item);
    assertNotNull(causeOfBlockage);

    assertEquals(
        "Blocking job " + blockingJobName + " is running.", causeOfBlockage.getShortDescription());

    while (!(future1.isDone() && future2.isDone() && future3.isDone())) {
      // wait until jobs are done.
    }
  }
 public void testCopyToSlave() throws Exception {
   DumbSlave node = createSlave();
   SlaveComputer c = node.getComputer();
   c.connect(false).get(); // wait until it's connected
   if (c.isOffline()) fail("Slave failed to go online: " + c.getLog());
   FreeStyleProject other = createArtifactProject(),
       p = createProject(other.getName(), "", "", false, false, false);
   assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get());
   p.setAssignedLabel(node.getSelfLabel());
   FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get();
   assertBuildStatusSuccess(b);
   assertSame(node, b.getBuiltOn());
   assertFile(true, "foo.txt", b);
   assertFile(true, "subdir/subfoo.txt", b);
   assertFile(true, "deepfoo/a/b/c.log", b);
 }
  @LocalData
  @Test
  public void slave() throws Exception {
    Assume.assumeFalse(
        "TimeoutException from basic",
        "https://jenkins.ci.cloudbees.com/job/core/job/jenkins_main_trunk/"
            .equals(System.getenv("JOB_URL")));
    DumbSlave s = j.createOnlineSlave();
    project.setAssignedLabel(s.getSelfLabel());

    FilePath src = new FilePath(j.jenkins.getRootPath(), "jobs/junit/workspace/");
    assertNotNull(src);
    FilePath dest = s.getWorkspaceFor(project);
    assertNotNull(dest);
    src.copyRecursiveTo("*.xml", dest);

    basic();
  }